diff -r 0ff24a8f6ca2 -r 98307c651589 memspy/Driver/Kernel/Source/MemSpyDriverInspectedProcess.cpp --- a/memspy/Driver/Kernel/Source/MemSpyDriverInspectedProcess.cpp Fri Aug 27 11:37:29 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1268 +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 "MemSpyDriverInspectedProcess.h" - -// System includes -#include -#include -#include - -#ifdef __MARM__ -#include "kdebug.h" -#endif //__MARM__ - -// User includes -#include "MemSpyDriverUtils.h" -#include "MemSpyDriverDevice.h" -#include "MemSpyDriverOSAdaption.h" -#include "MemSpyDriverInspectedProcessManager.h" - -// Constants -_LIT8( KMemSpyLitDollarHeap, "$HEAP" ); -_LIT8( KMemSpyLitDollarDllData, "DLL$DATA" ); -_LIT8( KMemSpyLitDollarDat, "$DAT" ); -_LIT( KMemSpyInspectedProcessMutexName, "MemSpyInspectedProcess_0x" ); - - -DMemSpyInspectedProcess::DMemSpyInspectedProcess( DMemSpyDriverDevice& aDevice ) -: iDevice( aDevice ) - { - } - - -DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - START - this: 0x%08x, %O", this, iProcess )); - EventMonitor().RequestEventsCancel( *this ); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling NotifyOnChangeCancel..." ) ); - NotifyOnChangeCancel(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling ResetTrackedList..." ) ); - ResetTrackedList(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - calling ResetPendingChanges..." ) ); - ResetPendingChanges(); - - if ( iLock ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closing mutex..." ) ); - iLock->Close(NULL); - } - - if ( iProcess ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closing process..." ) ); - Kern::SafeClose( (DObject*&) iProcess, NULL ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - closed process!" ) ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::~DMemSpyInspectedProcess() - END - this: 0x%08x", this ) ); - } - - -TInt DMemSpyInspectedProcess::Open( DProcess* aProcess ) - { - __ASSERT_CRITICAL; - TRACE( Kern::Printf("DMemSpyInspectedProcess::Open() - START - this: 0x%08x, aProcess: 0x%08x (%O)", this, aProcess, aProcess )); - - TInt error = KErrNone; - // - iProcess = aProcess; - error = iProcess->Open(); - // - if ( error == KErrNone ) - { - iProcessId = iDevice.OSAdaption().DProcess().GetId( *aProcess ); - - // Create mutex - TName name( KMemSpyInspectedProcessMutexName ); - name.AppendNumFixedWidth( (TUint) this, EHex, 8 ); - error = Kern::MutexCreate( iLock, name, KMutexOrdNone ); - // - if ( error == KErrNone ) - { - // Get size of all stacks (user & supervsior) for process. Also - // updates iUserThreadStackSize with the current size of just - // the user-side thread stacks. - iInfoCurrent.iMemoryStack = StackSize( *aProcess ); - - // Request events - EventMonitor().RequestEvents( *this ); - - // Find initial chunks that are mapped into process - FindChunks( *aProcess ); - - // Indicate that we have data waiting for client. This will - // cause the client's RS to be completed as soon as it - // registers with us... - UpdateStatistics(); - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::Open() - END - this: 0x%08x, error: %d", this, error )); - return error; - } - - - - - - - - -TInt DMemSpyInspectedProcess::NotifyOnChange( DThread* aThread, TRequestStatus* aRequestStatus, TMemSpyDriverProcessInspectionInfo* aInfo ) - { - Lock(); - - TInt err = KErrInUse; - const TBool notificationQueued = NotifyOnChangeQueued(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - START - this: 0x%08x, iAmDead: %d, aRequestStatus: 0x%08x, notificationQueued: %d, iChangeObserverThread: 0x%08x (%O)", this, iAmDead, aRequestStatus, notificationQueued, iChangeObserverThread, iChangeObserverThread ) ); - // - if ( notificationQueued == EFalse ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - Saving client RS..." ) ); - iChangeObserverThread = aThread; - iChangeObserverRS = aRequestStatus; - iChangeObserverInfo = aInfo; - - // Whilst we still have items in the buffer, we let the client drain them fully. - // However, if the process is now marked as dead and the buffer is exhausted, - // we indicate this via KErrDied completion which will cause the client to - // stop requesting any more changes. - if ( !iPendingChanges.IsEmpty() ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - Have buffered changes - SENDING TO CLIENT IMMEDIATELY..." ) ); - - // We have something in the pending buffer so we can - // give it back to the client immediately. - TMemSpyTrackedChunkChangeInfo* cachedChange = _LOFF( iPendingChanges.First(), TMemSpyTrackedChunkChangeInfo, iLink ); - cachedChange->iLink.Deque(); - - // Notify about change - CompleteClientsRequest( KErrNone, &cachedChange->iInfo ); - - // Discard cached entry - delete cachedChange; - } - else if ( iAmDead ) - { - // We must stop listening outside of an event monitor callback... - EventMonitor().RequestEventsCancel( *this ); - CompleteClientsRequest( KErrDied ); - } - // - err = KErrNone; - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChange() - END - this: 0x%08x, err: %d", this, err ) ); - - Unlock(); - return err; - } - - -TInt DMemSpyInspectedProcess::NotifyOnChangeCancel() - { - Lock(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeCancel() - START - this: 0x%08x, queued: %d, iChangeObserverThread: 0x%08x, iChangeObserverRS: 0x%08x", this, NotifyOnChangeQueued(), iChangeObserverThread, iChangeObserverRS ) ); - // - if ( NotifyOnChangeQueued() ) - { - TRACE( Kern::Printf( "DMemSpyInspectedProcess::NotifyOnChangeCancel() - this: 0x%08x, iChangeObserverRS: 0x%08x, iProcessId: %d (0x%04x)", this, iChangeObserverRS, iProcessId, iProcessId ) ); - Kern::RequestComplete( iChangeObserverThread, iChangeObserverRS, KErrCancel ); - iChangeObserverThread = NULL; - iChangeObserverRS = NULL; - iChangeObserverInfo = NULL; - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeCancel() - END - this: 0x%08x", this ) ); - Unlock(); - - return KErrNone; - } - - -TBool DMemSpyInspectedProcess::NotifyOnChangeQueued() const - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeQueued() - START - this: 0x%08x", this ) ); - // - Lock(); - const TBool queued = ( iChangeObserverRS != NULL ); - Unlock(); - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::NotifyOnChangeQueued() - END - this: 0x%08x, queued: %d", this, queued ) ); - return queued; - } - - - - - - - - - -void DMemSpyInspectedProcess::CompleteClientsRequest( TInt aCompletionCode, TMemSpyDriverProcessInspectionInfo* aInfo ) - { - const TBool notificationQueued = NotifyOnChangeQueued(); - TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - START - this: 0x%08x, iChangeObserverThread: 0x%08x, iChangeObserverRS: 0x%08x, iChangeObserverInfo: 0x%08x, notificationQueued: %d", this, iChangeObserverThread, iChangeObserverRS, iChangeObserverInfo, notificationQueued ) ); - TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - iAmDead: %d, buffer is empty: %d, aCompletionCode: %d, iProcessId: %d (0x%04x), aInfo: 0x%08x, iChangeDeliveryCounter: %d", iAmDead, iPendingChanges.IsEmpty(), aCompletionCode, iProcessId, iProcessId, aInfo, iChangeDeliveryCounter ) ); - - if ( notificationQueued ) - { - ++iChangeDeliveryCounter; - TInt completionCode = aCompletionCode; - - // Write them to client... - if ( aInfo != NULL ) - { - const TInt writeErr = Kern::ThreadRawWrite( iChangeObserverThread, iChangeObserverInfo, aInfo, sizeof(TMemSpyDriverProcessInspectionInfo) ); - if ( writeErr != KErrNone ) - { - completionCode = writeErr; - } - } - - // Complete client's async request - DThread* changeThread = iChangeObserverThread; - TRequestStatus* changeRS = iChangeObserverRS; - - // Zero these out first to avoid race condition - iChangeObserverThread = NULL; - iChangeObserverRS = NULL; - iChangeObserverInfo = NULL; - - // ...and then tell client. - TRACE( Kern::Printf( "DMemSpyInspectedProcess::CompleteClientsRequest() - SENDING CHANGE [%4d] TO CLIENT [err: %d]", iChangeDeliveryCounter, completionCode ) ); - Kern::RequestComplete( changeThread, changeRS, completionCode ); - } - else if ( aInfo ) - { - // Buffer the change for next time around... - TRACE( Kern::Printf("DMemSpyInspectedProcess::CompleteClientsRequest() - BUFFERING change event whilst client is AWOL...", this ) ); - NKern::ThreadEnterCS(); - - TMemSpyTrackedChunkChangeInfo* changeInfo = new TMemSpyTrackedChunkChangeInfo(); - if ( changeInfo ) - { - changeInfo->iInfo = *aInfo; - iPendingChanges.Add( &changeInfo->iLink ); - } - // - NKern::ThreadLeaveCS(); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::CompleteClientsRequest() - END - this: 0x%08x", this ) ); - } - - - - - - - - - - - - -void DMemSpyInspectedProcess::ResetTrackedList() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetTrackedList() - START - this: 0x%08x", this ) ); - NKern::ThreadEnterCS(); - // - SDblQueLink* link = iTrackedChunks.GetFirst(); - while( link ) - { - TMemSpyTrackedChunk* object = _LOFF( link, TMemSpyTrackedChunk, iLink ); - delete object; - link = iTrackedChunks.GetFirst(); - } - // - NKern::ThreadLeaveCS(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetTrackedList() - END - this: 0x%08x", this ) ); - } - - -void DMemSpyInspectedProcess::SetTrackedListUnused() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnused() - START - this: 0x%08x", this ) ); - SDblQueLink* anchor = &iTrackedChunks.iA; - for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext) - { - TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink ); - trackedChunk->SetUnused( ETrue ); - } - TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnused() - END - this: 0x%08x", this ) ); - } - - -void DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::TType aType, TBool aUnusedStatus ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType() - START - this: 0x%08x", this ) ); - SDblQueLink* anchor = &iTrackedChunks.iA; - for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext) - { - TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink ); - if ( trackedChunk->Type() == aType ) - { - trackedChunk->SetUnused( aUnusedStatus ); - } - } - TRACE( Kern::Printf("DMemSpyInspectedProcess::SetTrackedListUnusedStatusByType() - END - this: 0x%08x", this ) ); - } - - -void DMemSpyInspectedProcess::DiscardUnusedTrackListItems() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::DiscardUnusedTrackListItems() - START - this: 0x%08x", this ) ); - NKern::ThreadEnterCS(); - const SDblQueLink* const anchor = &iTrackedChunks.iA; - // - SDblQueLink* link = iTrackedChunks.First(); - while( link && link != anchor ) - { - TMemSpyTrackedChunk* trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink ); - const TBool unused = trackedChunk->iUnused; - // - link = link->iNext; - // - if ( unused ) - { - trackedChunk->iLink.Deque(); - delete trackedChunk; - } - else - { - trackedChunk->SetUnused( EFalse ); - } - } - // - NKern::ThreadLeaveCS(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::DiscardUnusedTrackListItems() - END - this: 0x%08x", this ) ); - } - - -void DMemSpyInspectedProcess::AddTrackedChunk( DChunk* aChunk, TMemSpyTrackedChunk::TType aType ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::AddTrackedChunk() - START - this: 0x%08x, aChunk: 0x%08x (%O)", this, aChunk, aChunk ) ); - NKern::ThreadEnterCS(); - // - TMemSpyTrackedChunk* wrapper = new TMemSpyTrackedChunk( aChunk, aType ); - if ( wrapper ) - { - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk(); - const TInt cSize = chunkAdaption.GetSize( *aChunk ); - wrapper->SetSize( cSize ); - iTrackedChunks.Add( &wrapper->iLink ); - } - // - NKern::ThreadLeaveCS(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::AddTrackedChunk() - END - this: 0x%08x", this ) ); - } - - -TMemSpyTrackedChunk* DMemSpyInspectedProcess::TrackedChunkByHandle( TAny* aHandle ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::TrackedChunkByHandle() - START - this: 0x%08x", this ) ); - TMemSpyTrackedChunk* ret = NULL; - // - const SDblQueLink* const anchor = &iTrackedChunks.iA; - for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext) - { - TMemSpyTrackedChunk* const trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink ); - - if ( trackedChunk && trackedChunk->Handle() == aHandle ) - { - ret = trackedChunk; - break; - } - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::TrackedChunkByHandle() - END - this: 0x%08x, entry: 0x%08x (%O)", this, ret, ret ? ret->iChunk : NULL ) ); - return ret; - } - - - - - - - - - - - -DMemSpyInspectedProcessManager& DMemSpyInspectedProcess::PManager() - { - return iDevice.ProcessInspectionManager(); - } - - -DMemSpyEventMonitor& DMemSpyInspectedProcess::EventMonitor() - { - return iDevice.EventMonitor(); - } - - - - - - - -TUint DMemSpyInspectedProcess::EMTypeMask() const - { - TUint ret = EMemSpyEventThreadAdd | EMemSpyEventThreadRemove | EMemSpyEventThreadKill | - EMemSpyEventProcessUpdate | EMemSpyEventProcessRemove | - EMemSpyEventChunkAdd | EMemSpyEventChunkUpdate | EMemSpyEventChunkDelete; - - if ( iAmDead ) - { - // Not interested anymore... - ret = 0; - } - - return ret; - } - - -void DMemSpyInspectedProcess::EMHandleProcessUpdated( DProcess& aProcess ) - { - const TUint procId = iDevice.OSAdaption().DProcess().GetId( aProcess ); - if ( procId == iProcessId ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessUpdated() - START - this: 0x%08x, iProcess: 0x%08x (%O)", this, iProcess, iProcess ) ); - - // Mark all tracked chunks as dirty whilst we work out - // what is and isn't mapped into the process - SetTrackedListUnused(); - SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkGlobalData, EFalse /* global data chunks are still in use */ ); - - // Locate any suitable chunks, tagging existing entries as - // 'in use' so that we can easily spot ones which are no longer - // mapped into the process. - FindChunks( *iProcess ); - - // Throw away and tracked chunks which aren't mapped into the - // process anymore. - DiscardUnusedTrackListItems(); - - // Calculate latest statistics... - const TBool changeDetected = UpdateStatistics(); - if ( changeDetected ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessUpdated() - END - this: 0x%08x", this ) ); - - Unlock(); - } - } - - -void DMemSpyInspectedProcess::EMHandleProcessRemoved( DProcess& aProcess ) - { - DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess(); - const TUint pid = dProcessAdaption.GetId( aProcess ); - - if ( pid == iProcessId ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessRemoved() - START - this: 0x%08x", this ) ); - - // We will implement a multi phased approach to the process being removed. - // - // The first notification we will send will show that the process heap and - // local chunks have been removed, leaving shared chunk sizes intact. - // - // We will then send another change, this time setting everything to zero... - SetTrackedListUnused(); - SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkShared, EFalse /* shared chunks are still in use */ ); - SetTrackedListUnusedStatusByType( TMemSpyTrackedChunk::ETypeChunkGlobalData, EFalse /* global data chunks are still in use */ ); - DiscardUnusedTrackListItems(); - const TBool changeDetected1 = UpdateStatistics(); - if ( changeDetected1 ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - - // Now repeat the exercise, this time removing everything. - ResetTrackedList(); - - // ... including stack - iInfoCurrent.iMemoryStack = 0; - - const TBool changeDetected2 = UpdateStatistics(); - if ( changeDetected2 ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - - // Stop listening to events since we've drained everything now... - iAmDead = ETrue; - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleProcessRemoved() - END - this: 0x%08x", this ) ); - - Unlock(); - } - } - - -void DMemSpyInspectedProcess::EMHandleThreadAdd( DThread& aThread ) - { - DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread(); - DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess(); - // - DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadAdd() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) ); - if ( owningProcess ) - { - const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess ); - const TUint myId = dProcessAdaption.GetId( *iProcess ); - // - if ( myId == owningProcessId ) - { - EMHandleThreadChanged( aThread ); - } - } - } - - -void DMemSpyInspectedProcess::EMHandleThreadRemoved( DThread& aThread ) - { - DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread(); - DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess(); - // - DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadRemoved() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) ); - if ( owningProcess ) - { - const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess ); - const TUint myId = dProcessAdaption.GetId( *iProcess ); - // - if ( myId == owningProcessId ) - { - EMHandleThreadChanged( aThread ); - } - } - } - - -void DMemSpyInspectedProcess::EMHandleThreadKilled( DThread& aThread ) - { - // - DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread(); - DMemSpyDriverOSAdaptionDProcess& dProcessAdaption = iDevice.OSAdaption().DProcess(); - // - DProcess* owningProcess = dThreadAdaption.GetOwningProcess( aThread ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadKilled() - this: 0x%08x, aThread: 0x%08x, owningProcess: 0x%08x", this, &aThread, owningProcess ) ); - if ( owningProcess ) - { - const TUint owningProcessId = dProcessAdaption.GetId( *owningProcess ); - const TUint myId = dProcessAdaption.GetId( *iProcess ); - // - if ( myId == owningProcessId ) - { - EMHandleThreadChanged( aThread ); - } - } - } - - -void DMemSpyInspectedProcess::EMHandleThreadChanged( DThread& /*aThread*/ ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadChanged() - START - this: 0x%08x", this ) ); - - // This is called when a thread is added, changed, or terminated/killed. - // We must be careful to only access the members of aThread that still - // exist as if it is being destroyed, the object may be in an intermediate - // state. - - // All we are really interested in is recalculating the stack usage - // for the process... - iInfoCurrent.iMemoryStack = StackSize( *iProcess ); - - // Always inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleThreadChanged() - END - this: 0x%08x", this ) ); - - Unlock(); - } - - -void DMemSpyInspectedProcess::EMHandleChunkAdd( DChunk& aChunk ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - START - this: 0x%08x, aChunk: 0x%08x (%O)", this, &aChunk, &aChunk ) ); - - // Is this chunk related to our process somehow? - if ( IsChunkRelevantToOurProcess( aChunk ) ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - processes match, checking chunk type..." ) ); - - const TMemSpyTrackedChunk::TType type = ChunkType( &aChunk ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - chunkType: %d", type ) ); - - if ( type != TMemSpyTrackedChunk::ETypeNotRelevant ) - { - // It's a new entry in our process - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - this: 0x%08x, creating new entry for chunk: 0x%08x", this, &aChunk ) ); - - AddTrackedChunk( &aChunk, type ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - added chunk..." )); - - const TBool changeDetected = UpdateStatistics(); - if ( changeDetected ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - } - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkAdd() - END - this: 0x%08x", this ) ); - - Unlock(); - } - - -void DMemSpyInspectedProcess::EMHandleChunkUpdated( DChunk& aChunk ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - START - this: 0x%08x, aChunk: 0x%08x [S: %8d] (%O)", this, &aChunk, aChunk.Size(), &aChunk ) ); - - // Is this chunk mapped into our process? - TMemSpyTrackedChunk* trackedEntry = TrackedChunkByHandle( &aChunk ); - if ( trackedEntry != NULL ) - { - const TInt oldSize = trackedEntry->Size(); - const TInt newSize = iDevice.OSAdaption().DChunk().GetSize( aChunk ); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - was tracked entry [0x%08x, size; %10d, type: %d] vs new size: %d", trackedEntry, oldSize, trackedEntry->Type(), newSize ) ); - - // If the existing entry had a size of 0 and the new size is non-zero - // then we may have enough data such that we can validate type information. - // For example, any secondary heap chunk that is created within the process will - // most likely have a Local-NNNNNN style name, and this chunk will be created with - // an initial size of zero. - // - // We can only identify it's type once the chunk has been updated with some data - // that supports vTable verification. Hence the type may fluctuate... - if ( oldSize == 0 && newSize > 0 ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - checking type again as chunk size was zero..." ) ); - - PrintChunkInfo( aChunk ); - const TMemSpyTrackedChunk::TType type = ChunkType( &aChunk ); - if ( type != trackedEntry->Type() ) - { - // Type has changed - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - type has transitioned from: %d to %d", trackedEntry->Type(), type ) ); - trackedEntry->SetType( type ); - } - } - - // Update our record with new chunk size - trackedEntry->SetSize( newSize ); - - const TBool changeDetected = UpdateStatistics(); - if ( changeDetected ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkUpdated() - END - this: 0x%08x", this ) ); - - Unlock(); - } - - -void DMemSpyInspectedProcess::EMHandleChunkDeleted( DChunk& aChunk ) - { - Lock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkDeleted() - START - this: 0x%08x", this ) ); - - // Is this chunk mapped into our process? - TMemSpyTrackedChunk* trackedEntry = TrackedChunkByHandle( &aChunk ); - if ( trackedEntry != NULL ) - { - // Delete entry - trackedEntry->iLink.Deque(); - delete trackedEntry; - - const TBool changeDetected = UpdateStatistics(); - if ( changeDetected ) - { - // Inform observer about new results. - CompleteClientsRequest( KErrNone, &iInfoCurrent ); - } - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::EMHandleChunkDeleted() - END - this: 0x%08x", this ) ); - - Unlock(); - } - - -void DMemSpyInspectedProcess::PrintChunkInfo( DChunk& aChunk ) const - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::PrintChunkInfo() - iProcess*: 0x%08x", iProcess ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::PrintChunkInfo() - iProcess id: 0x%04x", iProcessId ) ); - MemSpyDriverUtils::PrintChunkInfo( aChunk, iDevice.OSAdaption() ); - } - - -TBool DMemSpyInspectedProcess::IsChunkRelevantToOurProcess( DChunk& aChunk ) const - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - START - this: 0x%08x, iProcess: 0x%08x (%4d), aChunk: 0x%08x (%O)", this, iProcess, iProcessId, &aChunk, &aChunk) ); - - TBool relevant = EFalse; - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk(); - // - PrintChunkInfo( aChunk ); - // - DProcess* chunkProc = chunkAdaption.GetOwningProcess( aChunk ); - if ( chunkProc ) - { - const TUint procId = iDevice.OSAdaption().DProcess().GetId( *chunkProc ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Owning Process] Comparing chunk pid: 0x%04x with procPid: 0x%04x", this, procId, iProcessId ) ); - relevant = ( procId == iProcessId ); - } - else if ( chunkAdaption.GetOwner( aChunk ) == iProcess ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Owner Match]" ) ); - relevant = ETrue; - } - else - { - const TUint controllingOwnerPid = chunkAdaption.GetControllingOwnerId( aChunk ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - [Controlling Owner] Comparing chunk owner: 0x%04x with procPid: 0x%04x", this, controllingOwnerPid, iProcessId ) ); - relevant = ( controllingOwnerPid == iProcessId ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsChunkRelevantToOurProcess() - END - this: 0x%08x, relevant: %d", this, relevant ) ); - return relevant; - } - - -TMemSpyTrackedChunk::TType DMemSpyInspectedProcess::ChunkType( DObject* aObject ) const - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - START - this: 0x%08x, iProcess: 0x%08x, aObject: 0x%08x (%O)", this, iProcess, aObject, aObject ) ); - TMemSpyTrackedChunk::TType ret = TMemSpyTrackedChunk::ETypeNotRelevant; - - // Firstly, check if it's actually held within the chunk container. - if ( aObject ) - { - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk(); - const TObjectType objectType = chunkAdaption.GetObjectType( *aObject ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - objectType: %d vs EChunk (%d)", objectType, EChunk ) ); - - if ( objectType == EChunk ) - { - DChunk* chunk = (DChunk*) aObject; - // - if ( IsChunkRelevantToOurProcess( *chunk ) ) - { - TName name; - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - getting chunk name..." ) ); - chunk->Name( name ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - name: %S", &name ) ); - - // It is definitely owned by this process. That means that - // it could be a heap, or then it's a just some other kind - // of data chunk which our process happens to have created. - // - // The main thread within a process results in the creation - // of a heap called $HEAP, but that isn't the case for other - // secondary (etc) threads. - // - // Only way I can think to identify these is via vTables. - if ( name == KMemSpyLitDollarDllData ) - { - // This chunk contains Dll Global Data for the process - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkGlobalData" ) ); - ret = TMemSpyTrackedChunk::ETypeChunkGlobalData; - } - else if ( name == KMemSpyLitDollarDat ) - { - // This chunk contains process global data as well as user-side stacks for - // the process. However, we calculate the stacks independently, so we must - // adjust this later on to remove stack overhead. - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack" ) ); - ret = TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack; - } - else if ( IsHeapChunk( *chunk, name ) ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkHeap" ) ); - ret = TMemSpyTrackedChunk::ETypeChunkHeap; - } - else - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkLocal" ) ); - ret = TMemSpyTrackedChunk::ETypeChunkLocal; - } - } - else - { - // It's a chunk that is mapped into our process, - // but isn't owned by us. Therefore it is shared by some - // other process. - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - TMemSpyTrackedChunk::ETypeChunkShared" ) ); - ret = TMemSpyTrackedChunk::ETypeChunkShared; - } - } - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::ChunkType() - END - this: 0x%08x, ret: %d", this, ret ) ); - return ret; - } - - -TBool DMemSpyInspectedProcess::IsHeapChunk( DChunk& aChunk, const TName& aName ) const - { - const TUint rHeapVTable = iDevice.RHeapVTable(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - START - this: 0x%08x, aChunk: 0x%08x, RHeapVTable: 0x%08x, iProcess: 0x%08x, aName: %S, (%O)", this, &aChunk, rHeapVTable, iProcess, &aName, &aChunk ) ); - - // 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; - - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk(); - TUint8* base = chunkAdaption.GetBase( aChunk ); - const TInt size = chunkAdaption.GetSize( aChunk ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - base: 0x%08x, size: %d", base, size ) ); - - if ( iProcess && size >= 4 ) - { - // Chunks are mapped into entire process so any thread within the process is enough... - DThread* firstThread = iProcess->FirstThread(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - firstThread: 0x%08x (%O)", firstThread, firstThread ) ); - if ( firstThread != NULL ) - { - NKern::ThreadEnterCS(); - TInt err = firstThread->Open(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - firstThread open result: %d", err ) ); - - if ( err == KErrNone ) - { - TBuf8<4> allocatorVTableBuffer; - err = Kern::ThreadRawRead( firstThread, base, (TUint8*) allocatorVTableBuffer.Ptr(), allocatorVTableBuffer.MaxLength() ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::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("DMemSpyInspectedProcess::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("DMemSpyInspectedProcess::IsHeapChunk() - isHeap: %d", isHeap ) ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - closing first thread..." ) ); - Kern::SafeClose( (DObject*&) firstThread, NULL ); - } - NKern::ThreadLeaveCS(); - } - } - // - if ( !isHeap && aName == KMemSpyLitDollarHeap ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - is standard Symbian OS initial heap chunk - $HEAP" ) ); - isHeap = ETrue; - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::IsHeapChunk() - END - this: 0x%08x, isHeap: %d", this, isHeap ) ); - return isHeap; - } - - -TUint32 DMemSpyInspectedProcess::TotalStatistics( const TMemSpyDriverProcessInspectionInfo& aStats, TBool aIncludeShared ) - { - TUint32 total = aStats.iMemoryStack + - aStats.iMemoryHeap + - aStats.iMemoryChunkLocal + - aStats.iMemoryGlobalData; - // - if ( aIncludeShared ) - { - total += aStats.iMemoryChunkShared; - } - // - return total; - } - - -TBool DMemSpyInspectedProcess::IsEqual( const TMemSpyDriverProcessInspectionInfo& aLeft, const TMemSpyDriverProcessInspectionInfo& aRight ) - { - const TBool equal = ( aLeft.iMemoryStack == aRight.iMemoryStack && - aLeft.iMemoryHeap == aRight.iMemoryHeap && - aLeft.iMemoryChunkLocal == aRight.iMemoryChunkLocal && - aLeft.iMemoryChunkShared == aRight.iMemoryChunkShared && - aLeft.iMemoryGlobalData == aRight.iMemoryGlobalData - ); - return equal; - } - - -void DMemSpyInspectedProcess::ResetStatistics( TMemSpyDriverProcessInspectionInfo& aStats ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetStatistics() - START - this: 0x%08x", this ) ); - aStats.iProcessId = iProcessId; - aStats.iMemoryHeap = 0; - aStats.iMemoryChunkLocal = 0; - aStats.iMemoryChunkShared = 0; - aStats.iMemoryGlobalData = 0; - aStats.iTime = Kern::SystemTime(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetStatistics() - END - this: 0x%08x", this ) ); - } - - -TBool DMemSpyInspectedProcess::UpdateStatistics() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - START - this: 0x%08x, iChangeDeliveryCounter: %04d, iProcess: 0x%08x %O", this, iChangeDeliveryCounter, iProcess, iProcess ) ); - - // Preserve last stats so we can identify if something really changed... - iInfoLast = iInfoCurrent; - - // Reset current stats ready for updating. This doesn't wipe the stack field, since - // that only changes when some kind of thread event occurs... - ResetStatistics( iInfoCurrent ); - - // Go through all tracked chunks and update our stats based upon - // their current values... - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() CHUNK ENTRIES:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - const SDblQueLink* const anchor = &iTrackedChunks.iA; - for (SDblQueLink* link = iTrackedChunks.First(); link != anchor; link = link->iNext) - { - TMemSpyTrackedChunk* const trackedChunk = _LOFF( link, TMemSpyTrackedChunk, iLink ); - // - switch( trackedChunk->Type() ) - { - case TMemSpyTrackedChunk::ETypeChunkHeap: - iInfoCurrent.iMemoryHeap += trackedChunk->Size(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkHeap - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) ); - break; - case TMemSpyTrackedChunk::ETypeChunkLocal: - iInfoCurrent.iMemoryChunkLocal += trackedChunk->Size(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkLocal - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) ); - break; - case TMemSpyTrackedChunk::ETypeChunkShared: - iInfoCurrent.iMemoryChunkShared += trackedChunk->Size(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkShared - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) ); - break; - case TMemSpyTrackedChunk::ETypeChunkGlobalData: - iInfoCurrent.iMemoryGlobalData += trackedChunk->Size(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - [0x%08x] TMemSpyTrackedChunk::ETypeChunkGlobalData - %12d (0x%08x, %O)", trackedChunk, trackedChunk->Size(), trackedChunk->iChunk, trackedChunk->iChunk ) ); - break; - case TMemSpyTrackedChunk::ETypeChunkProcessGlobalDataAndUserStack: - break; - - default: - case TMemSpyTrackedChunk::ETypeNotRelevant: - break; - } - } - - const TUint32 totalLastIncShared = TotalStatistics( iInfoLast ); - const TUint32 totalLastExcShared = TotalStatistics( iInfoLast, EFalse ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() LAST:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryStack: %12d", iInfoLast.iMemoryStack ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryHeap: %12d", iInfoLast.iMemoryHeap ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryChunkLocal: %12d", iInfoLast.iMemoryChunkLocal ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryChunkShared: %12d", iInfoLast.iMemoryChunkShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast.iMemoryGlobalData: %12d", iInfoLast.iMemoryGlobalData ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - --------------------------------------------------------------------------" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoLast total: %12d / %12d", totalLastIncShared, totalLastExcShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - - - const TUint32 totalCurrentIncShared = TotalStatistics( iInfoCurrent ); - const TUint32 totalCurrentExcShared = TotalStatistics( iInfoCurrent, EFalse ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() CURRENT:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryStack: %12d", iInfoCurrent.iMemoryStack ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryHeap: %12d", iInfoCurrent.iMemoryHeap ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryChunkLocal: %12d", iInfoCurrent.iMemoryChunkLocal ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryChunkShared: %12d", iInfoCurrent.iMemoryChunkShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent.iMemoryGlobalData: %12d", iInfoCurrent.iMemoryGlobalData ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - --------------------------------------------------------------------------" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoCurrent total: %12d / %12d", totalCurrentIncShared, totalCurrentExcShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - - // Update peaks, i.e. how large each individual element reached - const TUint32 totalPeaks = TotalStatistics( iInfoPeaks ); - iInfoPeaks.iMemoryStack = Max( iInfoPeaks.iMemoryStack, iInfoCurrent.iMemoryStack ); - iInfoPeaks.iMemoryHeap = Max( iInfoPeaks.iMemoryHeap, iInfoCurrent.iMemoryHeap ); - iInfoPeaks.iMemoryChunkLocal = Max( iInfoPeaks.iMemoryChunkLocal, iInfoCurrent.iMemoryChunkLocal ); - iInfoPeaks.iMemoryChunkShared = Max( iInfoPeaks.iMemoryChunkShared, iInfoCurrent.iMemoryChunkShared ); - iInfoPeaks.iMemoryGlobalData = Max( iInfoPeaks.iMemoryGlobalData, iInfoCurrent.iMemoryGlobalData ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() PEAK:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryStack: %12d", iInfoPeaks.iMemoryStack ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryHeap: %12d", iInfoPeaks.iMemoryHeap ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryChunkLocal: %12d", iInfoPeaks.iMemoryChunkLocal ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryChunkShared: %12d", iInfoPeaks.iMemoryChunkShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks.iMemoryGlobalData: %12d", iInfoPeaks.iMemoryGlobalData ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoPeaks total: %12d", totalPeaks ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - - // Update HWM, i.e. the largest total so far. - const TUint32 totalHWMIncShared = TotalStatistics( iInfoHWMIncShared ); - const TUint32 totalHWMExcShared = TotalStatistics( iInfoHWMIncShared, EFalse ); - if ( totalCurrentIncShared > totalHWMIncShared ) - { - iInfoHWMIncShared = iInfoCurrent; - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() HWM INC SHARED:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryStack: %12d", iInfoHWMIncShared.iMemoryStack ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryHeap: %12d", iInfoHWMIncShared.iMemoryHeap ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryChunkLocal: %12d", iInfoHWMIncShared.iMemoryChunkLocal ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryChunkShared: %12d", iInfoHWMIncShared.iMemoryChunkShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared.iMemoryGlobalData: %12d", iInfoHWMIncShared.iMemoryGlobalData ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMIncShared total: %12d", totalHWMIncShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - } - if ( totalCurrentExcShared > totalHWMExcShared ) - { - iInfoHWMExcShared = iInfoCurrent; - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() HWM EXC SHARED:" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryStack: %12d", iInfoHWMExcShared.iMemoryStack ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryHeap: %12d", iInfoHWMExcShared.iMemoryHeap ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryChunkLocal: %12d", iInfoHWMExcShared.iMemoryChunkLocal ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryChunkShared: %12d", iInfoHWMExcShared.iMemoryChunkShared ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared.iMemoryGlobalData: %12d", iInfoHWMExcShared.iMemoryGlobalData ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - -----------------------------------------------------" ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - iInfoHWMExcShared total: %12d", totalHWMExcShared ) ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() " ) ); - - // Work out if something changed... - const TBool statsChanged = !IsEqual( iInfoLast, iInfoCurrent ); - if ( statsChanged ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - STATS CHANGED!" ) ); - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::UpdateStatistics() - END - this: 0x%08x, statsChanged: %d, iChangeDeliveryCounter: %04d, iProcess: 0x%08x %O", this, statsChanged, iChangeDeliveryCounter, iProcess, iProcess ) ); - return statsChanged; - } - - -void DMemSpyInspectedProcess::FindChunks( DProcess& aProcess ) - { - __ASSERT_CRITICAL; - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - START - this: 0x%08x", this ) ); - - DMemSpyDriverOSAdaptionDChunk& chunkAdaption = iDevice.OSAdaption().DChunk(); - DMemSpyDriverOSAdaptionDProcess& processAdaption = iDevice.OSAdaption().DProcess(); - - // Iterate through each handle in the process - if ( processAdaption.IsHandleIndexValid( aProcess ) ) - { - MemSpyObjectIx* processHandles = processAdaption.GetHandles( aProcess ); - - MemSpyObjectIx_HandleLookupLock(); - const TInt count = processHandles->Count(); - MemSpyObjectIx_HandleLookupUnlock(); - - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - got: %d handles...", count ) ); - - for( TInt i=0; i= processHandles->Count()) break; // Count may have changed in the meantime - DObject* object = (*processHandles)[ i ]; - if (object && object->Open() != KErrNone) object = NULL; - MemSpyObjectIx_HandleLookupUnlock(); - - const TObjectType objectType = ( object ? chunkAdaption.GetObjectType( *object ) : EObjectTypeAny ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - object: 0x%08x, type: %2d (%O)", object, objectType, object ) ); - - // Is it a chunk that is already mapped into our process? - // See if we're already aware of this chunk... - if ( object != NULL && objectType == EChunk ) - { - TMemSpyTrackedChunk* existingEntry = TrackedChunkByHandle( object ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - found a chunk, existing lookup entry: 0x%08x", existingEntry ) ); - - if ( existingEntry != NULL ) - { - const TInt cSize = chunkAdaption.GetSize( *existingEntry->iChunk ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - setting existing entry size to: %d", cSize ) ); - - // It must be a chunk then... Update size - existingEntry->SetSize( cSize ); - - // This item is in use, i.e. it is not unused - existingEntry->SetUnused( EFalse ); - } - else - { - DChunk* chunk = (DChunk*) object; - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - chunk not known, checking type..." ) ); - - // We have no record of this item so far. Is it really a chunk? - const TMemSpyTrackedChunk::TType type = ChunkType( object ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - type is: %d", type ) ); - - if ( type != TMemSpyTrackedChunk::ETypeNotRelevant ) - { - // It's a new entry - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - this: 0x%08x, creating new entry for chunk: 0x%08x", this, chunk ) ); - - AddTrackedChunk( chunk, type ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - added chunk..." )); - } - } - } - if (object) object->Close(NULL); - } - } - - TRACE( Kern::Printf("DMemSpyInspectedProcess::FindChunks() - END - this: 0x%08x", this ) ); - } - - -TInt DMemSpyInspectedProcess::StackSize( DProcess& aProcess ) - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - START - this: 0x%08x", this ) ); - TInt ret = 0; - // - DMemSpyDriverOSAdaptionDThread& dThreadAdaption = iDevice.OSAdaption().DThread(); - - iUserThreadStackSize = 0; - // - SDblQueLink* pLink = aProcess.iThreadQ.First(); - while(pLink != &aProcess.iThreadQ.iA) - { - DThread* pT = _LOFF( pLink, DThread, iProcessLink ); - // - const TUint32 userStackSize = dThreadAdaption.GetUserStackSize( *pT ); - const TUint32 suprStackSize = dThreadAdaption.GetSupervisorStackSize( *pT ); - TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - thread: 0x%08x, userStack: %8d, suprStack: %8d, total: %8d %O", pT, userStackSize, suprStackSize, userStackSize + suprStackSize, pT )); - // - iUserThreadStackSize += userStackSize; - ret += userStackSize + suprStackSize; - // - pLink = pLink->iNext; - } - // - TRACE( Kern::Printf("DMemSpyInspectedProcess::StackSize() - END - this: 0x%08x, total stack size for process: %8d, iUserThreadStackSize: %8d", this, ret, iUserThreadStackSize ) ); - return ret; - } - - -void DMemSpyInspectedProcess::ResetPendingChanges() - { - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetPendingChanges() - START - this: 0x%08x", this ) ); - NKern::ThreadEnterCS(); - // - SDblQueLink* link = iPendingChanges.GetFirst(); - while( link ) - { - TMemSpyTrackedChunkChangeInfo* cachedChange = _LOFF( link, TMemSpyTrackedChunkChangeInfo, iLink ); - delete cachedChange; - link = iPendingChanges.GetFirst(); - } - // - NKern::ThreadLeaveCS(); - TRACE( Kern::Printf("DMemSpyInspectedProcess::ResetPendingChanges() - END - this: 0x%08x", this ) ); - } - - -void DMemSpyInspectedProcess::Lock() const - { - NKern::ThreadEnterCS(); - Kern::MutexWait(*iLock); - } - -void DMemSpyInspectedProcess::Unlock() const - { - Kern::MutexSignal(*iLock); - NKern::ThreadLeaveCS(); - } - - - - - - - - - - -TMemSpyTrackedChunk::TMemSpyTrackedChunk( DChunk* aChunk, TType aType ) -: iChunk( aChunk ), iType( aType ), iSize( 0 ), iUnused( EFalse ) - { - } - - -void TMemSpyTrackedChunk::SetSize( TInt aSize ) - { - iSize = aSize; - } - - -void TMemSpyTrackedChunk::SetUnused( TBool aUnused ) - { - iUnused = aUnused; - } -