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" |
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 { |
446 { |
437 { |
447 return static_cast< TExitType >( aObject.iExitType ); |
438 return static_cast< TExitType >( aObject.iExitType ); |
448 } |
439 } |
449 |
440 |
450 |
441 |
451 DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const |
442 DThread* DMemSpyDriverOSAdaptionDProcess::OpenFirstThread( DProcess& aProcess ) const |
452 { |
443 { |
453 return aObject.FirstThread(); |
444 // It appears that the system lock needs to be held while manipulating the iThreadQ |
|
445 DThread* result = NULL; |
|
446 NKern::LockSystem(); |
|
447 // 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 |
|
448 SDblQueLink* threadLink = aProcess.iThreadQ.First(); |
|
449 if (threadLink != NULL && threadLink != &aProcess.iThreadQ.iA) |
|
450 { |
|
451 result = _LOFF(threadLink,DThread,iProcessLink); |
|
452 if (result->Open() != KErrNone) |
|
453 { |
|
454 result = NULL; |
|
455 } |
|
456 } |
|
457 NKern::UnlockSystem(); |
|
458 return result; |
454 } |
459 } |
455 |
460 |
456 |
461 |
457 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const |
462 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const |
458 { |
463 { |
543 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const |
548 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const |
544 { |
549 { |
545 return (TUint8*)aObject.iDataBssStackChunk; |
550 return (TUint8*)aObject.iDataBssStackChunk; |
546 } |
551 } |
547 |
552 |
|
553 TBool DMemSpyDriverOSAdaptionDProcess::IsKernProcess(DProcess& aProcess) const |
|
554 { |
|
555 // The kernel process always has pid 1 |
|
556 return GetId(aProcess) == 1; |
|
557 } |
548 |
558 |
549 |
559 |
550 |
560 |
551 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption ) |
561 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption ) |
552 : DMemSpyDriverOSAdaptionDObject( aOSAdaption ) |
562 : DMemSpyDriverOSAdaptionDObject( aOSAdaption ) |
564 { |
574 { |
565 return aObject.MaxSize(); |
575 return aObject.MaxSize(); |
566 } |
576 } |
567 |
577 |
568 |
578 |
569 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const |
579 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aChunk ) const |
570 { |
580 { |
571 return aObject.Base(); |
581 TUint8* base = aChunk.Base(); |
|
582 if (base == 0) |
|
583 { |
|
584 // Under flexible memory model, DChunk::Base() will return NULL (for non-fixed chunks anyway, and that means most of them) |
|
585 // A more useful thing to return is the base address in the owning process |
|
586 DProcess* proc = GetOwningProcess(aChunk); |
|
587 NKern::ThreadEnterCS(); |
|
588 if (proc && proc->Open() == KErrNone) |
|
589 { |
|
590 // Probably shouldn't call ChunkUserBase for a non-user-owned chunk |
|
591 if (!OSAdaption().DProcess().IsKernProcess(*proc)) |
|
592 { |
|
593 DThread* firstThread = OSAdaption().DProcess().OpenFirstThread(*proc); |
|
594 if (firstThread) |
|
595 { |
|
596 base = Kern::ChunkUserBase(&aChunk, firstThread); |
|
597 firstThread->Close(NULL); |
|
598 } |
|
599 } |
|
600 proc->Close(NULL); |
|
601 } |
|
602 NKern::ThreadLeaveCS(); |
|
603 } |
|
604 return base; |
572 } |
605 } |
573 |
606 |
574 |
607 |
575 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const |
608 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const |
576 { |
609 { |