memspy/Driver/Kernel/Source/MemSpyDriverHeapWalker.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 "MemSpyDriverHeapWalker.h"
       
    19 
       
    20 // User includes
       
    21 #include "MemSpyDriverUtils.h"
       
    22 
       
    23 // Defines
       
    24 #define __NEXT_CELL(p)				((RMemSpyDriverRHeapBase::SCell*)(((TUint8*)p)+p->len))
       
    25 #define PRINTDEBUG( a ) { if ( PrintDebug() ) a; }
       
    26 
       
    27 
       
    28 RMemSpyDriverHeapWalker::RMemSpyDriverHeapWalker( RMemSpyDriverRHeapBase& aHeap, TBool aDebugAllocator )
       
    29 :   iHeap( aHeap ), iIsDebugAllocator( aDebugAllocator ), iPrintDebug( EFalse ), iObserver( NULL )
       
    30     {
       
    31     InitialiseStats();
       
    32     }
       
    33 
       
    34 
       
    35 RMemSpyDriverHeapWalker::RMemSpyDriverHeapWalker( RMemSpyDriverRHeapBase& aHeap, TBool aDebugAllocator, MMemSpyHeapWalkerObserver& aObserver )
       
    36 :   iHeap( aHeap ), iIsDebugAllocator( aDebugAllocator ), iPrintDebug( EFalse ), iObserver( &aObserver )
       
    37     {
       
    38     InitialiseStats();
       
    39     }
       
    40 
       
    41 
       
    42 TInt RMemSpyDriverHeapWalker::Traverse()
       
    43 //
       
    44 // Walk the heap calling the info function.
       
    45 //
       
    46 	{
       
    47     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - START - delta: 0x%08x", iHeap.ClientToKernelDelta() ));
       
    48     InitialiseStats();
       
    49     if  ( iObserver )
       
    50         {
       
    51         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - heap walk init..." ));
       
    52         iObserver->HandleHeapWalkInit();
       
    53         }
       
    54 
       
    55     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - heap walk init complete" ));
       
    56     TAny* heapBase = KernelAddress( iHeap.iBase );
       
    57     TAny* heapTop = KernelAddress( iHeap.iTop );
       
    58 	PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - kernel-side chunk address: 0x%08x, chunkBase: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", iHeap.ChunkKernelAddress(), iHeap.Chunk().iBase, heapBase, heapTop));
       
    59 
       
    60     TRACE_DATA( MemSpyDriverUtils::DataDump("%lS", (TUint8*) iHeap.ChunkKernelAddress(), iHeap.Chunk().iSize, iHeap.Chunk().iSize ) );
       
    61    
       
    62 	TInt nestingLevel = 0;
       
    63 	TInt allocationNumber = 0;
       
    64 	//
       
    65 	RMemSpyDriverRHeapBase::SCell* pC = (RMemSpyDriverRHeapBase::SCell*) heapBase;		// allocated cells
       
    66 	RMemSpyDriverRHeapBase::SCell* pF = &iHeap.iFree;				            // free cells
       
    67 	PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - before while loop entry - pC: 0x%08x, pF: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pC, pF, heapBase, heapTop));
       
    68     //
       
    69     while( ( pF == &iHeap.iFree ) || ( pF >= heapBase && pF < heapTop ) )
       
    70 		{
       
    71         pF = (RMemSpyDriverRHeapBase::SCell*) KernelAddress( pF->next );				// next free cell
       
    72 	    PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - pC: 0x%08x, pF: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pC, pF, heapBase, heapTop));
       
    73 
       
    74         if  ( pF )
       
    75         	{
       
    76             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell:       0x%08x", pF ));
       
    77 
       
    78             if  ( pF >= heapBase && pF < heapTop )
       
    79                 {
       
    80                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell->next: 0x%08x", pF->next ));
       
    81                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell->len:  0x%08x", pF->len ));
       
    82                 }
       
    83             else
       
    84                 {
       
    85                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - FATAL ERROR - freeCell:  0x%08x is outside heap bounds!", pF ));
       
    86                 }
       
    87 
       
    88             PRINTDEBUG( Kern::Printf(" "));
       
    89             }
       
    90 		
       
    91         if  (!pF)
       
    92             {
       
    93             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - next free cell address is NULL"));
       
    94 			pF = (RMemSpyDriverRHeapBase::SCell*) heapTop;		// to make size checking work
       
    95             }
       
    96 		else if (  (TUint8*) pF < heapBase || (TUint8*) pF >= heapTop || (KernelAddress( pF->next ) && KernelAddress( pF->next ) <= pF ) )
       
    97 			{
       
    98 			// free cell pointer off the end or going backwards
       
    99             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellAddress: 0x%08x", pF ));
       
   100             NotifyCell( EMemSpyDriverBadFreeCellAddress, UserAddress(pF), 0 );
       
   101 			return KErrAbort;
       
   102 			}
       
   103 		else
       
   104 			{
       
   105 			TInt l = pF->len;
       
   106 			if ( l< iHeap.iMinCell || (l & (iHeap.iAlign-1)))
       
   107 				{
       
   108 				// free cell length invalid
       
   109                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellSize: 0x%08x", pF ));
       
   110 		        NotifyCell( EMemSpyDriverBadFreeCellSize, UserAddress(pF), l );
       
   111 			    return KErrAbort;
       
   112 				}
       
   113 			}
       
   114 
       
   115         while ( pC != pF )				// walk allocated cells up to next free cell
       
   116 			{
       
   117     	    if  ( pC )
       
   118         	    {
       
   119                 // The 'next' cell field is only applicable if the cell is a 'free' cell, hence we only print the cell's
       
   120                 // address, its length, and its _calculated_ next cell (based upon address + length). Calc length is done
       
   121                 // a bit later on...
       
   122                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell:       0x%08x", pC ));
       
   123                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell->len:  0x%08x", pC->len ));
       
   124                 PRINTDEBUG( Kern::Printf(" "));
       
   125                 }
       
   126             
       
   127             TInt l = pC->len;
       
   128 			if (l<iHeap.iMinCell || (l & (iHeap.iAlign-1)))
       
   129 				{
       
   130 				// allocated cell length invalid
       
   131                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellSize: 0x%08x", pC ));
       
   132 		        NotifyCell( EMemSpyDriverBadAllocatedCellSize, UserAddress(pC), l );
       
   133 			    return KErrAbort;
       
   134 				}
       
   135 
       
   136             // ALLOCATED CELL
       
   137             if  ( iIsDebugAllocator )
       
   138                 {
       
   139                 RMemSpyDriverRHeapBase::SDebugCell* debugCell = (RMemSpyDriverRHeapBase::SDebugCell*) pC;
       
   140                 nestingLevel = debugCell->nestingLevel;
       
   141                 allocationNumber = debugCell->allocCount;
       
   142                 }
       
   143 
       
   144             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodAllocatedCell: 0x%08x", pC ));
       
   145 	        if  ( NotifyCell( EMemSpyDriverGoodAllocatedCell, UserAddress(pC), l, nestingLevel, allocationNumber ) == EFalse )
       
   146                 {
       
   147                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END1 - KErrAbort on NotifyCell..."));
       
   148 			    return KErrAbort;
       
   149                 }
       
   150 
       
   151 			RMemSpyDriverRHeapBase::SCell* pN = (RMemSpyDriverRHeapBase::SCell*) __NEXT_CELL( pC );
       
   152             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell next:  0x%08x", pN ));
       
   153 			if (pN > pF)
       
   154 				{
       
   155 				// cell overlaps next free cell
       
   156                 PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellAddress: 0x%08x", pC ));
       
   157 		        NotifyCell( EMemSpyDriverBadAllocatedCellAddress, UserAddress(pC), l );
       
   158 			    return KErrAbort;
       
   159 				}
       
   160 
       
   161             pC = pN;
       
   162 			}
       
   163 
       
   164         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell before exit check is: 0x%08x", pF ));
       
   165         if  ((TUint8*) pF >= heapTop )
       
   166             {
       
   167             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell reached top of heap -> done"));
       
   168 			break;		// reached end of heap
       
   169             }
       
   170 		
       
   171         pC = (RMemSpyDriverRHeapBase::SCell*) __NEXT_CELL(pF);	// step to next allocated cell
       
   172 
       
   173         // FREE CELL
       
   174         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodFreeCell: 0x%08x", pF ));
       
   175         if  ( NotifyCell( EMemSpyDriverGoodFreeCell, UserAddress(pF), pF->len ) == EFalse )
       
   176             {
       
   177             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END2 - KErrAbort on NotifyCell..."));
       
   178 			return KErrAbort;
       
   179             }
       
   180 		}
       
   181 
       
   182     FinaliseStats();
       
   183     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END - pF: 0x%08x, pC: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pF, pC, heapBase, heapTop));
       
   184     return KErrNone;
       
   185 	}
       
   186 
       
   187 
       
   188 void RMemSpyDriverHeapWalker::CopyStatsTo( TMemSpyHeapStatisticsRHeap& aStats )
       
   189     {
       
   190 	PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::CopyStatsTo() - START"));
       
   191 
       
   192     // Copy free cell info
       
   193     TMemSpyHeapStatisticsRHeapFree& free = aStats.StatsFree();
       
   194     free.SetTypeCount( iStats.iFreeCellCount );
       
   195     free.SetTypeSize( iStats.iTotalFreeSpace );
       
   196 
       
   197     // If the last cell was a free cell, and it was also the largest cell
       
   198     // then we use the prior largest free cell instead. This is because
       
   199     // slack space is already reported separately.
       
   200     TAny* largestFreeCellAddress = (TAny*) iStats.iLargestCellAddressFree;
       
   201     TUint largestFreeCellSize = iStats.iLargestCellSizeFree;
       
   202     if ( iStats.iLastCellWasFreeCell && iStats.iLargestCellSizeFree == iStats.iSlackSpace && iStats.iSpackSpaceCellAddress == iStats.iLargestCellAddressFree )
       
   203         {
       
   204 	    PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::CopyStatsTo() - using previous max free cell stats, since largest free cell is slack cell at end of heap..."));
       
   205         largestFreeCellAddress = (TAny*) iStats.iLargestCellAddressFreePrevious;
       
   206         largestFreeCellSize = iStats.iLargestCellSizeFreePrevious;
       
   207         }
       
   208 
       
   209     free.SetLargestCellAddress( largestFreeCellAddress );
       
   210     free.SetLargestCellSize( largestFreeCellSize );
       
   211     free.SetSlackSpaceCellSize( iStats.iSlackSpace );
       
   212     free.SetSlackSpaceCellAddress( (TAny*) iStats.iSpackSpaceCellAddress );
       
   213     free.SetChecksum( iStats.iFreeCellCRC );
       
   214 
       
   215     // Copy allocated cell info
       
   216     TMemSpyHeapStatisticsRHeapAllocated& alloc = aStats.StatsAllocated();
       
   217     alloc.SetTypeCount( iStats.iAllocCellCount );
       
   218     alloc.SetTypeSize( iStats.iTotalAllocSpace );
       
   219     alloc.SetLargestCellAddress( (TAny*) iStats.iLargestCellAddressAlloc );
       
   220     alloc.SetLargestCellSize( iStats.iLargestCellSizeAlloc );
       
   221 
       
   222     // Copy common info
       
   223     TMemSpyHeapStatisticsRHeapCommon& common = aStats.StatsCommon();
       
   224     common.SetTotalCellCount( iStats.iNumberOfWalkedCells );
       
   225 
       
   226 	PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::CopyStatsTo() - END"));
       
   227     }
       
   228 
       
   229 
       
   230 void RMemSpyDriverHeapWalker::SetObserver( MMemSpyHeapWalkerObserver* aObserver )
       
   231     {
       
   232     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::SetObserver() - aObserver: 0x%08x", aObserver ));
       
   233     iObserver = aObserver;
       
   234     }
       
   235 
       
   236 
       
   237 TAny* RMemSpyDriverHeapWalker::KernelAddress( TAny* aUserAddress, TUint aDelta )
       
   238     {
       
   239     TAny* ret = NULL;
       
   240     //
       
   241     if  ( aUserAddress )
       
   242         {
       
   243 	    TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::KernelAddress() - aUserAddress: 0x%08x", aUserAddress));
       
   244         ret = (TUint8*) aUserAddress + aDelta;
       
   245         }
       
   246     //
       
   247 	TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::KernelAddress() - ret: 0x%08x", ret));
       
   248     return ret;
       
   249     }
       
   250 
       
   251  
       
   252 TAny* RMemSpyDriverHeapWalker::UserAddress( TAny* aKernelAddress, TUint aDelta )
       
   253     {
       
   254     TAny* ret = NULL;
       
   255     //
       
   256     if  ( aKernelAddress )
       
   257         {
       
   258 	    TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::UserAddress() - aKernelAddress: 0x%08x", aKernelAddress));
       
   259         ret = (TUint8*) aKernelAddress - aDelta;
       
   260         }
       
   261     //
       
   262 	TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::UserAddress() - ret: 0x%08x", ret));
       
   263     return ret;
       
   264     }
       
   265 
       
   266 
       
   267 TAny* RMemSpyDriverHeapWalker::KernelAddress( TAny* aUserAddress) const
       
   268     {
       
   269     return KernelAddress( aUserAddress, iHeap.ClientToKernelDelta() );
       
   270     }
       
   271 
       
   272 
       
   273 TAny* RMemSpyDriverHeapWalker::UserAddress( TAny* aKernelAddress ) const
       
   274     {
       
   275     return UserAddress( aKernelAddress, iHeap.ClientToKernelDelta() );
       
   276     }
       
   277 
       
   278 
       
   279 RMemSpyDriverRHeapBase::SCell* RMemSpyDriverHeapWalker::CellByUserAddress( TAny* aAddress, TUint aDelta )
       
   280     {
       
   281     RMemSpyDriverRHeapBase::SCell* ret = (RMemSpyDriverRHeapBase::SCell*) KernelAddress( aAddress, aDelta );
       
   282     return ret;
       
   283     }
       
   284 
       
   285 
       
   286 TBool RMemSpyDriverHeapWalker::NotifyCell( TMemSpyDriverCellType aType, TAny* aCellAddress, TInt aLength, TInt aNestingLevel, TInt aAllocNumber )
       
   287     {
       
   288     // Update stats first
       
   289     UpdateStats( aType, aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   290 	
       
   291     // Notify observer
       
   292     TBool continueTraversal = ETrue;
       
   293     if  ( iObserver )
       
   294         {
       
   295         continueTraversal = iObserver->HandleHeapCell( aType, aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   296         }
       
   297     //
       
   298     return continueTraversal;
       
   299     }
       
   300 
       
   301 
       
   302 void RMemSpyDriverHeapWalker::UpdateStats( TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt aNestingLevel, TInt aAllocNumber )
       
   303     {
       
   304     switch( aCellType )
       
   305         {
       
   306     case EMemSpyDriverGoodAllocatedCell:
       
   307         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EGoodAllocatedCell       - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber ));
       
   308         break;
       
   309     case EMemSpyDriverGoodFreeCell:
       
   310         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EGoodFreeCell            - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber ));
       
   311         break;
       
   312     case EMemSpyDriverBadAllocatedCellSize:
       
   313         Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadAllocatedCellSize    - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   314         break;
       
   315     case EMemSpyDriverBadAllocatedCellAddress:
       
   316         Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadAllocatedCellAddress - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   317         break;
       
   318     case EMemSpyDriverBadFreeCellAddress:
       
   319         Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadFreeCellAddress      - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   320         break;
       
   321     case EMemSpyDriverBadFreeCellSize:
       
   322         Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadFreeCellSize         - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
       
   323         break;
       
   324     default:
       
   325         Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - UHANDLED TYPE!           - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d, type: %d", aCellAddress, aLength, aNestingLevel, aAllocNumber, aCellType );
       
   326         break;
       
   327         }
       
   328 
       
   329     if  ( aCellType == EMemSpyDriverGoodFreeCell )
       
   330         {
       
   331         // Update checksum
       
   332         iStats.iFreeCellCRC = iStats.iFreeCellCRC ^ reinterpret_cast<TUint32>( aCellAddress );
       
   333 
       
   334         // Track cell counts and length
       
   335         ++iStats.iFreeCellCount;
       
   336         iStats.iTotalFreeSpace += aLength;
       
   337         iStats.iLastFreeCellLength = aLength;
       
   338 
       
   339         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - WAS FREE CELL - iFreeCellCRC: 0x%08x, iFreeCellCount: %d, iTotalFreeSpace: %d, iLastFreeCellLength: %d", iStats.iFreeCellCRC, iStats.iFreeCellCount, iStats.iTotalFreeSpace, iStats.iLastFreeCellLength));
       
   340         
       
   341         // Identify biggest cell
       
   342         if  ( (TUint) aLength > iStats.iLargestCellSizeFree )
       
   343             {
       
   344             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - this cell (%d bytes big) is bigger than previous largested FREE cell (%d bytes) => making it the new largest FREE cell", aLength, iStats.iLargestCellSizeFree));
       
   345             iStats.iLargestCellSizeFreePrevious = iStats.iLargestCellSizeFree;
       
   346             iStats.iLargestCellSizeFree = aLength;
       
   347             iStats.iLargestCellAddressFreePrevious = iStats.iLargestCellAddressFree;
       
   348             iStats.iLargestCellAddressFree = (TLinAddr) aCellAddress;
       
   349             }
       
   350 
       
   351         // Identify first cell
       
   352         if  ( iStats.iFirstFreeCellAddress == 0 )
       
   353             {
       
   354             iStats.iFirstFreeCellLength = aLength;
       
   355             iStats.iFirstFreeCellAddress = (TLinAddr) aCellAddress;
       
   356             }
       
   357         }
       
   358     else if ( aCellType == EMemSpyDriverGoodAllocatedCell )
       
   359         {
       
   360         // Track cell counts and length
       
   361         ++iStats.iAllocCellCount;
       
   362         iStats.iTotalAllocSpace += aLength;
       
   363         iStats.iLastFreeCellLength = 0; 
       
   364 
       
   365         PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - WAS ALLOC CELL - iAllocCellCount: %d, iTotalAllocSpace: %d", iStats.iAllocCellCount, iStats.iTotalAllocSpace));
       
   366 
       
   367         // Identify biggest cell
       
   368         if  ( (TUint) aLength > iStats.iLargestCellSizeAlloc )
       
   369             {
       
   370             PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - this cell (%d bytes big) is bigger than previous largested ALLOC cell (%d bytes) => making it the new largest ALLOC cell", aLength, iStats.iLargestCellSizeAlloc));
       
   371             iStats.iLargestCellSizeAlloc = aLength;
       
   372             iStats.iLargestCellAddressAlloc = (TLinAddr) aCellAddress;
       
   373             }
       
   374         }
       
   375     else
       
   376         {
       
   377         iStats.iLastFreeCellLength = aLength;
       
   378         }
       
   379 
       
   380     iStats.iLastCellType = aCellType;
       
   381     iStats.iLastCellAddress = (TLinAddr) aCellAddress;
       
   382     iStats.iLastCellWasFreeCell = ( aCellType == EMemSpyDriverGoodFreeCell );
       
   383     ++iStats.iNumberOfWalkedCells;
       
   384     }
       
   385 
       
   386 
       
   387 void RMemSpyDriverHeapWalker::InitialiseStats()
       
   388     {
       
   389     iStats.iFreeCellCRC = 0;
       
   390     iStats.iNumberOfWalkedCells = 0;
       
   391     iStats.iFirstFreeCellAddress = 0;
       
   392     iStats.iFirstFreeCellLength = 0;
       
   393     iStats.iLastCellType = EMemSpyDriverGoodAllocatedCell;
       
   394     iStats.iLastCellWasFreeCell = EFalse;
       
   395     iStats.iLastFreeCellLength = 0;
       
   396     iStats.iTotalFreeSpace = 0;
       
   397     iStats.iTotalAllocSpace = 0;
       
   398     iStats.iSlackSpace = 0;
       
   399     iStats.iFreeCellCount = 0;
       
   400     iStats.iAllocCellCount = 0;
       
   401     iStats.iLargestCellSizeFree = 0;
       
   402     iStats.iLargestCellSizeAlloc = 0;
       
   403     iStats.iLargestCellAddressFree = 0;
       
   404     iStats.iLargestCellAddressAlloc = 0;
       
   405     iStats.iLargestCellSizeFreePrevious = 0;
       
   406     iStats.iLargestCellAddressFreePrevious = 0;
       
   407     iStats.iSpackSpaceCellAddress = 0;
       
   408     iStats.iLastCellAddress = 0;
       
   409 
       
   410     // These two can be identified up front
       
   411     iStats.iFreeCellOverheadHeaderLength = RMemSpyDriverRHeapBase::FreeCellHeaderSize();
       
   412     iStats.iAllocCellOverheadHeaderLength = RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( iIsDebugAllocator );
       
   413     }
       
   414 
       
   415 
       
   416 void RMemSpyDriverHeapWalker::FinaliseStats()
       
   417     {
       
   418     if  ( iStats.iLastCellWasFreeCell )
       
   419         {
       
   420         iStats.iSlackSpace = iStats.iLastFreeCellLength;
       
   421         iStats.iSpackSpaceCellAddress = iStats.iLastCellAddress;
       
   422         }
       
   423 
       
   424     PrintStats();
       
   425     }
       
   426 
       
   427 
       
   428 void RMemSpyDriverHeapWalker::PrintStats()
       
   429     {
       
   430     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - HEAP SUMMARY FOR THREAD:" ) );
       
   431     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - ------------------------------------------------------------" ) );
       
   432     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iNumberOfWalkedCells         : %10d", iStats.iNumberOfWalkedCells ) );
       
   433     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iFirstFreeCellAddress        : 0x%08x", iStats.iFirstFreeCellAddress ) );
       
   434     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iFirstFreeCellLength         : %10d", iStats.iFirstFreeCellLength ) );
       
   435     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLastCellWasFreeCell         : %10d", iStats.iLastCellWasFreeCell ) );
       
   436     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLastCellType                : %10d", iStats.iLastCellType ) );
       
   437     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLastFreeCellLength          : %10d", iStats.iLastFreeCellLength ) );
       
   438     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iTotalFreeSpace              : %10d", iStats.iTotalFreeSpace ) );
       
   439     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iTotalAllocSpace             : %10d", iStats.iTotalAllocSpace ) );
       
   440     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iSlackSpace                  : %10d", iStats.iSlackSpace ) );
       
   441     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iFreeCellCount               : %10d", iStats.iFreeCellCount ) );
       
   442     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iAllocCellCount              : %10d", iStats.iAllocCellCount ) );
       
   443     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLargestCellSizeFree         : %10d", iStats.iLargestCellSizeFree ) );
       
   444     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLastFreeCellLength          : %10d", iStats.iLastFreeCellLength ) );
       
   445     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLargestCellSizeAlloc        : %10d", iStats.iLargestCellSizeAlloc ) );
       
   446     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLargestCellAddressFree      : 0x%08x", iStats.iLargestCellAddressFree ) );
       
   447     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLargestCellAddressAlloc     : 0x%08x", iStats.iLargestCellAddressAlloc ) );
       
   448     PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iFreeCellCRC                 : 0x%08x", iStats.iFreeCellCRC ) );
       
   449     }
       
   450