diff -r 185201be11b0 -r 516af714ebb4 memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanChunks.cpp --- a/memspy/Driver/Kernel/Source/SubChannels/MemSpyDriverLogChanChunks.cpp Thu Sep 02 22:05:40 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,557 +0,0 @@ -/* -* 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 "MemSpyDriverLogChanChunks.h" - -// System includes -#include - -// Shared includes -#include "MemSpyDriverOpCodes.h" -#include "MemSpyDriverObjectsInternal.h" - -// User includes -#include "MemSpyDriverUtils.h" -#include "MemSpyDriverDevice.h" -#include "MemSpyDriverOSAdaption.h" - -// Constants -_LIT8( KMemSpyLitDllDollarData, "DLL$DATA" ); -_LIT8( KMemSpyLitDollarDat, "$DAT" ); -_LIT8( KMemSpyLitDollarCode, "$CODE" ); -_LIT8( KMemSpyLitDollarGlobalCode, "GLOBAL$CODE" ); -_LIT8( KMemSpyLitLocalObject, "Local-" ); - - -DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks( DMemSpyDriverDevice& aDevice, DThread& aThread ) -: DMemSpyDriverLogChanBase( aDevice, aThread ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DMemSpyDriverLogChanChunks() - this: 0x%08x", this )); - } - - -DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - START - this: 0x%08x", this )); - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::~DMemSpyDriverLogChanChunks() - END - this: 0x%08x", this )); - } - - - -TInt DMemSpyDriverLogChanChunks::Request( TInt aFunction, TAny* a1, TAny* a2 ) - { - TInt r = DMemSpyDriverLogChanBase::Request( aFunction, a1, a2 ); - if ( r == KErrNone ) - { - switch( aFunction ) - { - case EMemSpyDriverOpCodeChunkGetHandles: - r = GetChunkHandles( (TMemSpyDriverInternalChunkHandleParams*) a1 ); - break; - case EMemSpyDriverOpCodeChunkGetInfo: - r = GetChunkInfo( (TMemSpyDriverInternalChunkInfoParams*) a1 ); - break; - - default: - r = KErrNotSupported; - break; - } - } - // - return r; - } - - -TBool DMemSpyDriverLogChanChunks::IsHandler( TInt aFunction ) const - { - return ( aFunction > EMemSpyDriverOpCodeChunkBase && aFunction < EMemSpyDriverOpCodeChunkEnd ); - } - - - - - - - - - - - - - - - - - - - - -TInt DMemSpyDriverLogChanChunks::GetChunkHandles( TMemSpyDriverInternalChunkHandleParams* aParams ) - { - TMemSpyDriverInternalChunkHandleParams params; - TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkHandleParams) ); - if ( r != KErrNone ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - params read error: %d", r)); - return r; - } - - const TInt maxCount = params.iMaxCount; - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - START - id: %d, maxCount: %d, type: %d", params.iId, maxCount, params.iType)); - - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); - DMemSpyDriverOSAdaptionDThread& threadAdaption = OSAdaption().DThread(); - DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); - - - // This variable holds the number of handles that we have already - // written to the client-side. - TInt currentWriteIndex = 0; - - if ( params.iType == EMemSpyDriverPrivateObjectTypeProcess || params.iType == EMemSpyDriverPrivateObjectTypeThread ) - { - if ( params.iType == EMemSpyDriverPrivateObjectTypeThread ) - { - r = OpenTempObject( params.iId, EThread ); - if ( r == KErrNone ) - { - // Open the owning process instead, so that we can see which chunks are mapped - // into the thread. - DThread* thread = (DThread*) TempObject(); - DProcess* process = threadAdaption.GetOwningProcess( *thread ); - if ( process ) - { - const TUint parentProcessId = processAdaption.GetId( *process ); - CloseTempObject(); - r = OpenTempObject( parentProcessId, EProcess ); - } - else - { - CloseTempObject(); - r = KErrNotFound; - } - } - } - else - { - r = OpenTempObject( params.iId, EProcess ); - } - - // Handle error opening correct process - if (r != KErrNone) - { - Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - parent process not found"); - return r; - } - - DProcess* process = (DProcess*) TempObject(); - NKern::ThreadEnterCS(); - - // Iterate through each handle in the process - MemSpyObjectIx* processHandles = processAdaption.GetHandles( *process ); - MemSpyObjectIx_HandleLookupLock(); - const TInt processHandleCount = processHandles->Count(); - MemSpyObjectIx_HandleLookupUnlock(); - - for( TInt processHandleIndex = 0; processHandleIndex= processHandles->Count()) break; // Count may have changed in the meantime - DObject* object = (*processHandles)[ processHandleIndex ]; - if (object && object->Open() != KErrNone) object = NULL; - MemSpyObjectIx_HandleLookupUnlock(); - - if ( object ) - { - const TObjectType objectType = processAdaption.GetObjectType( *object ); - if ( objectType == EChunk ) - { - DChunk* chunk = (DChunk*) object; - TAny* handle = (TAny*) chunk; - r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &handle, sizeof(TAny*) ); - if ( r == KErrNone ) - { - ++currentWriteIndex; - } - } - object->Close(NULL); - } - } - - // If we were asked for process-related chunks, also check the chunk container - // for entries which we don't have handles to, but do refer to our process - // Need a listing of all chunks in the system. Let client filter duplicates. - DObjectCon* container = Kern::Containers()[ EChunk ]; - container->Wait(); - // - const TInt count = container->Count(); - for( TInt i=0; iSignal(); - NKern::ThreadLeaveCS(); - - CloseTempObject(); - } - else - { - // Need a listing of all chunks in the system. Let client filter duplicates. - DObjectCon* container = Kern::Containers()[ EChunk ]; - NKern::ThreadEnterCS(); - container->Wait(); - // - const TInt count = container->Count(); - for( TInt i=0; iSignal(); - NKern::ThreadLeaveCS(); - } - - if ( r == KErrBadDescriptor ) - { - MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); - } - else - { - const TInt finalWrite = Kern::ThreadRawWrite( &ClientThread(), params.iCountPtr, ¤tWriteIndex, sizeof(TInt) ); - if ( r == KErrNone ) - { - r = finalWrite; - } - } - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkHandles() - END - number of handles written to client: %d, ret: %d", currentWriteIndex, r)); - return r; - } - - -TInt DMemSpyDriverLogChanChunks::GetChunkInfo( TMemSpyDriverInternalChunkInfoParams* aParams ) - { - TMemSpyDriverInternalChunkInfoParams params; - TInt r = Kern::ThreadRawRead( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); - if ( r != KErrNone ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - params read error: %d", r)); - return r; - } - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - START - handle: 0x%08x", params.iHandle)); - - DObjectCon* container = Kern::Containers()[EChunk]; - NKern::ThreadEnterCS(); - - container->Wait(); - const TInt count = container->Count(); - - DChunk* foundChunk = NULL; - - for(TInt i=0; iOpen(); - break; - } - } - - container->Signal(); - - if ( foundChunk == NULL ) - { - Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - KErrNotFound - couldnt find chunk"); - NKern::ThreadLeaveCS(); - return KErrNotFound; - } - if (r) - { - Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - %d - Failed to open chunk", r); - NKern::ThreadLeaveCS(); - return r; - } - - // Prepare return data - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); - // - params.iBaseAddress = chunkAdaption.GetBase( *foundChunk ); - params.iSize = chunkAdaption.GetSize( *foundChunk ); - params.iMaxSize = chunkAdaption.GetMaxSize( *foundChunk ); - foundChunk->FullName( params.iName ); - - // Mirror the process memory tracker - DProcess* owner = chunkAdaption.GetOwningProcess( *foundChunk ); - if ( owner ) - { - params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); - } - else - { - owner = static_cast< DProcess* >( chunkAdaption.GetOwner( *foundChunk, EProcess ) ); - if ( owner ) - { - params.iOwnerId = OSAdaption().DProcess().GetId( *owner ); - } - else - { - params.iOwnerId = chunkAdaption.GetControllingOwnerId( *foundChunk ); - } - } - - // Get type & attribs - params.iType = IdentifyChunkType( *foundChunk ); - params.iAttributes = chunkAdaption.GetAttributes( *foundChunk ); - - // Finished with foundChunk - foundChunk->Close(NULL); - NKern::ThreadLeaveCS(); - - // Write back to client - r = Kern::ThreadRawWrite( &ClientThread(), aParams, ¶ms, sizeof(TMemSpyDriverInternalChunkInfoParams) ); - if ( r == KErrBadDescriptor ) - { - MemSpyDriverUtils::PanicThread( ClientThread(), EPanicBadDescriptor ); - } - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::GetChunkInfo() - END - handle: 0x%08x, params.iOwnerId: %d, r: %d", params.iHandle, params.iOwnerId, r )); - return r; - } - - -void DMemSpyDriverLogChanChunks::PrintChunkInfo( DChunk& aChunk ) - { - MemSpyDriverUtils::PrintChunkInfo( aChunk, OSAdaption() ); - } - - -TMemSpyDriverChunkType DMemSpyDriverLogChanChunks::IdentifyChunkType( DChunk& aChunk ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - START" ) ); - - TMemSpyDriverChunkType ret = EMemSpyDriverChunkTypeUnknown; - - TName name; - aChunk.Name( name ); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - name: %S", &name ) ); - - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); - const TChunkType type = chunkAdaption.GetType( aChunk ); - - if ( name == KMemSpyLitDllDollarData ) - { - // This chunk contains Dll Global Data for the process - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobalData" ) ); - ret = EMemSpyDriverChunkTypeGlobalData; - } - else if ( type == ERamDrive ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeRamDrive" ) ); - ret = EMemSpyDriverChunkTypeRamDrive; - } - else if ( type == EKernelStack ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackKernel" ) ); - ret = EMemSpyDriverChunkTypeStackKernel; - } - else if ( name == KMemSpyLitDollarDat ) - { - // This chunk contains process global data as well as user-side stacks for - // the process. - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeStackAndProcessGlobalData" ) ); - ret = EMemSpyDriverChunkTypeStackAndProcessGlobalData; - } - else if ( name == KMemSpyLitDollarGlobalCode && type == EDll ) - { - // GLOBAL$CODE is used for RAM loaded code which is globally visible. This - // basically means locale DLLs - these must be visible to every process, even - // those which haven't loaded them. - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeGlobal" ) ); - ret = EMemSpyDriverChunkTypeCodeGlobal; - } - else if ( name == KMemSpyLitDollarCode || type == EKernelCode || type == EDll || type == EUserCode ) - { - // RAM-loaded code, which on the multiple memory model at least means that the code chunk is eseentially just a mapping - // artifact. The RAM itself is owned by the code segment, therefore counting the size of these CODE elements may result - // in inaccurate results if the code is shared amongst multiple processes. - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCode" ) ); - ret = EMemSpyDriverChunkTypeCode; - } - else if ( type == EUserSelfModCode ) - { - // Dynamically create code chunk - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeCodeSelfModifiable" ) ); - ret = EMemSpyDriverChunkTypeCodeSelfModifiable; - } - else if ( IsHeapChunk( aChunk, name ) ) - { - // Catch kernel heap too - if ( type == EKernelData ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeapKernel" ) ); - ret = EMemSpyDriverChunkTypeHeapKernel; - } - else - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeHeap" ) ); - ret = EMemSpyDriverChunkTypeHeap; - } - } - else if ( type == EUserData && chunkAdaption.GetOwningProcess( aChunk ) == NULL ) - { - // Global shared chunks match this pattern. Of course, we could check the memory model mapping attributes - // as that would give us the info in a heartbeat, but it's too specific. - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeGlobal" ) ); - ret = EMemSpyDriverChunkTypeGlobal; - } - else if ( type == EUserData && chunkAdaption.GetOwner( aChunk ) != NULL && name.Length() > KMemSpyLitLocalObject().Length() && name.Left( KMemSpyLitLocalObject().Length() ) == KMemSpyLitLocalObject ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeLocal" ) ); - ret = EMemSpyDriverChunkTypeLocal; - } - else - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IdentifyChunkType() - EMemSpyDriverChunkTypeUnknown" ) ); - TRACE( PrintChunkInfo( aChunk ) ); - ret = EMemSpyDriverChunkTypeUnknown; - } - - return ret; - } - - -TBool DMemSpyDriverLogChanChunks::IsHeapChunk( DChunk& aChunk, const TName& aName ) - { - (void) aName; // UREL warning - const TUint rHeapVTable = MemSpyDevice().RHeapVTable(); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, aName: %S, [%O]", this, &aChunk, rHeapVTable, &aName, &aChunk ) ); - - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); - DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); - - // The first 4 bytes of every chunk correspond to the allocator VTable (For heap chunks). - // If it matches RHeap's vtable, we'll treat it as a heap. - TBool isHeap = EFalse; - - // There must be an owning process or else it's definitely not a heap chunk. - DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); - TUint8* base = chunkAdaption.GetBase( aChunk ); - const TInt size = chunkAdaption.GetSize( aChunk ); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - base: 0x%08x, size: %d, process: 0x%08x (%O)", base, size, process, process ) ); - - if ( process && size >= 4 ) - { - NKern::ThreadEnterCS(); - // Chunks are mapped into entire process so any thread within the process is enough... - DThread* firstThread = processAdaption.OpenFirstThread( *process ); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) ); - if ( firstThread != NULL ) - { - TBuf8<4> allocatorVTableBuffer; - TInt err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() ); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - read result of vtable data from requested thread is: %d", err )); - // - if ( err == KErrNone ) - { - TRACE( MemSpyDriverUtils::DataDump("possible chunk vtable data - %lS", allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength(), allocatorVTableBuffer.MaxLength() ) ); - allocatorVTableBuffer.SetLength( allocatorVTableBuffer.MaxLength() ); - - const TUint32 vtable = allocatorVTableBuffer[0] + - (allocatorVTableBuffer[1] << 8) + - (allocatorVTableBuffer[2] << 16) + - (allocatorVTableBuffer[3] << 24); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk - [possible] vTable within chunk is: 0x%08x", vtable) ); - - // Check the v-table to work out if it really is an RHeap - isHeap = ( vtable == rHeapVTable ); - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - isHeap: %d", isHeap ) ); - } - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - closing first thread..." ) ); - Kern::SafeClose( (DObject*&) firstThread, NULL ); - } - NKern::ThreadLeaveCS(); - } - - /* We only want RHeap's at the moment - if ( !isHeap && aName == KMemSpyLitDollarHeap ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - its called $HEAP, but its not an RHeap... we\'ll let it through though..." ) ); - isHeap = ETrue; - } - */ - - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) ); - return isHeap; - } - - -TBool DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess( DChunk& aChunk, DProcess& aProcess ) - { - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - START - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O)", this, &aChunk, &aChunk, &aProcess, &aProcess ) ); - TBool ret = EFalse; - // - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = OSAdaption().DChunk(); - DMemSpyDriverOSAdaptionDProcess& processAdaption = OSAdaption().DProcess(); - // - const TUint pid = processAdaption.GetId( aProcess ); - DProcess* process = chunkAdaption.GetOwningProcess( aChunk ); - if ( process ) - { - ret = ( pid == processAdaption.GetId( *process ) ); - } - else - { - DObject* owner = chunkAdaption.GetOwner( aChunk, EProcess ); - if ( owner ) - { - process = (DProcess*) owner; - ret = ( pid == processAdaption.GetId( *process ) ); - } - else - { - ret = ( pid == chunkAdaption.GetControllingOwnerId( aChunk ) ); - } - } - // - TRACE( Kern::Printf("DMemSpyDriverLogChanChunks::DoesChunkRelateToProcess() - END - this: 0x%08x, chunk: 0x%08x (%O), process: 0x%08x (%O), ret: %d", this, &aChunk, &aChunk, &aProcess, &aProcess, ret ) ); - return ret; - } -