memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp
branchRCL_3
changeset 49 7fdc9a71d314
parent 44 52e343bb8f80
child 59 8ad140f3dd41
--- a/memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp	Wed Sep 15 00:19:18 2010 +0300
+++ b/memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp	Wed Sep 15 13:53:27 2010 +0300
@@ -22,20 +22,10 @@
 #include <nk_plat.h>
 
 #ifdef __MARM__
-
 #include <arm.h>
-// Necessary when accessing data members by steam via offsets in order
-// to prevent potential unaligned data aborts
+#endif
 
-#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"
@@ -43,7 +33,7 @@
 #include "MemSpyDriverDevice.h"
 
 // Internal constants
-const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeaep vTable
+const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeap vTable
 
 
 
@@ -164,10 +154,9 @@
     {
     DThread* dThread = &aObject;
     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_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;
+	TUint8 exitType = *reinterpret_cast<TUint8*>(pTarget);
+    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: %d", &aObject, (TInt)exitType ) );
+    return (TExitType)exitType;
     }
 
 
@@ -175,10 +164,11 @@
     {
     DThread* dThread = &aObject;
     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase;
-    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;
+
+	TUint32 ret;
+	memcpy(&ret, (const TAny*)pTarget, sizeof(TUint32));
+    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, ret ) );
+    return ret;
     }
 
 
@@ -186,10 +176,11 @@
     {
     DThread* dThread = &aObject;
     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize;
-    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;
+	
+	TInt ret;
+	memcpy(&ret, (const TAny*)pTarget, sizeof(TInt));
+    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: %d", &aObject, ret ) );
+    return ret;
     }
 
 
@@ -211,6 +202,7 @@
     }
 
 
+// TODO try to rework this without inspecting the stack!
 CActiveScheduler* DMemSpyDriverOSAdaptionDThread::GetActiveScheduler( DThread& aObject ) const
     {
     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - START" ) );
@@ -334,18 +326,19 @@
         }
     }
 
-
-RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aObject, TUint32& aStackAddress ) const
+// 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
     {
-    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START" ) );
+    TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START for aThread 0x%08x with ID %d", &aThread, aThread.iId ) );
     //
     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( aObject );
-    const TInt size = GetUserStackSize( aObject );
+    const TUint32 base = GetUserStackBase( aThread );
+    const TInt size = GetUserStackSize( aThread );
     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - base: 0x%08x, size: %d, KMemSpyLocalThreadDataSizeEstimate: %d", base, size, KMemSpyLocalThreadDataSizeEstimate ) );
     const TUint32 top = base + size;
 
@@ -363,12 +356,20 @@
         //
         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
         //
-        r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
+        r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) );
         if  ( r == KErrNone )
             {
-            Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
+            r = Kern::ThreadRawRead( &aThread, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
             }
-        TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) );
+
+        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 ) );
+            }
         }
 #endif
 
@@ -379,7 +380,7 @@
         //
         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
         //
-        r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
+        r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) );
         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - read from: 0x%08x, result: %d, value: 0x%08x", addr, r, value ) );
         //
         if  ( r == KErrNone )
@@ -388,7 +389,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( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
+            r = Kern::ThreadRawRead( &aThread, 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 )
                 {
@@ -448,9 +449,23 @@
     }
 
 
-DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const
+DThread* DMemSpyDriverOSAdaptionDProcess::OpenFirstThread( DProcess& aProcess ) const
     {
-    return aObject.FirstThread();
+	// 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;
     }
 
 
@@ -545,6 +560,11 @@
     return (TUint8*)aObject.iDataBssStackChunk;
     }
 
+TBool DMemSpyDriverOSAdaptionDProcess::IsKernProcess(DProcess& aProcess) const
+	{
+	// The kernel process always has pid 1
+	return GetId(aProcess) == 1;
+	}
 
 
 
@@ -566,9 +586,32 @@
     }
 
 
-TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const
+TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aChunk ) const
     {
-    return aObject.Base();
+    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; 
     }