diff -r 7fdc9a71d314 -r 8ad140f3dd41 memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp --- a/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp Wed Sep 15 13:53:27 2010 +0300 +++ b/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -47,6 +47,11 @@ DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() - START - this: 0x%08x", this )); + + ReleaseFreeCells(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() - END - this: 0x%08x", this )); } @@ -168,14 +173,243 @@ +TInt DMemSpyDriverLogChanHeapBase::OpenUserHeap( DThread& aClientThread, TUint aExpectedHeapVTable, RMemSpyDriverRHeapUser& aHeap, DChunk*& aUserHeapChunk, TDes8* aClientHeapChunkName ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap() - START - aHeap.ChunkIsInitialised: %d, aExpectedHeapVTable: 0x%08x, aClientThread: %O", aHeap.ChunkIsInitialised(), aExpectedHeapVTable, &aClientThread )); + __ASSERT_ALWAYS( aHeap.ChunkIsInitialised() == EFalse, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapChunkAlreadyCloned ) ); + + TInt r = KErrNotFound; + aUserHeapChunk = NULL; + + NKern::ThreadEnterCS(); + + const TBool allocatorIsReallyRHeap = GetUserHeapHandle( aClientThread, aHeap, aExpectedHeapVTable ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - allocatorIsReallyRHeap: %d", allocatorIsReallyRHeap)); + + if ( allocatorIsReallyRHeap ) + { + RAllocator* allocator = OSAdaption().DThread().GetAllocator( aClientThread ); + + // Open client's heap chunk in order to read it's dimensions + const TInt clientsHeapChunkHandle = aHeap.iChunkHandle; + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clientsHeapChunkHandle: 0x%08x, allocatorAddress: 0x%08x", clientsHeapChunkHandle, allocator)); + + NKern::LockSystem(); + DChunk* clientsHeapChunk = (DChunk*) Kern::ObjectFromHandle( &aClientThread, clientsHeapChunkHandle, EChunk ); + NKern::UnlockSystem(); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clientsHeapChunk: 0x%08x", clientsHeapChunk )); + + if ( clientsHeapChunk != NULL ) + { + // Get the chunk name (if the caller asked for it) + if ( aClientHeapChunkName ) + { + clientsHeapChunk->FullName( *aClientHeapChunkName ); + } + + // Update the heap chunk pointer. We do this now because this + // should point to the _real_ user-side heap chunk, rather than + // the copy of the chunk that we are about to make. + aUserHeapChunk = clientsHeapChunk; + + // Set up ourselves to duplicate their heap chunk + const TInt clientsHeapChunkSize = OSAdaption().DChunk().GetSize( *clientsHeapChunk ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - chunkBase: 0x%08x, size: %8d, maxLen: %8d, chunk: %O", clientsHeapChunk->iBase, clientsHeapChunkSize, clientsHeapChunk->iMaxSize, clientsHeapChunk )); + + // Make a new chunk that is the same size, owned by this thread. + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelSingle; + info.iMaxSize = clientsHeapChunkSize; + info.iOwnsMemory = ETrue; // Use memory from system's free pool + info.iDestroyedDfc = NULL; + #ifdef __EPOC32__ + info.iMapAttr = (TInt)EMapAttrFullyBlocking; // Full caching + #endif + + // Holds a copy of the client's heap chunk + DChunk* heapCopyChunk; + TLinAddr heapCopyChunkAddress; + TUint32 heapCopyChunkMappingAttributes; + r = Kern::ChunkCreate( info, heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - creating chunk returned: %d", r)); + // + if ( r == KErrNone ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - copy chunk base: 0x%08x, heapCopyChunkAddress: 0x%08x", heapCopyChunk->iBase, heapCopyChunkAddress)); + + // Commit memory for entire buffer + TUint32 physicalAddress = 0; + r = Kern::ChunkCommitContiguous( heapCopyChunk, 0, clientsHeapChunkSize, physicalAddress ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - commiting chunk returned: %d", r)); + + if ( r != KErrNone) + { + // On error, thow away the chunk we have created + Kern::ChunkClose( heapCopyChunk ); + heapCopyChunk = NULL; + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - heapCopyChunk->iSize: 0x%08x, heapCopyChunk->iBase: 0x%08x, heapCopyChunkAddress: 0x%08x, physicalAddress: 0x%08x", heapCopyChunk->iSize, heapCopyChunk->iBase, heapCopyChunkAddress, physicalAddress)); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - trying to copy %d bytes from clients allocator address of 0x%08x", clientsHeapChunkSize, allocator )); + r = Kern::ThreadRawRead( &aClientThread, allocator, (TAny*) heapCopyChunkAddress, clientsHeapChunkSize ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - read result of clients heap data is: %d", r)); + if ( r == KErrNone ) + { + // Transfer ownership of the copy heap chunk to the heap object. This also calculates the delta + // beween the heap addresses in the client's address space and the kernel address space. + aHeap.AssociateWithKernelChunk( heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + } + } + } + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - could not open clients heap chunk by its handle" ) ); + r = KErrNotFound; + } + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clients heap is not an RHeap (allocated vTable mismatch)" ) ); + r = KErrNotSupported; + } + + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - r: %d", r )); + return r; + } + + + + + + + + + + + + + + + + + + + + + + + +TBool DMemSpyDriverLogChanHeapBase::GetUserHeapHandle( DThread& aThread, RMemSpyDriverRHeapUser& aHeap, TUint aExpectedVTable ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle() - START - aExpectedVTable: 0x%08x", aExpectedVTable) ); + + RAllocator* allocator = OSAdaption().DThread().GetAllocator( aThread ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - allocator addr: 0x%08x", allocator) ); + TUint* pAllocator = (TUint*) allocator; + // + TBool vTableOkay = EFalse; + TUint vtable = 0; + + // Read a bit more data than is available for debugging purposes + TBuf8<32> vtableBuf; + TInt r = Kern::ThreadRawRead( &aThread, pAllocator, (TUint8*) vtableBuf.Ptr(), vtableBuf.MaxLength() ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - read result of vtable data from requested thread is: %d", r)); + if ( r == KErrNone ) + { + TRACE( MemSpyDriverUtils::DataDump("allocator vtable data - %lS", vtableBuf.Ptr(), vtableBuf.MaxLength(), vtableBuf.MaxLength() ) ); + vtableBuf.SetLength( vtableBuf.MaxLength() ); + + vtable = vtableBuf[0] + + (vtableBuf[1] << 8) + + (vtableBuf[2] << 16) + + (vtableBuf[3] << 24); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - client VTable is: 0x%08x", vtable) ); + + // Check the v-table to work out if it really is an RHeap + vTableOkay = ( vtable == aExpectedVTable ); + if ( vTableOkay ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - vtables okay") ); + r = aHeap.ReadFromUserAllocator( aThread ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - after userget, error: %d", r)); + + } + else + { + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - vtables dont match! - aExpectedVTable: 0x%08x, allocator addr: 0x%08x, client VTable is: 0x%08x, aThread: %O", aExpectedVTable, allocator, vtable, &aThread ) ); + } + } + else + { + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - error during client vTable reading: %d, aThread: %O", r, &aThread ) ); + } + // + return (vTableOkay && (r == KErrNone)); + } + + + + + + + + + + + + + + void DMemSpyDriverLogChanHeapBase::PrintHeapInfo( const TMemSpyHeapInfo& aInfo ) { const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap(); - //const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); + const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iAccessCount: %d", rHeapObjectData.iAccessCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iHandleCount: %d", rHeapObjectData.iHandleCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iHandles: 0x%08x", rHeapObjectData.iHandles ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iFlags: 0x%08x", rHeapObjectData.iFlags ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iCellCount: %d", rHeapObjectData.iCellCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iTotalAllocSize: %d", rHeapObjectData.iTotalAllocSize ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMinLength: %d", rHeapObjectData.iMinLength ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMaxLength: %d", rHeapObjectData.iMaxLength ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iOffset: %d", rHeapObjectData.iOffset ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iGrowBy: %d", rHeapObjectData.iGrowBy ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iChunkHandle: 0x%08x", rHeapObjectData.iChunkHandle ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iBase: 0x%08x", rHeapObjectData.iBase ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iTop: 0x%08x", rHeapObjectData.iTop ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iAlign: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMinCell: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iPageSize: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFree.next: 0x%08x", rHeapObjectData.iFree.next ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFree.len: %d", rHeapObjectData.iFree.len ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iNestingLevel: %d", rHeapObjectData.iNestingLevel ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iAllocCount: %d", rHeapObjectData.iAllocCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailType: %d", rHeapObjectData.iFailType ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailRate: %d", rHeapObjectData.iFailRate ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailed: %d", rHeapObjectData.iFailed ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailAllocCount: %d", rHeapObjectData.iFailAllocCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iRand: %d", rHeapObjectData.iRand ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iTestData: 0x%08x", rHeapObjectData.iTestData ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Stats (Free) -" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell count: %d", rHeapStats.StatsFree().TypeCount() ) ); @@ -197,6 +431,12 @@ TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Stats (Common) -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - total cell count: %d", rHeapStats.StatsCommon().TotalCellCount() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Misc. Info -" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - chunk size: %d", rHeapMetaData.ChunkSize() ) ); @@ -205,17 +445,73 @@ TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - debug allocator: %d", rHeapMetaData.IsDebugAllocator() ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - shared heap: %d", rHeapMetaData.IsSharedHeap() ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - user thread: %d", rHeapMetaData.IsUserThread() ) ); - //TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (free): %d", rHeapMetaData.HeaderSizeFree() ) ); - //TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (alloc): %d", rHeapMetaData.HeaderSizeAllocated() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (free): %d", rHeapMetaData.HeaderSizeFree() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (alloc): %d", rHeapMetaData.HeaderSizeAllocated() ) ); TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap vTable: 0x%08x", rHeapMetaData.VTable() ) ); - //TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap object size: %d", rHeapMetaData.ClassSize() ) ); - TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap size: %d", rHeapMetaData.iHeapSize ) ); - TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - allocator address: 0x%08x", rHeapMetaData.iAllocatorAddress ) ); - TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - min heap size: %d", rHeapMetaData.iMinHeapSize ) ); - TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - max heap size: %d", rHeapMetaData.iMaxHeapSize ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap object size: %d", rHeapMetaData.ClassSize() ) ); } -TInt DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel(RMemSpyDriverRHeapBase& aHeap, TMemSpyHeapInfo* aHeapInfo, TDes8* aTransferBuffer ) + + + + + + + + + +TBool DMemSpyDriverLogChanHeapBase::IsDebugKernel() + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - START") ); + + TInt r = KErrNone; + TBool debugKernel = EFalse; + + NKern::ThreadEnterCS(); + RMemSpyDriverRHeapKernelInPlace rHeap; + r = OpenKernelHeap( rHeap ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - open kernel heap returned: %d", r) ); + + if ( r == KErrNone ) + { + debugKernel = IsDebugKernel( rHeap ); + + // Tidy up + rHeap.DisassociateWithKernelChunk(); + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - debugKernel: %d", debugKernel) ); + NKern::ThreadLeaveCS(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - END - ret: %d", r) ); + return debugKernel; + } + + +TBool DMemSpyDriverLogChanHeapBase::IsDebugKernel( RMemSpyDriverRHeapKernelInPlace& aHeap ) + { + TBool debugKernel = EFalse; + // + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - START") ); + NKern::ThreadEnterCS(); + + // Request that the kernel fail the next heap allocation + aHeap.FailNext(); + + // Allocate a new cell, and in debug builds of the kernel, this should be NULL + TInt* cell = new TInt(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - cell: 0x%08x", cell) ); + debugKernel = ( cell == NULL ); + delete cell; + + NKern::ThreadLeaveCS(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - END - debugKernel: %d", debugKernel) ); + // + return debugKernel; + } + + +TInt DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel( RMemSpyDriverRHeapBase& aHeap, TBool aIsDebugAllocator, const TDesC8& aChunkName, TMemSpyHeapInfo* aHeapInfo, TDes8* aTransferBuffer ) { TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel() - START - aTransferBuffer: 0x%08x", aTransferBuffer ) ); @@ -224,13 +520,16 @@ // This object holds all of the info we will accumulate for the client. TMemSpyHeapInfo masterHeapInfo; - masterHeapInfo.SetType(aHeap.GetTypeFromHelper()); + masterHeapInfo.SetType( TMemSpyHeapInfo::ETypeRHeap ); masterHeapInfo.SetTid( 2 ); masterHeapInfo.SetPid( 1 ); // This is the RHeap-specific object that contains all RHeap info TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap(); + // This is the object data for the RHeap instance + TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); + aHeap.CopyObjectDataTo( rHeapObjectData ); // When walking the kernel heap we must keep track of the free cells // without allocating any more memory (on the kernel heap...) @@ -245,7 +544,7 @@ // We must walk the client's heap in order to build statistics TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - calling heap walker constructor...")); - RMemSpyDriverHeapWalker heapWalker(aHeap); + RMemSpyDriverHeapWalker heapWalker( aHeap, aIsDebugAllocator ); if ( aTransferBuffer ) { // This will allow us to identify that we're writing directly to the stream @@ -265,6 +564,10 @@ TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - not collecting free cells")); } + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - locking system..." )); + NKern::LockSystem(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - disabling interrupts..." )); + const TInt irq = NKern::DisableAllInterrupts(); TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - starting traversal..." )); #if defined( TRACE_TYPE_KERNELHEAP ) @@ -272,8 +575,11 @@ #endif r = heapWalker.Traverse(); - TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - finished traversal - err: %d, iStackStream: 0x%08x, pCount: 0x%08x, isOpen: %d", - r, iStackStream, pCount, ( iStackStream == NULL ? 0 : iStackStream->IsOpen() ) )); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - restoring interrupts..." )); + NKern::RestoreInterrupts( irq ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - finished traversal - err: %d, iStackStream: 0x%08x, pCount: 0x%08x, isOpen: %d", r, iStackStream, pCount, ( iStackStream == NULL ? 0 : iStackStream->IsOpen() ) )); + NKern::UnlockSystem(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - unlocked system" )); // Write free cells if requested if ( r == KErrNone && iStackStream && iStackStream->IsOpen() && pCount ) @@ -290,19 +596,18 @@ // Get remaining meta data that isn't stored elsewhere TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); - TFullName chunkName; - aHeap.Chunk().FullName(chunkName); - rHeapMetaData.SetChunkName(chunkName); + rHeapMetaData.SetChunkName( aChunkName ); rHeapMetaData.SetChunkSize( (TUint) aHeap.Chunk().Size() ); rHeapMetaData.SetChunkHandle( &aHeap.Chunk() ); - rHeapMetaData.SetChunkBaseAddress( OSAdaption().DChunk().GetBase(aHeap.Chunk()) ); - rHeapMetaData.SetDebugAllocator(aHeap.Helper()->AllocatorIsUdeb()); + rHeapMetaData.SetChunkBaseAddress( aHeap.Chunk().Base() ); + rHeapMetaData.SetDebugAllocator( aIsDebugAllocator ); + rHeapMetaData.SetHeaderSizeFree( RMemSpyDriverRHeapBase::FreeCellHeaderSize() ); + rHeapMetaData.SetHeaderSizeAllocated( RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( aIsDebugAllocator ) ); rHeapMetaData.SetUserThread( EFalse ); rHeapMetaData.SetSharedHeap( ETrue ); - rHeapMetaData.iHeapSize = aHeap.Helper()->CommittedSize(); - rHeapMetaData.iAllocatorAddress = (TAny*)aHeap.Helper()->AllocatorAddress(); - rHeapMetaData.iMinHeapSize = aHeap.Helper()->MinCommittedSize(); - rHeapMetaData.iMaxHeapSize = aHeap.Helper()->MaxCommittedSize(); + + // Get any heap-specific info + aHeap.GetHeapSpecificInfo( masterHeapInfo ); PrintHeapInfo( masterHeapInfo ); @@ -336,12 +641,17 @@ -TBool DMemSpyDriverLogChanHeapBase::HandleHeapCell(TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/) +TBool DMemSpyDriverLogChanHeapBase::HandleHeapCell( TInt aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/ ) { TInt error = KErrNone; // - if (aCellType & EMemSpyDriverFreeCellMask) + if ( aCellType == EMemSpyDriverGoodFreeCell || aCellType == EMemSpyDriverBadFreeCellAddress || aCellType == EMemSpyDriverBadFreeCellSize ) { + TMemSpyDriverFreeCell cell; + cell.iType = aCellType; + cell.iAddress = aCellAddress; + cell.iLength = aLength; + // if ( iStackStream ) { if ( !iStackStream->IsFull() ) @@ -359,16 +669,163 @@ error = KErrAbort; } } - } + else + { + NKern::ThreadEnterCS(); + error = iFreeCells.Append( cell ); + NKern::ThreadLeaveCS(); + // + if ( error == KErrNone ) + { + ++iFreeCellCount; + } + } + } // return ( error == KErrNone ); } void DMemSpyDriverLogChanHeapBase::HandleHeapWalkInit() - { - iFreeCellCount = 0; - } + { + // Can't delete the free cell list here as we might be walking the kernel heap + iFreeCellCount = 0; + } + + + + + + +TInt DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() + { + // Transfer free cells immediately from xfer stream + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - START - iHeapStream: 0x%08x", iHeapStream )); + __ASSERT_ALWAYS( !iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotClosed ) ); + // + TInt r = KErrNoMemory; + // + NKern::ThreadEnterCS(); + // + iHeapStream = new RMemSpyMemStreamWriter(); + if ( iHeapStream ) + { + const TInt requiredMemory = CalculateFreeCellBufferSize(); + r = OpenXferStream( *iHeapStream, requiredMemory ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - requested %d bytes for free cell list, r: %d", requiredMemory, r )); + + if ( r == KErrNone ) + { + const TInt count = iFreeCells.Count(); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - free cell count: %d", count )); + // + iHeapStream->WriteInt32( count ); + for( TInt i=0; iWriteInt32( cell.iType ); + iHeapStream->WriteUint32( reinterpret_cast( cell.iAddress ) ); + iHeapStream->WriteInt32( cell.iLength ); + } + + // Finished with the array now + iFreeCells.Reset(); + + // We return the amount of client-side memory that needs to be allocated to hold the buffer + r = requiredMemory; + } + } + // + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - END - r: %d", r)); + return r; + } + + +TInt DMemSpyDriverLogChanHeapBase::FetchFreeCells( TDes8* aBufferSink ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::FetchFreeCells() - START - iHeapStream: 0x%08x", iHeapStream )); + __ASSERT_ALWAYS( iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotOpen ) ); + + TInt r = KErrNone; + + // Write buffer to client + NKern::ThreadEnterCS(); + r = iHeapStream->WriteAndClose( aBufferSink ); + + // Tidy up + ReleaseFreeCells(); + + NKern::ThreadLeaveCS(); + // + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::FetchFreeCells() - END - r: %d", r)); + return r; + } + + + +TInt DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() const + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() - START" )); + + const TInt count = iFreeCells.Count(); + const TInt entrySize = sizeof( TInt32 ) + sizeof( TInt32 ) + sizeof( TUint32 ); + const TInt r = ( count * entrySize ) + sizeof( TInt ); // Extra TInt to hold count + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() - END - r: %d, count: %d, entrySize: %d", r, count, entrySize )); + return r; + } + + + +void DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() - START - this: 0x%08x", this )); + + // Housekeeping + NKern::ThreadEnterCS(); + iFreeCells.Reset(); + // + iStackStream = NULL; + // + delete iHeapStream; + iHeapStream = NULL; + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() - END - this: 0x%08x", this )); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RHeapK*& aHeap, DChunk*& aChunk, TDes8* aClientHeapChunkName ) { @@ -448,7 +905,7 @@ // Finalise construction of heap if ( kernelHeap != NULL ) { - TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeapChunk->Base(): 0x%08x", kernelHeapChunk->Base() ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeap->Base(): 0x%08x, kernelHeapChunk->Base(): 0x%08x", kernelHeap->Base(), kernelHeapChunk->Base() ) ); aHeap = kernelHeap; aChunk = kernelHeapChunk; @@ -478,6 +935,27 @@ return r; } + +TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RMemSpyDriverRHeapKernelInPlace& aHeap, TDes8* aClientHeapChunkName ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - START") ); + + RHeapK* heap = NULL; + DChunk* chunk = NULL; + TInt r = OpenKernelHeap( heap, chunk, aClientHeapChunkName ); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - open err: %d", r ) ); + if ( r == KErrNone ) + { + aHeap.SetKernelHeap( *heap ); + aHeap.AssociateWithKernelChunk( chunk, TLinAddr( chunk->iBase ), 0 ); + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - END - ret: %d", r ) ); + return r; + } + + TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RMemSpyDriverRHeapKernelFromCopy& aHeap, TDes8* aClientHeapChunkName ) { TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - START") ); @@ -539,7 +1017,7 @@ NKern::LockSystem(); const TUint32 copyLength = heapSize; // TODO Min( heap->Size(), heapSize ); - TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - trying to copy %d (vs orig estimate of %d) bytes from kernel allocator address: 0x%08x", copyLength, heapSize, heap)); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - trying to copy %d (vs orig estimate of %d) bytes from kernel allocator address: 0x%08x", copyLength, heapSize, heap->Base() )); memcpy( (TUint8*) heapCopyChunkAddress, heap, copyLength ); NKern::UnlockSystem();