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