diff -r 000000000000 -r a03f92240627 memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanHeapBase.cpp Tue Feb 02 01:57:15 2010 +0200 @@ -0,0 +1,1040 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include "MemSpyDriverLogChanHeapBase.h" + +// System includes +#include +#include +#include + +// Shared includes +#include "MemSpyDriverOpCodes.h" +#include "MemSpyDriverObjectsInternal.h" + +// User includes +#include "MemSpyDriverHeap.h" +#include "MemSpyDriverUtils.h" +#include "MemSpyDriverDevice.h" +#include "MemSpyDriverOSAdaption.h" + +// Constants +const TInt KMemSpyDriverLogChanHeapBaseXferBufferSize = 1024 * 16; + + + + +DMemSpyDriverLogChanHeapBase::DMemSpyDriverLogChanHeapBase( DMemSpyDriverDevice& aDevice, DThread& aThread ) +: DMemSpyDriverLogChanBase( aDevice, aThread ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::DMemSpyDriverLogChanHeapBase() - this: 0x%08x", this )); + } + + +DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() - START - this: 0x%08x", this )); + + ReleaseFreeCells(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::~DMemSpyDriverLogChanHeapBase() - END - this: 0x%08x", this )); + } + + +TInt DMemSpyDriverLogChanHeapBase::Construct() + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::Construct() - START - this: 0x%08x", this )); + + const TInt ret = BaseConstruct( KMemSpyDriverLogChanHeapBaseXferBufferSize ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::Construct() - END - this: 0x%08x, err: %d", this, ret )); + return ret; + } + + + + + + + + + + + +TInt DMemSpyDriverLogChanHeapBase::Request( TInt aFunction, TAny* a1, TAny* a2 ) + { + const TInt r = DMemSpyDriverLogChanBase::Request( aFunction, a1, a2 ); + return r; + } + + + + + + + + + + + + + +DMemSpyDriverLogChanHeapBase::TDrmMatchType DMemSpyDriverLogChanHeapBase::IsDrmThread( DThread& aThread ) + { + TDrmMatchType ret = EMatchTypeNone; + // + const TUid procUid = aThread.iOwningProcess->iUids.iUid[ 2 ]; + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::IsDrmThread() - START - aThread: %O, process uid: 0x%08x", &aThread, procUid.iUid )); + + // Some more rudimentary checks based upon process name and + // known uids. + TFullName fullName; + aThread.FullName( fullName ); + + // Exclude threads containing "DRM" + _LIT( KDrmThreadMatchText, "*DRM*" ); + const TInt matchPos = fullName.MatchF( KDrmThreadMatchText ); + if ( matchPos >= 0 ) + { + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::IsDrmThread() - found \'DRM\' at pos: %d (%S)", matchPos, &fullName )); + ret = EMatchTypeName; + } + else + { + // Some known DRM related process UIDs + switch( procUid.iUid ) + { + case 0x10005A22: // DRMEncryptor.exe + case 0x01105901: // DRMEncryptor.exe + case 0x101F85C7: // DRMRightsManager.exe + case 0x10205CA8: // DcfRepSrv.exe + case 0x101F51F2: // RightsServer.exe + case 0x101F6DC5: // DRMHelperServer.exe + case 0x10282F1B: // wmdrmserver.exe + ret = EMatchTypeUid; + break; + default: + ret = EMatchTypeNone; + break; + } + } + + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::IsDrmThread() - END - procUid: 0x%08x, matchType: %d", procUid.iUid, ret )); + return ret; + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TInt DMemSpyDriverLogChanHeapBase::OpenUserHeap( DThread& aClientThread, TUint aExpectedHeapVTable, RMemSpyDriverRHeapUser& aHeap, DChunk*& aUserHeapChunk, TDes8* aClientHeapChunkName ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap() - START - aHeap.ChunkIsInitialised: %d, aExpectedHeapVTable: 0x%08x, aClientThread: %O", aHeap.ChunkIsInitialised(), aExpectedHeapVTable, &aClientThread )); + __ASSERT_ALWAYS( aHeap.ChunkIsInitialised() == EFalse, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapChunkAlreadyCloned ) ); + + TInt r = KErrNotFound; + aUserHeapChunk = NULL; + + NKern::ThreadEnterCS(); + + const TBool allocatorIsReallyRHeap = GetUserHeapHandle( aClientThread, aHeap, aExpectedHeapVTable ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - allocatorIsReallyRHeap: %d", allocatorIsReallyRHeap)); + + if ( allocatorIsReallyRHeap ) + { + RAllocator* allocator = OSAdaption().DThread().GetAllocator( aClientThread ); + + // Open client's heap chunk in order to read it's dimensions + const TInt clientsHeapChunkHandle = aHeap.iChunkHandle; + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clientsHeapChunkHandle: 0x%08x, allocatorAddress: 0x%08x", clientsHeapChunkHandle, allocator)); + + NKern::LockSystem(); + DChunk* clientsHeapChunk = (DChunk*) Kern::ObjectFromHandle( &aClientThread, clientsHeapChunkHandle, EChunk ); + NKern::UnlockSystem(); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clientsHeapChunk: 0x%08x", clientsHeapChunk )); + + if ( clientsHeapChunk != NULL ) + { + // Get the chunk name (if the caller asked for it) + if ( aClientHeapChunkName ) + { + clientsHeapChunk->FullName( *aClientHeapChunkName ); + } + + // Update the heap chunk pointer. We do this now because this + // should point to the _real_ user-side heap chunk, rather than + // the copy of the chunk that we are about to make. + aUserHeapChunk = clientsHeapChunk; + + // Set up ourselves to duplicate their heap chunk + const TInt clientsHeapChunkSize = OSAdaption().DChunk().GetSize( *clientsHeapChunk ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - chunkBase: 0x%08x, size: %8d, maxLen: %8d, chunk: %O", clientsHeapChunk->iBase, clientsHeapChunkSize, clientsHeapChunk->iMaxSize, clientsHeapChunk )); + + // Make a new chunk that is the same size, owned by this thread. + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelSingle; + info.iMaxSize = clientsHeapChunkSize; + info.iOwnsMemory = ETrue; // Use memory from system's free pool + info.iDestroyedDfc = NULL; + #ifdef __EPOC32__ + info.iMapAttr = (TInt)EMapAttrFullyBlocking; // Full caching + #endif + + // Holds a copy of the client's heap chunk + DChunk* heapCopyChunk; + TLinAddr heapCopyChunkAddress; + TUint32 heapCopyChunkMappingAttributes; + r = Kern::ChunkCreate( info, heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - creating chunk returned: %d", r)); + // + if ( r == KErrNone ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - copy chunk base: 0x%08x, heapCopyChunkAddress: 0x%08x", heapCopyChunk->iBase, heapCopyChunkAddress)); + + // Commit memory for entire buffer + TUint32 physicalAddress = 0; + r = Kern::ChunkCommitContiguous( heapCopyChunk, 0, clientsHeapChunkSize, physicalAddress ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - commiting chunk returned: %d", r)); + + if ( r != KErrNone) + { + // On error, thow away the chunk we have created + Kern::ChunkClose( heapCopyChunk ); + heapCopyChunk = NULL; + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - heapCopyChunk->iSize: 0x%08x, heapCopyChunk->iBase: 0x%08x, heapCopyChunkAddress: 0x%08x, physicalAddress: 0x%08x", heapCopyChunk->iSize, heapCopyChunk->iBase, heapCopyChunkAddress, physicalAddress)); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - trying to copy %d bytes from clients allocator address of 0x%08x", clientsHeapChunkSize, allocator )); + r = Kern::ThreadRawRead( &aClientThread, allocator, (TAny*) heapCopyChunkAddress, clientsHeapChunkSize ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - read result of clients heap data is: %d", r)); + if ( r == KErrNone ) + { + // Transfer ownership of the copy heap chunk to the heap object. This also calculates the delta + // beween the heap addresses in the client's address space and the kernel address space. + aHeap.AssociateWithKernelChunk( heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + } + } + } + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - could not open clients heap chunk by its handle" ) ); + r = KErrNotFound; + } + } + else + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - clients heap is not an RHeap (allocated vTable mismatch)" ) ); + r = KErrNotSupported; + } + + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenUserHeap - r: %d", r )); + return r; + } + + + + + + + + + + + + + + + + + + + + + + + +TBool DMemSpyDriverLogChanHeapBase::GetUserHeapHandle( DThread& aThread, RMemSpyDriverRHeapUser& aHeap, TUint aExpectedVTable ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle() - START - aExpectedVTable: 0x%08x", aExpectedVTable) ); + + RAllocator* allocator = OSAdaption().DThread().GetAllocator( aThread ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - allocator addr: 0x%08x", allocator) ); + TUint* pAllocator = (TUint*) allocator; + // + TBool vTableOkay = EFalse; + TUint vtable = 0; + + // Read a bit more data than is available for debugging purposes + TBuf8<32> vtableBuf; + TInt r = Kern::ThreadRawRead( &aThread, pAllocator, (TUint8*) vtableBuf.Ptr(), vtableBuf.MaxLength() ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - read result of vtable data from requested thread is: %d", r)); + if ( r == KErrNone ) + { + TRACE( MemSpyDriverUtils::DataDump("allocator vtable data - %lS", vtableBuf.Ptr(), vtableBuf.MaxLength(), vtableBuf.MaxLength() ) ); + vtableBuf.SetLength( vtableBuf.MaxLength() ); + + vtable = vtableBuf[0] + + (vtableBuf[1] << 8) + + (vtableBuf[2] << 16) + + (vtableBuf[3] << 24); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - client VTable is: 0x%08x", vtable) ); + + // Check the v-table to work out if it really is an RHeap + vTableOkay = ( vtable == aExpectedVTable ); + if ( vTableOkay ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - vtables okay") ); + r = aHeap.ReadFromUserAllocator( aThread ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - after userget, error: %d", r)); + + } + else + { + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - vtables dont match! - aExpectedVTable: 0x%08x, allocator addr: 0x%08x, client VTable is: 0x%08x, aThread: %O", aExpectedVTable, allocator, vtable, &aThread ) ); + } + } + else + { + TRACE( Kern::Printf( "DMemSpyDriverLogChanHeapBase::GetUserHeapHandle - error during client vTable reading: %d, aThread: %O", r, &aThread ) ); + } + // + return (vTableOkay && (r == KErrNone)); + } + + + + + + + + + + + + + + +void DMemSpyDriverLogChanHeapBase::PrintHeapInfo( const TMemSpyHeapInfo& aInfo ) + { + const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap(); + const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); + const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); + const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iAccessCount: %d", rHeapObjectData.iAccessCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iHandleCount: %d", rHeapObjectData.iHandleCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iHandles: 0x%08x", rHeapObjectData.iHandles ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iFlags: 0x%08x", rHeapObjectData.iFlags ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iCellCount: %d", rHeapObjectData.iCellCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RAllocator::iTotalAllocSize: %d", rHeapObjectData.iTotalAllocSize ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMinLength: %d", rHeapObjectData.iMinLength ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMaxLength: %d", rHeapObjectData.iMaxLength ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iOffset: %d", rHeapObjectData.iOffset ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iGrowBy: %d", rHeapObjectData.iGrowBy ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iChunkHandle: 0x%08x", rHeapObjectData.iChunkHandle ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iBase: 0x%08x", rHeapObjectData.iBase ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iTop: 0x%08x", rHeapObjectData.iTop ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iAlign: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iMinCell: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iPageSize: %d", rHeapObjectData.iAlign ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFree.next: 0x%08x", rHeapObjectData.iFree.next ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFree.len: %d", rHeapObjectData.iFree.len ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iNestingLevel: %d", rHeapObjectData.iNestingLevel ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iAllocCount: %d", rHeapObjectData.iAllocCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailType: %d", rHeapObjectData.iFailType ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailRate: %d", rHeapObjectData.iFailRate ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailed: %d", rHeapObjectData.iFailed ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iFailAllocCount: %d", rHeapObjectData.iFailAllocCount ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iRand: %d", rHeapObjectData.iRand ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - RHeap::iTestData: 0x%08x", rHeapObjectData.iTestData ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Stats (Free) -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell count: %d", rHeapStats.StatsFree().TypeCount() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell size: %d", rHeapStats.StatsFree().TypeSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell largest: 0x%08x", rHeapStats.StatsFree().LargestCellAddress() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell largest size: %d", rHeapStats.StatsFree().LargestCellSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - slack: 0x%08x", rHeapStats.StatsFree().SlackSpaceCellAddress() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - slack size: %d", rHeapStats.StatsFree().SlackSpaceCellSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - checksum: 0x%08x", rHeapStats.StatsFree().Checksum() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Stats (Alloc) -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell count: %d", rHeapStats.StatsAllocated().TypeCount() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell size: %d", rHeapStats.StatsAllocated().TypeSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell largest: 0x%08x", rHeapStats.StatsAllocated().LargestCellAddress() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell largest size: %d", rHeapStats.StatsAllocated().LargestCellSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Stats (Common) -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - total cell count: %d", rHeapStats.StatsCommon().TotalCellCount() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - " ) ); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - Misc. Info -" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() ---------------------------------------------------" ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - chunk size: %d", rHeapMetaData.ChunkSize() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - chunk handle: 0x%08x", rHeapMetaData.ChunkHandle() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - chunk base address: 0x%08x", rHeapMetaData.ChunkBaseAddress() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - debug allocator: %d", rHeapMetaData.IsDebugAllocator() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - shared heap: %d", rHeapMetaData.IsSharedHeap() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - user thread: %d", rHeapMetaData.IsUserThread() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (free): %d", rHeapMetaData.HeaderSizeFree() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - cell header size (alloc): %d", rHeapMetaData.HeaderSizeAllocated() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap vTable: 0x%08x", rHeapMetaData.VTable() ) ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrintHeapInfo() - heap object size: %d", rHeapMetaData.ClassSize() ) ); + } + + + + + + + + + + +TBool DMemSpyDriverLogChanHeapBase::IsDebugKernel() + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - START") ); + + TInt r = KErrNone; + TBool debugKernel = EFalse; + + NKern::ThreadEnterCS(); + RMemSpyDriverRHeapKernelInPlace rHeap; + r = OpenKernelHeap( rHeap ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - open kernel heap returned: %d", r) ); + + if ( r == KErrNone ) + { + debugKernel = IsDebugKernel( rHeap ); + + // Tidy up + rHeap.DisassociateWithKernelChunk(); + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - debugKernel: %d", debugKernel) ); + NKern::ThreadLeaveCS(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - END - ret: %d", r) ); + return debugKernel; + } + + +TBool DMemSpyDriverLogChanHeapBase::IsDebugKernel( RMemSpyDriverRHeapKernelInPlace& aHeap ) + { + TBool debugKernel = EFalse; + // + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - START") ); + NKern::ThreadEnterCS(); + + // Request that the kernel fail the next heap allocation + aHeap.FailNext(); + + // Allocate a new cell, and in debug builds of the kernel, this should be NULL + TInt* cell = new TInt(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - cell: 0x%08x", cell) ); + debugKernel = ( cell == NULL ); + delete cell; + + NKern::ThreadLeaveCS(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::IsDebugKernel() - END - debugKernel: %d", debugKernel) ); + // + return debugKernel; + } + + +TInt DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel( RMemSpyDriverRHeapBase& aHeap, TBool aIsDebugAllocator, const TDesC8& aChunkName, TMemSpyHeapInfo* aHeapInfo, TDes8* aTransferBuffer ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel() - START - aTransferBuffer: 0x%08x", aTransferBuffer ) ); + + TInt r = KErrNone; + NKern::ThreadEnterCS(); + + // This object holds all of the info we will accumulate for the client. + TMemSpyHeapInfo masterHeapInfo; + masterHeapInfo.SetType( TMemSpyHeapInfo::ETypeRHeap ); + masterHeapInfo.SetTid( 2 ); + masterHeapInfo.SetPid( 1 ); + + // This is the RHeap-specific object that contains all RHeap info + TMemSpyHeapInfoRHeap& rHeapInfo = masterHeapInfo.AsRHeap(); + + // This is the object data for the RHeap instance + TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData(); + aHeap.CopyObjectDataTo( rHeapObjectData ); + + // When walking the kernel heap we must keep track of the free cells + // without allocating any more memory (on the kernel heap...) + // + // Therefore, we start a stream immediately, which is actually already + // pre-allocated. + // + // Start stream and pad with zero count, which we'll repopulate later on + // once we know the final score. + RMemSpyMemStreamWriter stream; + TInt32* pCount = NULL; + + // We must walk the client's heap in order to build statistics + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - calling heap walker constructor...")); + RMemSpyDriverHeapWalker heapWalker( aHeap, aIsDebugAllocator ); + if ( aTransferBuffer ) + { + // This will allow us to identify that we're writing directly to the stream + stream = OpenXferStream(); + iStackStream = &stream; + + // Writer marker value which we'll update after the traversal completes + pCount = stream.WriteInt32( 0 ); + + // Receive cell info as we walk the heap... + heapWalker.SetObserver( this ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - collecting free cells - iStackStream: 0x%08x, isOpen: %d, pCount: 0x%08x", iStackStream, stream.IsOpen(), pCount )); + } + else + { + iStackStream = NULL; + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - not collecting free cells")); + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - locking system..." )); + NKern::LockSystem(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - disabling interrupts..." )); + const TInt irq = NKern::DisableAllInterrupts(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - starting traversal..." )); + +#if defined( TRACE_TYPE_KERNELHEAP ) + heapWalker.SetPrintDebug(); +#endif + r = heapWalker.Traverse(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - restoring interrupts..." )); + NKern::RestoreInterrupts( irq ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - finished traversal - err: %d, iStackStream: 0x%08x, pCount: 0x%08x, isOpen: %d", r, iStackStream, pCount, ( iStackStream == NULL ? 0 : iStackStream->IsOpen() ) )); + NKern::UnlockSystem(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - unlocked system" )); + + // Write free cells if requested + if ( r == KErrNone && iStackStream && iStackStream->IsOpen() && pCount ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - final free cell count: %d", iFreeCellCount )); + *pCount = iFreeCellCount; + r = stream.WriteAndClose( aTransferBuffer ); + iStackStream = NULL; + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - stream commit result: %d", r )); + } + + TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics(); + heapWalker.CopyStatsTo( rHeapStats ); + + // Get remaining meta data that isn't stored elsewhere + TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData(); + rHeapMetaData.SetChunkName( aChunkName ); + rHeapMetaData.SetChunkSize( (TUint) aHeap.Chunk().Size() ); + rHeapMetaData.SetChunkHandle( &aHeap.Chunk() ); + rHeapMetaData.SetChunkBaseAddress( aHeap.Chunk().Base() ); + rHeapMetaData.SetDebugAllocator( aIsDebugAllocator ); + rHeapMetaData.SetHeaderSizeFree( RMemSpyDriverRHeapBase::FreeCellHeaderSize() ); + rHeapMetaData.SetHeaderSizeAllocated( RMemSpyDriverRHeapBase::AllocatedCellHeaderSize( aIsDebugAllocator ) ); + rHeapMetaData.SetUserThread( EFalse ); + rHeapMetaData.SetSharedHeap( ETrue ); + + // Get any heap-specific info + aHeap.GetHeapSpecificInfo( masterHeapInfo ); + + PrintHeapInfo( masterHeapInfo ); + + // Update info ready for writing back to the user-side + if ( r == KErrNone ) + { + // Write results back to user-side + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel - writing to user-side...")); + r = Kern::ThreadRawWrite( &ClientThread(), aHeapInfo, &masterHeapInfo, sizeof( TMemSpyHeapInfo ) ); + } + + NKern::ThreadLeaveCS(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::GetHeapInfoKernel() - END - ret: %d", r) ); + return r; + } + + + + + + + + + + + + + + + + + +TBool DMemSpyDriverLogChanHeapBase::HandleHeapCell( TInt aCellType, TAny* aCellAddress, TInt aLength, TInt /*aNestingLevel*/, TInt /*aAllocNumber*/ ) + { + TInt error = KErrNone; + // + if ( aCellType == EMemSpyDriverGoodFreeCell || aCellType == EMemSpyDriverBadFreeCellAddress || aCellType == EMemSpyDriverBadFreeCellSize ) + { + TMemSpyDriverFreeCell cell; + cell.iType = aCellType; + cell.iAddress = aCellAddress; + cell.iLength = aLength; + // + if ( iStackStream ) + { + if ( !iStackStream->IsFull() ) + { + ++iFreeCellCount; + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::HandleHeapCell - writing free cell %d @ 0x%08x, space left: %u", iFreeCellCount, aCellAddress, iStackStream->Remaining() )); + // + iStackStream->WriteInt32( aCellType ); + iStackStream->WriteUint32( reinterpret_cast( aCellAddress ) ); + iStackStream->WriteInt32( aLength ); + } + else + { + Kern::Printf( "DMemSpyDriverLogChanHeapBase::HandleHeapCell - Kernel Free Cell stack stream IS FULL!" ); + error = KErrAbort; + } + } + else + { + NKern::ThreadEnterCS(); + error = iFreeCells.Append( cell ); + NKern::ThreadLeaveCS(); + // + if ( error == KErrNone ) + { + ++iFreeCellCount; + } + } + } + // + return ( error == KErrNone ); + } + + +void DMemSpyDriverLogChanHeapBase::HandleHeapWalkInit() + { + // Can't delete the free cell list here as we might be walking the kernel heap + iFreeCellCount = 0; + } + + + + + + +TInt DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() + { + // Transfer free cells immediately from xfer stream + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - START - iHeapStream: 0x%08x", iHeapStream )); + __ASSERT_ALWAYS( !iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotClosed ) ); + // + TInt r = KErrNoMemory; + // + NKern::ThreadEnterCS(); + // + iHeapStream = new RMemSpyMemStreamWriter(); + if ( iHeapStream ) + { + const TInt requiredMemory = CalculateFreeCellBufferSize(); + r = OpenXferStream( *iHeapStream, requiredMemory ); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - requested %d bytes for free cell list, r: %d", requiredMemory, r )); + + if ( r == KErrNone ) + { + const TInt count = iFreeCells.Count(); + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - free cell count: %d", count )); + // + iHeapStream->WriteInt32( count ); + for( TInt i=0; iWriteInt32( cell.iType ); + iHeapStream->WriteUint32( reinterpret_cast( cell.iAddress ) ); + iHeapStream->WriteInt32( cell.iLength ); + } + + // Finished with the array now + iFreeCells.Reset(); + + // We return the amount of client-side memory that needs to be allocated to hold the buffer + r = requiredMemory; + } + } + // + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::PrepareFreeCellTransferBuffer() - END - r: %d", r)); + return r; + } + + +TInt DMemSpyDriverLogChanHeapBase::FetchFreeCells( TDes8* aBufferSink ) + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::FetchFreeCells() - START - iHeapStream: 0x%08x", iHeapStream )); + __ASSERT_ALWAYS( iHeapStream, MemSpyDriverUtils::PanicThread( ClientThread(), EPanicHeapFreeCellStreamNotOpen ) ); + + TInt r = KErrNone; + + // Write buffer to client + NKern::ThreadEnterCS(); + r = iHeapStream->WriteAndClose( aBufferSink ); + + // Tidy up + ReleaseFreeCells(); + + NKern::ThreadLeaveCS(); + // + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::FetchFreeCells() - END - r: %d", r)); + return r; + } + + + +TInt DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() const + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() - START" )); + + const TInt count = iFreeCells.Count(); + const TInt entrySize = sizeof( TInt32 ) + sizeof( TInt32 ) + sizeof( TUint32 ); + const TInt r = ( count * entrySize ) + sizeof( TInt ); // Extra TInt to hold count + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::CalculateFreeCellBufferSize() - END - r: %d, count: %d, entrySize: %d", r, count, entrySize )); + return r; + } + + + +void DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() + { + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() - START - this: 0x%08x", this )); + + // Housekeeping + NKern::ThreadEnterCS(); + iFreeCells.Reset(); + // + iStackStream = NULL; + // + delete iHeapStream; + iHeapStream = NULL; + NKern::ThreadLeaveCS(); + + TRACE( Kern::Printf("DMemSpyDriverLogChanHeapBase::ReleaseFreeCells() - END - this: 0x%08x", this )); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RHeapK*& aHeap, DChunk*& aChunk, TDes8* aClientHeapChunkName ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap() - START") ); + + // This is what we're searching for... + RHeapK* kernelHeap = NULL; + DChunk* kernelHeapChunk = NULL; + + // Find the SvHeap chunk.... + _LIT( KKernelServerHeapChunkName, "SvHeap" ); + NKern::ThreadEnterCS(); + + DObjectCon* chunkContainer = Kern::Containers()[EChunk]; + chunkContainer->Wait(); + NKern::LockSystem(); + const TInt chunkCount = chunkContainer->Count(); + + for(TInt i=0; iNameBuf() ) + { + const TInt findResult = chunk->NameBuf()->Find( KKernelServerHeapChunkName ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - checking chunk: %O against %S => %d", chunk, &KKernelServerHeapChunkName, findResult ) ); + if ( findResult != KErrNotFound ) + { + // Found it. + kernelHeapChunk = chunk; + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - found chunk with base: 0x%08x", chunk->iBase ) ); + break; + } + } + } + + NKern::UnlockSystem(); + chunkContainer->Signal(); + + TInt r = KErrNotFound; + if ( kernelHeapChunk != NULL ) + { +#ifndef __WINS__ + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeapChunk: 0x%08x", kernelHeapChunk ) ); + + const TRomHeader& romHdr = Epoc::RomHeader(); + const TRomEntry* primaryEntry = (const TRomEntry*) Kern::SuperPage().iPrimaryEntry; + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - primaryEntry: 0x%08x, primaryEntry->iAddressLin: 0x%08x", primaryEntry, primaryEntry->iAddressLin ) ); + const TRomImageHeader* primaryImageHeader = (const TRomImageHeader*) primaryEntry->iAddressLin; + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - primaryEntry: 0x%08x", primaryImageHeader ) ); + + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iCodeSize: 0x%08x", primaryImageHeader->iCodeSize ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iTextSize: 0x%08x", primaryImageHeader->iTextSize ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iDataSize: 0x%08x", primaryImageHeader->iDataSize ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iBssSize: 0x%08x", primaryImageHeader->iBssSize ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iHeapSizeMin: 0x%08x", primaryImageHeader->iHeapSizeMin ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iHeapSizeMax: 0x%08x", primaryImageHeader->iHeapSizeMax ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - TRomImageHeader::iStackSize: 0x%08x", primaryImageHeader->iStackSize ) ); + + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - romHdr.iKernDataAddress: 0x%08x", romHdr.iKernDataAddress ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - Kern::RoundToPageSize( romHdr.iTotalSvDataSize ): 0x%08x", Kern::RoundToPageSize( romHdr.iTotalSvDataSize ) ) ); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - Kern::RoundToPageSize( kernelProcessCreateInfo.iStackSize ): 0x%08x", Kern::RoundToPageSize( primaryImageHeader->iStackSize ) ) ); + + TAny* stack = (TAny*)( romHdr.iKernDataAddress + Kern::RoundToPageSize( romHdr.iTotalSvDataSize )); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - aStack: 0x%08x", stack ) ); + + // NB: This is supposed to be Kern::RoundToPageSize( kernelProcessCreateInfo.iStackSize ) but that + // sometimes returns very dodgy values on ARMv5 Multiple Memory Model when using MemSpy's driver + // installed via a SIS file. No idea why. Cache problem? + TAny* heap = (TAny*)(TLinAddr( stack ) + Kern::RoundToPageSize( primaryImageHeader->iStackSize )); + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - aHeap: 0x%08x", heap ) ); + + kernelHeap = (RHeapK*) heap; +#else + kernelHeap = (RHeapK*) kernelHeapChunk->Base(); +#endif + // Finalise construction of heap + if ( kernelHeap != NULL ) + { + TRACE_KH( Kern::Printf( "DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernelHeap->Base(): 0x%08x, kernelHeapChunk->Base(): 0x%08x", kernelHeap->Base(), kernelHeapChunk->Base() ) ); + aHeap = kernelHeap; + aChunk = kernelHeapChunk; + + // Get the chunk name (if the caller asked for it) + if ( aClientHeapChunkName ) + { + kernelHeapChunk->FullName( *aClientHeapChunkName ); + } + + // Opened okay + r = KErrNone; + } + else + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - kernel heap was NULL...")); + } + } + else + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap - couldnt find kernel chunk...")); + r = KErrNotFound; + } + + NKern::ThreadLeaveCS(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap() - END - ret: %d", r ) ); + return r; + } + + +TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RMemSpyDriverRHeapKernelInPlace& aHeap, TDes8* aClientHeapChunkName ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - START") ); + + RHeapK* heap = NULL; + DChunk* chunk = NULL; + TInt r = OpenKernelHeap( heap, chunk, aClientHeapChunkName ); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - open err: %d", r ) ); + if ( r == KErrNone ) + { + aHeap.SetKernelHeap( *heap ); + aHeap.AssociateWithKernelChunk( chunk, TLinAddr( chunk->iBase ), 0 ); + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(IP) - END - ret: %d", r ) ); + return r; + } + + +TInt DMemSpyDriverLogChanHeapBase::OpenKernelHeap( RMemSpyDriverRHeapKernelFromCopy& aHeap, TDes8* aClientHeapChunkName ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - START") ); + + RHeapK* heap = NULL; + DChunk* chunk = NULL; + TInt r = OpenKernelHeap( heap, chunk, aClientHeapChunkName ); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - open err: %d", r ) ); + if ( r == KErrNone ) + { + const TInt heapSize = heap->Size(); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - heapSize: %d, heap: 0x%08x, chunkBase: 0x%08x", heapSize, heap, chunk->Base() ) ); + + // Make a new chunk that we can copy the kernel heap into. We cannot lock the system the entire time + // we need to do this, therefore there is no guarantee that the chunk will be large enough to hold the + // (current) heap data at the time we need to make the copy. We oversize the chunk by 1mb in the "hope" + // that it will be enough... :( + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelSingle; + info.iMaxSize = heapSize + ( 1024 * 1024 ); + info.iOwnsMemory = ETrue; // Use memory from system's free pool + info.iDestroyedDfc = NULL; + #ifdef __EPOC32__ + info.iMapAttr = (TInt)EMapAttrFullyBlocking; // Full caching + #endif + + // Holds a copy of the client's heap chunk + DChunk* heapCopyChunk; + TLinAddr heapCopyChunkAddress; + TUint32 heapCopyChunkMappingAttributes; + r = Kern::ChunkCreate( info, heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - creating chunk returned: %d", r)); + + if ( r == KErrNone ) + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copy chunk base: 0x%08x, heapCopyChunkAddress: 0x%08x", heapCopyChunk->iBase, heapCopyChunkAddress)); + + // Commit memory for entire buffer + TUint32 physicalAddress = 0; + r = Kern::ChunkCommitContiguous( heapCopyChunk, 0, heapSize, physicalAddress ); + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - commiting chunk returned: %d", r)); + + if ( r != KErrNone) + { + // On error, throw away the chunk we have created + Kern::ChunkClose( heapCopyChunk ); + heapCopyChunk = NULL; + } + else + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - heapCopyChunk->iSize: 0x%08x, heapCopyChunk->iBase: 0x%08x, heapCopyChunkAddress: 0x%08x, physicalAddress: 0x%08x", heapCopyChunk->iSize, heapCopyChunk->iBase, heapCopyChunkAddress, physicalAddress)); + + NKern::LockSystem(); + const TUint32 copyLength = Min( heap->Size(), heapSize ); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - trying to copy %d (vs orig estimate of %d) bytes from kernel allocator address: 0x%08x", copyLength, heapSize, heap->Base() )); + memcpy( (TUint8*) heapCopyChunkAddress, heap, copyLength ); + + NKern::UnlockSystem(); + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copied kernel heap data" )); + + // Transfer ownership of the copy heap chunk to the heap object. This also calculates the delta + // beween the heap addresses in the client's address space and the kernel address space. + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - associate chunk and transfer ownership..." )); + aHeap.SetKernelHeap( *heap ); + aHeap.AssociateWithKernelChunk( heapCopyChunk, heapCopyChunkAddress, heapCopyChunkMappingAttributes ); + } + } + else + { + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - copy chunk create error: %d", r ) ); + } + } + + TRACE_KH( Kern::Printf("DMemSpyDriverLogChanHeapBase::OpenKernelHeap(CP) - END - ret: %d", r ) ); + return r; + } + + +