--- a/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp Tue Aug 31 16:45:49 2010 +0300
+++ b/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp Wed Sep 01 12:37:10 2010 +0100
@@ -162,20 +162,24 @@
//
// 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, aInfo, aFreeCells );
+ r = GetHeapInfoKernel( iKernelHeap, debugAllocator, heapChunkName, 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
@@ -186,10 +190,10 @@
r = OSAdaption().DChunk().GetSize( iKernelHeap.Chunk() );
TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapInfo::GetHeapInfoKernel() - user side buffer needs to be: %d", r) );
}
- else
+ else if ( iKernelHeap.ChunkIsInitialised() )
{
// Error scenario - must close heap
- iKernelHeap.Close();
+ iKernelHeap.DisassociateWithKernelChunk();
}
}
@@ -202,15 +206,12 @@
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.Helper() != NULL;
+ const TBool isInit = iKernelHeap.ChunkIsInitialised();
TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataKernelFetch() - isInit: %d", isInit ));
__ASSERT_ALWAYS( isInit, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicKernelHeapDataFetchError ) );
@@ -260,7 +261,6 @@
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,110 +304,135 @@
return KErrAccessDenied;
}
}
-
+
// Check that the process' thread's are suspended
DThread* thread = (DThread*) TempObject();
if ( SuspensionManager().IsSuspended( *thread ) )
{
- // Open the heap
+ // Find the chunk with the correct handle
TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - thread: %O", thread) );
RMemSpyDriverRHeapUser heap( OSAdaption() );
- r = heap.OpenUserHeap(*thread, aParams.iDebugAllocator);
- TRACE( Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - opening heap returned: %d", r) );
- if (r == KErrNone)
+ const TBool allocatorIsReallyRHeap = GetUserHeapHandle( *thread, heap, aParams.iRHeapVTable );
+ if ( allocatorIsReallyRHeap )
{
- if ( aParams.iChecksum != 0 )
+ 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 )
{
- 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 ));
+ 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 - 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;
- }
- }
+ 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 ));
- // 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
+ // Release resources
+ rHeap.DisassociateWithKernelChunk();
+ 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 )
{
- 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 )
- {
- // Initial case, start from the bottom
- readAddress = chunkBase;
- aParams.iRemaining = heap.Helper()->CommittedSize();
- }
+ 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 ));
- // 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) );
+ if ( r == KErrNone )
+ {
+ // 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;
+ }
- 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;
+ // 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;
}
-
- // 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 open heap for thread %O, err=%d", thread, r);
+ Kern::Printf("DMemSpyDriverLogChanHeapData::GetHeapDataUser - couldnt find heap - vtable mis-match? thread: %O", thread );
r = KErrNotSupported;
}
- heap.Close();
}
else
{