--- a/memspy/Driver/Kernel/Source/MemSpyDriverHeapWalker.cpp Tue Aug 31 16:45:49 2010 +0300
+++ b/memspy/Driver/Kernel/Source/MemSpyDriverHeapWalker.cpp Wed Sep 01 12:37:10 2010 +0100
@@ -21,14 +21,22 @@
#include "MemSpyDriverUtils.h"
// Defines
+#define __NEXT_CELL(p) ((RMemSpyDriverRHeapBase::SCell*)(((TUint8*)p)+p->len))
#define PRINTDEBUG( a ) { if ( PrintDebug() ) a; }
-RMemSpyDriverHeapWalker::RMemSpyDriverHeapWalker(RMemSpyDriverRHeapBase& aHeap, MMemSpyHeapWalkerObserver* aObserver)
- : iHeap(aHeap), iPrintDebug(EFalse), iObserver(aObserver)
- {
- InitialiseStats();
- }
+RMemSpyDriverHeapWalker::RMemSpyDriverHeapWalker( RMemSpyDriverRHeapBase& aHeap, TBool aDebugAllocator )
+: iHeap( aHeap ), iIsDebugAllocator( aDebugAllocator ), iPrintDebug( EFalse ), iObserver( NULL )
+ {
+ InitialiseStats();
+ }
+
+
+RMemSpyDriverHeapWalker::RMemSpyDriverHeapWalker( RMemSpyDriverRHeapBase& aHeap, TBool aDebugAllocator, MMemSpyHeapWalkerObserver& aObserver )
+: iHeap( aHeap ), iIsDebugAllocator( aDebugAllocator ), iPrintDebug( EFalse ), iObserver( &aObserver )
+ {
+ InitialiseStats();
+ }
TInt RMemSpyDriverHeapWalker::Traverse()
@@ -36,7 +44,7 @@
// Walk the heap calling the info function.
//
{
- PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - START"));
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - START - delta: 0x%08x", iHeap.ClientToKernelDelta() ));
InitialiseStats();
if ( iObserver )
{
@@ -45,64 +53,135 @@
}
PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - heap walk init complete" ));
-
- TInt err = iHeap.Helper()->Walk(&CellCallback, this);
- FinaliseStats();
- //PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END - pF: 0x%08x, pC: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pF, pC, heapBase, heapTop));
- return err;
- }
+ TAny* heapBase = KernelAddress( iHeap.iBase );
+ TAny* heapTop = KernelAddress( iHeap.iTop );
+ 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));
-TBool RMemSpyDriverHeapWalker::CellCallback(RAllocatorHelper& aHelper, TAny* aContext, RAllocatorHelper::TExtendedCellType aCellType, TLinAddr aCellAddress, TInt aLength)
- {
- return static_cast<RMemSpyDriverHeapWalker*>(aContext)->DoCellCallback(aHelper, aCellType, aCellAddress, aLength);
- }
-
-TBool RMemSpyDriverHeapWalker::DoCellCallback(RAllocatorHelper& aHelper, RAllocatorHelper::TExtendedCellType aCellType, TLinAddr aCellAddress, TInt aLength)
- {
- TAny* cellAddress = (TAny*)aCellAddress;
- TMemSpyDriverCellType memspyCellType = (TMemSpyDriverCellType)aCellType; // We make sure these use the same values
- switch (aCellType)
+ TRACE_DATA( MemSpyDriverUtils::DataDump("%lS", (TUint8*) iHeap.ChunkKernelAddress(), iHeap.Chunk().iSize, iHeap.Chunk().iSize ) );
+
+ TInt nestingLevel = 0;
+ TInt allocationNumber = 0;
+ //
+ RMemSpyDriverRHeapBase::SCell* pC = (RMemSpyDriverRHeapBase::SCell*) heapBase; // allocated cells
+ RMemSpyDriverRHeapBase::SCell* pF = &iHeap.iFree; // free cells
+ 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));
+ //
+ while( ( pF == &iHeap.iFree ) || ( pF >= heapBase && pF < heapTop ) )
{
- case RAllocatorHelper::EHeapBadFreeCellAddress:
- PRINTDEBUG(Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellAddress: 0x%08x", cellAddress));
- NotifyCell(memspyCellType, cellAddress, 0);
- return EFalse;
- case RAllocatorHelper::EHeapBadFreeCellSize:
- PRINTDEBUG(Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellSize: 0x%08x", cellAddress));
- NotifyCell(memspyCellType, cellAddress, aLength);
- return EFalse;
- case RAllocatorHelper::EHeapBadAllocatedCellSize:
- PRINTDEBUG(Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellSize: 0x%08x", cellAddress));
- NotifyCell(memspyCellType, cellAddress, aLength);
- return EFalse;
- case RAllocatorHelper::EHeapBadAllocatedCellAddress:
- PRINTDEBUG(Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellAddress: 0x%08x", cellAddress));
- NotifyCell(memspyCellType, cellAddress, aLength);
- return EFalse;
- default:
- break;
+ pF = (RMemSpyDriverRHeapBase::SCell*) KernelAddress( pF->next ); // next free cell
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - pC: 0x%08x, pF: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pC, pF, heapBase, heapTop));
+
+ if ( pF )
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell: 0x%08x", pF ));
+
+ if ( pF >= heapBase && pF < heapTop )
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell->next: 0x%08x", pF->next ));
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell->len: 0x%08x", pF->len ));
+ }
+ else
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - FATAL ERROR - freeCell: 0x%08x is outside heap bounds!", pF ));
+ }
+
+ PRINTDEBUG( Kern::Printf(" "));
+ }
+
+ if (!pF)
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - next free cell address is NULL"));
+ pF = (RMemSpyDriverRHeapBase::SCell*) heapTop; // to make size checking work
+ }
+ else if ( (TUint8*) pF < heapBase || (TUint8*) pF >= heapTop || (KernelAddress( pF->next ) && KernelAddress( pF->next ) <= pF ) )
+ {
+ // free cell pointer off the end or going backwards
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellAddress: 0x%08x", pF ));
+ NotifyCell( EMemSpyDriverBadFreeCellAddress, UserAddress(pF), 0 );
+ return KErrAbort;
+ }
+ else
+ {
+ TInt l = pF->len;
+ if ( l< iHeap.iMinCell || (l & (iHeap.iAlign-1)))
+ {
+ // free cell length invalid
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadFreeCellSize: 0x%08x", pF ));
+ NotifyCell( EMemSpyDriverBadFreeCellSize, UserAddress(pF), l );
+ return KErrAbort;
+ }
+ }
+
+ while ( pC != pF ) // walk allocated cells up to next free cell
+ {
+ if ( pC )
+ {
+ // The 'next' cell field is only applicable if the cell is a 'free' cell, hence we only print the cell's
+ // address, its length, and its _calculated_ next cell (based upon address + length). Calc length is done
+ // a bit later on...
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell: 0x%08x", pC ));
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell->len: 0x%08x", pC->len ));
+ PRINTDEBUG( Kern::Printf(" "));
+ }
+
+ TInt l = pC->len;
+ if (l<iHeap.iMinCell || (l & (iHeap.iAlign-1)))
+ {
+ // allocated cell length invalid
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellSize: 0x%08x", pC ));
+ NotifyCell( EMemSpyDriverBadAllocatedCellSize, UserAddress(pC), l );
+ return KErrAbort;
+ }
+
+ // ALLOCATED CELL
+ if ( iIsDebugAllocator )
+ {
+ RMemSpyDriverRHeapBase::SDebugCell* debugCell = (RMemSpyDriverRHeapBase::SDebugCell*) pC;
+ nestingLevel = debugCell->nestingLevel;
+ allocationNumber = debugCell->allocCount;
+ }
+
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodAllocatedCell: 0x%08x", pC ));
+ if ( NotifyCell( EMemSpyDriverGoodAllocatedCell, UserAddress(pC), l, nestingLevel, allocationNumber ) == EFalse )
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END1 - KErrAbort on NotifyCell..."));
+ return KErrAbort;
+ }
+
+ RMemSpyDriverRHeapBase::SCell* pN = (RMemSpyDriverRHeapBase::SCell*) __NEXT_CELL( pC );
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - allocCell next: 0x%08x", pN ));
+ if (pN > pF)
+ {
+ // cell overlaps next free cell
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EBadAllocatedCellAddress: 0x%08x", pC ));
+ NotifyCell( EMemSpyDriverBadAllocatedCellAddress, UserAddress(pC), l );
+ return KErrAbort;
+ }
+
+ pC = pN;
+ }
+
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell before exit check is: 0x%08x", pF ));
+ if ((TUint8*) pF >= heapTop )
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - freeCell reached top of heap -> done"));
+ break; // reached end of heap
+ }
+
+ pC = (RMemSpyDriverRHeapBase::SCell*) __NEXT_CELL(pF); // step to next allocated cell
+
+ // FREE CELL
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodFreeCell: 0x%08x", pF ));
+ if ( NotifyCell( EMemSpyDriverGoodFreeCell, UserAddress(pF), pF->len ) == EFalse )
+ {
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END2 - KErrAbort on NotifyCell..."));
+ return KErrAbort;
+ }
}
- if (aCellType & RAllocatorHelper::EAllocationMask)
- {
- PRINTDEBUG(Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodAllocatedCell: 0x%08x", cellAddress));
- TInt nestingLevel = -1;
- aHelper.GetCellNestingLevel(cellAddress, nestingLevel);
- TInt allocCount = aHelper.AllocCountForCell(cellAddress);
- if (allocCount < 0) allocCount = -1; // This is what NotifyCell expects
- return NotifyCell(memspyCellType, cellAddress, aLength, nestingLevel, allocCount);
- }
- else if (aCellType & RAllocatorHelper::EFreeMask)
- {
- PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - EGoodFreeCell: 0x%08x", cellAddress));
- return NotifyCell(memspyCellType, cellAddress, aLength);
- }
- else if (aCellType & RAllocatorHelper::EBadnessMask)
- {
- NotifyCell(memspyCellType, cellAddress, aLength);
- return EFalse;
- }
- return ETrue; // For any new types that get added
+ FinaliseStats();
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::Traverse() - END - pF: 0x%08x, pC: 0x%08x, heapBase: 0x%08x, heapTop: 0x%08x", pF, pC, heapBase, heapTop));
+ return KErrNone;
}
@@ -140,7 +219,9 @@
alloc.SetLargestCellAddress( (TAny*) iStats.iLargestCellAddressAlloc );
alloc.SetLargestCellSize( iStats.iLargestCellSizeAlloc );
- aStats.iCommittedFreeSpace = iHeap.Helper()->CommittedFreeSpace();
+ // Copy common info
+ TMemSpyHeapStatisticsRHeapCommon& common = aStats.StatsCommon();
+ common.SetTotalCellCount( iStats.iNumberOfWalkedCells );
PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::CopyStatsTo() - END"));
}
@@ -152,6 +233,56 @@
iObserver = aObserver;
}
+
+TAny* RMemSpyDriverHeapWalker::KernelAddress( TAny* aUserAddress, TUint aDelta )
+ {
+ TAny* ret = NULL;
+ //
+ if ( aUserAddress )
+ {
+ TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::KernelAddress() - aUserAddress: 0x%08x", aUserAddress));
+ ret = (TUint8*) aUserAddress + aDelta;
+ }
+ //
+ TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::KernelAddress() - ret: 0x%08x", ret));
+ return ret;
+ }
+
+
+TAny* RMemSpyDriverHeapWalker::UserAddress( TAny* aKernelAddress, TUint aDelta )
+ {
+ TAny* ret = NULL;
+ //
+ if ( aKernelAddress )
+ {
+ TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::UserAddress() - aKernelAddress: 0x%08x", aKernelAddress));
+ ret = (TUint8*) aKernelAddress - aDelta;
+ }
+ //
+ TRACE_HEAP( Kern::Printf("RMemSpyDriverHeapWalker::UserAddress() - ret: 0x%08x", ret));
+ return ret;
+ }
+
+
+TAny* RMemSpyDriverHeapWalker::KernelAddress( TAny* aUserAddress) const
+ {
+ return KernelAddress( aUserAddress, iHeap.ClientToKernelDelta() );
+ }
+
+
+TAny* RMemSpyDriverHeapWalker::UserAddress( TAny* aKernelAddress ) const
+ {
+ return UserAddress( aKernelAddress, iHeap.ClientToKernelDelta() );
+ }
+
+
+RMemSpyDriverRHeapBase::SCell* RMemSpyDriverHeapWalker::CellByUserAddress( TAny* aAddress, TUint aDelta )
+ {
+ RMemSpyDriverRHeapBase::SCell* ret = (RMemSpyDriverRHeapBase::SCell*) KernelAddress( aAddress, aDelta );
+ return ret;
+ }
+
+
TBool RMemSpyDriverHeapWalker::NotifyCell( TMemSpyDriverCellType aType, TAny* aCellAddress, TInt aLength, TInt aNestingLevel, TInt aAllocNumber )
{
// Update stats first
@@ -170,9 +301,32 @@
void RMemSpyDriverHeapWalker::UpdateStats( TMemSpyDriverCellType aCellType, TAny* aCellAddress, TInt aLength, TInt aNestingLevel, TInt aAllocNumber )
{
- PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - type: %d address: 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellType, aCellAddress, aLength, aNestingLevel, aAllocNumber ));
+ switch( aCellType )
+ {
+ case EMemSpyDriverGoodAllocatedCell:
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EGoodAllocatedCell - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber ));
+ break;
+ case EMemSpyDriverGoodFreeCell:
+ PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EGoodFreeCell - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber ));
+ break;
+ case EMemSpyDriverBadAllocatedCellSize:
+ Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadAllocatedCellSize - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
+ break;
+ case EMemSpyDriverBadAllocatedCellAddress:
+ Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadAllocatedCellAddress - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
+ break;
+ case EMemSpyDriverBadFreeCellAddress:
+ Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadFreeCellAddress - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
+ break;
+ case EMemSpyDriverBadFreeCellSize:
+ Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - EBadFreeCellSize - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d", aCellAddress, aLength, aNestingLevel, aAllocNumber );
+ break;
+ default:
+ Kern::Printf("RMemSpyDriverHeapWalker::UpdateStats - UHANDLED TYPE! - 0x%08x, len: %8d, nestingLev: %8d, allocNum: %8d, type: %d", aCellAddress, aLength, aNestingLevel, aAllocNumber, aCellType );
+ break;
+ }
- if (aCellType & EMemSpyDriverFreeCellMask)
+ if ( aCellType == EMemSpyDriverGoodFreeCell )
{
// Update checksum
iStats.iFreeCellCRC = iStats.iFreeCellCRC ^ reinterpret_cast<TUint32>( aCellAddress );
@@ -201,7 +355,7 @@
iStats.iFirstFreeCellAddress = (TLinAddr) aCellAddress;
}
}
- else if (aCellType & EMemSpyDriverAllocatedCellMask)
+ else if ( aCellType == EMemSpyDriverGoodAllocatedCell )
{
// Track cell counts and length
++iStats.iAllocCellCount;
@@ -218,10 +372,14 @@
iStats.iLargestCellAddressAlloc = (TLinAddr) aCellAddress;
}
}
+ else
+ {
+ iStats.iLastFreeCellLength = aLength;
+ }
iStats.iLastCellType = aCellType;
iStats.iLastCellAddress = (TLinAddr) aCellAddress;
- iStats.iLastCellWasFreeCell = (aCellType & EMemSpyDriverFreeCellMask);
+ iStats.iLastCellWasFreeCell = ( aCellType == EMemSpyDriverGoodFreeCell );
++iStats.iNumberOfWalkedCells;
}
@@ -232,7 +390,7 @@
iStats.iNumberOfWalkedCells = 0;
iStats.iFirstFreeCellAddress = 0;
iStats.iFirstFreeCellLength = 0;
- iStats.iLastCellType = EMemSpyDriverAllocatedCellMask;
+ iStats.iLastCellType = EMemSpyDriverGoodAllocatedCell;
iStats.iLastCellWasFreeCell = EFalse;
iStats.iLastFreeCellLength = 0;
iStats.iTotalFreeSpace = 0;
@@ -248,6 +406,10 @@
iStats.iLargestCellAddressFreePrevious = 0;
iStats.iSpackSpaceCellAddress = 0;
iStats.iLastCellAddress = 0;
+
+ // These two can be identified up front
+ iStats.iFreeCellOverheadHeaderLength = RMemSpyDriverRHeapBase::FreeCellHeaderSize();
+ iStats.iAllocCellOverheadHeaderLength = RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( iIsDebugAllocator );
}
@@ -285,3 +447,4 @@
PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iLargestCellAddressAlloc : 0x%08x", iStats.iLargestCellAddressAlloc ) );
PRINTDEBUG( Kern::Printf("RMemSpyDriverHeapWalker::PrintStats - iFreeCellCRC : 0x%08x", iStats.iFreeCellCRC ) );
}
+