--- 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
{