memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp
branchRCL_3
changeset 20 ca8a1b6995f6
parent 0 a03f92240627
child 21 52e343bb8f80
--- a/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp	Thu Aug 19 11:25:43 2010 +0300
+++ b/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp	Tue Aug 31 16:45:49 2010 +0300
@@ -162,24 +162,20 @@
     //
     // The driver leaves kernel context with the copy of the kernel heap still associated with MemSpy's process.
     // The second driver call will copy the chunk data to user side and release the kernel side chunk.
-    const TBool isInit = iKernelHeap.ChunkIsInitialised();
-    TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - START - isInit: %d", isInit ));
-    __ASSERT_ALWAYS( !isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataInitError ) );
+    //const TBool isInit = iKernelHeap.ChunkIsInitialised();
+    //TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - START - isInit: %d", isInit ));
+    //__ASSERT_ALWAYS( !isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataInitError ) );
 
     iKernelHeap.Reset();
     NKern::ThreadEnterCS();
 
-    // We must identify if we have a debug kernel allocator
-    const TBool debugAllocator = IsDebugKernel();
-    TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - debugAllocator: %d", debugAllocator ) );
-
     TFullName heapChunkName;
     TInt r = OpenKernelHeap( iKernelHeap, &heapChunkName );
     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelInit() - open err: %d", r));
 
     if  ( r == KErrNone )
         {
-        r = GetHeapInfoKernel( iKernelHeap, debugAllocator, heapChunkName, aInfo, aFreeCells );
+        r = GetHeapInfoKernel( iKernelHeap, aInfo, aFreeCells );
         TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - base class get heap info: %d", r) );
 
         // If everything was okay, we can now return back to user-side, indicating the amount of heap data
@@ -190,10 +186,10 @@
             r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
             TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - user side buffer needs to be: %d", r) );
             }
-        else if ( iKernelHeap.ChunkIsInitialised() )
+        else
             {
             // Error scenario - must close heap
-            iKernelHeap.DisassociateWithKernelChunk();
+            iKernelHeap.Close();
             }
         }
 
@@ -206,12 +202,15 @@
 
 TInt DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch( TDes8* aSink )
     {
+	//TOMSCI TODO this function is fundamentally flawed
+	return KErrNotSupported;
+	/*
     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - START"));
 
     NKern::ThreadEnterCS();
 
     // We should already have an initialised copy of the kernel heap
-    const TBool isInit = iKernelHeap.ChunkIsInitialised();
+    const TBool isInit = iKernelHeap.Helper() != NULL;
     TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
     __ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
 
@@ -261,6 +260,7 @@
 
 	TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - END - ret: %d", r));
     return r;
+	*/
     }
 
 
@@ -279,7 +279,7 @@
 
 
 
-
+const TInt KPageSize = 4096;
 
 TInt DMemSpyDriverLogChanHeapData::GetHeapDataUser( TMemSpyDriverInternalHeapDataParams& aParams )
     {
@@ -304,135 +304,110 @@
 		    return KErrAccessDenied;
             }
         }
