diff -r 185201be11b0 -r 516af714ebb4 memspy/Engine/Source/Helpers/MemSpyEngineHelperHeap.cpp --- a/memspy/Engine/Source/Helpers/MemSpyEngineHelperHeap.cpp Thu Sep 02 22:05:40 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1207 +0,0 @@ -/* -* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* -*/ - -#include - -// System includes -#include - -// Driver includes -#include - -// User includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Constants -const TBool KMemSpyHeapDumpCreateOwnDataStream = ETrue; - -// Literal constants -_LIT( KCellTypeGoodAllocatedCell, "[Allocated Cell] "); -_LIT( KCellTypeGoodFreeCell, "[Free Cell] "); -_LIT( KCellTypeBadAllocatedCellSize, "[Bad Allocated Cell Size] "); -_LIT( KCellTypeBadAllocatedCellAddress, "[Bad Allocated Cell Address]"); -_LIT( KCellTypeBadFreeCellAddress, "[Bad Free Cell Address] "); -_LIT( KCellTypeBadFreeCellSize, "[Bad Free Cell Size] "); -_LIT( KCellTypeBad, "[Bad Cell] "); -_LIT( KCellTypeUnknown, "[Unknown!] "); -_LIT( KCellListLineFormat, "%S cell: 0x%08x, cellLen: %8d, allocNum: %8d, nestingLev: %8d, cellData: 0x%08x, cellDataAddr: 0x%08x, headerSize: %02d"); -_LIT( KMemSpyMarkerHeapData, "<%SMEMSPY_HEAP_DATA_%03d>" ); -_LIT( KMemSpyMarkerCSV, "<%SMEMSPY_HEAP_CSV>" ); -_LIT( KMemSpyPrefixHeapData, "HeapData - %S - "); -_LIT( KMemSpyPrefixCellList, "CellList - %S - "); -_LIT( KMemSpyPrefixCSV, "CSV - " ); - - -CMemSpyEngineHelperHeap::CMemSpyEngineHelperHeap( CMemSpyEngine& aEngine ) -: iEngine( aEngine ) - { - } - - -CMemSpyEngineHelperHeap::~CMemSpyEngineHelperHeap() - { - } - - -void CMemSpyEngineHelperHeap::ConstructL() - { - } - - -CMemSpyEngineHelperHeap* CMemSpyEngineHelperHeap::NewL( CMemSpyEngine& aEngine ) - { - CMemSpyEngineHelperHeap* self = new(ELeave) CMemSpyEngineHelperHeap( aEngine ); - CleanupStack::PushL( self ); - self->ConstructL(); - CleanupStack::Pop( self ); - return self; - } - - - - - - - - - - -EXPORT_C void CMemSpyEngineHelperHeap::OutputCellListingUserL( const CMemSpyThread& aThread ) - { - // Suspend the process - iEngine.ProcessSuspendLC( aThread.Process().Id() ); - - // Free cells - RArray 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 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 CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread ) - { - OutputHeapDataUserL( aThread, KMemSpyHeapDumpCreateOwnDataStream ); - } - - -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 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::OutputHeapDataUserL(const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, const RArray* aCells) - { - OutputHeapDataUserL(aPid, aTid, aThreadName, aInfo, ETrue, aCells); - } - -void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, TBool aCreateDataStream, const RArray* aCells ) - { - TBuf printFormat; - - // Begin a new data stream - if ( aCreateDataStream ) - { - _LIT( KMemSpyFolder, "Heap\\Data" ); - _LIT( KMemSpyContext, "Heap Data - %S" ); - HBufC* context = HBufC::NewLC( KMaxFileName ); - TPtr pContext( context->Des() ); - pContext.Format( KMemSpyContext, &aThreadName ); - iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); - CleanupStack::PopAndDestroy( context ); - } - - // Get the heap info first of all - iEngine.ProcessSuspendLC( aPid ); - - // Start marker - iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, (TUint) aTid ); - - // Set overall prefix - iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &aThreadName ); - - // Info section - OutputHeapInfoL( aInfo, aThreadName, aCells ); - - // Code segments (needed for map file reading...) - _LIT(KCellListCodeSegInfoFormat, "CodeSegs - "); - iEngine.HelperCodeSegment().OutputCodeSegmentsL( aPid, printFormat, KCellListCodeSegInfoFormat, '-', ETrue ); - - // Dump section - _LIT(KHeaderDump, "Heap Data"); - iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' ); - - HBufC8* data = HBufC8::NewLC( 4096 * 12 ); - TPtr8 pData(data->Des()); - TUint remaining = 0; - TUint readAddress = 0; - - // When we obtained the heap info, we also obtained a checksum of all the free cells - // within the specified heap. We validate that this hasn't changed at the time we - // request the heap data for paranoia purposes (There have been "Issues" with MemSpy - // not actually suspending a process between fetching heap info & heap data, causing - // a mismatch in free cell information). - const TUint32 checksum = aInfo.AsRHeap().Statistics().StatsFree().Checksum(); - TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum: 0x%08x", checksum ) ); - - TInt r = iEngine.Driver().GetHeapData( aTid, checksum, pData, readAddress, remaining ); - TUint prevEndAddress = readAddress + pData.Length(); - if (r == KErrNone) - { - while (r == KErrNone) - { - if (readAddress > prevEndAddress) - { - // We've hit a discontinuity, ie one or more unmapped pages - _LIT(KBreak, "........"); - iEngine.Sink().OutputLineL(KBreak); - } - _LIT(KHeapDumpDataFormat, "%S"); - iEngine.Sink().OutputBinaryDataL(KHeapDumpDataFormat, pData.Ptr(), (const TUint8*) readAddress, pData.Length()); - readAddress += pData.Length(); - if (remaining > 0) - { - prevEndAddress = readAddress; - r = iEngine.Driver().GetHeapDataNext(aTid, pData, readAddress, remaining); - } - else - break; - } - } - else - { - _LIT( KHeapFetchError, "Heap error: %d"); - iEngine.Sink().OutputLineFormattedL( KHeapFetchError, r ); - } - - CleanupStack::PopAndDestroy( data ); - - CleanupStack::PopAndDestroy(); // clear prefix - CleanupStack::PopAndDestroy(); // resume process - - // End marker - iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, (TUint) aTid ); - - if ( aCreateDataStream ) - { - iEngine.Sink().DataStreamEndL(); - } - } - - - - - - - - - - - - - - - - - - - -EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoL( const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const RArray* aCells ) - { - CMemSpyEngineOutputList* list = NewHeapSummaryExtendedLC(aInfo, aCells); - - // Format the thread name according to upper/lower case request parameters - _LIT( KOverallCaption1, "HEAP INFO FOR THREAD '%S'"); - list->InsertItemFormatUCL( 0, KOverallCaption1, &aThreadName ); - list->InsertUnderlineForItemAtL( 0 ); - - // Print it - list->PrintL(); - - // Tidy up - CleanupStack::PopAndDestroy( list ); - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CMemSpyEngineHelperHeap::OutputCSVEntryL( TInt aIndex, const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const TDesC& aProcessName ) - { - const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap(); - const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); - const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); - - // Example: - // - // - // ESock_IP - // c32exe.exe[101f7989]0001 - // Local-c812ba58 - // 1,0x12400000,0x00c00074,36744,4092,524288,0x00c011a4,0,13,6872,1368,1680,2584,219,40,28996,0 - // - - _LIT( KFmtTagOpenAndClose, "<%S_%04d>%S" ); - - _LIT( KFmtEntryId, "<%SENTRY_%04d>"); - _LIT( KFmtNameThread, "THREAD_NAME"); - _LIT( KFmtNameProcess, "PROCESS_NAME"); - _LIT( KFmtNameChunk, "CHUNK_NAME"); - _LIT( KFmtFields, "FIELDS"); - _LIT( KFmtFieldContent , "<%S_%04d>%06d,0x%08x,0x%08x,%d,%d,%d,0x%08x,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d"); - - // - iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KNullDesC, aIndex ); - - // ESock_IP - iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameThread, aIndex, &aThreadName, &KFmtNameThread, aIndex ); - - // c32exe.exe[101f7989]0001 - iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameProcess, aIndex, &aProcessName, &KFmtNameProcess, aIndex ); - - // Local-c812ba58 - const TPtrC pChunkName( rHeapMetaData.ChunkName() ); - iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameChunk, aIndex, &pChunkName, &KFmtNameChunk, aIndex ); - - // Fields - iEngine.Sink().OutputLineFormattedL( KFmtFieldContent, - &KFmtFields, - aIndex, - aInfo.Tid(), - rHeapMetaData.ChunkHandle(), - /*rHeapObjectData.Base(),*/ rHeapMetaData.iAllocatorAddress, - /*rHeapObjectData.Size(),*/ rHeapMetaData.iHeapSize, - /*rHeapObjectData.iMinLength,*/ rHeapMetaData.iMinHeapSize, - /*rHeapObjectData.iMaxLength,*/ rHeapMetaData.iMaxHeapSize, - /*rHeapObjectData.iFree.next,*/ NULL, - /*rHeapObjectData.iFree.len,*/ 0, - rHeapStats.StatsFree().TypeCount(), - rHeapStats.StatsFree().TypeSize(), - rHeapStats.StatsFree().SlackSpaceCellSize(), - rHeapStats.StatsFree().LargestCellSize(), - rHeapStats.StatsAllocated().LargestCellSize(), - /*rHeapObjectData.iCellCount,*/ rHeapStats.StatsAllocated().TypeCount(), - /*rHeapObjectData.iMinCell,*/ 0, - /*rHeapObjectData.iTotalAllocSize,*/ rHeapStats.StatsAllocated().TypeSize(), - rHeapMetaData.IsSharedHeap(), - &KFmtFields, - aIndex - ); - - // - iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KMemSpySinkTagClose, aIndex ); - } - - - -EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoForDeviceL( TBool aIncludeKernel ) - { - // NB: The goal here is to minimise the line length. We already look like we - // could exceed the available RDebug::Print length... - const TInt count = iEngine.Container().Count(); - TInt index = 0; - // - HBufC* buf = HBufC::NewLC( 1024 ); - TPtr pBuf(buf->Des()); - // - _LIT( KMemSpyFolder, "Heap\\Compact" ); - _LIT( KMemSpyContext, "Heap Compact" ); - _LIT( KMemSpyExtension, ".log" ); - iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder, KMemSpyExtension ); - - // Start marker - iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerCSV, &KNullDesC ); - - // Set overall prefix - iEngine.Sink().OutputPrefixSetLC( KMemSpyPrefixCSV ); - - // Output version info - _LIT( KVersionNumber, "1" ); - iEngine.Sink().OutputLineL( KVersionNumber ); - - // Output time stamp - _LIT( KTimeStamp, "%u" ); - iEngine.Sink().OutputLineFormattedL( KTimeStamp, User::FastCounter() ); - - // Heap info we'll populate by calling the driver - TMemSpyHeapInfo info; - TFullName processName; - - if ( aIncludeKernel ) - { - // Get kernel heap info - GetHeapInfoKernelL( info ); - - if ( info.Type() != TMemSpyHeapInfo::ETypeUnknown ) - { - TName threadName; - MemSpyEngineUtils::GetKernelHeapThreadAndProcessNames( threadName, processName ); - OutputCSVEntryL( index++, info, threadName, processName ); - } - } - - for(TInt ii=0; ii* aFreeCells) - { - GetHeapInfoUserL(aProcess, aThread, aInfo, aFreeCells, EFalse); - } - -EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL(const TProcessId& aProcess, const TThreadId& aThread, TMemSpyHeapInfo& aInfo, RArray* aCells, TBool aCollectAllocatedCellsAsWellAsFree) - { - iEngine.ProcessSuspendLC( aProcess ); - TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum1: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); - - TInt r = KErrNone; - // - if (aCells) - { - r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread, *aCells, aCollectAllocatedCellsAsWellAsFree); - } - else - { - r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread ); - } - if ( !r ) - { - UpdateSharedHeapInfoL( aProcess, aThread, aInfo ); - } - - // - TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum2: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) ); - CleanupStack::PopAndDestroy(); // ProcessSuspendLC - User::LeaveIfError( r ); - } - - -EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL( const CMemSpyProcess& aProcess, RArray& aInfos ) - { - aInfos.Reset(); - iEngine.ProcessSuspendLC( aProcess.Id() ); - // - TMemSpyHeapInfo info; - // - const TInt count = aProcess.Count(); - for( TInt i=0; i 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::GetHeapInfoKernelL( TMemSpyHeapInfo& aInfo, RArray* aFreeCells ) - { - TInt error = KErrNone; - // - if ( aFreeCells ) - { - error = iEngine.Driver().GetHeapInfoKernel( aInfo, *aFreeCells ); - } - else - { - error = iEngine.Driver().GetHeapInfoKernel( aInfo ); - } - // - User::LeaveIfError( error ); - } - - -EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoKernelL() - { - // Get thread name - TFullName threadName; - MemSpyEngineUtils::GetKernelHeapThreadName( threadName ); - - // Free cells - RArray freeCells; - CleanupClosePushL( freeCells ); - - // Get info - TMemSpyHeapInfo info; - GetHeapInfoKernelL( info, &freeCells ); - - // Ouput - OutputHeapInfoL( info, threadName, &freeCells ); - - CleanupStack::PopAndDestroy( &freeCells ); - } - - -EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataKernelL() - { - OutputHeapDataKernelL( KMemSpyHeapDumpCreateOwnDataStream ); - } - - -void CMemSpyEngineHelperHeap::OutputHeapDataKernelL( TBool aCreateDataStream ) - { - // Get thread name - TFullName threadName; - MemSpyEngineUtils::GetKernelHeapThreadName( threadName, EFalse ); - - // Begin a new data stream - if ( aCreateDataStream ) - { - _LIT( KMemSpyFolder, "Heap\\Data" ); - _LIT( KMemSpyContext, "Heap Data - %S" ); - HBufC* context = HBufC::NewLC( KMaxFileName ); - TPtr pContext( context->Des() ); - pContext.Format( KMemSpyContext, &threadName ); - iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder ); - CleanupStack::PopAndDestroy( context ); - } - - RArray freeCells; - CleanupClosePushL( freeCells ); - - // Get kernel data and heap info before outputting anything... - TMemSpyHeapInfo info; - HBufC8* data = iEngine.Driver().GetHeapDataKernelLC( info, freeCells ); - - // Start marker - iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, info.Tid() ); - - // Set overall prefix - iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &threadName ); - - // Info section - OutputHeapInfoL( info, threadName, &freeCells ); - - // Dump section - _LIT(KHeaderDump, "Heap Data"); - iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' ); - - /*TOMSCI TODO this stuff needs fixing - _LIT(KHeapDumpDataFormat, "%S"); - const TUint8* heapBaseAddress = info.AsRHeap().ObjectData().Base(); - iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, data->Ptr(), heapBaseAddress, data->Length() ); - */ - - CleanupStack::PopAndDestroy(); // clear prefix - CleanupStack::PopAndDestroy( data ); - CleanupStack::PopAndDestroy( &freeCells ); - - // End marker - iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, info.Tid() ); - - if ( aCreateDataStream ) - { - iEngine.Sink().DataStreamEndL(); - } - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryShortLC( const TMemSpyHeapInfo& aInfo ) - { - CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() ); - - // Heap type - _LIT( KItem0, "Heap type" ); - if ( aInfo.Type() == TMemSpyHeapInfo::ETypeUnknown ) - { - _LIT( KItem0_Type_Unknown, "Unknown" ); - list->AddItemL( KItem0, KItem0_Type_Unknown ); - } - else - { - const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); - const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData(); - const TMemSpyHeapStatisticsRHeap& statistics = rHeap.Statistics(); - - _LIT( KItem0_Type_RHeap, "RHeap" ); - _LIT( KItem0_Type_RHybridHeap, "RHybridHeap" ); - if (aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap) - { - list->AddItemL( KItem0, KItem0_Type_RHeap ); - } - else - { - list->AddItemL( KItem0, KItem0_Type_RHybridHeap ); - } - - // Heap size is the size of the heap minus the size of the embedded (in-place) RHeap. - _LIT( KItem1, "Heap size" ); - list->AddItemL(KItem1, metaData.iHeapSize); - - _LIT( KItem8b, "Allocator address" ); - list->AddItemHexL( KItem8b, (TUint)metaData.iAllocatorAddress ); - - _LIT( KItem1b, "Shared" ); - list->AddItemYesNoL( KItem1b, metaData.IsSharedHeap() ); - - // This is the size (rounded to the page) of memory associated with - // the underlying heap chunk - _LIT( KItem2, "Chunk size" ); - list->AddItemL( KItem2, metaData.ChunkSize() ); - - _LIT( KItem3, "Alloc. count" ); - list->AddItemL( KItem3, statistics.StatsAllocated().TypeCount() ); - - _LIT( KItem4, "Free. count" ); - list->AddItemL( KItem4, statistics.StatsFree().TypeCount() ); - - _LIT( KItem5, "Biggest alloc." ); - list->AddItemL( KItem5, statistics.StatsAllocated().LargestCellSize() ); - - _LIT( KItem6, "Biggest free" ); - list->AddItemL( KItem6, statistics.StatsFree().LargestCellSize() ); - - _LIT( KItem6a, "Total alloc." ); - list->AddItemL( KItem6a, statistics.StatsAllocated().TypeSize() ); - - _LIT( KItem6b, "Total free" ); - list->AddItemL( KItem6b, statistics.StatsFree().TypeSize() ); - - // Slack is the free space at the end of the heap - _LIT( KItem7, "Slack free space" ); - list->AddItemL( KItem7, statistics.StatsFree().SlackSpaceCellSize() ); - - // Fragmentation is a measurement of free space scattered throughout the heap, but ignoring - // any slack space at the end (which can often be recovered, to the granularity of one page of ram) - _LIT( KItem8a, "Fragmentation" ); - list->AddItemPercentageL( KItem8a, metaData.iHeapSize, ( statistics.StatsFree().TypeSize() - statistics.StatsFree().SlackSpaceCellSize() ) ); - - - _LIT( KItem9c, "Overhead (total)" ); - const TInt totalOverhead = metaData.iHeapSize - statistics.StatsAllocated().TypeSize(); - list->AddItemL( KItem9c, totalOverhead ); - - _LIT( KItem9d, "Overhead" ); - list->AddItemPercentageL( KItem9d, metaData.iHeapSize, totalOverhead ); - - _LIT( KItem10, "Min. length" ); - list->AddItemL( KItem10, metaData.iMinHeapSize ); - - _LIT( KItem11, "Max. length" ); - list->AddItemL( KItem11, metaData.iMaxHeapSize ); - - _LIT( KItem12, "Debug Allocator Library" ); - list->AddItemYesNoL( KItem12, metaData.IsDebugAllocator() ); - } - - return list; - } - - -EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryExtendedLC( const TMemSpyHeapInfo& aInfo, const RArray* aCells ) - { - CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() ); - // - AppendMetaDataL( aInfo, *list ); - AppendStatisticsL( aInfo, *list ); - // - if ( aCells ) - { - AppendCellsL( *aCells, *list ); - } - // - return list; - } - - -//cigasto: not formatted - raw heap info -EXPORT_C TMemSpyHeapData CMemSpyEngineHelperHeap::NewHeapRawInfo( const TMemSpyHeapInfo& aInfo ) - { - _LIT(KUnknown, "Unknown"); - TMemSpyHeapData list; - list.iType.Copy(KUnknown); - - // Heap type - if (aInfo.Type() != TMemSpyHeapInfo::ETypeUnknown) - { - const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); - const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData(); - const TMemSpyHeapStatisticsRHeap& statistics = rHeap.Statistics(); - - _LIT(KRHeap, "RHeap"); - _LIT(KRHybridHeap, "RHybridHeap"); - switch (aInfo.Type()) - { - case TMemSpyHeapInfo::ETypeRHeap: - list.iType.Copy(KRHeap); - break; - case TMemSpyHeapInfo::ETypeRHybridHeap: - list.iType.Copy(KRHybridHeap); - break; - default: - break; - } - - // Heap size is the total amount of memory committed to the heap, which includes the size of the embedded (in-place) RHeap/RHybridHeap. - list.iSize = metaData.iHeapSize; - list.iBaseAddress = (TUint)metaData.iAllocatorAddress; // TODO we can't do the base address any more, allocator address is the closest thing - list.iShared = metaData.IsSharedHeap(); - list.iChunkSize = metaData.ChunkSize(); - list.iAllocationsCount = statistics.StatsAllocated().TypeCount(); - list.iFreeCount = statistics.StatsFree().TypeCount(); - list.iBiggestAllocation = statistics.StatsAllocated().LargestCellSize(); - list.iBiggestFree = statistics.StatsFree().LargestCellSize(); - list.iTotalAllocations = statistics.StatsAllocated().TypeSize(); - list.iTotalFree = statistics.StatsFree().TypeSize(); - list.iSlackFreeSpace = statistics.StatsFree().SlackSpaceCellSize(); - list.iFragmentation = statistics.StatsFree().TypeSize() - statistics.StatsFree().SlackSpaceCellSize(); //to calculate percentage value use iSize as 100% value - list.iHeaderSizeA = 0; //metaData.HeaderSizeAllocated(); - list.iHeaderSizeF = 0; //metaData.HeaderSizeFree(); - TInt allocOverhead = rHeap.Overhead(); //metaData.HeaderSizeAllocated() * statistics.StatsAllocated().TypeCount(); - list.iAllocationOverhead = allocOverhead; - //TInt freeOverhead = metaData.HeaderSizeFree() * statistics.StatsFree().TypeCount(); - list.iFreeOverhead = 0; // TODO there is no way of calculating this - list.iTotalOverhead = allocOverhead; // freeOverhead + allocOverhead - list.iOverhead = allocOverhead; //freeOverhead + allocOverhead; //to calculate percentage value use iSize as 100% value - list.iMinLength = metaData.iMinHeapSize; - list.iMaxLength = metaData.iMaxHeapSize; - list.iDebugAllocatorLibrary = metaData.IsDebugAllocator(); - } - - return list; - } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -TUint CMemSpyEngineHelperHeap::DescriptorAsDWORD( const TDesC8& aItem) - { - __ASSERT_ALWAYS( aItem.Length() >= 4, User::Invariant() ); - const TUint ret = aItem[0] + - (aItem[1] << 8) + - (aItem[2] << 16) + - (aItem[3] << 24); - return ret; - } - - -void CMemSpyEngineHelperHeap::AppendMetaDataL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList ) - { - const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); - - // Make caption - _LIT( KOverallCaption1, "Meta Data" ); - aList.AddItemL( KOverallCaption1 ); - aList.AddUnderlineForPreviousItemL( '=', 0 ); - - // Type - _LIT( KMetaData_Type, "Type:" ); - if ( aInfo.Type() == TMemSpyHeapInfo::ETypeUnknown ) - { - _LIT( KMetaData_Type_Unknown, "Unknown" ); - aList.AddItemL( KMetaData_Type, KMetaData_Type_Unknown ); - } - else - { - const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData(); - - // Type - _LIT( KMetaData_Type_RHeap, "Symbian OS RHeap" ); - _LIT( KMetaData_Type_RHybridHeap, "Symbian OS RHybridHeap" ); - if (aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap) - { - aList.AddItemL( KMetaData_Type, KMetaData_Type_RHeap ); - } - else - { - aList.AddItemL( KMetaData_Type, KMetaData_Type_RHybridHeap ); - } - - // VTable - //_LIT( KMetaData_VTable, "VTable:" ); - //aList.AddItemHexL( KMetaData_VTable, metaData.VTable() ); - - // Object size - //_LIT( KMetaData_ObjectSize, "Object Size:" ); - //aList.AddItemL( KMetaData_ObjectSize, metaData.ClassSize() ); - - // Chunk name - _LIT( KMetaData_ChunkName, "Chunk Name:" ); - TPtrC pChunkName( metaData.ChunkName() ); - aList.AddItemL( KMetaData_ChunkName, pChunkName ); - - // Chunk size - _LIT( KMetaData_ChunkSize, "Chunk Size:" ); - aList.AddItemL( KMetaData_ChunkSize, metaData.ChunkSize() ); - - // Chunk base address - _LIT( KMetaData_ChunkBaseAddress, "Chunk Base Address:" ); - aList.AddItemL( KMetaData_ChunkBaseAddress, metaData.ChunkBaseAddress() ); - - // Debug allocator - _LIT( KMetaData_DebugAllocator, "Debug Allocator:" ); - aList.AddItemYesNoL( KMetaData_DebugAllocator, metaData.IsDebugAllocator() ); - - // Shared Heap - _LIT( KMetaData_Shared, "Shared:" ); - aList.AddItemYesNoL( KMetaData_Shared, metaData.IsSharedHeap() ); - - // Add ROM info - iEngine.HelperROM().AddInfoL( aList ); - } - - aList.AddBlankItemL( 1 ); - } - -void CMemSpyEngineHelperHeap::AppendStatisticsL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList ) - { - if (aInfo.Type() != TMemSpyHeapInfo::ETypeUnknown) - { - const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap(); - const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeap.Statistics(); - - // Shared captions - _LIT( KStatsData_CellCount, "Number of cells:" ); - _LIT( KStatsData_CellSize, "Size of cells:" ); - _LIT( KStatsData_LargestCellAddress, "Largest cell:" ); - _LIT( KStatsData_LargestCellSize, "Largest cell size:" ); - - // Free space - _LIT( KOverallCaption1, "Free Cell Statistics" ); - aList.AddItemL( KOverallCaption1 ); - aList.AddUnderlineForPreviousItemL( '=', 0 ); - - aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsFree().TypeCount() ); - aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsFree().TypeSize() ); - aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsFree().LargestCellAddress() ); - aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsFree().LargestCellSize() ); - if (aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap) - { - _LIT( KStatsData_Free_SlackCellAddress, "Slack:" ); - aList.AddItemL( KStatsData_Free_SlackCellAddress, rHeapStats.StatsFree().SlackSpaceCellAddress() ); - _LIT( KStatsData_Free_SlackCellSize, "Slack size:" ); - aList.AddItemL( KStatsData_Free_SlackCellSize, rHeapStats.StatsFree().SlackSpaceCellSize() ); - } - _LIT( KStatsData_Free_Checksum, "Checksum:" ); - aList.AddItemHexL( KStatsData_Free_Checksum, rHeapStats.StatsFree().Checksum() ); - - aList.AddBlankItemL( 1 ); - - // Allocated space - _LIT( KOverallCaption2, "Allocated Cell Statistics" ); - aList.AddItemL( KOverallCaption2 ); - aList.AddUnderlineForPreviousItemL( '=', 0 ); - - aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsAllocated().TypeCount() ); - aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsAllocated().TypeSize() ); - aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsAllocated().LargestCellAddress() ); - aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsAllocated().LargestCellSize() ); - - aList.AddBlankItemL( 1 ); - } - } - - -void CMemSpyEngineHelperHeap::AppendCellsL(const RArray& aCells, CMemSpyEngineOutputList& aList) - { - // For reasons that may or may not turn out to be sensible, we separate free and allocated cells in the output data - - _LIT( KOverallCaption1, "Free Cell List" ); - aList.AddItemL( KOverallCaption1 ); - aList.AddUnderlineForPreviousItemL( '=', 0 ); - - TBuf<128> caption; - _LIT( KCaptionFormat, "FC %04d" ); - _LIT( KValueFormat, "0x%08x %8d %d" ); - - TBool foundAllocatedCells = EFalse; - const TInt count = aCells.Count(); - for( TInt i=0; i