--- 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 <memspy/driver/memspydriverobjectsshared.h>
-
-// 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<processHandleCount && r == KErrNone && currentWriteIndex < maxCount; processHandleIndex++ )
- {
- // Get a handle from the process container...
- MemSpyObjectIx_HandleLookupLock();
- if (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; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
- {
- DChunk* chunk= (DChunk*) (*container)[ i ];
- //
- const TBool isRelated = DoesChunkRelateToProcess( *chunk, TempObjectAsProcess() );
- if ( isRelated )
- {
- r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
- if ( r == KErrNone )
- {
- ++currentWriteIndex;
- }
- }
- }
- //
- container->Signal();
- 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; i<count && r == KErrNone && currentWriteIndex < maxCount; i++ )
- {
- DChunk* chunk= (DChunk*) (*container)[ i ];
- //
- r = Kern::ThreadRawWrite( &ClientThread(), params.iHandles + currentWriteIndex, &chunk, sizeof(TAny*) );
- if (r == KErrNone)
- {
- ++currentWriteIndex;
- }
- }
- //
- container->Signal();
- 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; i<count; i++)
- {
- DChunk* chunk = (DChunk*) (*container)[i];
- if ( chunk == params.iHandle )
- {
- foundChunk = chunk;
- TRACE( PrintChunkInfo( *chunk ) );
- r = foundChunk->Open();
- 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;
- }
-