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 |
25 #include <arm.h> |
26 #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 |
26 #endif |
38 #endif |
27 |
|
28 // I've removed UNALIGNED_DATA_MEMBER in preference for just using memcpy to get round the potential unaligned access. -TomS |
|
29 |
39 |
30 // User includes |
40 // User includes |
31 #include "MemSpyDriverLog.h" |
41 #include "MemSpyDriverLog.h" |
32 #include "MemSpyDriverPAndS.h" |
42 #include "MemSpyDriverPAndS.h" |
33 #include "MemSpyDriverDevice.h" |
43 #include "MemSpyDriverDevice.h" |
152 |
162 |
153 TExitType DMemSpyDriverOSAdaptionDThread::GetExitType( DThread& aObject ) const |
163 TExitType DMemSpyDriverOSAdaptionDThread::GetExitType( DThread& aObject ) const |
154 { |
164 { |
155 DThread* dThread = &aObject; |
165 DThread* dThread = &aObject; |
156 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_ExitType; |
166 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_ExitType; |
157 TUint8 exitType = *reinterpret_cast<TUint8*>(pTarget); |
167 UNALIGNED_DATA_MEMBER TExitType* pRet = reinterpret_cast< TExitType* >( pTarget ); |
158 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: %d", &aObject, (TInt)exitType ) ); |
168 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); |
159 return (TExitType)exitType; |
169 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetExitType() - value: %d", *pRet ) ); |
|
170 return *pRet; |
160 } |
171 } |
161 |
172 |
162 |
173 |
163 TUint32 DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase( DThread& aObject ) const |
174 TUint32 DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase( DThread& aObject ) const |
164 { |
175 { |
165 DThread* dThread = &aObject; |
176 DThread* dThread = &aObject; |
166 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase; |
177 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackBase; |
167 |
178 UNALIGNED_DATA_MEMBER TUint32* pRet = reinterpret_cast< TUint32* >( pTarget ); |
168 TUint32 ret; |
179 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); |
169 memcpy(&ret, (const TAny*)pTarget, sizeof(TUint32)); |
180 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - 0x%08x: %d", *pRet ) ); |
170 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackBase() - aObject: 0x%08x, ret: 0x%08x", &aObject, ret ) ); |
181 return *pRet; |
171 return ret; |
|
172 } |
182 } |
173 |
183 |
174 |
184 |
175 TInt DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize( DThread& aObject ) const |
185 TInt DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize( DThread& aObject ) const |
176 { |
186 { |
177 DThread* dThread = &aObject; |
187 DThread* dThread = &aObject; |
178 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize; |
188 TUint32 pTarget = reinterpret_cast<TUint32>( dThread ) + iOffset_SupervisorStackSize; |
179 |
189 UNALIGNED_DATA_MEMBER TInt* pRet = reinterpret_cast< TInt* >( pTarget ); |
180 TInt ret; |
190 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: 0x%08x", &aObject, pRet ) ); |
181 memcpy(&ret, (const TAny*)pTarget, sizeof(TInt)); |
191 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - value: %d", *pRet ) ); |
182 TRACE( Kern::Printf( "DMemSpyDriverOSAdaptionDThread::GetSupervisorStackSize() - aObject: 0x%08x, ret: %d", &aObject, ret ) ); |
192 return *pRet; |
183 return ret; |
|
184 } |
193 } |
185 |
194 |
186 |
195 |
187 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocator( DThread& aObject ) const |
196 RAllocator* DMemSpyDriverOSAdaptionDThread::GetAllocator( DThread& aObject ) const |
188 { |
197 { |
437 { |
446 { |
438 return static_cast< TExitType >( aObject.iExitType ); |
447 return static_cast< TExitType >( aObject.iExitType ); |
439 } |
448 } |
440 |
449 |
441 |
450 |
442 DThread* DMemSpyDriverOSAdaptionDProcess::OpenFirstThread( DProcess& aProcess ) const |
451 DThread* DMemSpyDriverOSAdaptionDProcess::GetFirstThread( DProcess& aObject ) const |
443 { |
452 { |
444 // It appears that the system lock needs to be held while manipulating the iThreadQ |
453 return aObject.FirstThread(); |
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; |
|
459 } |
454 } |
460 |
455 |
461 |
456 |
462 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const |
457 TUint32 DMemSpyDriverOSAdaptionDProcess::GetSID( DProcess& aObject ) const |
463 { |
458 { |
548 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const |
543 TUint8* DMemSpyDriverOSAdaptionDProcess::GetAddressOfDataBssStackChunk( DProcess& aObject ) const |
549 { |
544 { |
550 return (TUint8*)aObject.iDataBssStackChunk; |
545 return (TUint8*)aObject.iDataBssStackChunk; |
551 } |
546 } |
552 |
547 |
553 TBool DMemSpyDriverOSAdaptionDProcess::IsKernProcess(DProcess& aProcess) const |
|
554 { |
|
555 // The kernel process always has pid 1 |
|
556 return GetId(aProcess) == 1; |
|
557 } |
|
558 |
548 |
559 |
549 |
560 |
550 |
561 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption ) |
551 DMemSpyDriverOSAdaptionDChunk::DMemSpyDriverOSAdaptionDChunk( DMemSpyDriverOSAdaption& aOSAdaption ) |
562 : DMemSpyDriverOSAdaptionDObject( aOSAdaption ) |
552 : DMemSpyDriverOSAdaptionDObject( aOSAdaption ) |
574 { |
564 { |
575 return aObject.MaxSize(); |
565 return aObject.MaxSize(); |
576 } |
566 } |
577 |
567 |
578 |
568 |
579 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aChunk ) const |
569 TUint8* DMemSpyDriverOSAdaptionDChunk::GetBase( DChunk& aObject ) const |
580 { |
570 { |
581 TUint8* base = aChunk.Base(); |
571 return aObject.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; |
|
605 } |
572 } |
606 |
573 |
607 |
574 |
608 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const |
575 DProcess* DMemSpyDriverOSAdaptionDChunk::GetOwningProcess( DChunk& aObject ) const |
609 { |
576 { |