void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread, TBool aCreateDataStream ) { // Make sure the process is suspended for the entire time we are manipulating it's heap iEngine.ProcessSuspendLC( aThread.Process().Id() ); // Get the heap info, including cell information RArray<TMemSpyDriverCell> cells; CleanupClosePushL( cells ); TMemSpyHeapInfo heapInfo; TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum1: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); GetHeapInfoUserL(aThread.Process().Id(), aThread.Id(), heapInfo, &cells, ETrue); TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum2: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); // Get the heap data const TFullName pName( aThread.FullName() ); OutputHeapDataUserL( aThread.Process().Id(), aThread.Id(), pName, heapInfo, aCreateDataStream, &cells ); CleanupStack::PopAndDestroy( &cells ); // Resume process CleanupStack::PopAndDestroy(); }
EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoUserL( const CMemSpyThread& aThread ) { HBufC* threadName = aThread.FullName().AllocLC(); // RArray<TMemSpyDriverFreeCell> freeCells; CleanupClosePushL( freeCells ); // TMemSpyHeapInfo info; GetHeapInfoUserL( aThread.Process().Id(), aThread.Id(), info, &freeCells ); OutputHeapInfoL( info, *threadName, &freeCells ); // CleanupStack::PopAndDestroy( 2, threadName ); // freecells & thread name }
EXPORT_C void CMemSpyEngineHelperHeap::OutputCellListingUserL( const CMemSpyThread& aThread ) { // Suspend the process iEngine.ProcessSuspendLC( aThread.Process().Id() ); // Free cells RArray<TMemSpyDriverFreeCell> freeCells; CleanupClosePushL( freeCells ); // Info section TMemSpyHeapInfo heapInfo; const TInt error = iEngine.Driver().GetHeapInfoUser( heapInfo, aThread.Id(), freeCells ); if ( error == KErrNone ) { UpdateSharedHeapInfoL( aThread.Process().Id(), aThread.Id(), heapInfo ); } if ( error == KErrNone && heapInfo.Type() != TMemSpyHeapInfo::ETypeUnknown ) { // Get thread name for context const TFullName pName( aThread.FullName() ); // Begin a new data stream _LIT( KMemSpyFolder, "Heap\\Cell List" ); _LIT( KMemSpyContext, "Cell List - %S" ); HBufC* context = HBufC::NewLC( KMaxFileName ); TPtr pContext( context->Des() ); pContext.Format( KMemSpyContext, &pName ); iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); CleanupStack::PopAndDestroy( context ); // Set prefix for overall listing iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixCellList, &pName ); // Start new section _LIT(KHeader, "CELL LISTING"); iEngine.Sink().OutputSectionHeadingL( KHeader, '=' ); // Prepare temp buffers TBuf<KMaxFullName + 100> printFormat; HBufC* tempBuffer = HBufC::NewLC( 2048 ); TPtr pTempBuffer( tempBuffer->Des() ); // Print initial info OutputHeapInfoL( heapInfo, pName, &freeCells ); // Code segments (needed for map file reading...) _LIT(KCellListCodeSegInfoFormat, "CodeSegs - "); iEngine.HelperCodeSegment().OutputCodeSegmentsL( aThread.Process().Id(), printFormat, KCellListCodeSegInfoFormat, '-', ETrue ); // Now walk the heap! TInt r = iEngine.Driver().WalkHeapInit( aThread.Id() ); if ( r == KErrNone ) { _LIT(KHeader2, "Cells"); iEngine.Sink().OutputSectionHeadingL( KHeader2, '-' ); TMemSpyDriverCellType cellType; TAny* cellAddress; TInt cellLength; TInt cellNestingLevel; TInt cellAllocationNumber; TInt cellHeaderSize; TAny* cellPayloadAddress; TBuf8<4> cellData; // r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress ); while( r == KErrNone ) { TUint fourByteCellData = 0; TPtrC pType(KNullDesC); // if (cellType & EMemSpyDriverAllocatedCellMask) { r = iEngine.Driver().WalkHeapReadCellData( cellAddress, cellData, 4 ); if ( r == KErrNone ) { fourByteCellData = DescriptorAsDWORD( cellData ); } pType.Set(KCellTypeGoodAllocatedCell); } else if (cellType & EMemSpyDriverFreeCellMask) { pType.Set(KCellTypeGoodFreeCell); } else if (cellType & EMemSpyDriverBadCellMask) { switch (cellType) { case EMemSpyDriverHeapBadAllocatedCellSize: pType.Set(KCellTypeBadAllocatedCellSize); break; case EMemSpyDriverHeapBadAllocatedCellAddress: pType.Set(KCellTypeBadAllocatedCellAddress); break; case EMemSpyDriverHeapBadFreeCellAddress: pType.Set(KCellTypeBadFreeCellAddress); break; case EMemSpyDriverHeapBadFreeCellSize: pType.Set(KCellTypeBadFreeCellSize); break; default: pType.Set(KCellTypeBad); break; } } else { pType.Set(KCellTypeUnknown); } if ( r == KErrNone ) { pTempBuffer.Format( KCellListLineFormat, &pType, cellAddress, cellLength, cellAllocationNumber, cellNestingLevel, fourByteCellData, cellPayloadAddress, cellHeaderSize ); iEngine.Sink().OutputLineL( pTempBuffer ); // r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress ); } } // iEngine.Driver().WalkHeapClose(); } CleanupStack::PopAndDestroy( tempBuffer ); CleanupStack::PopAndDestroy(); // clear prefix iEngine.Sink().DataStreamEndL(); } CleanupStack::PopAndDestroy( &freeCells ); CleanupStack::PopAndDestroy(); // resume process }
EXPORT_C void CMemSpyEngineHelperChunk::OutputChunkInfoForThreadL( const CMemSpyThread& aThread ) { OutputChunkInfoForThreadL( aThread.Id() ); }