-    
+
     // Check that the process' thread's are suspended
     DThread* thread = (DThread*) TempObject();
     if  ( SuspensionManager().IsSuspended( *thread ) )
         {
-        // Find the chunk with the correct handle
+        // Open the heap
 	    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - thread: %O", thread) );
         RMemSpyDriverRHeapUser heap( OSAdaption() );
-        const TBool allocatorIsReallyRHeap = GetUserHeapHandle( *thread, heap, aParams.iRHeapVTable );
-        if  ( allocatorIsReallyRHeap )
+		r = heap.OpenUserHeap(*thread, aParams.iDebugAllocator);
+		TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening heap returned: %d", r) );
+        if  (r == KErrNone)
             {
-            const TInt chunkHandle = heap.iChunkHandle;
-	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkHandle: 0x%08x, thread: %O", chunkHandle, thread) );
-
-  	        NKern::ThreadEnterCS();
- 	        NKern::LockSystem();
-            DChunk* chunk = (DChunk*) Kern::ObjectFromHandle( thread, chunkHandle, EChunk );
-            NKern::UnlockSystem();
-	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunk: 0x%08x", chunk ) );
-  	        NKern::ThreadLeaveCS();
-
-            if  ( chunk != NULL )
+            if  ( aParams.iChecksum != 0 )
                 {
-                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase: 0x%08x, size: %8d, maxLen: %8d, chunk: %O", chunk->iBase, chunk->iSize, chunk->iMaxSize, chunk) );
-
-                // If the client specified a checksum value, then we must walk the heap just to make sure
-                // it hasn't changed. Expensive operation, but good for paranoia purposes...
-                if  ( aParams.iChecksum != 0 )
-                    {
-                    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
+                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - checksum validation requested - expecting: 0x%08x", aParams.iChecksum ) );
+                RMemSpyDriverHeapWalker heapWalker(heap);
+                
+                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - starting traversal..." ));
+#if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
+                heapWalker.SetPrintDebug();
+#endif
+                r = heapWalker.Traverse();
+                const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
+                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
 
-                    RMemSpyDriverRHeapUser rHeap( OSAdaption() );
-                    DChunk* userHeapChunk = NULL;
-                    r = OpenUserHeap( *thread, aParams.iRHeapVTable, rHeap, userHeapChunk );
-                    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening client heap returned: %d", r) );
-                    if  ( r == KErrNone )
-                        {
-                        TMemSpyHeapWalkerNullObserver observer; 
-                        RMemSpyDriverHeapWalker heapWalker( rHeap, aParams.iDebugAllocator );
-                        heapWalker.SetObserver( &observer );
-                        
-                        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - starting traversal..." ));
-#if ( defined( TRACE_TYPE_USERHEAP ) && defined( TRACE_TYPE_HEAPWALK ) )
-                        heapWalker.SetPrintDebug();
-#endif
-                        r = heapWalker.Traverse();
-                        const TUint32 calculatedChecksum = heapWalker.Stats().iFreeCellCRC;
-                        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - finished traversal - err: %d, checksum: 0x%08x", r, calculatedChecksum ));
+                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
+                if  ( calculatedChecksum != aParams.iChecksum )
+                    {
+                    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, thread );
+                    r = KErrCorrupt;
+                    }
+                }
 
-                        // Release resources
-                        rHeap.DisassociateWithKernelChunk();
+            // Get user side (MemSpy) descriptor length info
+            if  ( r == KErrNone )
+                {
+                TInt destLen = 0;
+                TInt destMax = 0;
+                TUint8* destPtr = NULL;
+                r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
+                TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", aParams.iDes, destPtr, destLen, destMax, r ));
+				destMax = destMax & ~(KPageSize-1); // Round down dest max to page size
+				if (destMax <= 0 || (aParams.iReadAddress & (KPageSize-1))) r = KErrArgument; // If destMax is less than a page or the read address isn't a multiple of page size then we don't want to know
 
-                        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x", calculatedChecksum, aParams.iChecksum ));
-                        if  ( calculatedChecksum != aParams.iChecksum )
-                            {
-                            Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - comparing CALCULATED: 0x%08x vs EXPECTED: 0x%08x for thread %O", calculatedChecksum, aParams.iChecksum, thread );
-                            r = KErrCorrupt;
-                            }
-                        }
-                    else
-                        {
-                        // Couldn't verify checksum in this situation...
-                        }
-                    }
-
-                // Get user side (MemSpy) descriptor length info
                 if  ( r == KErrNone )
                     {
-                    TInt destLen;
-                    TInt destMax;
-                    TUint8* destPtr = NULL;
-                    r = Kern::ThreadGetDesInfo( &ClientThread(), aParams.iDes, destLen, destMax, destPtr, ETrue );
-                    TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - user side descriptor: 0x%08x (0x%08x), len: %8d, maxLen: %8d, r: %d", aParams.iDes, destPtr, destLen, destMax, r ));
-
-                    if  ( r == KErrNone )
+					const TLinAddr chunkBase = (TLinAddr)OSAdaption().DChunk().GetBase(heap.Chunk());
+					const TLinAddr chunkMaxAddr = chunkBase + OSAdaption().DChunk().GetMaxSize(heap.Chunk());
+        	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunkBase:    0x%08x", chunkBase) );
+        
+					TLinAddr readAddress = aParams.iReadAddress;
+                    if (aParams.iRemaining < 0 )
                         {
-                        // Calculate start of real heap data (skipping over embedded RHeap object)
-                        const TUint8* startOfHeapOffset = heap.iBase;
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - startOfHeapOffset:    0x%08x", startOfHeapOffset) );
-            
-                        // Deal with initial case
-                        const TUint heapSize = heap.Size();
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - heapSize:               %8d", heapSize) );
-                        if  ( aParams.iRemaining < 0 )
-                            {
-                            // Initial case, remaining initialised to -1
-                            aParams.iRemaining = heapSize;
-                            }
+                        // Initial case, start from the bottom
+                        readAddress = chunkBase;
+						aParams.iRemaining = heap.Helper()->CommittedSize();
+                        }
+
+                    // The remaining number of bytes should allow us to calculate the position
+                    // to read from.
+                    TInt amountToRead = Min( aParams.iRemaining, destMax );
+        	        TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - amountToRead:           %8d", amountToRead) );
+        
+                    // Do the read from the heap we are spying on into MemSpy's address space
+					// TomS: I didn't know you could do this - you live and learn
+					do
+						{
+						r = Kern::ThreadRawRead( thread, (const void*)readAddress, destPtr, amountToRead );
+        				TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - read result: %d", r) );
 
-                        // The remaining number of bytes should allow us to calculate the position
-                        // to read from.
-                        const TInt amountToRead = Min( aParams.iRemaining, destMax );
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - amountToRead:           %8d", amountToRead) );
-                        const TInt readOffset = ( heapSize - aParams.iRemaining );
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - readOffset:             %8d", readOffset) );
-                        const TAny* readAddress = startOfHeapOffset + readOffset;
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - readAddress:          0x%08x", readAddress) );
-            
-                        // Do the read from the heap we are spying on into MemSpy's address space
-                        r = Kern::ThreadRawRead( thread, readAddress, destPtr, amountToRead );
-        	            TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - read result: %d", r) );
-                        //
-                        if  (r == KErrNone)
-                            {
-                            // Client takes care of updating descriptor length.
-                            r = amountToRead;
-                            }
-                        else if ( r == KErrBadDescriptor )
-                            {
-                            MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor );
-                            }
-            
-                        // Update remaining bytes
-                        aParams.iRemaining -= amountToRead;
-                        aParams.iReadAddress = (TUint) readAddress;
+						if (r == KErrBadDescriptor)
+							{
+							// This is not necessarily an error - it could be we've hit an unmapped page
+							if (amountToRead > KPageSize)
+								{
+								// retry reading a single page instead
+								amountToRead = KPageSize;
+								}
+							else
+								{
+								// Try the next page
+								readAddress += KPageSize;
+								}
+							}
+						} while (r == KErrBadDescriptor && readAddress < chunkMaxAddr);
+                    //
+                    if  (r == KErrNone)
+                        {
+                        // Client takes care of updating descriptor length.
+                        r = amountToRead;
                         }
+        
+                    // Update remaining bytes
+                    aParams.iRemaining -= amountToRead;
+                    aParams.iReadAddress = readAddress;
                     }
                 }
-            else
-                {
-    	        Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - chunk not found! thread: %O", thread );
-                r = KErrNotFound;
-                }
-            }
+			}
         else
             {
-    	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt find heap - vtable mis-match? thread: %O", thread );
+    	    Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt open heap for thread %O, err=%d", thread, r);
             r = KErrNotSupported;
             }
+		heap.Close();
         }
     else
         {