memspy/Driver/Kernel/Source/MemSpyDriverOSAdaption.cpp
branchRCL_3
changeset 49 7fdc9a71d314
parent 44 52e343bb8f80
child 59 8ad140f3dd41
equal deleted inserted replaced
46:e26895079d7c 49:7fdc9a71d314
    20 #include <kern_priv.h>
    20 #include <kern_priv.h>
    21 #include <nkern.h>
    21 #include <nkern.h>
    22 #include <nk_plat.h>
    22 #include <nk_plat.h>
    23 
    23 
    24 #ifdef __MARM__
    24 #ifdef __MARM__
    25 
       
    26 #include <arm.h>
    25 #include <arm.h>
    27 // Necessary when accessing data members by steam via offsets in order
       
    28 // to prevent potential unaligned data aborts
       
    29 
       
    30 #ifdef __CC_ARM
       
    31 #define UNALIGNED_DATA_MEMBER __packed
       
    32 #endif /* __CC_ARM */
       
    33 
       
    34 #endif /* __MARM__ */
       
    35 
       
    36 #ifndef UNALIGNED_DATA_MEMBER
       
    37 #define UNALIGNED_DATA_MEMBER
       
    38 #endif
    26 #endif
       
    27 
       
    28 // I've removed UNALIGNED_DATA_MEMBER in preference for just using memcpy to get round the potential unaligned access. -TomS
    39 
    29 
    40 // User includes
    30 // User includes
    41 #include "MemSpyDriverLog.h"
    31 #include "MemSpyDriverLog.h"
    42 #include "MemSpyDriverPAndS.h"
    32 #include "MemSpyDriverPAndS.h"
    43 #include "MemSpyDriverDevice.h"
    33 #include "MemSpyDriverDevice.h"
    44 
    34 
    45 // Internal constants
    35 // Internal constants
    46 const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeaep vTable
    36 const TInt KMemSpyLocalThreadDataSizeEstimate = 0x80; // The amount of user stack that MemSpy attempts to scan for the RHeap vTable
    47 
    37 
    48 
    38 
    49 
    39 
    50 DMemSpyDriverOSAdaptionDObject::DMemSpyDriverOSAdaptionDObject( DMemSpyDriverOSAdaption& aOSAdaption )
    40 DMemSpyDriverOSAdaptionDObject::DMemSpyDriverOSAdaptionDObject( DMemSpyDriverOSAdaption& aOSAdaption )
    51 :   iOSAdaption( aOSAdaption )
    41 :   iOSAdaption( aOSAdaption )
   162 
   152 
   163 TExitType DMemSpyDriverOSAdaptionDThread::GetExitType( DThread& aObject ) const
   153 TExitType DMemSpyDriverOSAdaptionDThread::GetExitType( DThread& aObject ) const
   164     {
   154     {
   165     DThread* dThread = &aObject;
   155     DThread* dThread = &aObject;
   166     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_ExitType;
   156     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_ExitType;
   167     UNALIGNED_DATA_MEMBER TExitType* pRet = reinterpret_cast< TExitType* >( pTarget );
   157 	TUint8 exitType = *reinterpret_cast<TUint8*>(pTarget);
   168     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
   158     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: %d", &aObject, (TInt)exitType ) );
   169     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - value: %d", *pRet ) );
   159     return (TExitType)exitType;
   170     return *pRet;
       
   171     }
   160     }
   172 
   161 
   173 
   162 
   174 TUint32 DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase( DThread& aObject ) const
   163 TUint32 DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase( DThread& aObject ) const
   175     {
   164     {
   176     DThread* dThread = &aObject;
   165     DThread* dThread = &aObject;
   177     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase;
   166     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase;
   178     UNALIGNED_DATA_MEMBER TUint32* pRet = reinterpret_cast< TUint32* >( pTarget );
   167 
   179     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
   168 	TUint32 ret;
   180     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - 0x%08x: %d", *pRet ) );
   169 	memcpy(&ret, (const TAny*)pTarget, sizeof(TUint32));
   181     return *pRet;
   170     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, ret ) );
       
   171     return ret;
   182     }
   172     }
   183 
   173 
   184 
   174 
   185 TInt DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize( DThread& aObject ) const
   175 TInt DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize( DThread& aObject ) const
   186     {
   176     {
   187     DThread* dThread = &aObject;
   177     DThread* dThread = &aObject;
   188     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize;
   178     TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize;
   189     UNALIGNED_DATA_MEMBER TInt* pRet = reinterpret_cast< TInt* >( pTarget );
   179 	
   190     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) );
   180 	TInt ret;
   191     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - value: %d", *pRet ) );
   181 	memcpy(&ret, (const TAny*)pTarget, sizeof(TInt));
   192     return *pRet;
   182     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: %d", &aObject, ret ) );
       
   183     return ret;
   193     }
   184     }
   194 
   185 
   195 
   186 
   196 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocator( DThread& aObject ) const
   187 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocator( DThread& aObject ) const
   197     {
   188     {
   209     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocator() - END - ret: 0x%08x", ret ) );
   200     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocator() - END - ret: 0x%08x", ret ) );
   210     return ret;
   201     return ret;
   211     }
   202     }
   212 
   203 
   213 
   204 
       
   205 // TODO try to rework this without inspecting the stack!
   214 CActiveScheduler* DMemSpyDriverOSAdaptionDThread::GetActiveScheduler( DThread& aObject ) const
   206 CActiveScheduler* DMemSpyDriverOSAdaptionDThread::GetActiveScheduler( DThread& aObject ) const
   215     {
   207     {
   216     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - START" ) );
   208     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetActiveScheduler() - START" ) );
   217     CActiveScheduler* ret = aObject.iScheduler;
   209     CActiveScheduler* ret = aObject.iScheduler;
   218     //
   210     //
   332         {
   324         {
   333         aObject.iOwningProcess->FullName( aName );
   325         aObject.iOwningProcess->FullName( aName );
   334         }
   326         }
   335     }
   327     }
   336 
   328 
   337 
   329 // TODO re-work this without inspecting the stack.
   338 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aObject, TUint32& aStackAddress ) const
   330 // In particular we can get the allocator from the DThread object's iAllocator object
   339     {
   331 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress( DThread& aThread, TUint32& aStackAddress ) const
   340     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START" ) );
   332     {
       
   333     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - START for aThread 0x%08x with ID %d", &aThread, aThread.iId ) );
   341     //
   334     //
   342     aStackAddress = 0;
   335     aStackAddress = 0;
   343     RAllocator* ret = NULL;
   336     RAllocator* ret = NULL;
   344 
   337 
   345     // We will assume the thread is running and that the user-side stack has been set up
   338     // We will assume the thread is running and that the user-side stack has been set up
   346     // accordingly.
   339     // accordingly.
   347     const TUint32 base = GetUserStackBase( aObject );
   340     const TUint32 base = GetUserStackBase( aThread );
   348     const TInt size = GetUserStackSize( aObject );
   341     const TInt size = GetUserStackSize( aThread );
   349     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - base: 0x%08x, size: %d, KMemSpyLocalThreadDataSizeEstimate: %d", base, size, KMemSpyLocalThreadDataSizeEstimate ) );
   342     TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - base: 0x%08x, size: %d, KMemSpyLocalThreadDataSizeEstimate: %d", base, size, KMemSpyLocalThreadDataSizeEstimate ) );
   350     const TUint32 top = base + size;
   343     const TUint32 top = base + size;
   351 
   344 
   352     // This is the RHeap vtable we are looking for
   345     // This is the RHeap vtable we are looking for
   353     const TUint32 rHeapVTable = OSAdaption().Device().RHeapVTable();
   346     const TUint32 rHeapVTable = OSAdaption().Device().RHeapVTable();
   361         TUint32 value = 0;
   354         TUint32 value = 0;
   362         TUint32 possibleVTable = 0;
   355         TUint32 possibleVTable = 0;
   363         //
   356         //
   364         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
   357         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
   365         //
   358         //
   366         r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
   359         r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) );
   367         if  ( r == KErrNone )
   360         if  ( r == KErrNone )
   368             {
   361             {
   369             Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
   362             r = Kern::ThreadRawRead( &aThread, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
   370             }
   363             }
   371         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) );
   364 
       
   365         if ( r == KErrNone )
       
   366             {
       
   367             TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, vTable: 0x%08x (offset: %04d)", addr, value, possibleVTable, top - addr ) );
       
   368             }
       
   369         else
       
   370             {
       
   371             TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - stack[0x%08x] 0x%08x, (offset: %04d) read failed: %d", addr, value, top - addr, r ) );
       
   372             }
   372         }
   373         }
   373 #endif
   374 #endif
   374 
   375 
   375     for( TUint32 addr = top - 4; addr >= top - KMemSpyLocalThreadDataSizeEstimate; addr -= 4 )
   376     for( TUint32 addr = top - 4; addr >= top - KMemSpyLocalThreadDataSizeEstimate; addr -= 4 )
   376         {
   377         {
   377         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - addr to read from: 0x%08x", addr ) );
   378         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - addr to read from: 0x%08x", addr ) );
   378         TUint32 value = 0;
   379         TUint32 value = 0;
   379         //
   380         //
   380         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
   381         TUint32* ptr = reinterpret_cast< TUint32* >( addr );
   381         //
   382         //
   382         r = Kern::ThreadRawRead( &aObject, ptr, &value, sizeof( value ) );
   383         r = Kern::ThreadRawRead( &aThread, ptr, &value, sizeof( value ) );
   383         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - read from: 0x%08x, result: %d, value: 0x%08x", addr, r, value ) );
   384         TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - read from: 0x%08x, result: %d, value: 0x%08x", addr, r, value ) );
   384         //
   385         //
   385         if  ( r == KErrNone )
   386         if  ( r == KErrNone )
   386             {
   387             {
   387             // Try and read from the address which is now stored within 'value'. We must do this because 
   388             // Try and read from the address which is now stored within 'value'. We must do this because 
   388             // the TLD class holds an RAllocator* and we need to ascertain the vTable of the RAllocator* matches the
   389             // the TLD class holds an RAllocator* and we need to ascertain the vTable of the RAllocator* matches the
   389             // only supported vTable that MemSpy understands (RHeap*).
   390             // only supported vTable that MemSpy understands (RHeap*).
   390             TUint32 possibleVTable = 0;
   391             TUint32 possibleVTable = 0;
   391             r = Kern::ThreadRawRead( &aObject, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
   392             r = Kern::ThreadRawRead( &aThread, reinterpret_cast< const TAny* >( value ), &possibleVTable, sizeof( possibleVTable ) );
   392             TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - possible vtable read from: 0x%08x, result: %d, possibleVTable: 0x%08x", value, r, possibleVTable ) );
   393             TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetAllocatorAndStackAddress() - possible vtable read from: 0x%08x, result: %d, possibleVTable: 0x%08x", value, r, possibleVTable ) );
   393             if  ( r == KErrNone && possibleVTable == rHeapVTable )
   394             if  ( r == KErrNone && possibleVTable == rHeapVTable )
   394                 {
   395                 {
   395                 aStackAddress = addr;
   396                 aStackAddress = addr;
   396                 ret = reinterpret_cast< RAllocator* >( value );
   397                 ret = reinterpret_cast< RAllocator* >( value );
   446     {
   447     {
   447     return static_cast< TExitType >( aObject.iExitType );
   448     return static_cast< TExitType >( aObject.iExitType );
   448     }
   449     }
   449 
   450 
   450 
   451 
   451 DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const
   452 DThread* DMemSpyDriverOSAdaptionDProcess::OpenFirstThread( DProcess& aProcess ) const
   452     {
   453     {
   453     return aObject.FirstThread();
   454 	// It appears that the system lock needs to be held while manipulating the iThreadQ
       
   455 	DThread* result = NULL;
       
   456 	NKern::LockSystem();
       
   457 	// 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
       
   458 	SDblQueLink* threadLink = aProcess.iThreadQ.First();
       
   459 	if (threadLink != NULL && threadLink != &aProcess.iThreadQ.iA)
       
   460 		{
       
   461 		result = _LOFF(threadLink,DThread,iProcessLink);
       
   462 		if (result->Open() != KErrNone)
       
   463 			{
       
   464 			result = NULL;
       
   465 			}
       
   466 		}
       
   467 	NKern::UnlockSystem();
       
   468     return result;
   454     }
   469     }
   455 
   470 
   456 
   471 
   457 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const
   472 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const
   458     {
   473     {
   543 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const
   558 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const
   544     {
   559     {
   545     return (TUint8*)aObject.iDataBssStackChunk;
   560     return (TUint8*)aObject.iDataBssStackChunk;
   546     }
   561     }
   547 
   562 
       
   563 TBool DMemSpyDriverOSAdaptionDProcess::IsKernProcess(DProcess& aProcess) const
       
   564 	{
       
   565 	// The kernel process always has pid 1
       
   566 	return GetId(aProcess) == 1;
       
   567 	}
   548 
   568 
   549 
   569 
   550 
   570 
   551 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption )
   571 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption )
   552 :   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
   572 :   DMemSpyDriverOSAdaptionDObject( aOSAdaption )
   564     {
   584     {
   565     return aObject.MaxSize();
   585     return aObject.MaxSize();
   566     }
   586     }
   567 
   587 
   568 
   588 
   569 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const
   589 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aChunk ) const
   570     {
   590     {
   571     return aObject.Base();
   591     TUint8* base = aChunk.Base();
       
   592 	if (base == 0)
       
   593 		{
       
   594 		// Under flexible memory model, DChunk::Base() will return NULL (for non-fixed chunks anyway, and that means most of them)
       
   595 		// A more useful thing to return is the base address in the owning process
       
   596 		DProcess* proc = GetOwningProcess(aChunk);
       
   597 		NKern::ThreadEnterCS();
       
   598 		if (proc && proc->Open() == KErrNone)
       
   599 			{
       
   600 			// Probably shouldn't call ChunkUserBase for a non-user-owned chunk
       
   601 			if (!OSAdaption().DProcess().IsKernProcess(*proc))
       
   602 				{
       
   603 				DThread* firstThread = OSAdaption().DProcess().OpenFirstThread(*proc);
       
   604 				if (firstThread)
       
   605 					{
       
   606 					base = Kern::ChunkUserBase(&aChunk, firstThread);
       
   607 					firstThread->Close(NULL);
       
   608 					}
       
   609 				}
       
   610 			proc->Close(NULL);
       
   611 			}
       
   612 		NKern::ThreadLeaveCS();
       
   613 		}
       
   614 	return base; 
   572     }
   615     }
   573 
   616 
   574 
   617 
   575 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const
   618 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const
   576     {
   619     {