diff -r 7fdc9a71d314 -r 8ad140f3dd41 memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp --- a/memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp Wed Sep 15 13:53:27 2010 +0300 +++ b/memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -22,18 +22,28 @@ #include #ifdef __MARM__ + #include +// Necessary when accessing data members by steam via offsets in order +// to prevent potential unaligned data aborts + +#ifdef __CC_ARM +#define UNALIGNED_DATA_MEMBER __packed +#endif /* __CC_ARM */ + +#endif /* __MARM__ */ + +#ifndef UNALIGNED_DATA_MEMBER +#define UNALIGNED_DATA_MEMBER #endif -// I've removed UNALIGNED_DATA_MEMBER in preference for just using memcpy to get round the potential unaligned access. -TomS - // User includes #include "MemSpyDriverLog.h" #include "MemSpyDriverPAndS.h" #include "MemSpyDriverDevice.h" // Internal constants -const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeap vTable +const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeaep vTable @@ -154,9 +164,10 @@ { DThread* dThread = &aObject; TUint32 pTarget = reinterpret_cast( dThread ) + iOffset_ExitType; - TUint8 exitType = *reinterpret_cast(pTarget); - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: %d", &aObject, (TInt)exitType ) ); - return (TExitType)exitType; + UNALIGNED_DATA_MEMBER TExitType* pRet = reinterpret_cast< TExitType* >( pTarget ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - value: %d", *pRet ) ); + return *pRet; } @@ -164,11 +175,10 @@ { DThread* dThread = &aObject; TUint32 pTarget = reinterpret_cast( dThread ) + iOffset_SupervisorStackBase; - - TUint32 ret; - memcpy(&ret, (const TAny*)pTarget, sizeof(TUint32)); - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, ret ) ); - return ret; + UNALIGNED_DATA_MEMBER TUint32* pRet = reinterpret_cast< TUint32* >( pTarget ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - 0x%08x: %d", *pRet ) ); + return *pRet; } @@ -176,11 +186,10 @@ { DThread* dThread = &aObject; TUint32 pTarget = reinterpret_cast( dThread ) + iOffset_SupervisorStackSize; - - TInt ret; - memcpy(&ret, (const TAny*)pTarget, sizeof(TInt)); - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: %d", &aObject, ret ) ); - return ret; + UNALIGNED_DATA_MEMBER TInt* pRet = reinterpret_cast< TInt* >( pTarget ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - value: %d", *pRet ) ); + return *pRet; } @@ -202,7 +211,6 @@ } -// TODO try to rework this without inspecting the stack! CActiveScheduler* DMemSpyDriverOSAdaptionDThread::GetActiveScheduler( DThread& aObject ) const { TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - START" ) ); @@ -326,19 +334,18 @@ } } -// TODO re-work this without inspecting the stack. -// In particular we can get the allocator from the DThread object's iAllocator object -RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aThread, TUint32& aStackAddress ) const + +RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aObject, TUint32& aStackAddress ) const { - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START for aThread 0x%08x with ID %d", &aThread, aThread.iId ) ); + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START" ) ); // aStackAddress = 0; RAllocator* ret = NULL; // We will assume the thread is running and that the user-side stack has been set up // accordingly. - const TUint32 base = GetUserStackBase( aThread ); - const TInt size = GetUserStackSize( aThread ); + const TUint32 base = GetUserStackBase( aObject ); + const TInt size = GetUserStackSize( aObject ); TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - base: 0x%08x, size: %d, KMemSpyLocalThreadDataSizeEstimate: %d", base, size, KMemSpyLocalThreadDataSizeEstimate ) ); const TUint32 top = base + size; @@ -356,20 +363,12 @@ // TUint32* ptr = reinterpret_cast< TUint32* >( addr ); // - r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) ); + r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) ); if ( r == KErrNone ) { - r = Kern::ThreadRawRead( &aThread, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) ); + Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) ); } - - if ( r == KErrNone ) - { - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) ); - } - else - { - TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, (offset: %04d) read failed: %d", addr, value, top - addr, r ) ); - } + TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) ); } #endif @@ -380,7 +379,7 @@ // TUint32* ptr = reinterpret_cast< TUint32* >( addr ); // - r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) ); + r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) ); TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - read from: 0x%08x, result: %d, value: 0x%08x", addr, r, value ) ); // if ( r == KErrNone ) @@ -389,7 +388,7 @@ // the TLD class holds an RAllocator* and we need to ascertain the vTable of the RAllocator* matches the // only supported vTable that MemSpy understands (RHeap*). TUint32 possibleVTable = 0; - r = Kern::ThreadRawRead( &aThread, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) ); + r = Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) ); TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - possible vtable read from: 0x%08x, result: %d, possibleVTable: 0x%08x", value, r, possibleVTable ) ); if ( r == KErrNone && possibleVTable == rHeapVTable ) { @@ -449,23 +448,9 @@ } -DThread* DMemSpyDriverOSAdaptionDProcess::OpenFirstThread( DProcess& aProcess ) const +DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const { - // It appears that the system lock needs to be held while manipulating the iThreadQ - DThread* result = NULL; - NKern::LockSystem(); - // We don't use DProcess::FirstThread() as that doesn't appear to do any checking of whether the list is empty, ie if there are no threads at all - SDblQueLink* threadLink = aProcess.iThreadQ.First(); - if (threadLink != NULL && threadLink != &aProcess.iThreadQ.iA) - { - result = _LOFF(threadLink,DThread,iProcessLink); - if (result->Open() != KErrNone) - { - result = NULL; - } - } - NKern::UnlockSystem(); - return result; + return aObject.FirstThread(); } @@ -560,11 +545,6 @@ return (TUint8*)aObject.iDataBssStackChunk; } -TBool DMemSpyDriverOSAdaptionDProcess::IsKernProcess(DProcess& aProcess) const - { - // The kernel process always has pid 1 - return GetId(aProcess) == 1; - } @@ -586,32 +566,9 @@ } -TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aChunk ) const +TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const { - TUint8* base = aChunk.Base(); - if (base == 0) - { - // Under flexible memory model, DChunk::Base() will return NULL (for non-fixed chunks anyway, and that means most of them) - // A more useful thing to return is the base address in the owning process - DProcess* proc = GetOwningProcess(aChunk); - NKern::ThreadEnterCS(); - if (proc && proc->Open() == KErrNone) - { - // Probably shouldn't call ChunkUserBase for a non-user-owned chunk - if (!OSAdaption().DProcess().IsKernProcess(*proc)) - { - DThread* firstThread = OSAdaption().DProcess().OpenFirstThread(*proc); - if (firstThread) - { - base = Kern::ChunkUserBase(&aChunk, firstThread); - firstThread->Close(NULL); - } - } - proc->Close(NULL); - } - NKern::ThreadLeaveCS(); - } - return base; + return aObject.Base(); }