diff -r ca8a1b6995f6 -r 52e343bb8f80 memspy/Driver/Kernel/Source/MemSpyDriverHeapWalker.cpp --- 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(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 (lnestingLevel; + 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( 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 ) ); } +