diff -r 07b41fa8d1dd -r ca8a1b6995f6 memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapData.cpp --- 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 {