/*
* 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 <memspy/driver/memspydriverclient.h>
// System includes
#include <e32svr.h>
// User includes
#include "MemSpyDriverOpCodes.h"
#include <memspy/driver/memspydriverconstants.h>
#include <memspy/driver/memspydriverobjectsshared.h>
#include "MemSpyDriverStreamReaderImp.h"
#include "MemSpyDriverObjectsInternal.h"
#include "heaputils.h"
// Constants
const TInt KMemSpyClientBufferGrowSize = 0x1000 * 8; // 32kb
// Forward declarations
static void PrintHeapInfo( const TMemSpyHeapInfo& aInfo );
EXPORT_C TInt RMemSpyDriverClient::Open()
{
TInt err = iBuffer.Create( KMemSpyClientBufferGrowSize );
if ( err == KErrNone )
{
err = User::LoadLogicalDevice( KMemSpyDriverDeviceName );
if ( err == KErrNone || err == KErrAlreadyExists )
{
err = DoCreate( KMemSpyDriverDeviceName, KMemSpyDriverVersion(), KNullUnit, NULL, NULL, EOwnerThread );
if ( err == KErrNone )
{
TUint heapVTable = RHeapVTable();
err = DoControl( EMemSpyDriverOpCodeMiscSetRHeapVTable, (TAny*) heapVTable );
}
}
}
//
if ( err != KErrNone )
{
RDebug::Printf( "[MemSpy] RMemSpyDriverClient::Open() - END - err: %d", err );
}
//
return err;
}
EXPORT_C void RMemSpyDriverClient::Close()
{
RBusLogicalChannel::Close();
const TInt err = User::FreeLogicalDevice( KMemSpyDriverDeviceName );
//
if ( err != KErrNone )
{
RDebug::Printf( "[MemSpy] RMemSpyDriverClient::Close() - free logical device error: %d", err );
}
//
iBuffer.Close();
(void) err;
}
EXPORT_C void RMemSpyDriverClient::GetVersion( TVersion& aVersion )
{
TVersion v = KMemSpyDriverVersion();
Mem::Copy( (TAny*)&aVersion, (TAny*)&v, sizeof( TVersion ) );
}
EXPORT_C TInt RMemSpyDriverClient::ReadMemory( TUint aTid, TLinAddr aSrc, TDes8& aDest )
{
TMemSpyDriverInternalReadMemParams params;
params.iTid = aTid;
params.iAddr = aSrc;
params.iDes = &aDest;
aDest.Zero();
//
TInt r = DoControl( EMemSpyDriverOpCodeRawMemoryRead, ¶ms, NULL );
if ( r >= KErrNone )
{
aDest.SetLength( r );
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetCodeSegs( TAny** aHandleArray, TInt& aHandleCount, TBool aOnlyRamLoaded )
{
TMemSpyDriverInternalCodeSnapshotParams params;
params.iFilter = aOnlyRamLoaded;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeCodeSegsGetAll, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetCodeSegs( TUint aPid, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalCodeSnapshotParams params;
params.iFilter = aPid;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeCodeSegsGetCodeSegsForProcess, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetCodeSegInfo( TAny* aHandle, TUint aPid, TMemSpyDriverCodeSegInfo& aInfo )
{
TMemSpyDriverInternalCodeSegParams params;
params.iPid = aPid;
params.iHandle = aHandle;
params.iInfoPointer = &aInfo;
//
const TInt r = DoControl( EMemSpyDriverOpCodeCodeSegsGetCodeSegInfo, ¶ms, NULL );
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetChunkHandles( TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalChunkHandleParams params;
params.iId = 0;
params.iType = EMemSpyDriverPrivateObjectTypeAll;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
//
aHandleCount = 0;
//
const TInt err = DoControl( EMemSpyDriverOpCodeChunkGetHandles, ¶ms, NULL );
return err;
}
EXPORT_C TInt RMemSpyDriverClient::GetChunkInfo( TAny* aHandle, TMemSpyDriverChunkInfo& aInfo )
{
TMemSpyDriverInternalChunkInfoParams params;
TBuf8<KMaxFullName> name;
params.iHandle = aHandle;
const TInt r = DoControl( EMemSpyDriverOpCodeChunkGetInfo, ¶ms, NULL );
//
if ( r == KErrNone )
{
aInfo.iHandle = aHandle;
aInfo.iBaseAddress = params.iBaseAddress;
aInfo.iSize = params.iSize;
aInfo.iMaxSize = params.iMaxSize;
aInfo.iOwnerId = params.iOwnerId;
aInfo.iType = params.iType;
aInfo.iAttributes = params.iAttributes;
aInfo.iName.Copy( params.iName );
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetChunkInfo( TAny* aHandle, TMemSpyDriverChunkInfoWithoutName& aInfo )
{
TMemSpyDriverChunkInfo info;
//
const TInt r = GetChunkInfo( aHandle, info );
if ( r == KErrNone )
{
aInfo = info;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetChunkHandlesForProcess( TUint aPid, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalChunkHandleParams params;
params.iId = aPid;
params.iType = EMemSpyDriverPrivateObjectTypeProcess;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeChunkGetHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetChunkHandlesForThread( TUint aTid, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalChunkHandleParams params;
params.iId = aTid;
params.iType = EMemSpyDriverPrivateObjectTypeThread;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeChunkGetHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetThreadInfo( TUint aTid, TMemSpyDriverThreadInfo& aInfo )
{
TMemSpyDriverInternalThreadInfoParams params;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
//
TInt r = DoControl( EMemSpyDriverOpCodeThreadAndProcessGetInfoThread, (TAny*)aTid, ¶ms);
//
if ( r == KErrNone )
{
// Copy common properties
Mem::Copy( &aInfo, ¶ms, sizeof( TMemSpyDriverThreadInfoBase ) );
// Copy name
aInfo.iFullName.Copy( params.iFullName );
// Get other basic properties via RThread
RThread thread;
r = OpenThread( aTid, thread );
if ( r == KErrNone )
{
RProcess process;
r = thread.Process( process );
if ( r == KErrNone )
{
aInfo.iPid = process.Id();
process.Close();
}
aInfo.iThreadPriority = thread.Priority();
aInfo.iExitReason = thread.ExitReason();
aInfo.iExitType = thread.ExitType();
aInfo.iExitCategory = thread.ExitCategory();
thread.Close();
}
}
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetProcessInfo( TUint aPid, TMemSpyDriverProcessInfo& aInfo )
{
TInt r = DoControl( EMemSpyDriverOpCodeThreadAndProcessGetInfoProcess, (TAny*)aPid, &aInfo);
// Get other properties via RProcess.
if ( r == KErrNone )
{
RProcess process;
r = OpenProcess( aPid, process );
if ( r == KErrNone )
{
aInfo.iUids = process.Type();
aInfo.iPriority = process.Priority();
//
process.Close();
}
}
return r;
}
EXPORT_C TInt RMemSpyDriverClient::ProcessThreadsSuspend( TUint aPid )
{
return DoControl( EMemSpyDriverOpCodeThreadAndProcessSuspendAllThreads, (TAny*) aPid, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::ProcessThreadsResume( TUint aPid )
{
return DoControl( EMemSpyDriverOpCodeThreadAndProcessResumeAllThreads, (TAny*) aPid, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::ThreadEnd( TUint aId, TExitType aType )
{
TInt err = KErrNone;
//
if ( aType == EExitPending )
{
err = KErrArgument;
}
else
{
err = DoControl( EMemSpyDriverOpCodeThreadAndProcessEndThread, (TAny*) aId, (TAny*) aType );
}
//
return err;
}
EXPORT_C TInt RMemSpyDriverClient::OpenThread( TUint aId, RThread& aThread )
{
TInt ret = KErrNone;
aThread.Close();
//
const TInt err = DoControl( EMemSpyDriverOpCodeThreadAndProcessOpenThread, (TAny*) aId );
if ( err > 0 )
{
aThread.SetHandle( err );
ret = KErrNone;
}
else
{
ret = err;
}
//
return ret;
}
EXPORT_C TInt RMemSpyDriverClient::OpenProcess( TUint aId, RProcess& aProcess )
{
TInt ret = KErrNone;
aProcess.Close();
//
const TInt err = DoControl( EMemSpyDriverOpCodeThreadAndProcessOpenProcess, (TAny*) aId );
if ( err > 0 )
{
aProcess.SetHandle( err );
ret = KErrNone;
}
else
{
ret = err;
}
//
return ret;
}
EXPORT_C void RMemSpyDriverClient::GetThreadsL( const TProcessId& aId, RArray<TThreadId>& aThreads )
{
aThreads.Reset();
//
ResetStreamBuffer();
const TInt err = DoControl( EMemSpyDriverOpCodeThreadAndProcessGetThreads, (TAny*) (TUint) aId, (TAny*) &iBuffer );
User::LeaveIfError( err );
// Open stream
RMemSpyMemStreamReader stream = StreamOpenL();
CleanupClosePushL( stream );
// Extract thread ids
const TInt threadCount = stream.ReadInt32L();
for( TInt i=0; i<threadCount; i++ )
{
const TThreadId id( stream.ReadUint32L() );
aThreads.AppendL( id );
}
// Tidy up
CleanupStack::PopAndDestroy( &stream );
}
EXPORT_C TInt RMemSpyDriverClient::SetPriority( TUint aId, TThreadPriority aPriority )
{
// The kernel side API to set thread priority expects a value in the range of 0-63, i.e. an absolute
// NThread priority. In order to support process-relative thread priorities, we'd need to duplicate
// the kernel priority mapping tables - not a good idea - therefore we'll only support absolute values.
TInt err = KErrNone;
if ( aPriority < EPriorityAbsoluteVeryLow )
{
err = KErrArgument;
}
else
{
err = DoControl( EMemSpyDriverOpCodeThreadAndProcessSetPriorityThread, (TAny*) aId, (TAny*) aPriority );
}
//
return err;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapInfoUser( TMemSpyHeapInfo& aInfo, TUint aTid )
{
TMemSpyDriverInternalHeapRequestParameters params;
//
params.iTid = aTid;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
params.iMasterInfo = &aInfo;
//
TInt r = DoControl( EMemSpyDriverOpCodeHeapInfoGetUser, ¶ms, NULL );
//
if ( r == KErrNone )
{
PrintHeapInfo( aInfo );
// Need to do this on the user-side
if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
{
TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap();
TMemSpyHeapMetaDataRHeap& metaData = rHeapInfo.MetaData();
metaData.SetVTable( RHeapVTable() );
//metaData.SetClassSize( sizeof( RHeap ) );
}
}
else if ( r == KErrNotSupported )
{
aInfo.SetType( TMemSpyHeapInfo::ETypeUnknown );
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapInfoUser( TMemSpyHeapInfo& aInfo, TUint aTid, RArray< TMemSpyDriverFreeCell >& aFreeCells )
{
return GetHeapInfoUser(aInfo, aTid, aFreeCells, EFalse);
}
// For the record I don't think this function should be exported, but since the one above was I'm going with the flow. -TomS
EXPORT_C TInt RMemSpyDriverClient::GetHeapInfoUser(TMemSpyHeapInfo& aInfo, TUint aTid, RArray<TMemSpyDriverCell>& aCells, TBool aCollectAllocatedCellsAsWellAsFree)
{
TMemSpyDriverInternalHeapRequestParameters params;
//
params.iTid = aTid;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
params.iMasterInfo = &aInfo;
params.iBuildFreeCellList = ETrue;
params.iBuildAllocCellList = aCollectAllocatedCellsAsWellAsFree;
//
aCells.Reset();
ResetStreamBuffer();
TInt r = DoControl( EMemSpyDriverOpCodeHeapInfoGetUser, ¶ms );
//
if ( r >= KErrNone )
{
PrintHeapInfo( aInfo );
// Need to do this on the user-side
if ( aInfo.Type() == TMemSpyHeapInfo::ETypeRHeap )
{
TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap();
TMemSpyHeapMetaDataRHeap& metaData = rHeapInfo.MetaData();
metaData.SetVTable( RHeapVTable() );
//metaData.SetClassSize( sizeof( RHeap ) );
}
// Resize transfer buffer to make room for free cells. We only make the buffer
// bigger, not smaller.
if ( iBuffer.Size() < r )
{
r = iBuffer.ReAlloc( r );
}
// Now fetch the heap data
if ( r == KErrNone )
{
r = DoControl( EMemSpyDriverOpCodeHeapInfoFetchCellList, &iBuffer );
if ( r == KErrNone )
{
TRAP( r, ReadHeapInfoFreeCellsFromXferBufferL( aCells ) );
}
}
}
else if ( r == KErrNotSupported )
{
aInfo.SetType( TMemSpyHeapInfo::ETypeUnknown );
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapInfoKernel( TMemSpyHeapInfo& aInfo )
{
TMemSpyDriverInternalHeapRequestParameters params;
params.iTid = KMemSpyDriverGetKernelHeapDataPseudoThreadId;
params.iRHeapVTable = NULL;
params.iMasterInfo = &aInfo;
TInt r = DoControl( EMemSpyDriverOpCodeHeapInfoGetKernel, ¶ms, NULL );
//
if ( r == KErrNone )
{
PrintHeapInfo( aInfo );
}
else if ( r == KErrNotSupported )
{
aInfo.SetType( TMemSpyHeapInfo::ETypeUnknown );
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapInfoKernel( TMemSpyHeapInfo& aInfo, RArray< TMemSpyDriverFreeCell >& aFreeCells )
{
TMemSpyDriverInternalHeapRequestParameters params;
params.iTid = KMemSpyDriverGetKernelHeapDataPseudoThreadId;
params.iRHeapVTable = NULL;
params.iMasterInfo = &aInfo;
//
aFreeCells.Reset();
ResetStreamBuffer();
TInt r = DoControl( EMemSpyDriverOpCodeHeapInfoGetKernel, ¶ms, (TAny*) &iBuffer );
//
if ( r == KErrNone )
{
PrintHeapInfo( aInfo );
TRAP( r, ReadHeapInfoFreeCellsFromXferBufferL( aFreeCells ) );
}
else if ( r == KErrNotSupported )
{
aInfo.SetType( TMemSpyHeapInfo::ETypeUnknown );
r = KErrNone;
}
//
return r;
}
EXPORT_C TBool RMemSpyDriverClient::IsDebugKernel()
{
TBool isDebugKernel = EFalse;
DoControl( EMemSpyDriverOpCodeHeapInfoGetIsDebugKernel, (TAny*) &isDebugKernel );
return isDebugKernel;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapData( TUint aTid, TUint32 aFreeCellChecksum, TDes8& aDest, TUint& aReadAddress, TUint& aAmountRemaining )
{
TMemSpyDriverInternalHeapDataParams params;
params.iTid = aTid;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
params.iDes = &aDest;
params.iChecksum = aFreeCellChecksum;
params.iRemaining = -1;
params.iReadAddress = 0;
aDest.Zero();
//
TInt r = DoControl( EMemSpyDriverOpCodeHeapDataGetUser, ¶ms, NULL );
//
if ( r >= KErrNone )
{
aDest.SetLength( r );
aReadAddress = params.iReadAddress;
aAmountRemaining = params.iRemaining;
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetHeapDataNext( TUint aTid, TDes8& aDest, TUint& aReadAddress, TUint& aAmountRemaining )
{
TMemSpyDriverInternalHeapDataParams params;
params.iTid = aTid;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
params.iDes = &aDest;
params.iChecksum = 0;
params.iRemaining = aAmountRemaining;
params.iReadAddress = aReadAddress;
aDest.Zero();
//
TInt r = DoControl( EMemSpyDriverOpCodeHeapDataGetUser, ¶ms, NULL );
//
if ( r >= KErrNone )
{
aDest.SetLength( r );
aReadAddress = params.iReadAddress;
aAmountRemaining = params.iRemaining;
r = KErrNone;
}
//
return r;
}
EXPORT_C HBufC8* RMemSpyDriverClient::GetHeapDataKernelLC( TMemSpyHeapInfo& aInfo, RArray<TMemSpyDriverFreeCell>& aFreeCells )
{
HBufC8* data = NULL;
// Going to fetch free cells via stream buffer...
ResetStreamBuffer();
// First pass is to preallocate buffer for kernel heap, and fetch metadata and free cells
TInt sizeOrError = DoControl( EMemSpyDriverOpCodeHeapDataGetKernelInit, (TAny*) &aInfo, (TAny*) &iBuffer );
if ( sizeOrError >= KErrNone )
{
const TInt kernelHeapSize = sizeOrError;
if ( aInfo.Type() != TMemSpyHeapInfo::ETypeRHeap )
{
User::Leave( KErrNotSupported );
}
else
{
// Extract free cells
ReadHeapInfoFreeCellsFromXferBufferL( aFreeCells );
// It's okay to treat the heap info as an RHeap
PrintHeapInfo( aInfo );
// Allocate data sink and do fetch
data = HBufC8::NewLC( kernelHeapSize );
TPtr8 pBuffer( data->Des() );
sizeOrError = DoControl( EMemSpyDriverOpCodeHeapDataGetKernelFetch, &pBuffer, NULL );
}
}
User::LeaveIfError( sizeOrError );
return data;
}
EXPORT_C TInt RMemSpyDriverClient::WalkHeapInit( TUint aTid )
{
TMemSpyDriverInternalWalkHeapParamsInit params;
params.iTid = aTid;
params.iRHeapVTable = RHeapVTable();
params.iDebugAllocator = DebugEUser();
//
const TInt r = DoControl( EMemSpyDriverOpCodeWalkHeapInit, ¶ms, NULL );
return r;
}
EXPORT_C TInt RMemSpyDriverClient::WalkHeapNextCell( TUint aTid, TMemSpyDriverCellType& aCellType, TAny*& aCellAddress, TInt& aLength, TInt& aNestingLevel, TInt& aAllocNumber, TInt& aCellHeaderSize, TAny*& aCellPayloadAddress )
{
aCellType = EMemSpyDriverBadCellMask;
aCellAddress = NULL;
aLength = 0;
aNestingLevel = 0;
aAllocNumber = 0;
aCellHeaderSize = 0;
aCellPayloadAddress = NULL;
//
TMemSpyDriverInternalWalkHeapParamsCell params;
const TInt r = DoControl( EMemSpyDriverOpCodeWalkHeapNextCell, (TAny*) aTid, ¶ms );
//
if ( r == KErrNone )
{
aCellType = (TMemSpyDriverCellType) params.iCellType;
aCellAddress = params.iCellAddress;
aLength = params.iLength;
aNestingLevel = params.iNestingLevel;
aAllocNumber = params.iAllocNumber;
aCellPayloadAddress = ((TUint8*) aCellAddress) + aCellHeaderSize;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::WalkHeapReadCellData( TAny* aCellAddress, TDes8& aDest, TInt aReadLen )
{
TMemSpyDriverInternalWalkHeapCellDataReadParams params;
params.iCellAddress = aCellAddress;
params.iReadLen = aReadLen;
params.iDes = &aDest;
aDest.Zero();
//
TInt r = DoControl( EMemSpyDriverOpCodeWalkHeapReadCellData, ¶ms, NULL );
if ( r >= KErrNone )
{
aDest.SetLength( r );
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::WalkHeapGetCellInfo( TAny*& aCellAddress, TMemSpyDriverCellType& aCellType, TInt& aLength, TInt& aNestingLevel, TInt& aAllocNumber, TInt& aCellHeaderSize, TAny*& aCellPayloadAddress )
{
aCellType = EMemSpyDriverBadCellMask;
aLength = 0;
aNestingLevel = 0;
aAllocNumber = 0;
aCellHeaderSize = 0;
aCellPayloadAddress = NULL;
//
TMemSpyDriverInternalWalkHeapParamsCell params;
const TInt r = DoControl( EMemSpyDriverOpCodeWalkHeapGetCellInfo, aCellAddress, ¶ms );
//
if ( r == KErrNone )
{
aCellAddress = params.iCellAddress;
aCellType = (TMemSpyDriverCellType) params.iCellType;
aLength = params.iLength;
aNestingLevel = params.iNestingLevel;
aAllocNumber = params.iAllocNumber;
aCellPayloadAddress = ((TUint8*) aCellAddress) + aCellHeaderSize;
}
//
return r;
}
EXPORT_C void RMemSpyDriverClient::WalkHeapClose()
{
DoControl( EMemSpyDriverOpCodeWalkHeapClose, NULL, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetStackInfo( TUint aTid, TMemSpyDriverStackInfo& aInfo )
{
TMemSpyDriverStackInfo params;
const TInt r = DoControl( EMemSpyDriverOpCodeStackGetInfo, (TAny*)aTid, ¶ms );
if (r==KErrNone)
{
aInfo.iUserStackPointer = params.iUserStackPointer;
aInfo.iUserStackBase = params.iUserStackBase;
aInfo.iUserStackSize = params.iUserStackSize;
aInfo.iUserStackHighWatermark = params.iUserStackHighWatermark;
aInfo.iSupervisorStackPointer = params.iSupervisorStackPointer;
aInfo.iSupervisorStackBase = params.iSupervisorStackBase;
aInfo.iSupervisorStackSize = params.iSupervisorStackSize;
aInfo.iSupervisorStackHighWatermark = params.iSupervisorStackHighWatermark;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetStackData( TUint aTid, TDes8& aDest, TUint& aAmountRemaining, TMemSpyDriverDomainType aDomain, TBool aEntireStack )
{
TMemSpyDriverInternalStackDataParams params;
params.iTid = aTid;
params.iDes = &aDest;
params.iDomain = aDomain;
params.iEntireStack = aEntireStack;
params.iRemaining = -1;
aDest.Zero();
//
TInt r = DoControl( EMemSpyDriverOpCodeStackGetData, ¶ms, NULL );
//
if ( r >= KErrNone )
{
aDest.SetLength( r );
aAmountRemaining = params.iRemaining;
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetStackDataNext( TUint aTid, TDes8& aDest, TUint& aAmountRemaining, TMemSpyDriverDomainType aDomain, TBool aEntireStack )
{
TMemSpyDriverInternalStackDataParams params;
params.iTid = aTid;
params.iDes = &aDest;
params.iDomain = aDomain;
params.iEntireStack = aEntireStack;
params.iRemaining = aAmountRemaining;
//
TInt r = DoControl( EMemSpyDriverOpCodeStackGetData, ¶ms, NULL );
//
if ( r >= KErrNone )
{
aDest.SetLength( r );
aAmountRemaining = params.iRemaining;
r = KErrNone;
}
//
return r;
}
EXPORT_C TInt RMemSpyDriverClient::EventMonitorOpen( TUint& aHandle )
{
const TInt error = DoControl( EMemSpyDriverOpCodeEventMonitorOpen, (TAny*) &aHandle );
return error;
}
EXPORT_C TInt RMemSpyDriverClient::EventMonitorClose( TUint aHandle )
{
const TInt error = DoControl( EMemSpyDriverOpCodeEventMonitorClose, (TAny*) aHandle );
return error;
}
EXPORT_C void RMemSpyDriverClient::EventMonitorNotify( TUint aHandle, TRequestStatus& aStatus, TUint& aContext )
{
aStatus = KRequestPending;
//
TMemSpyDriverInternalEventMonitorParams params;
params.iHandle = aHandle;
params.iStatus = &aStatus;
params.iContext = (TAny*) &aContext;
//
const TInt err = DoControl( EMemSpyDriverOpCodeEventMonitorNotify, (TAny*) ¶ms );
if ( err != KErrNone )
{
TRequestStatus* status = &aStatus;
User::RequestComplete( status, err );
}
}
EXPORT_C void RMemSpyDriverClient::EventMonitorNotifyCancel( TUint aHandle )
{
const TInt error = DoControl( EMemSpyDriverOpCodeEventMonitorNotifyCancel, (TAny*) aHandle );
(void) error;
}
EXPORT_C TInt RMemSpyDriverClient::ProcessInspectionOpen( TUint aPid )
{
const TInt error = DoControl( EMemSpyDriverOpCodeProcessInspectOpen, (TAny*) aPid );
return error;
}
EXPORT_C TInt RMemSpyDriverClient::ProcessInspectionClose( TUint aPid )
{
const TInt error = DoControl( EMemSpyDriverOpCodeProcessInspectClose, (TAny*) aPid );
return error;
}
EXPORT_C void RMemSpyDriverClient::ProcessInspectionRequestChanges( TUint aPid, TRequestStatus& aStatus, TMemSpyDriverProcessInspectionInfo& aInfo )
{
aInfo.iProcessId = aPid;
aStatus = KRequestPending;
const TInt err = DoControl( EMemSpyDriverOpCodeProcessInspectRequestChanges, (TAny*) &aStatus, (TAny*) &aInfo );
if ( err != KErrNone )
{
TRequestStatus* status = &aStatus;
User::RequestComplete( status, err );
}
}
EXPORT_C void RMemSpyDriverClient::ProcessInspectionRequestChangesCancel( TUint aPid )
{
const TInt error = DoControl( EMemSpyDriverOpCodeProcessInspectRequestChangesCancel, (TAny*) aPid );
(void) error;
}
EXPORT_C void RMemSpyDriverClient::ProcessInspectionAutoStartItemsReset()
{
const TInt error = DoControl( EMemSpyDriverOpCodeProcessInspectAutoStartListReset );
(void) error;
}
EXPORT_C TInt RMemSpyDriverClient::ProcessInspectionAutoStartItemsAdd( TUint aSID )
{
const TInt error = DoControl( EMemSpyDriverOpCodeProcessInspectAutoStartListAdd, (TAny*) aSID );
return error;
}
EXPORT_C TInt RMemSpyDriverClient::GetContainerHandles( TMemSpyDriverContainerType aContainer, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalContainerHandleParams params;
params.iTidOrPid = KMemSpyDriverEnumerateContainerHandles;
params.iContainer = aContainer;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
params.iHandleSource = EMemSpyDriverThreadOrProcessTypeThread; // Not used
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeContainersGetHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetThreadHandlesByType( TInt aTid, TMemSpyDriverContainerType aType, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalContainerHandleParams params;
params.iTidOrPid = aTid;
params.iContainer = aType;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
params.iHandleSource = EMemSpyDriverThreadOrProcessTypeThread;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeContainersGetHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetProcessHandlesByType( TInt aPid, TMemSpyDriverContainerType aType, TAny** aHandleArray, TInt& aHandleCount )
{
TMemSpyDriverInternalContainerHandleParams params;
params.iTidOrPid = aPid;
params.iContainer = aType;
params.iHandles = aHandleArray;
params.iCountPtr = &aHandleCount;
params.iMaxCount = aHandleCount;
params.iHandleSource = EMemSpyDriverThreadOrProcessTypeProcess;
//
aHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeContainersGetHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetGenericHandleInfo( TInt aTid, TMemSpyDriverContainerType aType, TAny* aHandle, TMemSpyDriverHandleInfoGeneric& aParams )
{
aParams.iType = aType;
aParams.iHandle = aHandle;
//
const TInt r = DoControl( EMemSpyDriverOpCodeContainersGetHandleInfo, (TAny*) aTid, &aParams );
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetApproximateKernelObjectSize( TMemSpyDriverContainerType aType )
{
TInt size = 0;
const TInt error = DoControl( EMemSpyDriverOpCodeContainersGetApproxSize, (TAny*) aType, (TAny*) &size );
(void) error;
//
return size;
}
EXPORT_C TInt RMemSpyDriverClient::GetReferencesToMyThread( TUint aTid )
{
ResetStreamBuffer();
return DoControl( EMemSpyDriverOpCodeContainersGetReferencesToMyThread, (TAny*) aTid, (TAny*) &iBuffer );
}
EXPORT_C TInt RMemSpyDriverClient::GetReferencesToMyProcess( TUint aPid )
{
ResetStreamBuffer();
return DoControl( EMemSpyDriverOpCodeContainersGetReferencesToMyProcess, (TAny*) aPid, (TAny*) &iBuffer );
}
EXPORT_C TInt RMemSpyDriverClient::GetPAndSInfo( TAny* aHandle, TMemSpyDriverPAndSInfo& aInfo )
{
const TInt r = DoControl( EMemSpyDriverOpCodeContainersGetPAndSInfo, (TAny*) aHandle, &aInfo );
return r;
}
EXPORT_C TInt RMemSpyDriverClient::GetCondVarSuspendedThreads( TAny* aCondVarHandle, TAny** aThreadHandleArray, TInt& aThreadCount )
{
TMemSpyDriverInternalCondVarSuspendedThreadParams params;
params.iCondVarHandle = aCondVarHandle;
params.iThrHandles = aThreadHandleArray;
params.iThrCountPtr = &aThreadCount;
params.iMaxCount = aThreadCount;
//
aThreadCount = 0;
//
return DoControl( EMemSpyDriverOpCodeContainersGetCondVarSuspendedThreads, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetCondVarSuspendedThreadInfo( TAny* aHandle, TMemSpyDriverCondVarSuspendedThreadInfo& aParams )
{
return DoControl( EMemSpyDriverOpCodeContainersGetCondVarSuspendedThreadInfo, aHandle, &aParams );
}
EXPORT_C TInt RMemSpyDriverClient::GetServerSessionHandles( TAny* aServerHandle, TAny** aSessionHandleArray, TInt& aSessionHandleCount )
{
TMemSpyDriverInternalServerSessionHandleParams params;
params.iServerHandle = aServerHandle;
params.iSessionHandles = aSessionHandleArray;
params.iSessionCountPtr = &aSessionHandleCount;
params.iMaxCount = aSessionHandleCount;
//
aSessionHandleCount = 0;
//
return DoControl( EMemSpyDriverOpCodeClientServerGetServerSessionHandles, ¶ms, NULL );
}
EXPORT_C TInt RMemSpyDriverClient::GetServerSessionInfo( TAny* aSessionHandle, TMemSpyDriverServerSessionInfo& aParams )
{
return DoControl( EMemSpyDriverOpCodeClientServerGetServerSessionInfo, aSessionHandle, &aParams );
}
EXPORT_C RMemSpyMemStreamReader RMemSpyDriverClient::StreamOpenL()
{
CMemSpyMemStreamReader* imp = new(ELeave) CMemSpyMemStreamReader( iBuffer );
RMemSpyMemStreamReader ret( imp );
CleanupClosePushL( ret );
imp->ConstructL();
CleanupStack::Pop( &ret );
return ret;
}
EXPORT_C TMemSpyMemoryModelType RMemSpyDriverClient::MemoryModelType()
{
TMemSpyMemoryModelType ret = EMemSpyMemoryModelTypeUnknown;
//
const TInt err = DoControl( EMemSpyDriverOpCodeMiscGetMemoryModelType );
switch( err )
{
default:
case EMemSpyMemoryModelTypeUnknown:
ret = EMemSpyMemoryModelTypeUnknown;
break;
case EMemSpyMemoryModelTypeMoving:
ret = EMemSpyMemoryModelTypeMoving;
break;
case EMemSpyMemoryModelTypeMultiple:
ret = EMemSpyMemoryModelTypeMultiple;
break;
case EMemSpyMemoryModelTypeEmulator:
ret = EMemSpyMemoryModelTypeEmulator;
break;
}
//
return ret;
}
EXPORT_C TUint32 RMemSpyDriverClient::RoundToPageSize( TUint32 aValue )
{
TUint32 temp = aValue;
TAny* pValue = (TAny*) &temp;
DoControl( EMemSpyDriverOpCodeMiscGetRoundToPageSize, pValue );
return temp;
}
EXPORT_C TInt RMemSpyDriverClient::Impersonate( TUint32 aValue )
{
return DoControl( EMemSpyDriverOpCodeMiscImpersonate, (TAny*) aValue );
}
TUint RMemSpyDriverClient::RHeapVTable()
{
RHeap* heap = (RHeap*) &User::Allocator();
//
TUint* pHeap = (TUint*) heap;
const TUint heapVTable = *pHeap;
//
////RDebug::Printf( "[MemSpy] RMemSpyDriverClient::RHeapVTable() - ret: 0x%08x", heapVTable );
return heapVTable;
}
TBool RMemSpyDriverClient::DebugEUser()
{
LtkUtils::RAllocatorHelper allocHelper;
TBool result = EFalse;
TInt err = allocHelper.Open(&User::Allocator());
if (!err)
{
result = allocHelper.AllocatorIsUdeb();
allocHelper.Close();
}
return result;
}
void RMemSpyDriverClient::ResetStreamBuffer()
{
iBuffer.Zero();
}
void RMemSpyDriverClient::ReadHeapInfoFreeCellsFromXferBufferL( RArray<TMemSpyDriverFreeCell>& aFreeCells )
{
aFreeCells.Reset();
#ifdef _DEBUG
RDebug::Printf( "[MemSpy] RMemSpyDriverClient::ReadHeapInfoFreeCellsFromXferBufferL() - buf len: %d", iBuffer.Length() );
#endif
if ( iBuffer.Length() )
{
RMemSpyMemStreamReader stream = StreamOpenL();
CleanupClosePushL( stream );
const TInt count = stream.ReadInt32L();
#ifdef _DEBUG
RDebug::Printf( "[MemSpy] RMemSpyDriverClient::ReadHeapInfoFreeCellsFromXferBufferL() - count: %d", count );
#endif
for( TInt i=0; i<count; i++ )
{
TMemSpyDriverFreeCell entry;
entry.iType = (TMemSpyDriverCellType)stream.ReadInt32L();
entry.iAddress = reinterpret_cast< TAny* >( stream.ReadUint32L() );
entry.iLength = stream.ReadInt32L();
aFreeCells.AppendL( entry );
}
CleanupStack::PopAndDestroy( &stream );
}
ResetStreamBuffer();
}
static void PrintHeapInfo( const TMemSpyHeapInfo& aInfo )
{
#if defined( _DEBUG ) && !defined( __WINS__ )
const TMemSpyHeapInfoRHeap& rHeapInfo = aInfo.AsRHeap();
//const TMemSpyHeapObjectDataRHeap& rHeapObjectData = rHeapInfo.ObjectData();
const TMemSpyHeapStatisticsRHeap& rHeapStats = rHeapInfo.Statistics();
const TMemSpyHeapMetaDataRHeap& rHeapMetaData = rHeapInfo.MetaData();
/*
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator -");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iAccessCount: %d", rHeapObjectData.iAccessCount);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iHandleCount: %d", rHeapObjectData.iHandleCount);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iHandles: 0x%08x", rHeapObjectData.iHandles);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iFlags: 0x%08x", rHeapObjectData.iFlags);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iCellCount: %d", rHeapObjectData.iCellCount);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RAllocator::iTotalAllocSize: %d", rHeapObjectData.iTotalAllocSize);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - ");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap -");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iMinLength: %d", rHeapObjectData.iMinLength);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iMaxLength: %d", rHeapObjectData.iMaxLength);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iOffset: %d", rHeapObjectData.iOffset);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iGrowBy: %d", rHeapObjectData.iGrowBy);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iChunkHandle: 0x%08x", rHeapObjectData.iChunkHandle);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iBase: 0x%08x", rHeapObjectData.iBase);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iTop: 0x%08x", rHeapObjectData.iTop);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iAlign: %d", rHeapObjectData.iAlign);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iMinCell: %d", rHeapObjectData.iAlign);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iPageSize: %d", rHeapObjectData.iAlign);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFree.next: 0x%08x", rHeapObjectData.iFree.next);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFree.len: %d", rHeapObjectData.iFree.len);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iNestingLevel: %d", rHeapObjectData.iNestingLevel);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iAllocCount: %d", rHeapObjectData.iAllocCount);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFailType: %d", rHeapObjectData.iFailType);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFailRate: %d", rHeapObjectData.iFailRate);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFailed: %d", rHeapObjectData.iFailed);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iFailAllocCount: %d", rHeapObjectData.iFailAllocCount);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iRand: %d", rHeapObjectData.iRand);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - RHeap::iTestData: 0x%08x", rHeapObjectData.iTestData);
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - ");
*/
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - Stats (Free) -");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell count: %d", rHeapStats.StatsFree().TypeCount());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell size: %d", rHeapStats.StatsFree().TypeSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell largest: 0x%08x", rHeapStats.StatsFree().LargestCellAddress());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell largest size: %d", rHeapStats.StatsFree().LargestCellSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - slack: 0x%08x", rHeapStats.StatsFree().SlackSpaceCellAddress());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - slack size: %d", rHeapStats.StatsFree().SlackSpaceCellSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - checksum: 0x%08x", rHeapStats.StatsFree().Checksum());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - ");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - Stats (Alloc) -");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell count: %d", rHeapStats.StatsAllocated().TypeCount());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell size: %d", rHeapStats.StatsAllocated().TypeSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell largest: 0x%08x", rHeapStats.StatsAllocated().LargestCellAddress());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell largest size: %d", rHeapStats.StatsAllocated().LargestCellSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - ");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - Misc. Info -");
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() ---------------------------------------------------");
const TPtrC chunkName( rHeapMetaData.ChunkName() );
RDebug::Print(_L("RMemSpyDriverClient::PrintHeapInfo() - chunk name: [%S]"), &chunkName );
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - chunk size: %d", rHeapMetaData.ChunkSize());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - chunk handle: 0x%08x", rHeapMetaData.ChunkHandle());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - chunk base address: 0x%08x", rHeapMetaData.ChunkBaseAddress());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - debug allocator: %d", rHeapMetaData.IsDebugAllocator());
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - shared heap: %d", rHeapMetaData.IsSharedHeap() );
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - user thread: %d", rHeapMetaData.IsUserThread() );
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - thread id: %d", aInfo.Tid() );
RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - process id: %d", aInfo.Pid() );
//RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell header size (free): %d", rHeapMetaData.HeaderSizeFree());
//RDebug::Printf("RMemSpyDriverClient::PrintHeapInfo() - cell header size (alloc): %d", rHeapMetaData.HeaderSizeAllocated());
#else
(void) aInfo;
#endif
}