memspy/Engine/Source/Helpers/MemSpyEngineHelperHeap.cpp
changeset 0 a03f92240627
child 20 ca8a1b6995f6
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyenginehelperheap.h>
       
    19 
       
    20 // System includes
       
    21 #include <s32mem.h>
       
    22 
       
    23 // Driver includes
       
    24 #include <memspy/driver/memspydriverclient.h>
       
    25 
       
    26 // User includes
       
    27 #include <memspy/engine/memspyengine.h>
       
    28 #include <memspy/engine/memspyengineutils.h>
       
    29 #include <memspy/engine/memspyengineoutputsink.h>
       
    30 #include <memspy/engine/memspyengineoutputlist.h>
       
    31 #include <memspy/engine/memspyengineobjectthread.h>
       
    32 #include <memspy/engine/memspyengineobjectprocess.h>
       
    33 #include <memspy/engine/memspyenginehelperrom.h>
       
    34 #include <memspy/engine/memspyengineobjectcontainer.h>
       
    35 #include <memspy/engine/memspyenginehelpercodesegment.h>
       
    36 #include <memspy/driver/memspydriverenumerationsshared.h>
       
    37 
       
    38 // Constants
       
    39 const TBool KMemSpyHeapDumpCreateOwnDataStream = ETrue;
       
    40 
       
    41 // Literal constants
       
    42 _LIT( KCellTypeGoodAllocatedCell,        "[Allocated Cell]            ");
       
    43 _LIT( KCellTypeGoodFreeCell,             "[Free Cell]                 ");
       
    44 _LIT( KCellTypeBadAllocatedCellSize,     "[Bad Allocated Cell Size]   ");
       
    45 _LIT( KCellTypeBadAllocatedCellAddress,  "[Bad Allocated Cell Address]");
       
    46 _LIT( KCellTypeBadFreeCellAddress,       "[Bad Free Cell Address]     ");
       
    47 _LIT( KCellTypeBadFreeCellSize,          "[Bad Free Cell Size]        ");
       
    48 _LIT( KCellTypeUnknown,                  "[Unknown!]                  ");
       
    49 _LIT( KCellListLineFormat, "%S cell: 0x%08x, cellLen: %8d, allocNum: %8d, nestingLev: %8d, cellData: 0x%08x, cellDataAddr: 0x%08x, headerSize: %02d");
       
    50 _LIT( KMemSpyMarkerHeapData, "<%SMEMSPY_HEAP_DATA_%03d>" );
       
    51 _LIT( KMemSpyMarkerCSV, "<%SMEMSPY_HEAP_CSV>" );
       
    52 _LIT( KMemSpyPrefixHeapData, "HeapData - %S - ");
       
    53 _LIT( KMemSpyPrefixCellList, "CellList - %S - ");
       
    54 _LIT( KMemSpyPrefixCSV, "CSV - " );
       
    55 
       
    56 
       
    57 CMemSpyEngineHelperHeap::CMemSpyEngineHelperHeap( CMemSpyEngine& aEngine )
       
    58 :   iEngine( aEngine )
       
    59     {
       
    60     }
       
    61 
       
    62     
       
    63 CMemSpyEngineHelperHeap::~CMemSpyEngineHelperHeap()
       
    64     {
       
    65     }
       
    66 
       
    67 
       
    68 void CMemSpyEngineHelperHeap::ConstructL()
       
    69     {
       
    70     }
       
    71 
       
    72 
       
    73 CMemSpyEngineHelperHeap* CMemSpyEngineHelperHeap::NewL( CMemSpyEngine& aEngine )
       
    74     {
       
    75     CMemSpyEngineHelperHeap* self = new(ELeave) CMemSpyEngineHelperHeap( aEngine );
       
    76     CleanupStack::PushL( self );
       
    77     self->ConstructL();
       
    78     CleanupStack::Pop( self );
       
    79     return self;
       
    80     }
       
    81 
       
    82 
       
    83 
       
    84 
       
    85 
       
    86 
       
    87 
       
    88 
       
    89 
       
    90 
       
    91 EXPORT_C void CMemSpyEngineHelperHeap::OutputCellListingUserL( const CMemSpyThread& aThread )
       
    92     {
       
    93     // Suspend the process
       
    94     iEngine.ProcessSuspendLC( aThread.Process().Id() );
       
    95 
       
    96     // Free cells
       
    97     RArray<TMemSpyDriverFreeCell> freeCells;
       
    98     CleanupClosePushL( freeCells );
       
    99 
       
   100     // Info section
       
   101     TMemSpyHeapInfo heapInfo;
       
   102     const TInt error = iEngine.Driver().GetHeapInfoUser( heapInfo, aThread.Id(), freeCells );
       
   103     if ( error == KErrNone )
       
   104         {
       
   105         UpdateSharedHeapInfoL( aThread.Process().Id(), aThread.Id(), heapInfo );
       
   106         }
       
   107     if  ( error == KErrNone && heapInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   108         {
       
   109         // Get thread name for context
       
   110         const TFullName pName( aThread.FullName() );
       
   111 
       
   112         // Begin a new data stream
       
   113         _LIT( KMemSpyFolder, "Heap\\Cell List" );
       
   114         _LIT( KMemSpyContext, "Cell List - %S" );
       
   115         HBufC* context = HBufC::NewLC( KMaxFileName );
       
   116         TPtr pContext( context->Des() );
       
   117         pContext.Format( KMemSpyContext, &pName );
       
   118         iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder );
       
   119         CleanupStack::PopAndDestroy( context );
       
   120 
       
   121         // Set prefix for overall listing
       
   122         iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixCellList, &pName );
       
   123 
       
   124         // Start new section
       
   125         _LIT(KHeader, "CELL LISTING");
       
   126         iEngine.Sink().OutputSectionHeadingL( KHeader, '=' );
       
   127 
       
   128         // Prepare temp buffers
       
   129         TBuf<KMaxFullName + 100> printFormat;
       
   130         HBufC* tempBuffer = HBufC::NewLC( 2048 );
       
   131         TPtr pTempBuffer( tempBuffer->Des() );
       
   132 
       
   133         // Print initial info
       
   134         OutputHeapInfoL( heapInfo, pName, &freeCells );
       
   135 
       
   136         // Code segments (needed for map file reading...)
       
   137         _LIT(KCellListCodeSegInfoFormat, "CodeSegs - ");
       
   138         iEngine.HelperCodeSegment().OutputCodeSegmentsL( aThread.Process().Id(), printFormat, KCellListCodeSegInfoFormat, '-', ETrue );
       
   139     
       
   140         // Now walk the heap!
       
   141         TInt r = iEngine.Driver().WalkHeapInit( aThread.Id() );
       
   142         if  ( r == KErrNone )
       
   143             {
       
   144              _LIT(KHeader2, "Cells");
       
   145             iEngine.Sink().OutputSectionHeadingL( KHeader2, '-' );
       
   146 
       
   147             TMemSpyDriverCellType cellType;
       
   148             TAny* cellAddress;
       
   149             TInt cellLength;
       
   150             TInt cellNestingLevel;
       
   151             TInt cellAllocationNumber;
       
   152             TInt cellHeaderSize;
       
   153             TAny* cellPayloadAddress;
       
   154             TBuf8<4> cellData;
       
   155             //
       
   156             r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   157             while( r == KErrNone )
       
   158                 {
       
   159                 TUint fourByteCellData = 0;
       
   160                 TPtrC pType(KNullDesC);
       
   161                 //
       
   162                 switch(cellType)
       
   163                     {
       
   164                 case EMemSpyDriverGoodAllocatedCell:
       
   165                     {
       
   166                     r = iEngine.Driver().WalkHeapReadCellData( cellAddress, cellData, 4 );
       
   167                     if  ( r == KErrNone )
       
   168                         {
       
   169                         fourByteCellData = DescriptorAsDWORD( cellData );
       
   170                         }
       
   171                     pType.Set(KCellTypeGoodAllocatedCell);
       
   172                     break;
       
   173                     }
       
   174                 case EMemSpyDriverGoodFreeCell:
       
   175                     pType.Set(KCellTypeGoodFreeCell);
       
   176                     break;
       
   177                 case EMemSpyDriverBadAllocatedCellSize:
       
   178                     pType.Set(KCellTypeBadAllocatedCellSize);
       
   179                     break;
       
   180                 case EMemSpyDriverBadAllocatedCellAddress:
       
   181                     pType.Set(KCellTypeBadAllocatedCellAddress);
       
   182                     break;
       
   183                 case EMemSpyDriverBadFreeCellAddress:
       
   184                     pType.Set(KCellTypeBadFreeCellAddress);
       
   185                     break;
       
   186                 case EMemSpyDriverBadFreeCellSize:
       
   187                     pType.Set(KCellTypeBadFreeCellSize);
       
   188                     break;
       
   189                 default:
       
   190                     pType.Set(KCellTypeUnknown);
       
   191                     break;
       
   192                     }
       
   193 
       
   194                 if  ( r == KErrNone )
       
   195                     {
       
   196                     pTempBuffer.Format( KCellListLineFormat, &pType, cellAddress, cellLength, cellAllocationNumber, cellNestingLevel, fourByteCellData, cellPayloadAddress, cellHeaderSize );
       
   197                     iEngine.Sink().OutputLineL( pTempBuffer );
       
   198                     //
       
   199                     r = iEngine.Driver().WalkHeapNextCell( aThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   200                     }
       
   201                 }
       
   202             //
       
   203             iEngine.Driver().WalkHeapClose();
       
   204             }
       
   205         CleanupStack::PopAndDestroy( tempBuffer );
       
   206         CleanupStack::PopAndDestroy(); // clear prefix
       
   207 
       
   208         iEngine.Sink().DataStreamEndL();
       
   209         }
       
   210 
       
   211     CleanupStack::PopAndDestroy( &freeCells );
       
   212     CleanupStack::PopAndDestroy(); // resume process
       
   213     }
       
   214 
       
   215 
       
   216 
       
   217 
       
   218 
       
   219 
       
   220 
       
   221 
       
   222 
       
   223 
       
   224 
       
   225 
       
   226 
       
   227 
       
   228 
       
   229 
       
   230 
       
   231 
       
   232 
       
   233 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread )
       
   234     {
       
   235     OutputHeapDataUserL( aThread, KMemSpyHeapDumpCreateOwnDataStream );
       
   236     }
       
   237 
       
   238 
       
   239 void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const CMemSpyThread& aThread, TBool aCreateDataStream )
       
   240     {
       
   241     // Make sure the process is suspended for the entire time we are manipulating it's heap
       
   242     iEngine.ProcessSuspendLC( aThread.Process().Id() );
       
   243 
       
   244     // Get the heap info, including free cell information
       
   245     RArray<TMemSpyDriverFreeCell> freeCells;
       
   246     CleanupClosePushL( freeCells );
       
   247     TMemSpyHeapInfo heapInfo;
       
   248     TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum1: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) );
       
   249     GetHeapInfoUserL( aThread.Process().Id(), aThread.Id(), heapInfo, &freeCells );
       
   250     TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum2: 0x%08x", heapInfo.AsRHeap().Statistics().StatsFree().Checksum() ) );
       
   251 
       
   252     // Get the heap data
       
   253     const TFullName pName( aThread.FullName() );
       
   254     OutputHeapDataUserL( aThread.Process().Id(), aThread.Id(), pName, heapInfo, aCreateDataStream, &freeCells );
       
   255     CleanupStack::PopAndDestroy( &freeCells );
       
   256 
       
   257     // Resume process
       
   258     CleanupStack::PopAndDestroy();
       
   259     }
       
   260 
       
   261 
       
   262 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, const RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   263     {
       
   264     OutputHeapDataUserL( aPid, aTid, aThreadName, aInfo, ETrue, aFreeCells );
       
   265     }
       
   266 
       
   267 
       
   268 void CMemSpyEngineHelperHeap::OutputHeapDataUserL( const TProcessId& aPid, const TThreadId& aTid, const TDesC& aThreadName, const TMemSpyHeapInfo& aInfo, TBool aCreateDataStream, const RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   269     {
       
   270     TBuf<KMaxFullName + 100> printFormat;
       
   271 
       
   272     // Begin a new data stream
       
   273     if  ( aCreateDataStream )
       
   274         {
       
   275         _LIT( KMemSpyFolder, "Heap\\Data" );
       
   276         _LIT( KMemSpyContext, "Heap Data - %S" );
       
   277         HBufC* context = HBufC::NewLC( KMaxFileName );
       
   278         TPtr pContext( context->Des() );
       
   279         pContext.Format( KMemSpyContext, &aThreadName );
       
   280         iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder );
       
   281         CleanupStack::PopAndDestroy( context );
       
   282         }
       
   283 
       
   284     // Get the heap info first of all
       
   285     iEngine.ProcessSuspendLC( aPid );
       
   286 
       
   287     // Start marker
       
   288     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, (TUint) aTid );
       
   289 
       
   290     // Set overall prefix
       
   291     iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &aThreadName );
       
   292 
       
   293     // Info section
       
   294     OutputHeapInfoL( aInfo, aThreadName, aFreeCells );
       
   295 
       
   296     // Code segments (needed for map file reading...)
       
   297     _LIT(KCellListCodeSegInfoFormat, "CodeSegs - ");
       
   298     iEngine.HelperCodeSegment().OutputCodeSegmentsL( aPid, printFormat, KCellListCodeSegInfoFormat, '-', ETrue );
       
   299 
       
   300     // Dump section
       
   301     _LIT(KHeaderDump, "Heap Data");
       
   302     iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' );
       
   303 
       
   304     HBufC8* data = HBufC8::NewLC( 4096 * 12 );
       
   305     TPtr8 pData(data->Des());
       
   306     TUint remaining = 0;
       
   307     TUint readAddress = 0;
       
   308 
       
   309     // When we obtained the heap info, we also obtained a checksum of all the free cells
       
   310     // within the specified heap. We validate that this hasn't changed at the time we
       
   311     // request the heap data for paranoia purposes (There have been "Issues" with MemSpy
       
   312     // not actually suspending a process between fetching heap info & heap data, causing
       
   313     // a mismatch in free cell information).
       
   314     const TUint32 checksum = aInfo.AsRHeap().Statistics().StatsFree().Checksum();
       
   315     TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::OutputHeapDataUserL() - checksum: 0x%08x", checksum ) );
       
   316 
       
   317     TInt r = iEngine.Driver().GetHeapData( aTid, checksum, pData, readAddress, remaining );
       
   318     if  ( r == KErrNone )
       
   319         {
       
   320         while ( r == KErrNone )
       
   321             {
       
   322             _LIT(KHeapDumpDataFormat, "%S");
       
   323             iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, pData.Ptr(), (const TUint8*) readAddress, pData.Length() );
       
   324             if  ( remaining > 0 )
       
   325                 r = iEngine.Driver().GetHeapDataNext( aTid, pData, readAddress, remaining );
       
   326             else
       
   327                 break;
       
   328             }
       
   329         }
       
   330     else
       
   331         {
       
   332         _LIT( KHeapFetchError, "Heap error: %d");
       
   333         iEngine.Sink().OutputLineFormattedL( KHeapFetchError, r );
       
   334         }
       
   335 
       
   336     CleanupStack::PopAndDestroy( data );
       
   337 
       
   338     CleanupStack::PopAndDestroy(); // clear prefix
       
   339     CleanupStack::PopAndDestroy(); // resume process
       
   340 
       
   341     // End marker
       
   342     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, (TUint) aTid );
       
   343 
       
   344     if  ( aCreateDataStream )
       
   345         {
       
   346         iEngine.Sink().DataStreamEndL();
       
   347         }
       
   348     }
       
   349 
       
   350 
       
   351 
       
   352 
       
   353 
       
   354 
       
   355 
       
   356 
       
   357 
       
   358 
       
   359 
       
   360 
       
   361 
       
   362 
       
   363 
       
   364 
       
   365 
       
   366 
       
   367 
       
   368 
       
   369 
       
   370 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoL( const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   371     {
       
   372     CMemSpyEngineOutputList* list = NewHeapSummaryExtendedLC( aInfo, aFreeCells );
       
   373 
       
   374     // Format the thread name according to upper/lower case request parameters
       
   375     _LIT( KOverallCaption1, "HEAP INFO FOR THREAD '%S'");
       
   376     list->InsertItemFormatUCL( 0, KOverallCaption1, &aThreadName );
       
   377     list->InsertUnderlineForItemAtL( 0 );
       
   378 
       
   379     // Print it
       
   380     list->PrintL();
       
   381 
       
   382     // Tidy up
       
   383     CleanupStack::PopAndDestroy( list );
       
   384     }
       
   385 
       
   386 
       
   387 
       
   388 
       
   389 
       
   390 
       
   391 
       
   392 
       
   393 
       
   394 
       
   395 
       
   396 
       
   397 
       
   398 
       
   399 
       
   400 
       
   401 
       
   402 
       
   403 
       
   404 
       
   405 
       
   406 
       
   407 
       
   408 
       
   409 
       
   410 
       
   411 
       
   412 
       
   413 
       
   414 
       
   415 void CMemSpyEngineHelperHeap::OutputCSVEntryL( TInt aIndex, const TMemSpyHeapInfo& aInfo, const TDesC& aThreadName, const TDesC& aProcessName )
       
   416     {
       
   417     const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap();
       
   418     const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData();
       
   419     const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData();
       
   420     const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics();
       
   421 
       
   422     // Example:
       
   423     //
       
   424     //  <ENTRY_001>
       
   425     //      <THREAD_NAME_001>ESock_IP</THREAD_NAME_001>
       
   426     //      <PROCESS_NAME_001>c32exe.exe[101f7989]0001</PROCESS_NAME_001>
       
   427     //      <CHUNK_NAME_001>Local-c812ba58</CHUNK_NAME_001>
       
   428     //      <FIELDS_001>1,0x12400000,0x00c00074,36744,4092,524288,0x00c011a4,0,13,6872,1368,1680,2584,219,40,28996,0</FIELDS_001>
       
   429     //  </ENTRY_001>
       
   430     
       
   431     _LIT( KFmtTagOpenAndClose, "<%S_%04d>%S</%S_%04d>" );
       
   432     
       
   433     _LIT( KFmtEntryId, "<%SENTRY_%04d>");
       
   434     _LIT( KFmtNameThread, "THREAD_NAME");
       
   435     _LIT( KFmtNameProcess, "PROCESS_NAME");
       
   436     _LIT( KFmtNameChunk, "CHUNK_NAME");
       
   437     _LIT( KFmtFields, "FIELDS");
       
   438     _LIT( KFmtFieldContent , "<%S_%04d>%06d,0x%08x,0x%08x,%d,%d,%d,0x%08x,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d</%S_%04d>");
       
   439 
       
   440     // <ENTRY_001>
       
   441     iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KNullDesC, aIndex );
       
   442     
       
   443     //      <THREAD_NAME_001>ESock_IP</THREAD_NAME_001>
       
   444     iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameThread, aIndex, &aThreadName, &KFmtNameThread, aIndex );
       
   445     
       
   446     //      <PROCESS_NAME_001>c32exe.exe[101f7989]0001</PROCESS_NAME_001>
       
   447     iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameProcess, aIndex, &aProcessName, &KFmtNameProcess, aIndex );
       
   448     
       
   449     //      <CHUNK_NAME_001>Local-c812ba58</CHUNK_NAME_001>
       
   450     const TPtrC pChunkName( rHeapMetaData.ChunkName() );
       
   451     iEngine.Sink().OutputLineFormattedL( KFmtTagOpenAndClose, &KFmtNameChunk, aIndex, &pChunkName, &KFmtNameChunk, aIndex );
       
   452     
       
   453     // Fields
       
   454     iEngine.Sink().OutputLineFormattedL( KFmtFieldContent,
       
   455                                          &KFmtFields,
       
   456                                          aIndex,
       
   457                                          aInfo.Tid(),
       
   458                                          rHeapMetaData.ChunkHandle(),
       
   459                                          rHeapObjectData.Base(),
       
   460                                          rHeapObjectData.Size(),
       
   461                                          rHeapObjectData.iMinLength,
       
   462                                          rHeapObjectData.iMaxLength,
       
   463                                          rHeapObjectData.iFree.next,
       
   464                                          rHeapObjectData.iFree.len,
       
   465                                          rHeapStats.StatsFree().TypeCount(),
       
   466                                          rHeapStats.StatsFree().TypeSize(),
       
   467                                          rHeapStats.StatsFree().SlackSpaceCellSize(),
       
   468                                          rHeapStats.StatsFree().LargestCellSize(),
       
   469                                          rHeapStats.StatsAllocated().LargestCellSize(),
       
   470                                          rHeapObjectData.iCellCount,
       
   471                                          rHeapObjectData.iMinCell,
       
   472                                          rHeapObjectData.iTotalAllocSize,
       
   473                                          rHeapMetaData.IsSharedHeap(),
       
   474                                          &KFmtFields,
       
   475                                          aIndex
       
   476                                          );
       
   477     
       
   478     // </ENTRY_001>
       
   479     iEngine.Sink().OutputLineFormattedL( KFmtEntryId, &KMemSpySinkTagClose, aIndex );
       
   480     }
       
   481 
       
   482 
       
   483 
       
   484 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoForDeviceL( TBool aIncludeKernel )
       
   485     {
       
   486     // NB: The goal here is to minimise the line length. We already look like we
       
   487     // could exceed the available RDebug::Print length...
       
   488     const TInt count = iEngine.Container().Count();
       
   489     TInt index = 0;
       
   490     //
       
   491     HBufC* buf = HBufC::NewLC( 1024 );
       
   492     TPtr pBuf(buf->Des());
       
   493     //
       
   494     _LIT( KMemSpyFolder, "Heap\\Compact" );
       
   495     _LIT( KMemSpyContext, "Heap Compact" );
       
   496     _LIT( KMemSpyExtension, ".log" );
       
   497     iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder, KMemSpyExtension );
       
   498 
       
   499     // Start marker
       
   500     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerCSV, &KNullDesC );
       
   501 
       
   502     // Set overall prefix
       
   503     iEngine.Sink().OutputPrefixSetLC( KMemSpyPrefixCSV );
       
   504     
       
   505     // Output version info
       
   506     _LIT( KVersionNumber, "<VERSION>1</VERSION>" );
       
   507     iEngine.Sink().OutputLineL( KVersionNumber );
       
   508     
       
   509     // Output time stamp
       
   510     _LIT( KTimeStamp, "<TIMESTAMP>%u</TIMESTAMP>" );
       
   511     iEngine.Sink().OutputLineFormattedL( KTimeStamp, User::FastCounter() );
       
   512  
       
   513     // Heap info we'll populate by calling the driver
       
   514     TMemSpyHeapInfo info;
       
   515     TFullName processName;
       
   516 
       
   517     if  ( aIncludeKernel )
       
   518         {
       
   519         // Get kernel heap info
       
   520         GetHeapInfoKernelL( info );
       
   521 
       
   522         if ( info.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   523             {
       
   524             TName threadName;
       
   525             MemSpyEngineUtils::GetKernelHeapThreadAndProcessNames( threadName, processName );
       
   526             OutputCSVEntryL( index++, info, threadName, processName );
       
   527             }
       
   528         }
       
   529 
       
   530 	for(TInt ii=0; ii<count; ii++)
       
   531         {
       
   532         const CMemSpyProcess& process = iEngine.Container().At( ii );
       
   533         process.FullName( processName );
       
   534         //
       
   535         if  ( iEngine.ProcessSuspendAndGetErrorLC( process.Id() ) == KErrNone )
       
   536             {
       
   537             const TInt threadCount = process.Count();
       
   538             //
       
   539             for(TInt j=0; j<threadCount; j++)
       
   540                 {
       
   541                 const CMemSpyThread& thread = process.At( j );
       
   542                 const TPtrC threadName( thread.Name() );
       
   543                 //
       
   544                 const TInt error = iEngine.Driver().GetHeapInfoUser( info, thread.Id() );
       
   545                 if ( error == KErrNone )
       
   546                     {
       
   547                     UpdateSharedHeapInfoL( process.Id(), thread.Id(), info );
       
   548                     }
       
   549                 if  ( error == KErrNone && info.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   550                     {
       
   551                     OutputCSVEntryL( index++, info, threadName, processName );
       
   552                     }
       
   553                 }
       
   554     
       
   555             CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
   556             }
       
   557         }
       
   558 
       
   559     CleanupStack::PopAndDestroy(); // clear prefix
       
   560     CleanupStack::PopAndDestroy( buf );
       
   561 
       
   562 	// End marker
       
   563 	iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerCSV, &KMemSpySinkTagClose );
       
   564     iEngine.Sink().DataStreamEndL();
       
   565     }
       
   566 
       
   567 
       
   568 
       
   569 
       
   570 
       
   571 
       
   572 
       
   573 
       
   574 
       
   575 
       
   576 
       
   577 
       
   578 
       
   579 
       
   580 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL( const TProcessId& aProcess, const TThreadId& aThread, TMemSpyHeapInfo& aInfo, RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   581     {
       
   582     iEngine.ProcessSuspendLC( aProcess );
       
   583     TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum1: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) );
       
   584     
       
   585     TInt r = KErrNone;
       
   586     //
       
   587     if  ( aFreeCells )
       
   588         {
       
   589         r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread, *aFreeCells );
       
   590         }
       
   591     else
       
   592         {
       
   593         r = iEngine.Driver().GetHeapInfoUser( aInfo, aThread );
       
   594         }
       
   595     if ( !r )
       
   596         {
       
   597         UpdateSharedHeapInfoL( aProcess, aThread, aInfo );
       
   598         }
       
   599     
       
   600     //
       
   601     TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::GetHeapInfoUserL() - checksum2: 0x%08x", aInfo.AsRHeap().Statistics().StatsFree().Checksum() ) );
       
   602     CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
   603     User::LeaveIfError( r );
       
   604     }
       
   605 
       
   606 
       
   607 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoUserL( const CMemSpyProcess& aProcess, RArray<TMemSpyHeapInfo >& aInfos )
       
   608     {
       
   609     aInfos.Reset();
       
   610     iEngine.ProcessSuspendLC( aProcess.Id() );
       
   611     //
       
   612     TMemSpyHeapInfo info;
       
   613     //
       
   614     const TInt count = aProcess.Count();
       
   615     for( TInt i=0; i<count; i++ )
       
   616         {
       
   617         const CMemSpyThread& thread = aProcess.At( i );
       
   618         //
       
   619         GetHeapInfoUserL( aProcess.Id(), thread.Id(), info );
       
   620         aInfos.AppendL( info );
       
   621         }
       
   622     //
       
   623     CleanupStack::PopAndDestroy(); // ProcessSuspendLC
       
   624     }
       
   625 
       
   626 
       
   627 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoUserL( const CMemSpyThread& aThread )
       
   628     {
       
   629     HBufC* threadName = aThread.FullName().AllocLC();
       
   630     //
       
   631     RArray<TMemSpyDriverFreeCell> freeCells;
       
   632     CleanupClosePushL( freeCells );
       
   633     //
       
   634     TMemSpyHeapInfo info;
       
   635     GetHeapInfoUserL( aThread.Process().Id(), aThread.Id(), info, &freeCells );
       
   636     OutputHeapInfoL( info, *threadName, &freeCells );
       
   637     //
       
   638     CleanupStack::PopAndDestroy( 2, threadName ); // freecells & thread name
       
   639     }
       
   640 
       
   641 
       
   642 
       
   643 
       
   644 
       
   645 
       
   646 
       
   647 
       
   648 
       
   649 
       
   650 
       
   651 
       
   652 
       
   653 
       
   654 
       
   655 
       
   656 
       
   657 EXPORT_C void CMemSpyEngineHelperHeap::GetHeapInfoKernelL( TMemSpyHeapInfo& aInfo, RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   658     {
       
   659     TInt error = KErrNone;
       
   660     //
       
   661     if  ( aFreeCells )
       
   662         {
       
   663         error = iEngine.Driver().GetHeapInfoKernel( aInfo, *aFreeCells );
       
   664         }
       
   665     else
       
   666         {
       
   667         error = iEngine.Driver().GetHeapInfoKernel( aInfo );
       
   668         }
       
   669     //
       
   670     User::LeaveIfError( error );
       
   671     }
       
   672 
       
   673 
       
   674 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapInfoKernelL()
       
   675     {
       
   676     // Get thread name
       
   677     TFullName threadName;
       
   678     MemSpyEngineUtils::GetKernelHeapThreadName( threadName );
       
   679 
       
   680     // Free cells
       
   681     RArray<TMemSpyDriverFreeCell> freeCells;
       
   682     CleanupClosePushL( freeCells );
       
   683 
       
   684     // Get info
       
   685     TMemSpyHeapInfo info;
       
   686     GetHeapInfoKernelL( info, &freeCells );
       
   687 
       
   688     // Ouput
       
   689     OutputHeapInfoL( info, threadName, &freeCells );
       
   690 
       
   691     CleanupStack::PopAndDestroy( &freeCells );
       
   692     }
       
   693 
       
   694 
       
   695 EXPORT_C void CMemSpyEngineHelperHeap::OutputHeapDataKernelL()
       
   696     {
       
   697     OutputHeapDataKernelL( KMemSpyHeapDumpCreateOwnDataStream );
       
   698     }
       
   699 
       
   700 
       
   701 void CMemSpyEngineHelperHeap::OutputHeapDataKernelL( TBool aCreateDataStream )
       
   702     {
       
   703     // Get thread name
       
   704     TFullName threadName;
       
   705     MemSpyEngineUtils::GetKernelHeapThreadName( threadName, EFalse );
       
   706 
       
   707     // Begin a new data stream
       
   708     if  ( aCreateDataStream )
       
   709         {
       
   710         _LIT( KMemSpyFolder, "Heap\\Data" );
       
   711         _LIT( KMemSpyContext, "Heap Data - %S" );
       
   712         HBufC* context = HBufC::NewLC( KMaxFileName );
       
   713         TPtr pContext( context->Des() );
       
   714         pContext.Format( KMemSpyContext, &threadName );
       
   715         iEngine.Sink().DataStreamBeginL( pContext, KMemSpyFolder );
       
   716         CleanupStack::PopAndDestroy( context );
       
   717         }
       
   718 
       
   719     RArray<TMemSpyDriverFreeCell> freeCells;
       
   720     CleanupClosePushL( freeCells );
       
   721 
       
   722     // Get kernel data and heap info before outputting anything...
       
   723     TMemSpyHeapInfo info;
       
   724     HBufC8* data = iEngine.Driver().GetHeapDataKernelLC( info, freeCells );
       
   725 
       
   726     // Start marker
       
   727     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KNullDesC, info.Tid() );
       
   728 
       
   729     // Set overall prefix
       
   730     iEngine.Sink().OutputPrefixSetFormattedLC( KMemSpyPrefixHeapData, &threadName );
       
   731 
       
   732     // Info section
       
   733     OutputHeapInfoL( info, threadName, &freeCells );
       
   734 
       
   735     // Dump section
       
   736     _LIT(KHeaderDump, "Heap Data");
       
   737     iEngine.Sink().OutputSectionHeadingL( KHeaderDump, '-' );
       
   738 
       
   739     _LIT(KHeapDumpDataFormat, "%S");
       
   740     const TUint8* heapBaseAddress = info.AsRHeap().ObjectData().Base();
       
   741     iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, data->Ptr(), heapBaseAddress, data->Length() );
       
   742 
       
   743     CleanupStack::PopAndDestroy(); // clear prefix
       
   744     CleanupStack::PopAndDestroy( data );
       
   745     CleanupStack::PopAndDestroy( &freeCells );
       
   746 
       
   747     // End marker
       
   748     iEngine.Sink().OutputLineFormattedL( KMemSpyMarkerHeapData, &KMemSpySinkTagClose, info.Tid() );
       
   749 
       
   750     if  ( aCreateDataStream )
       
   751         {
       
   752         iEngine.Sink().DataStreamEndL();
       
   753         }
       
   754     }
       
   755 
       
   756 
       
   757 
       
   758 
       
   759 
       
   760 
       
   761 
       
   762 
       
   763 
       
   764 
       
   765 
       
   766 
       
   767 
       
   768 
       
   769 
       
   770 
       
   771 
       
   772 
       
   773 
       
   774 
       
   775 
       
   776 
       
   777 
       
   778 
       
   779 
       
   780 
       
   781 
       
   782 
       
   783 
       
   784 
       
   785 
       
   786 
       
   787 EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryShortLC( const TMemSpyHeapInfo& aInfo )
       
   788     {
       
   789     CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() );
       
   790 
       
   791     // Heap type
       
   792     _LIT( KItem0, "Heap type" );
       
   793     if ( aInfo.Type() == TMemSpyHeapInfo::ETypeUnknown )
       
   794         {
       
   795         _LIT( KItem0_Type_Unknown, "Unknown" );
       
   796         list->AddItemL( KItem0, KItem0_Type_Unknown );
       
   797         }
       
   798     else if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
   799         {
       
   800         const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap();
       
   801         const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData();
       
   802         const TMemSpyHeapObjectDataRHeap& objectData = rHeap.ObjectData();
       
   803         const TMemSpyHeapStatisticsRHeap& statistics = rHeap.Statistics();
       
   804 
       
   805         _LIT( KItem0_Type_RHeap, "RHeap" );
       
   806         list->AddItemL( KItem0, KItem0_Type_RHeap );
       
   807 
       
   808         // Heap size is the size of the heap minus the size of the embedded (in-place) RHeap. 
       
   809         _LIT( KItem1, "Heap size" );
       
   810         list->AddItemL( KItem1, objectData.Size() );
       
   811 
       
   812         _LIT( KItem8b, "Heap base address" );
       
   813         list->AddItemHexL( KItem8b, (TUint) objectData.Base() );
       
   814         
       
   815         _LIT( KItem1b, "Shared" );
       
   816         list->AddItemYesNoL( KItem1b, metaData.IsSharedHeap() );
       
   817 
       
   818         // This is the size (rounded to the page) of memory associated with
       
   819         // the underlying heap chunk
       
   820         _LIT( KItem2, "Chunk size" );
       
   821         list->AddItemL( KItem2, metaData.ChunkSize() );
       
   822 
       
   823         _LIT( KItem3, "Alloc. count" );
       
   824         list->AddItemL( KItem3, statistics.StatsAllocated().TypeCount() );
       
   825 
       
   826         _LIT( KItem4, "Free. count" );
       
   827         list->AddItemL( KItem4, statistics.StatsFree().TypeCount() );
       
   828 
       
   829         _LIT( KItem5, "Biggest alloc." );
       
   830         list->AddItemL( KItem5, statistics.StatsAllocated().LargestCellSize() );
       
   831 
       
   832         _LIT( KItem6, "Biggest free" );
       
   833         list->AddItemL( KItem6, statistics.StatsFree().LargestCellSize() );
       
   834 
       
   835         _LIT( KItem6a, "Total alloc." );
       
   836         list->AddItemL( KItem6a, statistics.StatsAllocated().TypeSize() );
       
   837 
       
   838         _LIT( KItem6b, "Total free" );
       
   839         list->AddItemL( KItem6b, statistics.StatsFree().TypeSize() );
       
   840 
       
   841         // Slack is the free space at the end of the heap
       
   842         _LIT( KItem7, "Slack free space" );
       
   843         list->AddItemL( KItem7, statistics.StatsFree().SlackSpaceCellSize() );
       
   844 
       
   845         // Fragmentation is a measurement of free space scattered throughout the heap, but ignoring
       
   846         // any slack space at the end (which can often be recovered, to the granularity of one page of ram)
       
   847         _LIT( KItem8a, "Fragmentation" );
       
   848         list->AddItemPercentageL( KItem8a, objectData.Size(), ( statistics.StatsFree().TypeSize()  - statistics.StatsFree().SlackSpaceCellSize() ) );
       
   849 
       
   850         _LIT( KItem13, "Header size (A)" );
       
   851         list->AddItemL( KItem13, metaData.HeaderSizeAllocated() );
       
   852 
       
   853         _LIT( KItem14, "Header size (F)" );
       
   854         list->AddItemL( KItem14, metaData.HeaderSizeFree() );
       
   855 
       
   856         _LIT( KItem9a, "Overhead (alloc)" );
       
   857         const TInt allocOverhead = metaData.HeaderSizeAllocated() * statistics.StatsAllocated().TypeCount();
       
   858         list->AddItemL( KItem9a, allocOverhead );
       
   859 
       
   860         _LIT( KItem9b, "Overhead (free)" );
       
   861         const TInt freeOverhead = metaData.HeaderSizeFree() * statistics.StatsFree().TypeCount();
       
   862         list->AddItemL( KItem9b, freeOverhead );
       
   863 
       
   864         _LIT( KItem9c, "Overhead (total)" );
       
   865         const TInt totalOverhead = freeOverhead + allocOverhead;
       
   866         list->AddItemL( KItem9c, totalOverhead );
       
   867 
       
   868         _LIT( KItem9d, "Overhead" );
       
   869         list->AddItemPercentageL( KItem9d, objectData.Size(), totalOverhead  );
       
   870 
       
   871         _LIT( KItem10, "Min. length" );
       
   872         list->AddItemL( KItem10, objectData.iMinLength );
       
   873 
       
   874         _LIT( KItem11, "Max. length" );
       
   875         list->AddItemL( KItem11, objectData.iMaxLength );
       
   876 
       
   877         _LIT( KItem12, "Debug Allocator Library" );
       
   878         list->AddItemYesNoL( KItem12, metaData.IsDebugAllocator() );
       
   879         }
       
   880 
       
   881     return list;
       
   882     }
       
   883 
       
   884 
       
   885 EXPORT_C CMemSpyEngineOutputList* CMemSpyEngineHelperHeap::NewHeapSummaryExtendedLC( const TMemSpyHeapInfo& aInfo, const RArray<TMemSpyDriverFreeCell>* aFreeCells )
       
   886     {
       
   887     CMemSpyEngineOutputList* list = CMemSpyEngineOutputList::NewLC( iEngine.Sink() );
       
   888     //
       
   889     AppendMetaDataL( aInfo, *list );
       
   890     AppendObjectDataL( aInfo, *list );
       
   891     AppendStatisticsL( aInfo, *list );
       
   892     //
       
   893     if  ( aFreeCells )
       
   894         {
       
   895         AppendFreeCellsL( *aFreeCells, *list );
       
   896         }
       
   897     //
       
   898     return list;
       
   899     }
       
   900 
       
   901 
       
   902 
       
   903 
       
   904 
       
   905 
       
   906 
       
   907 
       
   908 
       
   909 
       
   910 
       
   911 
       
   912 
       
   913 
       
   914 
       
   915 
       
   916 
       
   917 
       
   918 
       
   919 
       
   920 
       
   921 
       
   922 
       
   923 
       
   924 
       
   925 
       
   926 
       
   927 
       
   928 
       
   929 
       
   930 
       
   931 
       
   932 
       
   933 TUint CMemSpyEngineHelperHeap::DescriptorAsDWORD( const TDesC8& aItem)
       
   934     {
       
   935     __ASSERT_ALWAYS( aItem.Length() >= 4, User::Invariant() );
       
   936     const TUint ret =  aItem[0] +
       
   937                       (aItem[1] << 8) + 
       
   938                       (aItem[2] << 16) + 
       
   939                       (aItem[3] << 24);
       
   940     return ret;
       
   941     }
       
   942 
       
   943 
       
   944 void CMemSpyEngineHelperHeap::AppendMetaDataL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList )
       
   945     {
       
   946     const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap();
       
   947 
       
   948     // Make caption
       
   949     _LIT( KOverallCaption1, "Meta Data" );
       
   950     aList.AddItemL( KOverallCaption1 );
       
   951     aList.AddUnderlineForPreviousItemL( '=', 0 );
       
   952 
       
   953     // Type
       
   954     _LIT( KMetaData_Type,  "Type:" );
       
   955     if ( aInfo.Type() != TMemSpyHeapInfo::ETypeRHeap )
       
   956         {
       
   957         _LIT( KMetaData_Type_Unknown,  "Unknown" );
       
   958         aList.AddItemL( KMetaData_Type, KMetaData_Type_Unknown );
       
   959         }
       
   960     else
       
   961         {
       
   962         const TMemSpyHeapMetaDataRHeap& metaData = rHeap.MetaData();
       
   963     
       
   964         // Type
       
   965         _LIT( KMetaData_Type_RHeap,  "Symbian OS RHeap" );
       
   966         aList.AddItemL( KMetaData_Type, KMetaData_Type_RHeap );
       
   967 
       
   968         // VTable
       
   969         _LIT( KMetaData_VTable,  "VTable:" );
       
   970         aList.AddItemHexL( KMetaData_VTable, metaData.VTable() );
       
   971 
       
   972         // Object size
       
   973         _LIT( KMetaData_ObjectSize,  "Object Size:" );
       
   974         aList.AddItemL( KMetaData_ObjectSize, metaData.ClassSize() );
       
   975 
       
   976         // Chunk name
       
   977         _LIT( KMetaData_ChunkName,  "Chunk Name:" );
       
   978         TPtrC pChunkName( metaData.ChunkName() );
       
   979         aList.AddItemL( KMetaData_ChunkName, pChunkName );
       
   980 
       
   981         // Chunk size
       
   982         _LIT( KMetaData_ChunkSize,  "Chunk Size:" );
       
   983         aList.AddItemL( KMetaData_ChunkSize, metaData.ChunkSize() );
       
   984 
       
   985         // Chunk base address
       
   986         _LIT( KMetaData_ChunkBaseAddress,  "Chunk Base Address:" );
       
   987         aList.AddItemL( KMetaData_ChunkBaseAddress, metaData.ChunkBaseAddress() );
       
   988 
       
   989         // Debug allocator
       
   990         _LIT( KMetaData_DebugAllocator,  "Debug Allocator:" );
       
   991         aList.AddItemYesNoL( KMetaData_DebugAllocator, metaData.IsDebugAllocator() );
       
   992 
       
   993         // Cell header overhead (free cells)
       
   994         _LIT( KMetaData_CellHeaderOverheadFree,  "Overhead (Free):" );
       
   995         aList.AddItemL( KMetaData_CellHeaderOverheadFree, metaData.HeaderSizeFree() );
       
   996 
       
   997         // Cell header overhead (allocated cells)
       
   998         _LIT( KMetaData_CellHeaderOverheadAlloc,  "Overhead (Alloc):" );
       
   999         aList.AddItemL( KMetaData_CellHeaderOverheadAlloc, metaData.HeaderSizeAllocated() );
       
  1000 
       
  1001         // Shared Heap
       
  1002         _LIT( KMetaData_Shared,  "Shared:" );
       
  1003         aList.AddItemYesNoL( KMetaData_Shared, metaData.IsSharedHeap() );
       
  1004 
       
  1005         // Add ROM info
       
  1006         iEngine.HelperROM().AddInfoL( aList );
       
  1007         }
       
  1008 
       
  1009     aList.AddBlankItemL( 1 );
       
  1010     }
       
  1011 
       
  1012 
       
  1013 void CMemSpyEngineHelperHeap::AppendObjectDataL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList )
       
  1014     {
       
  1015     if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
  1016         {
       
  1017         const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap();
       
  1018         const TMemSpyHeapObjectDataRHeap& objectData = rHeap.ObjectData();
       
  1019 
       
  1020         // Make caption
       
  1021         _LIT( KOverallCaption1, "RAllocator" );
       
  1022         aList.AddItemL( KOverallCaption1 );
       
  1023         aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1024 
       
  1025         // RAllocator
       
  1026         _LIT( KObjectData_RAllocator_iAccessCount,  "RAllocator::iAccessCount" );
       
  1027         aList.AddItemL( KObjectData_RAllocator_iAccessCount, objectData.iAccessCount );
       
  1028         _LIT( KObjectData_RAllocator_iHandleCount,  "RAllocator::iHandleCount" );
       
  1029         aList.AddItemL( KObjectData_RAllocator_iHandleCount, objectData.iHandleCount );
       
  1030         _LIT( KObjectData_RAllocator_iHandles,  "RAllocator::iHandles" );
       
  1031         aList.AddItemL( KObjectData_RAllocator_iHandles, objectData.iHandles );
       
  1032         _LIT( KObjectData_RAllocator_iFlags,  "RAllocator::iFlags" );
       
  1033         aList.AddItemHexL( KObjectData_RAllocator_iFlags, objectData.iFlags );
       
  1034         _LIT( KObjectData_RAllocator_iCellCount,  "RAllocator::iCellCount" );
       
  1035         aList.AddItemL( KObjectData_RAllocator_iCellCount, objectData.iCellCount );
       
  1036         _LIT( KObjectData_RAllocator_iTotalAllocSize,  "RAllocator::iTotalAllocSize" );
       
  1037         aList.AddItemL( KObjectData_RAllocator_iTotalAllocSize, objectData.iTotalAllocSize );
       
  1038 
       
  1039         aList.AddBlankItemL( 1 );
       
  1040 
       
  1041         // Make caption
       
  1042         _LIT( KOverallCaption2, "RHeap" );
       
  1043         aList.AddItemL( KOverallCaption2 );
       
  1044         aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1045 
       
  1046         // RHeap
       
  1047         _LIT( KObjectData_RHeap_iMinLength,  "RHeap::iMinLength" );
       
  1048         aList.AddItemL( KObjectData_RHeap_iMinLength, objectData.iMinLength );
       
  1049         _LIT( KObjectData_RHeap_iMaxLength,  "RHeap::iMaxLength" );
       
  1050         aList.AddItemL( KObjectData_RHeap_iMaxLength, objectData.iMaxLength );
       
  1051         _LIT( KObjectData_RHeap_iOffset,  "RHeap::iOffset" );
       
  1052         aList.AddItemL( KObjectData_RHeap_iOffset, objectData.iOffset );
       
  1053         _LIT( KObjectData_RHeap_iGrowBy,  "RHeap::iGrowBy" );
       
  1054         aList.AddItemL( KObjectData_RHeap_iGrowBy, objectData.iGrowBy );
       
  1055         _LIT( KObjectData_RHeap_iChunkHandle,  "RHeap::iChunkHandle" );
       
  1056         aList.AddItemHexL( KObjectData_RHeap_iChunkHandle, objectData.iChunkHandle );
       
  1057         _LIT( KObjectData_RHeap_iBase,  "RHeap::iBase" );
       
  1058         aList.AddItemL( KObjectData_RHeap_iBase, objectData.iBase );
       
  1059         _LIT( KObjectData_RHeap_iTop,  "RHeap::iTop" );
       
  1060         aList.AddItemL( KObjectData_RHeap_iTop, objectData.iTop );
       
  1061         _LIT( KObjectData_RHeap_iAlign,  "RHeap::iAlign" );
       
  1062         aList.AddItemL( KObjectData_RHeap_iAlign, objectData.iAlign );
       
  1063         _LIT( KObjectData_RHeap_iMinCell,  "RHeap::iMinCell" );
       
  1064         aList.AddItemL( KObjectData_RHeap_iMinCell, objectData.iMinCell );
       
  1065         _LIT( KObjectData_RHeap_iPageSize,  "RHeap::iPageSize" );
       
  1066         aList.AddItemL( KObjectData_RHeap_iPageSize, objectData.iPageSize );
       
  1067         _LIT( KObjectData_RHeap_iFree_next,  "RHeap::iFree.next" );
       
  1068         aList.AddItemL( KObjectData_RHeap_iFree_next, objectData.iFree.next );
       
  1069         _LIT( KObjectData_RHeap_iFree_len,  "RHeap::iFree.len" );
       
  1070         aList.AddItemL( KObjectData_RHeap_iFree_len, objectData.iFree.len );
       
  1071         _LIT( KObjectData_RHeap_iNestingLevel,  "RHeap::iNestingLevel" );
       
  1072         aList.AddItemL( KObjectData_RHeap_iNestingLevel, objectData.iNestingLevel );
       
  1073         _LIT( KObjectData_RHeap_iAllocCount,  "RHeap::iAllocCount" );
       
  1074         aList.AddItemL( KObjectData_RHeap_iAllocCount, objectData.iAllocCount );
       
  1075         _LIT( KObjectData_RHeap_iFailType,  "RHeap::iFailType" );
       
  1076         aList.AddItemL( KObjectData_RHeap_iFailType, (TInt) objectData.iFailType );
       
  1077         _LIT( KObjectData_RHeap_iFailRate,  "RHeap::iFailRate" );
       
  1078         aList.AddItemL( KObjectData_RHeap_iFailRate, objectData.iFailRate );
       
  1079         _LIT( KObjectData_RHeap_iFailed,  "RHeap::iFailed" );
       
  1080         aList.AddItemTrueFalseL( KObjectData_RHeap_iFailed, objectData.iFailed );
       
  1081         _LIT( KObjectData_RHeap_iFailAllocCount,  "RHeap::iFailAllocCount" );
       
  1082         aList.AddItemL( KObjectData_RHeap_iFailAllocCount, objectData.iFailAllocCount );
       
  1083         _LIT( KObjectData_RHeap_iRand,  "RHeap::iRand" );
       
  1084         aList.AddItemL( KObjectData_RHeap_iRand, objectData.iRand );
       
  1085         _LIT( KObjectData_RHeap_iTestData,  "RHeap::iTestData" );
       
  1086         aList.AddItemL( KObjectData_RHeap_iTestData, objectData.iTestData );
       
  1087 
       
  1088         aList.AddBlankItemL( 1 );
       
  1089         }
       
  1090     }
       
  1091 
       
  1092 
       
  1093 void CMemSpyEngineHelperHeap::AppendStatisticsL( const TMemSpyHeapInfo& aInfo, CMemSpyEngineOutputList& aList )
       
  1094     {
       
  1095     if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
       
  1096         {
       
  1097         const TMemSpyHeapInfoRHeap& rHeap = aInfo.AsRHeap();
       
  1098         const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeap.Statistics();
       
  1099 
       
  1100         // Shared captions
       
  1101         _LIT( KStatsData_CellCount,  "Number of cells:" );
       
  1102         _LIT( KStatsData_CellSize,  "Size of cells:" );
       
  1103         _LIT( KStatsData_LargestCellAddress,  "Largest cell:" );
       
  1104         _LIT( KStatsData_LargestCellSize,  "Largest cell size:" );
       
  1105 
       
  1106         // Free space
       
  1107         _LIT( KOverallCaption1, "Free Cell Statistics" );
       
  1108         aList.AddItemL( KOverallCaption1 );
       
  1109         aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1110 
       
  1111         aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsFree().TypeCount() );
       
  1112         aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsFree().TypeSize() );
       
  1113         aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsFree().LargestCellAddress() );
       
  1114         aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsFree().LargestCellSize() );
       
  1115         _LIT( KStatsData_Free_SlackCellAddress,  "Slack:" );
       
  1116         aList.AddItemL( KStatsData_Free_SlackCellAddress, rHeapStats.StatsFree().SlackSpaceCellAddress() );
       
  1117         _LIT( KStatsData_Free_SlackCellSize,  "Slack size:" );
       
  1118         aList.AddItemL( KStatsData_Free_SlackCellSize, rHeapStats.StatsFree().SlackSpaceCellSize() );
       
  1119         _LIT( KStatsData_Free_Checksum,  "Checksum:" );
       
  1120         aList.AddItemHexL( KStatsData_Free_Checksum, rHeapStats.StatsFree().Checksum() );
       
  1121 
       
  1122         aList.AddBlankItemL( 1 );
       
  1123 
       
  1124         // Allocated space
       
  1125         _LIT( KOverallCaption2, "Allocated Cell Statistics" );
       
  1126         aList.AddItemL( KOverallCaption2 );
       
  1127         aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1128 
       
  1129         aList.AddItemL( KStatsData_CellCount, rHeapStats.StatsAllocated().TypeCount() );
       
  1130         aList.AddItemL( KStatsData_CellSize, rHeapStats.StatsAllocated().TypeSize() );
       
  1131         aList.AddItemL( KStatsData_LargestCellAddress, rHeapStats.StatsAllocated().LargestCellAddress() );
       
  1132         aList.AddItemL( KStatsData_LargestCellSize, rHeapStats.StatsAllocated().LargestCellSize() );
       
  1133 
       
  1134         aList.AddBlankItemL( 1 );
       
  1135 
       
  1136         // Common
       
  1137         _LIT( KOverallCaption3, "Common Statistics" );
       
  1138         aList.AddItemL( KOverallCaption3 );
       
  1139         aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1140 
       
  1141         _LIT( KStatsData_Common_TotalCellCount,  "Total cell count:" );
       
  1142         aList.AddItemL( KStatsData_Common_TotalCellCount, rHeapStats.StatsCommon().TotalCellCount() );
       
  1143 
       
  1144         _LIT( KStatsData_Common_TotalSize,  "Total cell size:" );
       
  1145         aList.AddItemL( KStatsData_Common_TotalSize, rHeapStats.StatsAllocated().TypeSize() + rHeapStats.StatsFree().TypeSize() );
       
  1146 
       
  1147         aList.AddBlankItemL( 1 );
       
  1148         }
       
  1149     }
       
  1150 
       
  1151 
       
  1152 void CMemSpyEngineHelperHeap::AppendFreeCellsL( const RArray<TMemSpyDriverFreeCell>& aFreeCells, CMemSpyEngineOutputList& aList )
       
  1153     {
       
  1154     // Free space
       
  1155     _LIT( KOverallCaption1, "Free Cell List" );
       
  1156     aList.AddItemL( KOverallCaption1 );
       
  1157     aList.AddUnderlineForPreviousItemL( '=', 0 );
       
  1158 
       
  1159     TBuf<128> caption;
       
  1160     _LIT( KCaptionFormat, "FC %04d" );
       
  1161     _LIT( KValueFormat, "0x%08x %8d %1d" );
       
  1162 
       
  1163     const TInt count = aFreeCells.Count();
       
  1164     for( TInt i=0; i<count; i++ )
       
  1165         {
       
  1166         const TMemSpyDriverFreeCell& cell = aFreeCells[ i ];
       
  1167         caption.Format( KCaptionFormat, i + 1 );
       
  1168         aList.AddItemFormatL( caption, KValueFormat, cell.iAddress, cell.iLength, cell.iType );
       
  1169         }
       
  1170     }
       
  1171 
       
  1172 
       
  1173 void CMemSpyEngineHelperHeap::UpdateSharedHeapInfoL( const TProcessId& aProcess, const TThreadId& aThread, TMemSpyHeapInfo& aInfo )
       
  1174     {
       
  1175     RArray<TThreadId> threads;
       
  1176     CleanupClosePushL( threads );
       
  1177     iEngine.Driver().GetThreadsL( aProcess, threads );
       
  1178     TMemSpyHeapInfo otherHeap;
       
  1179     TThreadId otherThreadId;
       
  1180     TInt r( KErrNone );
       
  1181     for ( TInt i = 0; i < threads.Count(); i++ )
       
  1182         {
       
  1183         otherThreadId = threads[i];
       
  1184         if ( aThread != otherThreadId ) // skip current thread
       
  1185             {
       
  1186             r = iEngine.Driver().GetHeapInfoUser( otherHeap, otherThreadId );
       
  1187             if ( !r && otherHeap.AsRHeap().MetaData().ChunkHandle() == aInfo.AsRHeap().MetaData().ChunkHandle() )
       
  1188                 {
       
  1189                 TRACE( RDebug::Printf( "CMemSpyEngineHelperHeap::UpdateSharedHeapInfoL - shared heap detected chunkhandle: 0x%08x", aInfo.AsRHeap().MetaData().ChunkHandle() ) );
       
  1190                 aInfo.AsRHeap().MetaData().SetSharedHeap( ETrue );
       
  1191                 break;
       
  1192                 }
       
  1193             }
       
  1194         }
       
  1195     CleanupStack::PopAndDestroy( &threads );
       
  1196     }
       
  1197