|
1 // MemoryAccess.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 //#include <m32std.h> |
|
14 #include <nkern.h> |
|
15 #include <kernel.h> |
|
16 #include <kern_priv.h> |
|
17 |
|
18 #include <fshell/common.mmh> |
|
19 |
|
20 #ifdef FSHELL_DOBJECTIX_SUPPORT |
|
21 #include "dobject.h" // To pick up my defn of DObjectIx/DObjectIxNinePointOneHack |
|
22 #endif |
|
23 |
|
24 #include <e32cmn.h> |
|
25 #include "memoryaccess.h" |
|
26 #include "PropertyAccess.h" |
|
27 #include "fdebuggerkernel.h" |
|
28 #include "DynamicDfcSupport.h" |
|
29 |
|
30 //define this to get log output |
|
31 /*#define DO_LOGGING |
|
32 |
|
33 #ifdef DO_LOGGING |
|
34 #define DO_LOG(X) X |
|
35 #else |
|
36 #define DO_LOG(X) |
|
37 #endif */ |
|
38 |
|
39 const TInt KLocalBufferSize=4096; |
|
40 |
|
41 const TInt KMajorVersionNumber=1; |
|
42 const TInt KMinorVersionNumber=0; |
|
43 const TInt KBuildVersionNumber=0; |
|
44 _LIT(KMemAccessPanicCategory,"MemAccess"); |
|
45 enum TMemAccessPanic |
|
46 { |
|
47 EMemAccessPanicBadContainerType, |
|
48 EMemAccessMutexAlreadyHeld, |
|
49 EMemAccessMutexNotHeld |
|
50 }; |
|
51 |
|
52 class DMemoryAccess; |
|
53 |
|
54 // DMemoryAccessFactory |
|
55 // |
|
56 NONSHARABLE_CLASS(DMemoryAccessFactory) : public DLogicalDevice |
|
57 { |
|
58 public: |
|
59 DMemoryAccessFactory(); |
|
60 ~DMemoryAccessFactory(); |
|
61 |
|
62 TInt GetEventHandler(DDebuggerEventHandler*& aResult); |
|
63 TInt GetDfcQue(TDfcQue*& aResult); |
|
64 |
|
65 private: |
|
66 TInt Install(); //overriding pure virtual |
|
67 void GetCaps(TDes8& aDes) const; //overriding pure virtual |
|
68 TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual |
|
69 void Lock(); |
|
70 void Unlock(); |
|
71 |
|
72 private: |
|
73 DDebuggerEventHandler* iSharedEventHandler; |
|
74 TDynDfcQueWrapper* iDfcQueWrapper; |
|
75 NFastMutex iLock; |
|
76 }; |
|
77 |
|
78 |
|
79 // DECLARE_STANDARD_LDD |
|
80 // Standard Extension Framework export |
|
81 DECLARE_STANDARD_EXTENSION() |
|
82 { |
|
83 return KErrNone; |
|
84 } |
|
85 |
|
86 DECLARE_EXTENSION_LDD() |
|
87 { |
|
88 return new DMemoryAccessFactory(); |
|
89 } |
|
90 |
|
91 class DThreadChangeHandler; |
|
92 class DMsgQueue; |
|
93 |
|
94 // DMemoryAccess |
|
95 // |
|
96 NONSHARABLE_CLASS(DMemoryAccess) : public DLogicalChannel, public MDebuggerEventClient |
|
97 { |
|
98 public: |
|
99 DMemoryAccess(); |
|
100 ~DMemoryAccess(); |
|
101 private: |
|
102 //Framework |
|
103 TInt DoCreate(TInt aUnit,const TDesC* anInfo,const TVersion& aVer); |
|
104 void HandleMsg(TMessageBase* aMsg); |
|
105 void DoCancel(TInt aReqNo); |
|
106 TInt DoRequest(TInt aReqNo,TRequestStatus aStatus,TAny* a1,TAny* a2); |
|
107 TInt DoControl(TInt aFunction,TAny *a1,TAny *a2); |
|
108 //API |
|
109 TInt GetThreadMem(TAny* aParams, TAny* aBuf); |
|
110 TInt GetAllocatorAddress(TUint aId, TUint8*& aAddr, TBool aGetCurrentAllocator=EFalse); //TOMSCI If false, get the created allocator. If true, get the current one |
|
111 TInt GetContainerCount(const TObjectType aObjectType, TUint& aCount); |
|
112 TInt AcquireContainerMutex(const TObjectType aObjectType); |
|
113 TInt ReleaseContainerMutex(const TObjectType aObjectType); |
|
114 TInt GetObjectType(TUint8* aObjectPtr, TObjectType& aType); |
|
115 TInt GetObjectInfo(TObjectType aObjectType, TInt aObjectIndexInContainer, TDes8* aKernelInfoBuf); |
|
116 TInt GetObjectInfoByPtr(TObjectType aObjectType, TUint8* aObjectPtr, TDes8* aKernelInfoBuf); |
|
117 TInt GetObjectInfoByName(TObjectType aObjectType, const TDesC8& aObjectName, TDes8* aKernelInfoBuf); |
|
118 TInt GetObjectInfoByHandle(TObjectType aObjectType, TInt aThreadId, TInt aObjectHandle, TDes8* aKernelInfoBuf); |
|
119 TInt GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf); |
|
120 TInt GetChunkAddresses(TUint aControllingProcessId, TDes8* aKernelInfoBuf); |
|
121 TInt AcquireCodeSegMutex(); |
|
122 TInt ReleaseCodeSegMutex(); |
|
123 TInt GetNextCodeSegInfo(TDes8* aCodeSegInfoBuf); |
|
124 TInt ObjectDie(TObjectKillParamsBuf& aObjectKillParamsBuf); |
|
125 TInt FindPtrInCodeSegments(TAny* aDllNamePtr, TAny* aPtr); |
|
126 TInt GetHandleOwners(TAny* aObj, TAny* aOwnersBuf); |
|
127 TInt GetThreadHandles(TInt aThreadId, TAny* aHandlesBuf); |
|
128 TInt GetProcessHandles(TInt aProcessId, TAny* aHandlesBuf); |
|
129 TInt SetThreadPriority(TInt aThreadHandle, TInt aPriority); |
|
130 void NotifyThreadCreation(TRequestStatus* aStatus); |
|
131 void CancelNotifyThreadCreation(); |
|
132 TInt SetPriorityOverride(TInt aPriority, TAny* aMatchString); |
|
133 TInt SetCriticalFlags(TInt aThreadHandle, TUint aFlags); |
|
134 TInt OpenThread(TUint aTid); |
|
135 //Helpers |
|
136 void GetObjectInfo(DObject* aObject, TObjectKernelInfo& aInfo); |
|
137 TInt GetObjectPositionInContainer(TUint8* aObjectPtr, DObjectCon& aContainer, TInt& aPosInContainer); |
|
138 TInt GetThreadInfo(DThread* aThread, TDes8* aThreadInfoBuf); |
|
139 TInt GetProcessInfo(DProcess* aProcess, TDes8* aProcessInfoBuf); |
|
140 TInt GetChunkInfo(DChunk* aChunk, TDes8* aChunkInfoBuf); |
|
141 TInt GetLibraryInfo(DLibrary* aLibrary, TDes8* aLibraryInfoBuf); |
|
142 TInt GetSemaphoreInfo(DSemaphore* aSemaphore, TDes8* aLibraryInfoBuf); |
|
143 TInt GetMutexInfo(DMutex* aMutex, TDes8* aLibraryInfoBuf); |
|
144 TInt GetTimerInfo(DTimer* aTimer, TDes8* aTimerInfoBuf); |
|
145 TInt GetServerInfo(DServer* aServer, TDes8* aServerInfoBuf); |
|
146 TInt GetSessionInfo(DSession* aSession, TDes8* aSessionInfoBuf); |
|
147 TInt GetLogicalDeviceInfo(DLogicalDevice* aLogicalDevice, TDes8* aLogicalDeviceInfoBuf); |
|
148 TInt GetPhysicalDeviceInfo(DPhysicalDevice* aPhysicalDevice, TDes8* aPhysicalDeviceInfoBuf); |
|
149 TInt GetLogicalChannelInfo(DLogicalChannel* aLogicalChannel, TDes8* aLogicalChannelInfoBuf); |
|
150 TInt GetChangeNotifierInfo(DChangeNotifier* aChangeNotifier, TDes8* aChangeNotifierInfoBuf); |
|
151 TInt GetUndertakerInfo(DUndertaker* aUndertaker, TDes8* aUndertakerInfoBuf); |
|
152 TInt GetMsgQueueInfo(DMsgQueue* aMsgQueue, TDes8* aMsgQueueInfoBuf); |
|
153 // TInt GetPropertyRefInfo(DPropertyRef* aPropertyRef, TDes8* aPropertyRefInfoBuf); |
|
154 TInt GetCondVarInfo(DCondVar* aCondVar, TDes8* aCondVarInfoBuf); |
|
155 TInt InPlaceObjectRename(TAny* aParamsBuf, TAny* aNewNamePtr); |
|
156 TInt InPlaceSetProcessFileName(TAny* aParamsBuf, TAny* aNewNamePtr); |
|
157 TLinAddr DoGetAllocatorAddress(DThread* aThread, TBool aGetCurrent); |
|
158 TInt EnableHeapTracing(TUint aThreadId, TBool aEnable); |
|
159 TInt DefragRam(TInt aPriority); |
|
160 TInt EmptyRamZone(TInt aPriority, TUint aZone); |
|
161 TInt GetRamZoneInfo(TUint aZone, TAny* aInfoPkg); |
|
162 TInt SetProcessProperties(TInt aProcessHandle, TAny* aProperties); |
|
163 TInt WriteShadowMemory(TLinAddr aAddress, TAny* aNewContents); |
|
164 TInt FreeShadowMemory(TLinAddr aAddress, TInt aLength); |
|
165 TInt DebuggerFn(TInt aFn, TAny* a1, TAny* a2); |
|
166 TInt GetRegisters(TAny* a1, TAny* /*a2*/); |
|
167 DThread* ThreadFromHandle(TInt aHandle); |
|
168 |
|
169 |
|
170 private: // From MDebuggerEventClient |
|
171 void BreakpointHit(TDes& aPkg); |
|
172 |
|
173 private: |
|
174 DThread* iClient; |
|
175 TBool iLocks[ENumObjectTypes]; |
|
176 TBool iCodeSegLock; |
|
177 DCodeSeg* iCurrentCodeSeg; |
|
178 DThreadChangeHandler* iEventHandler; |
|
179 DPropertyAccess* iPropertyAccess; |
|
180 TAny* iClientBreakpointNotifyPkg; |
|
181 TRequestStatus* iClientBreakpointNotifyStatus; |
|
182 }; |
|
183 |
|
184 |
|
185 NONSHARABLE_CLASS(DThreadChangeHandler) : public DKernelEventHandler |
|
186 { |
|
187 public: |
|
188 DThreadChangeHandler(DThread* aClientThread); |
|
189 ~DThreadChangeHandler(); |
|
190 static TUint Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData); |
|
191 TUint DoEvent(TKernelEvent aEvent, TAny* a1, TAny* a2); |
|
192 void SetStatus(TRequestStatus* aStatus); |
|
193 |
|
194 private: |
|
195 DThread* iThread; |
|
196 TRequestStatus* iStatus; |
|
197 public: |
|
198 TBuf8<256> iMatch; |
|
199 TInt iPriorityToSet; |
|
200 }; |
|
201 |
|
202 // class DMemoryAccessFactory Implementation |
|
203 |
|
204 // |
|
205 // |
|
206 DMemoryAccessFactory::DMemoryAccessFactory() |
|
207 { |
|
208 iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
209 } |
|
210 |
|
211 // DMemoryAccessFactory::Create |
|
212 // |
|
213 TInt DMemoryAccessFactory::Create(DLogicalChannelBase*& aChannel) |
|
214 { |
|
215 aChannel=new DMemoryAccess(); |
|
216 if (aChannel==NULL) |
|
217 return KErrNoMemory; |
|
218 else |
|
219 return KErrNone; |
|
220 } |
|
221 |
|
222 // DMemoryAccessFactory::Install |
|
223 // |
|
224 TInt DMemoryAccessFactory::Install() |
|
225 { |
|
226 TInt err = SetName(&KMemoryAccessName); |
|
227 if (err == KErrNone) |
|
228 { |
|
229 DDebuggerEventHandler* dontCare; |
|
230 err = GetEventHandler(dontCare); // We call this to make sure the event handler is always running, so we can track creator info asap |
|
231 } |
|
232 return err; |
|
233 } |
|
234 |
|
235 // DMemoryAccessFactory::GetCaps |
|
236 // |
|
237 void DMemoryAccessFactory::GetCaps(TDes8& /*aDes*/) const |
|
238 { |
|
239 /* TCapsMemoryAccessV01 b; |
|
240 b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber); |
|
241 aDes.FillZ(aDes.MaxLength()); |
|
242 aDes.Copy((TUint8*)&b,Min(aDes.MaxLength(),sizeof(b))); |
|
243 */ } |
|
244 |
|
245 |
|
246 // class DMemoryAccess Implementation |
|
247 |
|
248 // Ctor |
|
249 // |
|
250 DMemoryAccess::DMemoryAccess() |
|
251 : DLogicalChannel() |
|
252 { |
|
253 //SetBehaviour(-1); //JR |
|
254 } |
|
255 |
|
256 |
|
257 const TInt KMemAccessDfcThreadPriority = 27; |
|
258 |
|
259 // DMemoryAccess::DoCreate |
|
260 // Check capabilities & version & start listening for events |
|
261 TInt DMemoryAccess::DoCreate(TInt /*aUnit*/,const TDesC* /*anInfo*/,const TVersion& aVer) |
|
262 { |
|
263 TInt ret=KErrNone; |
|
264 |
|
265 //Require Power Management to use this driver |
|
266 //Not ideal, but better than nothing |
|
267 //if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by MEMORYACCESS.LDD (Memory Access for Task Managers)"))) |
|
268 // return KErrPermissionDenied; |
|
269 |
|
270 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer)) |
|
271 { |
|
272 return KErrNotSupported; |
|
273 } |
|
274 iClient=&Kern::CurrentThread(); |
|
275 iClient->Open(); |
|
276 |
|
277 TDfcQue* q = NULL; |
|
278 ret = ((DMemoryAccessFactory*)iDevice)->GetDfcQue(q); |
|
279 |
|
280 if (ret == KErrNone) |
|
281 { |
|
282 SetDfcQ(q); |
|
283 iMsgQ.Receive(); |
|
284 } |
|
285 |
|
286 return ret; |
|
287 } |
|
288 |
|
289 TInt DMemoryAccessFactory::GetDfcQue(TDfcQue*& aQue) |
|
290 { |
|
291 Lock(); |
|
292 if (iDfcQueWrapper) |
|
293 { |
|
294 aQue = iDfcQueWrapper->Que(); |
|
295 Unlock(); |
|
296 return KErrNone; |
|
297 } |
|
298 Unlock(); // Can't hold a fast mutex around DFC q creation |
|
299 |
|
300 TDynDfcQueWrapper* wrapper = NULL; |
|
301 _LIT(KDfcThreadName, "MemoryAccess-fshell"); |
|
302 TInt ret = TDynDfcQueWrapper::Create(wrapper, KMemAccessDfcThreadPriority, KDfcThreadName); |
|
303 |
|
304 if (ret == KErrNone) |
|
305 { |
|
306 Lock(); |
|
307 if (iDfcQueWrapper) |
|
308 { |
|
309 // Someone beat us to it while we weren't holding the lock |
|
310 aQue = iDfcQueWrapper->Que(); |
|
311 Unlock(); |
|
312 wrapper->Destroy(); |
|
313 } |
|
314 else |
|
315 { |
|
316 iDfcQueWrapper = wrapper; |
|
317 aQue = iDfcQueWrapper->Que(); |
|
318 Unlock(); |
|
319 } |
|
320 } |
|
321 return ret; |
|
322 } |
|
323 |
|
324 |
|
325 // dtor |
|
326 // |
|
327 DMemoryAccess::~DMemoryAccess() |
|
328 { |
|
329 //Clean up any mutexes that have been left open |
|
330 DObjectCon* const * cons = Kern::Containers(); |
|
331 for (TInt ii=0;ii<ENumObjectTypes;++ii) |
|
332 { |
|
333 if (iLocks[ii]) |
|
334 { |
|
335 DObjectCon* container = cons[ii]; |
|
336 container->Signal(); |
|
337 } |
|
338 } |
|
339 |
|
340 DMutex* const codeSegLock = Kern::CodeSegLock(); |
|
341 |
|
342 if (iCodeSegLock && codeSegLock) |
|
343 { |
|
344 Kern::MutexSignal(*codeSegLock); |
|
345 } |
|
346 |
|
347 if (iClientBreakpointNotifyStatus) |
|
348 { |
|
349 // Hmm I'm sure there are some threading subtleties here that I'm missing |
|
350 DDebuggerEventHandler* handler = NULL; |
|
351 TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler); |
|
352 if (!err) handler->UnregisterForBreakpointNotification(this); |
|
353 Kern::RequestComplete(iClient, iClientBreakpointNotifyStatus, KErrCancel); |
|
354 } |
|
355 |
|
356 if (iEventHandler) |
|
357 { |
|
358 NKern::ThreadEnterCS(); |
|
359 iEventHandler->Close(); |
|
360 NKern::ThreadLeaveCS(); |
|
361 } |
|
362 |
|
363 delete iPropertyAccess; |
|
364 if (iClient) |
|
365 { |
|
366 iClient->Close(NULL); |
|
367 } |
|
368 } |
|
369 |
|
370 // DMemoryAccess::HandleMsg |
|
371 // Called when user side sends us something |
|
372 void DMemoryAccess::HandleMsg(TMessageBase* aMsg) |
|
373 { |
|
374 TThreadMessage& m=*(TThreadMessage*)aMsg; |
|
375 |
|
376 // Get message type |
|
377 TInt id=m.iValue; |
|
378 |
|
379 // Decode the message type and dispatch it to the relevent handler function... |
|
380 |
|
381 // A logical channel can be closed either explicitly by its user-side client, |
|
382 // or implicitly if the client thread dies. In the latter case, the channel |
|
383 // is closed in the context of the kernel supervisor thread. |
|
384 |
|
385 if (id==(TInt)ECloseMsg) |
|
386 { |
|
387 // Channel Close |
|
388 // We don't actually have any async requests |
|
389 //DoCancel(RMemoryAccess::EAllRequests); //JR |
|
390 m.Complete(KErrNone, EFalse); |
|
391 return; |
|
392 } |
|
393 |
|
394 // For all other message types, we check that the message is from the thread |
|
395 // that created us. |
|
396 if(m.Client()!=iClient) |
|
397 { |
|
398 Kern::ThreadKill(m.Client(),EExitPanic,ERequestFromWrongThread,KMemAccessPanicCategory); |
|
399 m.Complete(KErrNone,ETrue); |
|
400 return; |
|
401 } |
|
402 if (id==KMaxTInt) |
|
403 { |
|
404 // DoCancel |
|
405 DoCancel(m.Int0()); |
|
406 m.Complete(KErrNone,ETrue); |
|
407 return; |
|
408 } |
|
409 if (id<0) |
|
410 { |
|
411 // DoRequest |
|
412 TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); |
|
413 TInt r=DoRequest(~id, *pS, m.Ptr1(), m.Ptr2()); |
|
414 if (r!=KErrNone) |
|
415 Kern::RequestComplete(iClient,pS,r); |
|
416 m.Complete(KErrNone,ETrue); |
|
417 } |
|
418 else |
|
419 { |
|
420 // DoControl |
|
421 TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); |
|
422 m.Complete(r,ETrue); |
|
423 } |
|
424 } |
|
425 |
|
426 // DMemoryAccess::DoRequest |
|
427 // Handles async messages, called from HandleMsg |
|
428 TInt DMemoryAccess::DoRequest(TInt /*aReqNo*/, TRequestStatus /*aStatus*/, TAny* /*a1*/, TAny* /*a2*/) |
|
429 { |
|
430 return KErrNone; |
|
431 } |
|
432 |
|
433 // DMemoryAccess::DoCancel |
|
434 // Cancels async messages, called from HandleMsg |
|
435 void DMemoryAccess::DoCancel(TInt /*aReqNo*/) |
|
436 { |
|
437 } |
|
438 |
|
439 // DMemoryAccess::DoControl |
|
440 // Handles sync messages, called from HandleMsg |
|
441 TInt DMemoryAccess::DoControl(TInt aFunction, TAny* a1, TAny* a2) |
|
442 { |
|
443 // Kern::Printf("[DMemoryAccess] ::DoControl; Function: %d", aFunction); |
|
444 switch (aFunction) |
|
445 { |
|
446 case RMemoryAccess::EControlGetThreadMem: |
|
447 return GetThreadMem(a1, a2); |
|
448 case RMemoryAccess::EControlGetAllocatorAddress: |
|
449 return GetAllocatorAddress((TUint)a1, *(TUint8**)a2); |
|
450 case RMemoryAccess::EControlGetCurrentAllocatorAddress: |
|
451 return GetAllocatorAddress((TUint)a1, *(TUint8**)a2, ETrue); |
|
452 case RMemoryAccess::EControlFindPtrInCodeSegments: |
|
453 return FindPtrInCodeSegments(a1, a2); |
|
454 case RMemoryAccess::EControlGetHandleOwners: |
|
455 return GetHandleOwners(a1, a2); |
|
456 case RMemoryAccess::EControlGetThreadHandles: |
|
457 return GetThreadHandles((TUint)a1, a2); |
|
458 case RMemoryAccess::EControlGetProcessHandles: |
|
459 return GetProcessHandles((TUint)a1, a2); |
|
460 case RMemoryAccess::EControlForceCrash: |
|
461 Kern::Fault("ForceCrash-QR3", 0); |
|
462 return KErrNone; |
|
463 case RMemoryAccess::EControlReboot: |
|
464 Kern::Restart((TInt)a1); |
|
465 return KErrNone; |
|
466 case RMemoryAccess::EControlGetPropertyInt: |
|
467 case RMemoryAccess::EControlGetPropertyDesc: |
|
468 case RMemoryAccess::EControlSetPropertyInt: |
|
469 case RMemoryAccess::EControlSetPropertyDesc: |
|
470 case RMemoryAccess::EControlDeleteProperty: |
|
471 case RMemoryAccess::EControlPropertyNotify: |
|
472 case RMemoryAccess::EControlPropertyNotifyCancel: |
|
473 case RMemoryAccess::EControlSubscribeToProperty: |
|
474 if (!iPropertyAccess) |
|
475 { |
|
476 iPropertyAccess = new DPropertyAccess(iClient); |
|
477 } |
|
478 if (!iPropertyAccess) return KErrNoMemory; |
|
479 return iPropertyAccess->HandleProperty(aFunction, a1, a2); |
|
480 case RMemoryAccess::EControlSetThreadPriority: |
|
481 return SetThreadPriority((TInt)a1, (TInt)a2); |
|
482 case RMemoryAccess::EControlNotifyThreadCreation: |
|
483 NotifyThreadCreation((TRequestStatus*)a1); |
|
484 return KErrNone; |
|
485 case RMemoryAccess::EControlCancelNotifyThreadCreation: |
|
486 CancelNotifyThreadCreation(); |
|
487 return KErrNone; |
|
488 case RMemoryAccess::EControlSetPriorityOverride: |
|
489 return SetPriorityOverride((TInt)a1, a2); |
|
490 case RMemoryAccess::EControlSetCriticalFlags: |
|
491 return SetCriticalFlags((TInt)a1, (TUint)a2); |
|
492 case RMemoryAccess::EControlInPlaceThreadRename: |
|
493 { |
|
494 DThread* thread = ThreadFromHandle((TInt)a1); |
|
495 if (!thread) return 0; |
|
496 TBuf<64> buf; |
|
497 TInt err = Kern::ThreadDesRead(iClient, a2, buf, 0); |
|
498 if (err) |
|
499 { |
|
500 thread->Close(NULL); |
|
501 return err; |
|
502 } |
|
503 thread->iName->Copy(buf); |
|
504 TLinAddr addr = (TLinAddr)thread->iName; |
|
505 thread->Close(NULL); |
|
506 return addr; |
|
507 } |
|
508 case RMemoryAccess::EControlInPlaceObjectRename: |
|
509 return InPlaceObjectRename(a1, a2); |
|
510 case RMemoryAccess::EControlInPlaceSetProcessFileName: |
|
511 return InPlaceSetProcessFileName(a1, a2); |
|
512 case RMemoryAccess::EControlOpenThread: |
|
513 return OpenThread((TUint)a1); |
|
514 case RMemoryAccess::EControlResetTimer: |
|
515 return KErrNone; |
|
516 case RMemoryAccess::EControlGetContainerCount: |
|
517 return GetContainerCount(*(TObjectType*)&a1, *(TUint*)a2); |
|
518 case RMemoryAccess::EControlAcquireContainerMutex: |
|
519 return AcquireContainerMutex(*(TObjectType*)&a1); |
|
520 case RMemoryAccess::EControlReleaseContainerMutex: |
|
521 return ReleaseContainerMutex(*(TObjectType*)&a1); |
|
522 case RMemoryAccess::EControlGetObjectType: |
|
523 return GetObjectType((TUint8*)a1, *(TObjectType*)a2); |
|
524 case RMemoryAccess::EControlGetObjectInfo: |
|
525 { |
|
526 TObjectInfoByIndexParamsBuf params; |
|
527 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
528 if (err == KErrNone) |
|
529 { |
|
530 err = GetObjectInfo(params().iObjectType, params().iObjectIndex, (TDes8*)a2); |
|
531 } |
|
532 return err; |
|
533 } |
|
534 case RMemoryAccess::EControlGetObjectInfoByPtr: |
|
535 { |
|
536 TObjectInfoByPtrParamsBuf params; |
|
537 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
538 if (err == KErrNone) |
|
539 { |
|
540 err = GetObjectInfoByPtr(params().iObjectType, params().iObjectPtr, (TDes8*)a2); |
|
541 } |
|
542 return err; |
|
543 } |
|
544 case RMemoryAccess::EControlGetObjectInfoByName: |
|
545 { |
|
546 TObjectInfoByNameParamsBuf params; |
|
547 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
548 if (err == KErrNone) |
|
549 { |
|
550 err = GetObjectInfoByName(params().iObjectType, params().iObjectName, (TDes8*)a2); |
|
551 } |
|
552 return err; |
|
553 } |
|
554 case RMemoryAccess::EControlGetObjectInfoByHandle: |
|
555 { |
|
556 TObjectInfoByHandleParamsBuf params; |
|
557 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
558 if (err == KErrNone) |
|
559 { |
|
560 err = GetObjectInfoByHandle(params().iObjectType, params().iThreadId, params().iObjectHandle, (TDes8*)a2); |
|
561 } |
|
562 return err; |
|
563 } |
|
564 case RMemoryAccess::EControlAcquireCodeSegMutex: |
|
565 return AcquireCodeSegMutex(); |
|
566 case RMemoryAccess::EControlReleaseCodeSegMutex: |
|
567 return ReleaseCodeSegMutex(); |
|
568 case RMemoryAccess::EControlGetNextCodeSegInfo: |
|
569 return GetNextCodeSegInfo((TDes8*)a1); |
|
570 case RMemoryAccess::EControlObjectDie: |
|
571 { |
|
572 TObjectKillParamsBuf params; |
|
573 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
574 if (err == KErrNone) |
|
575 { |
|
576 err = ObjectDie(params); |
|
577 } |
|
578 return err; |
|
579 } |
|
580 case RMemoryAccess::EControlGetObjectAddresses: |
|
581 { |
|
582 TGetObjectAddressesParamsBuf params; |
|
583 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
584 if (err == KErrNone) |
|
585 { |
|
586 err = GetObjectAddresses(params().iObjectType,params().iOwningProcess,(TDes8*)a2); |
|
587 } |
|
588 return err; |
|
589 } |
|
590 case RMemoryAccess::EControlGetChunkAddresses: |
|
591 { |
|
592 TGetChunkAddressesParamsBuf params; |
|
593 TInt err = Kern::ThreadDesRead(iClient,a1,params,0); |
|
594 if (err == KErrNone) |
|
595 { |
|
596 err = GetChunkAddresses(params().iControllingProcessId,(TDes8*)a2); |
|
597 } |
|
598 return err; |
|
599 } |
|
600 case RMemoryAccess::EControlEnableHeapTracing: |
|
601 return EnableHeapTracing((TUint)a1, (TBool)a2); |
|
602 case RMemoryAccess::EControlDefragRam: |
|
603 return DefragRam((TInt)a1); |
|
604 case RMemoryAccess::EControlEmptyRamZone: |
|
605 return EmptyRamZone((TInt)a1, (TUint)a2); |
|
606 case RMemoryAccess::EControlGetRamZoneInfo: |
|
607 return GetRamZoneInfo((TUint)a1, a2); |
|
608 case RMemoryAccess::EControlSetProcessProperties: |
|
609 return SetProcessProperties((TInt)a1, a2); |
|
610 case RMemoryAccess::EControlWriteShadowMemory: |
|
611 return WriteShadowMemory((TLinAddr)a1, a2); |
|
612 case RMemoryAccess::EControlFreeShadowMemory: |
|
613 return FreeShadowMemory((TLinAddr)a1, (TInt)a2); |
|
614 case RMemoryAccess::EControlGetZombieDebugMode: |
|
615 case RMemoryAccess::EControlSetZombieDebugMode: |
|
616 case RMemoryAccess::EControlGetZombies: |
|
617 case RMemoryAccess::EControlReleaseZombie: |
|
618 case RMemoryAccess::EControlSuspendThread: |
|
619 case RMemoryAccess::EControlNotifyBreakpoint: |
|
620 case RMemoryAccess::EControlSetBreakpoint: |
|
621 case RMemoryAccess::EControlSetBreakpointEnabled: |
|
622 case RMemoryAccess::EControlClearBreakpoint: |
|
623 case RMemoryAccess::EControlContinueFromBreakpoint: |
|
624 case RMemoryAccess::EControlGetBreakpoints: |
|
625 case RMemoryAccess::EControlCancelNotifyBreakpoint: |
|
626 case RMemoryAccess::EControlRegisterPersistantBreakpoint: |
|
627 case RMemoryAccess::EControlSetSymbolicBreakpoint: |
|
628 return DebuggerFn(aFunction, a1, a2); |
|
629 case RMemoryAccess::EControlWriteMem: |
|
630 { |
|
631 TAny* args[3]; |
|
632 TInt err = Kern::ThreadRawRead(iClient, a1, &args, 3*sizeof(TAny*)); |
|
633 if (err) return err; |
|
634 TUint targetId = (TUint)args[0]; |
|
635 TAny* srcAddr = args[1]; |
|
636 TAny* destAddr = args[2]; |
|
637 Kern::Containers()[EThread]->Wait(); |
|
638 DThread* target = Kern::ThreadFromId(targetId); |
|
639 if (target) target->Open(); |
|
640 Kern::Containers()[EThread]->Signal(); |
|
641 if (!target) return KErrNotFound; |
|
642 TInt dataLen = Kern::ThreadGetDesLength(iClient, srcAddr); |
|
643 if (dataLen <= 0) err = dataLen; |
|
644 TAny* mem = NULL; |
|
645 if (!err) mem = Kern::Alloc(dataLen); |
|
646 if (!mem) err = KErrNoMemory; |
|
647 TPtr8 bah((TUint8*)mem, 0, dataLen); |
|
648 if (!err) err = Kern::ThreadDesRead(iClient, srcAddr, bah, dataLen); |
|
649 if (!err) err = Kern::ThreadRawWrite(target, destAddr, mem, dataLen); |
|
650 Kern::Free(mem); |
|
651 target->Close(NULL); |
|
652 return err; |
|
653 } |
|
654 #ifdef FSHELL_BTRACE_SUPPORT // SetTextTraceMode went in at the same time as btrace, afaik |
|
655 case RMemoryAccess::EControlSetTextTraceMode: |
|
656 { |
|
657 TUint traceMode = 0; |
|
658 TInt err = Kern::ThreadRawRead(iClient, a1, &traceMode, sizeof(TUint)); |
|
659 if (!err) |
|
660 { |
|
661 TUint origMode = Kern::SetTextTraceMode(traceMode, (TUint)a2); |
|
662 err = Kern::ThreadRawWrite(iClient, a1, &origMode, sizeof(TUint)); |
|
663 } |
|
664 return err; |
|
665 } |
|
666 #endif |
|
667 case RMemoryAccess::EControlGetRegisters: |
|
668 return GetRegisters(a1, a2); |
|
669 case RMemoryAccess::EControlSetDebugPort: |
|
670 Kern::SuperPage().iDebugPort = (TInt)a1; |
|
671 return KErrNone; |
|
672 case RMemoryAccess::EControlGetCreatorThread: |
|
673 { |
|
674 DDebuggerEventHandler* handler = NULL; |
|
675 TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler); |
|
676 if (err) return err; |
|
677 TUint creator = handler->GetCreatorThread((TUint)a1); |
|
678 if (creator == 0) |
|
679 { |
|
680 err = KErrNotFound; |
|
681 } |
|
682 else |
|
683 { |
|
684 err = Kern::ThreadRawWrite(iClient, a2, &creator, sizeof(TUint)); |
|
685 } |
|
686 return err; |
|
687 } |
|
688 default: |
|
689 return KErrNotSupported; |
|
690 } |
|
691 } |
|
692 |
|
693 // DMemoryAccess::GetThreadMem |
|
694 // Gets a buffer of memory from a thread |
|
695 TInt DMemoryAccess::GetThreadMem(TAny* aParams, TAny* aBuf) |
|
696 { |
|
697 TThreadMemoryAccessParams params; |
|
698 TPckg<TThreadMemoryAccessParams> paramsBuf(params); |
|
699 TInt err = Kern::ThreadDesRead(iClient, aParams, paramsBuf, 0); |
|
700 if (err) return err; |
|
701 |
|
702 // Copy the memory in page-sized chunks, so we don't have to allocate a huge buffer kernel-side |
|
703 TInt localBufSize = Min(params.iSize, KLocalBufferSize); |
|
704 HBuf8* localBuf = HBuf8::New(localBufSize); |
|
705 if (!localBuf) return KErrNoMemory; |
|
706 |
|
707 Kern::Containers()[EThread]->Wait(); |
|
708 DThread* thread = Kern::ThreadFromId(params.iId); |
|
709 if (thread) thread->Open(); |
|
710 Kern::Containers()[EThread]->Signal(); |
|
711 if (!thread) |
|
712 { |
|
713 delete localBuf; |
|
714 return KErrNotFound; |
|
715 } |
|
716 |
|
717 TInt bytesCopied = 0; |
|
718 TUint8* localPtr = (TUint8*)localBuf->Ptr(); |
|
719 while (!err && bytesCopied < params.iSize) |
|
720 { |
|
721 TInt toCopy = Min(params.iSize - bytesCopied, localBufSize); |
|
722 localBuf->SetLength(toCopy); |
|
723 err = Kern::ThreadRawRead(thread, params.iAddr + bytesCopied, localPtr, toCopy); |
|
724 if (err) break; |
|
725 err = Kern::ThreadDesWrite(iClient, aBuf, *localBuf, bytesCopied, 0, NULL); |
|
726 bytesCopied += toCopy; |
|
727 } |
|
728 delete localBuf; |
|
729 thread->Close(NULL); |
|
730 return err; |
|
731 } |
|
732 |
|
733 // DMemoryAccess::GetHeapBase |
|
734 // Gets the base addess of a thread's heap |
|
735 TInt DMemoryAccess::GetAllocatorAddress(TUint aId, TUint8*& aAddr, TBool aGetCurrent) |
|
736 { |
|
737 TInt err = KErrNone; |
|
738 |
|
739 //Acquire the threads container mutex |
|
740 DObjectCon* const * cons = Kern::Containers(); |
|
741 DObjectCon* threads = cons[EThread]; |
|
742 threads->Wait(); |
|
743 |
|
744 NKern::ThreadEnterCS(); |
|
745 DThread* thread = Kern::ThreadFromId(aId); |
|
746 if (thread) thread->Open(); |
|
747 NKern::ThreadLeaveCS(); |
|
748 |
|
749 threads->Signal(); |
|
750 |
|
751 if (!thread) |
|
752 err = KErrNotFound; |
|
753 |
|
754 if (!err) |
|
755 { |
|
756 TLinAddr allocator = DoGetAllocatorAddress(thread, aGetCurrent); |
|
757 thread->Close(NULL); |
|
758 err = Kern::ThreadRawWrite(iClient, &aAddr, (TUint8*)&allocator, sizeof(TUint8*)); |
|
759 } |
|
760 return err; |
|
761 } |
|
762 |
|
763 TLinAddr DMemoryAccess::DoGetAllocatorAddress(DThread* aThread, TBool aGetCurrent) |
|
764 { |
|
765 RAllocator* allocator = NULL; |
|
766 |
|
767 allocator = aGetCurrent ? aThread->iAllocator : aThread->iCreatedAllocator; |
|
768 if (!allocator) |
|
769 { |
|
770 // Check if it's a kernel thread |
|
771 Kern::Containers()[EProcess]->Wait(); |
|
772 DProcess* kernProc = Kern::ProcessFromId(1); |
|
773 Kern::Containers()[EProcess]->Signal(); |
|
774 if (aThread->iOwningProcess == kernProc) |
|
775 { |
|
776 // GeorgeN's cunning approach - the kern DProcess is one of the first things allocated to the kern heap and the heap is page aligned, so rounding down the dprocess pointer will give you the RHeapK addresss |
|
777 allocator = (RAllocator*)(Kern::RoundToPageSize((TLinAddr)kernProc) - Kern::RoundToPageSize(1)); |
|
778 } |
|
779 } |
|
780 |
|
781 return (TLinAddr)allocator; |
|
782 } |
|
783 |
|
784 // DMemoryAccess::GetContainerCount |
|
785 // Gets the object count of a kernel container specified by aObjectType |
|
786 TInt DMemoryAccess::GetContainerCount(const TObjectType aObjectType, TUint& aCount) |
|
787 { |
|
788 // Kern::Printf("[DMemoryAccess] ::GetContainerCount"); |
|
789 TInt err=KErrNone; |
|
790 if (aObjectType<0 || aObjectType>= ENumObjectTypes) |
|
791 { |
|
792 Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory); |
|
793 } |
|
794 |
|
795 DObjectCon* const * cons = Kern::Containers(); |
|
796 DObjectCon* container = cons[aObjectType]; |
|
797 container->Wait(); |
|
798 |
|
799 TUint count=container->Count(); |
|
800 err = Kern::ThreadRawWrite(iClient, &aCount, (TUint8*)&count, sizeof(TUint)); |
|
801 |
|
802 container->Signal(); |
|
803 // Kern::Printf("[DMemoryAccess] ::GetContainerCount returning %d; count %d",err,count); |
|
804 return err; |
|
805 } |
|
806 |
|
807 // DMemoryAccess::AcquireContainerMutex |
|
808 // Acquire a mutex on the specified kernel container |
|
809 // Must be called before attempting to retrieve any info from the container |
|
810 // Must only be called once per container |
|
811 TInt DMemoryAccess::AcquireContainerMutex(const TObjectType aObjectType) |
|
812 { |
|
813 // Kern::Printf("[DMemoryAccess] ::AcquireContainerMutex, object type %d", aObjectType); |
|
814 TInt err=KErrNone; |
|
815 if (aObjectType<0 || aObjectType>= ENumObjectTypes) |
|
816 { //Check this is a valid container type |
|
817 Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory); |
|
818 err=KErrArgument; |
|
819 } |
|
820 else |
|
821 { |
|
822 //Make sure none of the containers are already locked |
|
823 for (TInt ii=0; ii<ENumObjectTypes;ii++) |
|
824 { |
|
825 if (iLocks[ii]) |
|
826 { //Check the lock on this container is not currently held |
|
827 Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexAlreadyHeld,KMemAccessPanicCategory); |
|
828 } |
|
829 } |
|
830 |
|
831 DObjectCon* const * cons = Kern::Containers(); |
|
832 DObjectCon* container = cons[aObjectType]; |
|
833 container->Wait(); |
|
834 |
|
835 iLocks[aObjectType]=ETrue; |
|
836 } |
|
837 // Kern::Printf("[DMemoryAccess] ::AcquireContainerMutex returning %d", err); |
|
838 return err; |
|
839 } |
|
840 |
|
841 // DMemoryAccess::ReleaseContainerMutex |
|
842 // Releases a mutex on the specified kernel container |
|
843 // Must only be called when the mutex on the container is already held |
|
844 TInt DMemoryAccess::ReleaseContainerMutex(const TObjectType aObjectType) |
|
845 { |
|
846 // Kern::Printf("[DMemoryAccess] ::ReleaseContainerMutex, object type %d", aObjectType); |
|
847 TInt err=KErrNone; |
|
848 if (aObjectType<0 || aObjectType>= ENumObjectTypes) |
|
849 { //Check this is a valid container type |
|
850 Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory); |
|
851 err=KErrArgument; |
|
852 } |
|
853 if (!iLocks[aObjectType]) |
|
854 { //Check the lock on this container is currently held |
|
855 Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexNotHeld,KMemAccessPanicCategory); |
|
856 err=KErrGeneral; |
|
857 } |
|
858 |
|
859 if (err==KErrNone) |
|
860 { |
|
861 DObjectCon* const * cons = Kern::Containers(); |
|
862 DObjectCon* container = cons[aObjectType]; |
|
863 __ASSERT_MUTEX(container->Lock()); |
|
864 |
|
865 container->Signal(); |
|
866 iLocks[aObjectType]=EFalse; |
|
867 } |
|
868 // Kern::Printf("[DMemoryAccess] ::ReleaseContainerMutex returning %d", err); |
|
869 return err; |
|
870 } |
|
871 |
|
872 // DMemoryAccess::GetObjectInfo |
|
873 // Utility function to extract generic info from a DObject |
|
874 void DMemoryAccess::GetObjectInfo(DObject* aObject, TObjectKernelInfo& aInfo) |
|
875 { |
|
876 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo"); |
|
877 if (aObject) |
|
878 { |
|
879 aInfo.iAddressOfKernelObject=(TUint8*)aObject; |
|
880 aObject->FullName(aInfo.iFullName); |
|
881 aObject->Name(aInfo.iName); |
|
882 aInfo.iAccessCount=aObject->AccessCount(); |
|
883 aInfo.iUniqueID=aObject->UniqueID(); |
|
884 aInfo.iProtection=aObject->Protection(); |
|
885 aInfo.iAddressOfKernelOwner=(TUint8*)aObject->Owner(); |
|
886 } |
|
887 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo returning"); |
|
888 } |
|
889 |
|
890 // DMemoryAccess::GetObjectType |
|
891 // Finds the type of a kernel side DObject pointer by iterating the kernel containers |
|
892 // Requires that none of the kernel containers are already locked |
|
893 // returns KErrNotFound if the object does not exist in any of the kernel's containers |
|
894 TInt DMemoryAccess::GetObjectType(TUint8* aObjectPtr, TObjectType& aType) |
|
895 { |
|
896 // Kern::Printf("[DMemoryAccess] ::GetObjectType"); |
|
897 TInt err=KErrNotFound; |
|
898 //Make sure none of the containers are already locked |
|
899 for (TInt ii=0; ii<ENumObjectTypes;ii++) |
|
900 { |
|
901 if (iLocks[ii]) |
|
902 { //Check the lock on this container is not currently held |
|
903 Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexAlreadyHeld,KMemAccessPanicCategory); |
|
904 err=KErrGeneral; |
|
905 } |
|
906 } |
|
907 |
|
908 if (err==KErrNone || err==KErrNotFound) |
|
909 { |
|
910 // Kern::Printf("[DMemoryAccess] Looking for object 0x%08X",aObjectPtr); |
|
911 for (TInt ii=EThread; ii<ENumObjectTypes; ii++) |
|
912 { |
|
913 TInt posInContainer=KErrNotFound; |
|
914 DObjectCon* const * cons = Kern::Containers(); |
|
915 DObjectCon& container = *cons[ii]; |
|
916 container.Wait(); |
|
917 if (GetObjectPositionInContainer(aObjectPtr, container, posInContainer)==KErrNone) |
|
918 { |
|
919 // Kern::Printf("[DMemoryAccess] ::GetObjectType found type %d",ii); |
|
920 err = Kern::ThreadRawWrite(iClient, &aType, (TUint8*)&ii, sizeof(TObjectType)); |
|
921 ii=ENumObjectTypes; //prevent further loop iterations |
|
922 } |
|
923 container.Signal(); |
|
924 } |
|
925 } |
|
926 // Kern::Printf("[DMemoryAccess] ::GetObjectType returning %d",err); |
|
927 return err; |
|
928 } |
|
929 |
|
930 // DMemoryAccess::ObjectPositionInContainer |
|
931 // Finds the position in the aContainer of the aObjectPtr kernel object |
|
932 // Returns KErrNone if found, KErrNotFound if not |
|
933 // Position in container will be returned in aPosInContainer |
|
934 // The container mutex corresponding to the specified container must be already locked |
|
935 TInt DMemoryAccess::GetObjectPositionInContainer(TUint8* aObjectPtr, DObjectCon& aContainer, TInt& aPosInContainer) |
|
936 { |
|
937 // Kern::Printf("[DMemoryAccess] ::GetObjectPositionInContainer"); |
|
938 TInt err=KErrNotFound; |
|
939 aPosInContainer=KErrNotFound; |
|
940 |
|
941 for (TInt jj=0; jj<aContainer.Count();jj++) |
|
942 { |
|
943 DObject* obj = (DObject*)aContainer[jj]; |
|
944 if ((TUint8*)obj == aObjectPtr) |
|
945 { |
|
946 aPosInContainer=jj; |
|
947 err=KErrNone; |
|
948 continue; |
|
949 } |
|
950 } |
|
951 // Kern::Printf("[DMemoryAccess] ::GetObjectPositionInContainer returning %d; position %d",err,aPosInContainer); |
|
952 return err; |
|
953 } |
|
954 |
|
955 // DMemoryAccess::GetObjectInfo |
|
956 // Provides data about a kernel object |
|
957 // aObjectType specifies the type of object |
|
958 // aObjectIndexInContainer specifies the index of the required object in the respective kernel container |
|
959 // aKernelInfoBuf provides a buffer to populate with info. Should be a derived class of TObjectKernelInfo corresponding to the object type |
|
960 // The appropriate kernel container must already be locked |
|
961 TInt DMemoryAccess::GetObjectInfo(TObjectType aObjectType, TInt aObjectIndexInContainer, TDes8* aKernelInfoBuf) |
|
962 { |
|
963 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo"); |
|
964 TInt err=KErrNone; |
|
965 |
|
966 TBool alreadyHeld = iLocks[aObjectType]; |
|
967 if (!alreadyHeld) |
|
968 { |
|
969 // Automatically grab the lock |
|
970 DObjectCon* const * cons = Kern::Containers(); |
|
971 DObjectCon& container = *cons[aObjectType]; |
|
972 container.Wait(); |
|
973 iLocks[aObjectType] = ETrue; |
|
974 } |
|
975 |
|
976 if (!iLocks[aObjectType]) |
|
977 { //Check the lock on this container is currently held |
|
978 Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexNotHeld,KMemAccessPanicCategory); |
|
979 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo: No Lock!"); |
|
980 err=KErrGeneral; |
|
981 } |
|
982 else |
|
983 { |
|
984 DObjectCon* const * cons = Kern::Containers(); |
|
985 DObjectCon& container = *cons[aObjectType]; |
|
986 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Asserting lock..."); |
|
987 __ASSERT_MUTEX(container.Lock()); |
|
988 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Lock OK"); |
|
989 |
|
990 // Bounds check index: because we acquire and release the locks more, we risk the container changing size after the client has got the size |
|
991 if (aObjectIndexInContainer >= container.Count()) |
|
992 { |
|
993 err = KErrOverflow; |
|
994 goto returnAndReleaseLock; // Not elegant, and in fact the first goto I've used in over 5 years |
|
995 } |
|
996 |
|
997 DObject* object = (DObject*)container[aObjectIndexInContainer]; |
|
998 |
|
999 //Get the object info according to its type |
|
1000 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Calling specific function"); |
|
1001 switch (aObjectType) |
|
1002 { |
|
1003 case EThread: |
|
1004 err=GetThreadInfo((DThread*)object, aKernelInfoBuf); |
|
1005 break; |
|
1006 case EProcess: |
|
1007 err=GetProcessInfo((DProcess*)object, aKernelInfoBuf); |
|
1008 break; |
|
1009 case EChunk: |
|
1010 err=GetChunkInfo((DChunk*)object, aKernelInfoBuf); |
|
1011 break; |
|
1012 case ELibrary: |
|
1013 err=GetLibraryInfo((DLibrary*)object, aKernelInfoBuf); |
|
1014 break; |
|
1015 case ESemaphore: |
|
1016 err=GetSemaphoreInfo((DSemaphore*)object, aKernelInfoBuf); |
|
1017 break; |
|
1018 case EMutex: |
|
1019 err=GetMutexInfo((DMutex*)object, aKernelInfoBuf); |
|
1020 break; |
|
1021 case ETimer: |
|
1022 err=GetTimerInfo((DTimer*)object, aKernelInfoBuf); |
|
1023 break; |
|
1024 case EServer: |
|
1025 err=GetServerInfo((DServer*)object, aKernelInfoBuf); |
|
1026 break; |
|
1027 case ESession: |
|
1028 err=GetSessionInfo((DSession*)object, aKernelInfoBuf); |
|
1029 break; |
|
1030 case ELogicalDevice: |
|
1031 err=GetLogicalDeviceInfo((DLogicalDevice*)object, aKernelInfoBuf); |
|
1032 break; |
|
1033 case EPhysicalDevice: |
|
1034 err=GetPhysicalDeviceInfo((DPhysicalDevice*)object, aKernelInfoBuf); |
|
1035 break; |
|
1036 case ELogicalChannel: |
|
1037 err=GetLogicalChannelInfo((DLogicalChannel*)object, aKernelInfoBuf); |
|
1038 break; |
|
1039 case EChangeNotifier: |
|
1040 err=GetChangeNotifierInfo((DChangeNotifier*)object, aKernelInfoBuf); |
|
1041 break; |
|
1042 case EUndertaker: |
|
1043 err=GetUndertakerInfo((DUndertaker*)object, aKernelInfoBuf); |
|
1044 break; |
|
1045 case EMsgQueue: |
|
1046 err=GetMsgQueueInfo((DMsgQueue*)object, aKernelInfoBuf); |
|
1047 break; |
|
1048 case EPropertyRef: |
|
1049 // err=GetPropertyRefInfo((DPropertyRef*)object, aKernelInfoBuf); |
|
1050 break; |
|
1051 case ECondVar: |
|
1052 err=GetCondVarInfo((DCondVar*)object, aKernelInfoBuf); |
|
1053 break; |
|
1054 default: |
|
1055 err=KErrNotFound; |
|
1056 } |
|
1057 } |
|
1058 returnAndReleaseLock: |
|
1059 if (!alreadyHeld) |
|
1060 { |
|
1061 // Release the lock if we grabbed it automatically |
|
1062 DObjectCon* const * cons = Kern::Containers(); |
|
1063 DObjectCon& container = *cons[aObjectType]; |
|
1064 container.Signal(); |
|
1065 iLocks[aObjectType] = alreadyHeld; |
|
1066 } |
|
1067 //Kern::Printf("[DMemoryAccess] ::GetObjectInfo returning %d",err); |
|
1068 return err; |
|
1069 } |
|
1070 |
|
1071 // DMemoryAccess::GetObjectInfoByPtr |
|
1072 // Provides data about a kernel object |
|
1073 // aObjectType specifies the type of object |
|
1074 // aObjectPtr specifies address of the required DObject in the kernel |
|
1075 // aKernelInfoBuf provides a buffer to populate with info. Should be a derived class of TObjectKernelInfo corresponding to the object type |
|
1076 // No kernel container locks other than the one selected should be held |
|
1077 TInt DMemoryAccess::GetObjectInfoByPtr(TObjectType aObjectType, TUint8* aObjectPtr, TDes8* aKernelInfoBuf) |
|
1078 { |
|
1079 // Kern::Printf("[DMemoryAccess] ::GetObjectInfoByPtr"); |
|
1080 TInt posInContainer=KErrNotFound; |
|
1081 DObjectCon* const * cons = Kern::Containers(); |
|
1082 DObjectCon& container = *cons[aObjectType]; |
|
1083 container.Wait(); |
|
1084 TBool alreadyHeld = iLocks[aObjectType]; |
|
1085 iLocks[aObjectType] = ETrue; |
|
1086 |
|
1087 TInt err=GetObjectPositionInContainer(aObjectPtr,container,posInContainer); |
|
1088 |
|
1089 if (err==KErrNone) |
|
1090 err=GetObjectInfo(aObjectType, posInContainer, aKernelInfoBuf); |
|
1091 |
|
1092 container.Signal(); |
|
1093 iLocks[aObjectType] = alreadyHeld; |
|
1094 return err; |
|
1095 } |
|
1096 |
|
1097 // DMemoryAccess::GetObjectInfoByName |
|
1098 // Provides data about a kernel object |
|
1099 // aObjectType specifies the type of object |
|
1100 // aObjectName specifies name of the required DObject in the kernel |
|
1101 // aKernelInfoBuf provides a buffer to populate with info. Should be a derived class of TObjectKernelInfo corresponding to the object type |
|
1102 // No kernel container locks other than the one selected should be held |
|
1103 TInt DMemoryAccess::GetObjectInfoByName(TObjectType aObjectType, const TDesC8& aObjectName, TDes8* aKernelInfoBuf) |
|
1104 { |
|
1105 DObjectCon* const * cons = Kern::Containers(); |
|
1106 DObjectCon& container = *cons[aObjectType]; |
|
1107 container.Wait(); |
|
1108 TBool alreadyHeld = iLocks[aObjectType]; |
|
1109 iLocks[aObjectType] = ETrue; |
|
1110 |
|
1111 TInt err = KErrNotFound; |
|
1112 for (TInt jj=0; jj<container.Count();jj++) |
|
1113 { |
|
1114 DObject* obj = (DObject*)container[jj]; |
|
1115 TBuf8<KMaxFullName> fullName; |
|
1116 obj->FullName(fullName); |
|
1117 if (fullName == aObjectName) |
|
1118 { |
|
1119 err=GetObjectInfo(aObjectType, jj, aKernelInfoBuf); |
|
1120 break; |
|
1121 } |
|
1122 } |
|
1123 |
|
1124 container.Signal(); |
|
1125 iLocks[aObjectType] = alreadyHeld; |
|
1126 return err; |
|
1127 } |
|
1128 |
|
1129 // DMemoryAccess::GetObjectInfoByHandle |
|
1130 // Provides data about a kernel object |
|
1131 // aObjectType specifies the type of object |
|
1132 // aThreadHandle specifies the user side handle of the thread in which context to find the required object |
|
1133 // aObjectHandle specifies the user side handle of the required object |
|
1134 // aKernelInfoBuf provides a buffer to populate with info. Should be a derived class of TObjectKernelInfo corresponding to the object type |
|
1135 // No kernel container locks other than the one selected should be held |
|
1136 TInt DMemoryAccess::GetObjectInfoByHandle(TObjectType aObjectType, TInt aThreadId, TInt aObjectHandle, TDes8* aKernelInfoBuf) |
|
1137 { |
|
1138 // Kern::Printf("[DMemoryAccess] ::GetObjectInfoByHandle"); |
|
1139 TInt err=KErrNone; |
|
1140 |
|
1141 DObjectCon* const * cons = Kern::Containers(); |
|
1142 DObjectCon& container = *cons[EThread]; |
|
1143 container.Wait(); |
|
1144 NKern::ThreadEnterCS(); |
|
1145 DThread* thread = Kern::ThreadFromId(aThreadId); |
|
1146 NKern::ThreadLeaveCS(); |
|
1147 container.Signal(); |
|
1148 |
|
1149 if (!thread) |
|
1150 { |
|
1151 err=KErrNotFound; |
|
1152 } |
|
1153 else |
|
1154 { |
|
1155 DObject* object; |
|
1156 |
|
1157 if (aObjectHandle == (KCurrentThreadHandle&~KHandleNoClose)) |
|
1158 object = thread; |
|
1159 else if (aObjectHandle == (KCurrentProcessHandle&~KHandleNoClose)) |
|
1160 object = thread->iOwningProcess; |
|
1161 else |
|
1162 { |
|
1163 NKern::ThreadEnterCS(); |
|
1164 NKern::LockSystem(); |
|
1165 object = thread->ObjectFromHandle(aObjectHandle,aObjectType); |
|
1166 NKern::UnlockSystem(); |
|
1167 NKern::ThreadLeaveCS(); |
|
1168 } |
|
1169 |
|
1170 if (!object) |
|
1171 { |
|
1172 err=KErrNotFound; |
|
1173 } |
|
1174 else |
|
1175 { |
|
1176 err=GetObjectInfoByPtr(aObjectType, (TUint8*)object, aKernelInfoBuf); |
|
1177 } |
|
1178 } |
|
1179 |
|
1180 return err; |
|
1181 } |
|
1182 |
|
1183 |
|
1184 // DMemoryAccess::AcquireCodeSegMutex |
|
1185 // Acquires the code segment mutex |
|
1186 TInt DMemoryAccess::AcquireCodeSegMutex() |
|
1187 { |
|
1188 // Kern::Printf("[DMemoryAccess] ::AcquireCodeSegMutex"); |
|
1189 TInt err=KErrNone; |
|
1190 |
|
1191 if (iCodeSegLock) |
|
1192 { //Check the lock on code segs is not currently held |
|
1193 Kern::ThreadKill(iClient, EExitPanic, EMemAccessMutexAlreadyHeld, KMemAccessPanicCategory); |
|
1194 err = KErrAbort; |
|
1195 } |
|
1196 |
|
1197 DMutex* const codeSegLock = Kern::CodeSegLock(); |
|
1198 |
|
1199 if (!err) |
|
1200 { |
|
1201 if (codeSegLock) |
|
1202 { |
|
1203 Kern::MutexWait(*codeSegLock); |
|
1204 iCodeSegLock = ETrue; |
|
1205 } |
|
1206 else |
|
1207 { |
|
1208 err = KErrNotFound; |
|
1209 } |
|
1210 } |
|
1211 // Kern::Printf("[DMemoryAccess] ::AcquireCodeSegMutex returning %d", err); |
|
1212 return err; |
|
1213 } |
|
1214 |
|
1215 TInt DMemoryAccess::GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf) |
|
1216 { |
|
1217 DObjectCon* const * cons = Kern::Containers(); |
|
1218 DObjectCon& container = *cons[aObjectType]; |
|
1219 container.Wait(); |
|
1220 TBool alreadyHeld = iLocks[aObjectType]; |
|
1221 iLocks[aObjectType] = ETrue; |
|
1222 |
|
1223 TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aKernelInfoBuf); |
|
1224 TInt err = KErrNone; |
|
1225 TInt offset = 0; |
|
1226 |
|
1227 for (TInt jj=0;jj<container.Count();jj++) |
|
1228 { |
|
1229 if (offset >= maxLength) |
|
1230 { |
|
1231 err = KErrOverflow; |
|
1232 break; |
|
1233 } |
|
1234 |
|
1235 TBool doAppend(EFalse); |
|
1236 DObject* obj = (DObject*)container[jj]; |
|
1237 if (aOwningProcess.Length() > 0) |
|
1238 { |
|
1239 if (obj->Owner()) |
|
1240 { |
|
1241 TBuf8<KMaxFullName> fullName; |
|
1242 obj->Owner()->FullName(fullName); |
|
1243 if (fullName.MatchF(aOwningProcess) == 0) |
|
1244 { |
|
1245 doAppend = ETrue; |
|
1246 } |
|
1247 } |
|
1248 } |
|
1249 else |
|
1250 { |
|
1251 doAppend = ETrue; |
|
1252 } |
|
1253 |
|
1254 |
|
1255 if (doAppend) |
|
1256 { |
|
1257 err = Kern::ThreadDesWrite(iClient, aKernelInfoBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient); |
|
1258 if (err) |
|
1259 { |
|
1260 break; |
|
1261 } |
|
1262 else |
|
1263 { |
|
1264 offset += sizeof(TAny*); |
|
1265 } |
|
1266 } |
|
1267 } |
|
1268 |
|
1269 container.Signal(); |
|
1270 iLocks[aObjectType] = alreadyHeld; |
|
1271 return err; |
|
1272 } |
|
1273 |
|
1274 TInt DMemoryAccess::GetChunkAddresses(TUint aControllingProcessId, TDes8* aKernelInfoBuf) |
|
1275 { |
|
1276 DObjectCon* const * cons = Kern::Containers(); |
|
1277 DObjectCon& container = *cons[EChunk]; |
|
1278 container.Wait(); |
|
1279 TBool alreadyHeld = iLocks[EChunk]; |
|
1280 iLocks[EChunk] = ETrue; |
|
1281 |
|
1282 TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aKernelInfoBuf); |
|
1283 const TInt maxPtrs = maxLength / sizeof (TUint32*); |
|
1284 TInt err = KErrNone; |
|
1285 |
|
1286 if (maxPtrs == 0) |
|
1287 { |
|
1288 err = KErrOverflow; |
|
1289 } |
|
1290 else |
|
1291 { |
|
1292 TInt offset = 0; |
|
1293 |
|
1294 for (TInt jj=0;jj<container.Count();jj++) |
|
1295 { |
|
1296 DChunk* chunk = (DChunk*)container[jj]; |
|
1297 if ((aControllingProcessId == KNullProcessId) || (chunk->iControllingOwner == aControllingProcessId)) |
|
1298 { |
|
1299 err = Kern::ThreadDesWrite(iClient, aKernelInfoBuf, TPtrC8((TUint8*)&chunk, sizeof(TAny*)), offset, KChunkShiftBy0, iClient); |
|
1300 if (err) |
|
1301 { |
|
1302 break; |
|
1303 } |
|
1304 else |
|
1305 { |
|
1306 offset += sizeof(TAny*); |
|
1307 if (offset >= maxPtrs) |
|
1308 { |
|
1309 err = KErrOverflow; |
|
1310 break; |
|
1311 } |
|
1312 } |
|
1313 } |
|
1314 } |
|
1315 } |
|
1316 |
|
1317 container.Signal(); |
|
1318 iLocks[EChunk] = alreadyHeld; |
|
1319 return err; |
|
1320 } |
|
1321 |
|
1322 |
|
1323 // DMemoryAccess::ReleaseCodeSegMutex |
|
1324 // Releases the code segment mutex |
|
1325 TInt DMemoryAccess::ReleaseCodeSegMutex() |
|
1326 { |
|
1327 // Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex"); |
|
1328 TInt err=KErrNone; |
|
1329 |
|
1330 if (!iCodeSegLock) |
|
1331 { //Check the lock on code segs is not currently held |
|
1332 Kern::ThreadKill(iClient, EExitPanic, EMemAccessMutexNotHeld, KMemAccessPanicCategory); |
|
1333 err = KErrAbort; |
|
1334 } |
|
1335 |
|
1336 DMutex* const codeSegLock = Kern::CodeSegLock(); |
|
1337 |
|
1338 if (!err) |
|
1339 { |
|
1340 if (codeSegLock) |
|
1341 { |
|
1342 Kern::MutexSignal(*codeSegLock); |
|
1343 iCodeSegLock = EFalse; |
|
1344 } |
|
1345 else |
|
1346 { |
|
1347 err = KErrNotFound; |
|
1348 } |
|
1349 } |
|
1350 // Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex returning %d", err); |
|
1351 return err; |
|
1352 } |
|
1353 |
|
1354 |
|
1355 TInt DMemoryAccess::GetNextCodeSegInfo(TDes8* aCodeSegInfoBuf) |
|
1356 { |
|
1357 // Kern::Printf("[DMemoryAccess] ::GetNextCodeSegInfo"); |
|
1358 TInt err = KErrNone; |
|
1359 |
|
1360 SDblQue* p = Kern::CodeSegList(); |
|
1361 SDblQueLink* anchor=&p->iA; |
|
1362 |
|
1363 if (!iCurrentCodeSeg) |
|
1364 { |
|
1365 iCurrentCodeSeg = _LOFF(anchor->iNext, DCodeSeg, iLink); |
|
1366 } |
|
1367 |
|
1368 if (iCurrentCodeSeg->iLink.iNext != anchor) |
|
1369 { |
|
1370 iCurrentCodeSeg = _LOFF(iCurrentCodeSeg->iLink.iNext, DCodeSeg, iLink); |
|
1371 } |
|
1372 else |
|
1373 { |
|
1374 iCurrentCodeSeg = NULL; |
|
1375 err = KErrNotFound; |
|
1376 } |
|
1377 |
|
1378 if (!err) |
|
1379 { |
|
1380 //TCodeSegKernelInfoBuf* localInfoBuf = new TCodeSegKernelInfoBuf; |
|
1381 TPckgBuf<TTomsciCodeSegKernelInfo>* localInfoBuf = new TPckgBuf<TTomsciCodeSegKernelInfo>; |
|
1382 if (!localInfoBuf) |
|
1383 { |
|
1384 err = KErrNoMemory; |
|
1385 } |
|
1386 else |
|
1387 { |
|
1388 //Get the code seg info |
|
1389 (*localInfoBuf)().iRunAddress = iCurrentCodeSeg->iRunAddress; |
|
1390 (*localInfoBuf)().iSize = iCurrentCodeSeg->iSize; |
|
1391 (*localInfoBuf)().iFileName = iCurrentCodeSeg->iFileName->Right((*localInfoBuf)().iFileName.MaxLength()); |
|
1392 (*localInfoBuf)().iAccessCount = iCurrentCodeSeg->iAccessCount; |
|
1393 (*localInfoBuf)().iAddressOfKernelObject = (TUint8*)iCurrentCodeSeg; |
|
1394 (*localInfoBuf)().iName = iCurrentCodeSeg->iRootName; |
|
1395 (*localInfoBuf)().iDepCount = iCurrentCodeSeg->iDepCount; |
|
1396 |
|
1397 //Copy the local info buffer into the client's address space |
|
1398 err = Kern::ThreadDesWrite(iClient, aCodeSegInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1399 delete localInfoBuf; |
|
1400 } |
|
1401 } |
|
1402 |
|
1403 // Kern::Printf("[DMemoryAccess] ::GetNextCodeSegInfo returning %d", err); |
|
1404 return err; |
|
1405 } |
|
1406 |
|
1407 TInt DMemoryAccess::ObjectDie(TObjectKillParamsBuf& aObjectKillParamsBuf) |
|
1408 { |
|
1409 TInt err=KErrNone; |
|
1410 DObjectCon* const * cons = Kern::Containers(); |
|
1411 |
|
1412 switch(aObjectKillParamsBuf().iObjectType) |
|
1413 { |
|
1414 case EThread: |
|
1415 { |
|
1416 //Use the address of the kernel object ... |
|
1417 DThread* thread = (DThread*)aObjectKillParamsBuf().iObjectPtr; |
|
1418 //... unless the client has supplied an object ID |
|
1419 if (aObjectKillParamsBuf().iObjectId!=0) |
|
1420 { |
|
1421 DObjectCon& container = *cons[EThread]; |
|
1422 container.Wait(); |
|
1423 NKern::ThreadEnterCS(); |
|
1424 thread = Kern::ThreadFromId(aObjectKillParamsBuf().iObjectId); |
|
1425 NKern::ThreadLeaveCS(); |
|
1426 container.Signal(); |
|
1427 } |
|
1428 if (thread==NULL) |
|
1429 err=KErrNotFound; |
|
1430 else |
|
1431 Kern::ThreadKill(thread, aObjectKillParamsBuf().iType, aObjectKillParamsBuf().iReason, aObjectKillParamsBuf().iCategory); |
|
1432 break; |
|
1433 } |
|
1434 case EProcess: |
|
1435 { |
|
1436 //Use the address of the kernel object ... |
|
1437 DProcess* process = (DProcess*)aObjectKillParamsBuf().iObjectPtr; |
|
1438 //... unless the client has supplied an object ID |
|
1439 if (aObjectKillParamsBuf().iObjectId!=0) |
|
1440 { |
|
1441 DObjectCon& container = *cons[EProcess]; |
|
1442 container.Wait(); |
|
1443 NKern::ThreadEnterCS(); |
|
1444 process = Kern::ProcessFromId(aObjectKillParamsBuf().iObjectId); |
|
1445 NKern::ThreadLeaveCS(); |
|
1446 container.Signal(); |
|
1447 } |
|
1448 if (process==NULL) |
|
1449 err=KErrNotFound; |
|
1450 else |
|
1451 { |
|
1452 Kern::ThreadKill(process->FirstThread(), aObjectKillParamsBuf().iType, aObjectKillParamsBuf().iReason, aObjectKillParamsBuf().iCategory); |
|
1453 } |
|
1454 break; |
|
1455 } |
|
1456 default: |
|
1457 err=KErrNotSupported; |
|
1458 break; |
|
1459 } |
|
1460 return err; |
|
1461 } |
|
1462 |
|
1463 |
|
1464 TInt DMemoryAccess::GetThreadInfo(DThread* aThread, TDes8* aThreadInfoBuf) |
|
1465 { |
|
1466 // Kern::Printf("[DMemoryAccess] ::GetThreadInfo"); |
|
1467 TInt err=KErrNone; |
|
1468 //construct local info buffer to populate |
|
1469 TThreadKernelInfoBuf* localInfoBuf = new TThreadKernelInfoBuf; |
|
1470 if (!localInfoBuf) |
|
1471 { |
|
1472 err=KErrNoMemory; |
|
1473 } |
|
1474 else |
|
1475 { |
|
1476 //Get the standard DObject info |
|
1477 TThreadKernelInfo& localInfo = (*localInfoBuf)(); |
|
1478 GetObjectInfo(aThread, localInfo); |
|
1479 //Get the thread specific info |
|
1480 localInfo.iThreadId=aThread->iId; |
|
1481 localInfo.iAddressOfOwningProcess=(TUint8*)aThread->iOwningProcess; |
|
1482 localInfo.iThreadPriority = aThread->iDefaultPriority; // iDefaultPriority is more useful to know than iThreadPriority |
|
1483 localInfo.iUserStackSize = aThread->iUserStackSize; |
|
1484 localInfo.iFlags = aThread->iFlags; |
|
1485 localInfo.iSupervisorStack = (TLinAddr)aThread->iSupervisorStack; |
|
1486 localInfo.iSupervisorStackSize = aThread->iSupervisorStackSize; |
|
1487 localInfo.iUserStackLimit = aThread->iUserStackRunAddress; |
|
1488 localInfo.iNThreadSuspendCount = aThread->iNThread.iSuspendCount; |
|
1489 //Copy the local info buffer into the client's address space |
|
1490 err = Kern::ThreadDesWrite(iClient, aThreadInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1491 delete localInfoBuf; |
|
1492 } |
|
1493 return err; |
|
1494 } |
|
1495 |
|
1496 TInt DMemoryAccess::GetProcessInfo(DProcess* aProcess, TDes8* aProcessInfoBuf) |
|
1497 { |
|
1498 //Kern::Printf("[DMemoryAccess] ::GetProcessInfo"); |
|
1499 TInt err=KErrNone; |
|
1500 |
|
1501 //construct local info buffer to populate |
|
1502 TProcessKernelInfoBuf* localInfoBuf = new TProcessKernelInfoBuf; |
|
1503 if (!localInfoBuf) |
|
1504 { |
|
1505 err=KErrNoMemory; |
|
1506 } |
|
1507 else |
|
1508 { |
|
1509 //Get the standard DObject info |
|
1510 // Kern::Printf("DMemoryAccess::GetProcessInfo getting object info"); |
|
1511 TProcessKernelInfo& localInfo = (*localInfoBuf)(); |
|
1512 GetObjectInfo (aProcess, localInfo); |
|
1513 //Get the process specific info |
|
1514 localInfo.iProcessId = aProcess->iId; |
|
1515 localInfo.iPriority = aProcess->iPriority; |
|
1516 localInfo.iAddressOfOwningProcess = (TUint8*)aProcess->iOwningProcess; |
|
1517 localInfo.iCreatorId = aProcess->iCreatorId; |
|
1518 localInfo.iSecurityZone = aProcess->iSecurityZone; |
|
1519 localInfo.iUids = aProcess->iUids; |
|
1520 localInfo.iAttributes = aProcess->iAttributes; |
|
1521 localInfo.iFlags = aProcess->iFlags; |
|
1522 localInfo.iAddressOfDataBssStackChunk = (TUint8*)aProcess->iDataBssStackChunk; |
|
1523 TInt ii=0; |
|
1524 SDblQueLink* pLink=aProcess->iThreadQ.First(); |
|
1525 while ((pLink!=&aProcess->iThreadQ.iA) && (ii<KQueBufferLength)) |
|
1526 { |
|
1527 DThread* pT=_LOFF(pLink,DThread,iProcessLink); |
|
1528 localInfo.iThreadQ.iBuffer[ii]=(TUint8*)pT; |
|
1529 pLink=pLink->iNext; |
|
1530 ii++; |
|
1531 } |
|
1532 localInfo.iThreadQ.iStartFrom=0; |
|
1533 localInfo.iThreadQ.iCount=ii; |
|
1534 localInfo.iProcessSecurityInfo=aProcess->iS; |
|
1535 localInfo.iProcessCreatorSecurityInfo=aProcess->iCreatorInfo; |
|
1536 HBuf* commandLine = aProcess->iCommandLine; |
|
1537 if (commandLine) |
|
1538 { |
|
1539 localInfo.iCommandLine = commandLine->Left(localInfo.iCommandLine.MaxLength()); |
|
1540 } |
|
1541 memcpy(localInfo.iEnvironmentData, aProcess->iEnvironmentData, sizeof(TInt)*KNumEnvironmentSlots); |
|
1542 localInfo.iFirstThreadId = 0; |
|
1543 if (aProcess->FirstThread()) localInfo.iFirstThreadId = aProcess->FirstThread()->iId; |
|
1544 |
|
1545 //Copy the local info buffer into the client's address space |
|
1546 // Kern::Printf("DMemoryAccess::GetProcessInfo writing back"); |
|
1547 err = Kern::ThreadDesWrite(iClient, aProcessInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1548 delete localInfoBuf; |
|
1549 } |
|
1550 return err; |
|
1551 } |
|
1552 |
|
1553 |
|
1554 TInt DMemoryAccess::GetChunkInfo(DChunk* aChunk, TDes8* aChunkInfoBuf) |
|
1555 { |
|
1556 // Kern::Printf("[DMemoryAccess] ::GetChunkInfo"); |
|
1557 TInt err=KErrNone; |
|
1558 //construct local info buffer to populate |
|
1559 TChunkKernelInfoBuf* localInfoBuf = new TChunkKernelInfoBuf; |
|
1560 if (!localInfoBuf) |
|
1561 { |
|
1562 err=KErrNoMemory; |
|
1563 } |
|
1564 else |
|
1565 { |
|
1566 TChunkKernelInfo& localInfo = (*localInfoBuf)(); |
|
1567 //Get the standard DObject info |
|
1568 GetObjectInfo (aChunk, localInfo); |
|
1569 //Get the chunk specific info |
|
1570 localInfo.iSize = aChunk->Size(); |
|
1571 localInfo.iMaxSize = aChunk->MaxSize(); |
|
1572 localInfo.iBase = aChunk->Base(); |
|
1573 localInfo.iBottom = aChunk->Bottom(); |
|
1574 localInfo.iTop = aChunk->Top(); |
|
1575 localInfo.iAttributes = aChunk->iAttributes; |
|
1576 localInfo.iStartPos = aChunk->iStartPos; |
|
1577 localInfo.iControllingOwnerProcessId = aChunk->iControllingOwner; |
|
1578 localInfo.iRestrictions = aChunk->iRestrictions; |
|
1579 localInfo.iMapAttr = aChunk->iMapAttr; |
|
1580 localInfo.iChunkType = aChunk->iChunkType; |
|
1581 localInfo.iAddressOfOwningProcess = (TUint8*)aChunk->iOwningProcess; |
|
1582 #ifdef FSHELL_FLEXIBLEMM_AWARE |
|
1583 if (localInfo.iBase == 0) |
|
1584 { |
|
1585 _LIT8(KKern, "ekern"); |
|
1586 DProcess* proc = aChunk->iOwningProcess; |
|
1587 if (localInfo.iFullName.Left(KKern().Length()) != KKern && proc && proc->Open() == KErrNone) |
|
1588 { |
|
1589 // Probably shouldn't call ChunkUserBase for a non-user-owned chunk |
|
1590 localInfo.iBase = Kern::ChunkUserBase(aChunk, proc->FirstThread()); |
|
1591 proc->Close(NULL); |
|
1592 } |
|
1593 } |
|
1594 #endif |
|
1595 //Copy the local info buffer into the client's address space |
|
1596 err = Kern::ThreadDesWrite(iClient, aChunkInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1597 delete localInfoBuf; |
|
1598 } |
|
1599 return err; |
|
1600 } |
|
1601 |
|
1602 TInt DMemoryAccess::GetLibraryInfo(DLibrary* aLibrary, TDes8* aLibraryInfoBuf) |
|
1603 { |
|
1604 // Kern::Printf("[DMemoryAccess] ::GetLibraryInfo"); |
|
1605 TInt err=KErrNone; |
|
1606 //construct local info buffer to populate |
|
1607 TLibraryKernelInfoBuf* localInfoBuf = new TLibraryKernelInfoBuf; |
|
1608 if (!localInfoBuf) |
|
1609 { |
|
1610 err=KErrNoMemory; |
|
1611 } |
|
1612 else |
|
1613 { |
|
1614 //Get the standard DObject info |
|
1615 GetObjectInfo (aLibrary, (*localInfoBuf)()); |
|
1616 //Get the library specific info |
|
1617 (*localInfoBuf)().iMapCount = aLibrary->iMapCount; |
|
1618 (*localInfoBuf)().iState = aLibrary->iState; |
|
1619 (*localInfoBuf)().iAddressOfCodeSeg = (TUint8*)aLibrary->iCodeSeg; |
|
1620 |
|
1621 //Copy the local info buffer into the client's address space |
|
1622 err = Kern::ThreadDesWrite(iClient, aLibraryInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1623 delete localInfoBuf; |
|
1624 } |
|
1625 return err; |
|
1626 } |
|
1627 |
|
1628 TInt DMemoryAccess::GetSemaphoreInfo(DSemaphore* aSemaphore, TDes8* aSemaphoreInfoBuf) |
|
1629 { |
|
1630 // Kern::Printf("[DMemoryAccess] ::GetSemaphoreInfo"); |
|
1631 TInt err=KErrNone; |
|
1632 //construct local info buffer to populate |
|
1633 TSemaphoreKernelInfoBuf* localInfoBuf = new TSemaphoreKernelInfoBuf; |
|
1634 if (!localInfoBuf) |
|
1635 { |
|
1636 err=KErrNoMemory; |
|
1637 } |
|
1638 else |
|
1639 { |
|
1640 //Get the standard DObject info |
|
1641 GetObjectInfo (aSemaphore, (*localInfoBuf)()); |
|
1642 //Get the Semaphore specific info |
|
1643 (*localInfoBuf)().iCount = aSemaphore->iCount; |
|
1644 (*localInfoBuf)().iResetting = aSemaphore->iResetting; |
|
1645 TInt ii=0; |
|
1646 SDblQueLink* pLink=aSemaphore->iSuspendedQ.First(); |
|
1647 while ((pLink!=&aSemaphore->iSuspendedQ.iA) && (ii<KQueBufferLength)) |
|
1648 { |
|
1649 DThread* pT=_LOFF(pLink,DThread,iWaitLink); |
|
1650 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT; |
|
1651 pLink=pLink->iNext; |
|
1652 ii++; |
|
1653 } |
|
1654 (*localInfoBuf)().iSuspendedQ.iStartFrom=0; |
|
1655 (*localInfoBuf)().iSuspendedQ.iCount=ii; |
|
1656 |
|
1657 //Copy the local info buffer into the client's address space |
|
1658 err = Kern::ThreadDesWrite(iClient, aSemaphoreInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1659 delete localInfoBuf; |
|
1660 } |
|
1661 return err; |
|
1662 } |
|
1663 |
|
1664 TInt DMemoryAccess::GetMutexInfo(DMutex* aMutex, TDes8* aMutexInfoBuf) |
|
1665 { |
|
1666 // Kern::Printf("[DMemoryAccess] ::GetMutexInfo"); |
|
1667 TInt err=KErrNone; |
|
1668 //construct local info buffer to populate |
|
1669 TMutexKernelInfoBuf* localInfoBuf = new TMutexKernelInfoBuf; |
|
1670 if (!localInfoBuf) |
|
1671 { |
|
1672 err=KErrNoMemory; |
|
1673 } |
|
1674 else |
|
1675 { |
|
1676 //Get the standard DObject info |
|
1677 GetObjectInfo (aMutex, (*localInfoBuf)()); |
|
1678 //Get the Mutex specific info |
|
1679 (*localInfoBuf)().iHoldCount = aMutex->iHoldCount; |
|
1680 (*localInfoBuf)().iWaitCount = aMutex->iWaitCount; |
|
1681 (*localInfoBuf)().iResetting = aMutex->iResetting; |
|
1682 (*localInfoBuf)().iOrder = aMutex->iOrder; |
|
1683 TInt ii=0; |
|
1684 SDblQueLink* pLink=aMutex->iSuspendedQ.First(); |
|
1685 while ((pLink!=&aMutex->iSuspendedQ.iA) && (ii<KQueBufferLength)) |
|
1686 { |
|
1687 DThread* pT=_LOFF(pLink,DThread,iWaitLink); |
|
1688 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT; |
|
1689 pLink=pLink->iNext; |
|
1690 ii++; |
|
1691 } |
|
1692 (*localInfoBuf)().iSuspendedQ.iStartFrom=0; |
|
1693 (*localInfoBuf)().iSuspendedQ.iCount=ii; |
|
1694 ii=0; |
|
1695 pLink=aMutex->iPendingQ.First(); |
|
1696 while ((pLink!=&aMutex->iPendingQ.iA) && (ii<KQueBufferLength)) |
|
1697 { |
|
1698 DThread* pT=_LOFF(pLink,DThread,iWaitLink); |
|
1699 (*localInfoBuf)().iPendingQ.iBuffer[ii]=(TUint8*)pT; |
|
1700 pLink=pLink->iNext; |
|
1701 ii++; |
|
1702 } |
|
1703 (*localInfoBuf)().iPendingQ.iStartFrom=0; |
|
1704 (*localInfoBuf)().iPendingQ.iCount=ii; |
|
1705 |
|
1706 //Copy the local info buffer into the client's address space |
|
1707 err = Kern::ThreadDesWrite(iClient, aMutexInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1708 delete localInfoBuf; |
|
1709 } |
|
1710 return err; |
|
1711 } |
|
1712 |
|
1713 TInt DMemoryAccess::GetTimerInfo(DTimer* aTimer, TDes8* aTimerInfoBuf) |
|
1714 { |
|
1715 // Kern::Printf("[DMemoryAccess] ::GetTimerInfo"); |
|
1716 TInt err=KErrNone; |
|
1717 //construct local info buffer to populate |
|
1718 TTimerKernelInfoBuf* localInfoBuf = new TTimerKernelInfoBuf; |
|
1719 if (!localInfoBuf) |
|
1720 { |
|
1721 err=KErrNoMemory; |
|
1722 } |
|
1723 else |
|
1724 { |
|
1725 //Get the standard DObject info |
|
1726 GetObjectInfo (aTimer, (*localInfoBuf)()); |
|
1727 //Get the timer specific info |
|
1728 (*localInfoBuf)().iState = aTimer->iTimer.iState; |
|
1729 (*localInfoBuf)().iType = aTimer->iTimer.iType; |
|
1730 #if FSHELL_PLATFORM_SYMTB >= 92 || FSHELL_PLATFORM_FOUNDATION >= 3 |
|
1731 (*localInfoBuf)().iClientStatus = NULL; //TOMSCI TEMP |
|
1732 #else |
|
1733 (*localInfoBuf)().iClientStatus = (TLinAddr)aTimer->iTimer.iStatus; |
|
1734 #endif |
|
1735 |
|
1736 //Copy the local info buffer into the client's address space |
|
1737 err = Kern::ThreadDesWrite(iClient, aTimerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1738 delete localInfoBuf; |
|
1739 } |
|
1740 return err; |
|
1741 } |
|
1742 |
|
1743 TInt DMemoryAccess::GetServerInfo(DServer* aServer, TDes8* aServerInfoBuf) |
|
1744 { |
|
1745 // Kern::Printf("[DMemoryAccess] ::GetServerInfo"); |
|
1746 TInt err=KErrNone; |
|
1747 //construct local info buffer to populate |
|
1748 TServerKernelInfoBuf* localInfoBuf = new TServerKernelInfoBuf; |
|
1749 if (!localInfoBuf) |
|
1750 { |
|
1751 err=KErrNoMemory; |
|
1752 } |
|
1753 else |
|
1754 { |
|
1755 //Get the standard DObject info |
|
1756 GetObjectInfo (aServer, (*localInfoBuf)()); |
|
1757 //Get the server specific info |
|
1758 (*localInfoBuf)().iAddressOfOwningThread = (TUint8*)aServer->iOwningThread; |
|
1759 (*localInfoBuf)().iOwningThreadId = aServer->iOwningThread->iId; |
|
1760 (*localInfoBuf)().iSessionType = aServer->iSessionType; |
|
1761 TInt ii=0; |
|
1762 SDblQueLink* pLink=aServer->iSessionQ.First(); |
|
1763 while ((pLink!=&aServer->iSessionQ.iA) && (ii<KQueBufferLength)) |
|
1764 { |
|
1765 DSession* pT=_LOFF(pLink,DSession,iServerLink); |
|
1766 (*localInfoBuf)().iSessionQ.iBuffer[ii]=(TUint8*)pT; |
|
1767 pLink=pLink->iNext; |
|
1768 ii++; |
|
1769 } |
|
1770 (*localInfoBuf)().iSessionQ.iStartFrom=0; |
|
1771 (*localInfoBuf)().iSessionQ.iCount=ii; |
|
1772 |
|
1773 //Copy the local info buffer into the client's address space |
|
1774 err = Kern::ThreadDesWrite(iClient, aServerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1775 delete localInfoBuf; |
|
1776 } |
|
1777 return err; |
|
1778 } |
|
1779 |
|
1780 TInt DMemoryAccess::GetSessionInfo(DSession* aSession, TDes8* aSessionInfoBuf) |
|
1781 { |
|
1782 // Kern::Printf("[DMemoryAccess] ::GetSessionInfo"); |
|
1783 TInt err=KErrNone; |
|
1784 //construct local info buffer to populate |
|
1785 TSessionKernelInfoBuf* localInfoBuf = new TSessionKernelInfoBuf; |
|
1786 if (!localInfoBuf) |
|
1787 { |
|
1788 err=KErrNoMemory; |
|
1789 } |
|
1790 else |
|
1791 { |
|
1792 //Get the standard DObject info |
|
1793 GetObjectInfo (aSession, (*localInfoBuf)()); |
|
1794 //Get the session specific info |
|
1795 (*localInfoBuf)().iServer = (TUint8*)aSession->iServer; |
|
1796 #if defined(FSHELL_PLATFORM_FOUNDATION) || defined(FSHELL_PLATFORM_SYMTB) |
|
1797 (*localInfoBuf)().iSessionPtr = (TAny*)aSession->iSessionCookie; |
|
1798 #else |
|
1799 (*localInfoBuf)().iSessionPtr = (TAny*)aSession->iSessionPtr; |
|
1800 #endif |
|
1801 (*localInfoBuf)().iTotalAccessCount = aSession->iTotalAccessCount; |
|
1802 (*localInfoBuf)().iSessionType = aSession->iSessionType; |
|
1803 (*localInfoBuf)().iSvrSessionType = aSession->iSvrSessionType; |
|
1804 (*localInfoBuf)().iMsgCount = aSession->iMsgCount; |
|
1805 (*localInfoBuf)().iMsgLimit = aSession->iMsgLimit; |
|
1806 |
|
1807 //Copy the local info buffer into the client's address space |
|
1808 err = Kern::ThreadDesWrite(iClient, aSessionInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1809 delete localInfoBuf; |
|
1810 } |
|
1811 return err; |
|
1812 } |
|
1813 |
|
1814 TInt DMemoryAccess::GetLogicalDeviceInfo(DLogicalDevice* aLogicalDevice, TDes8* aLogicalDeviceInfoBuf) |
|
1815 { |
|
1816 // Kern::Printf("[DMemoryAccess] ::GetLogicalDeviceInfo"); |
|
1817 TInt err=KErrNone; |
|
1818 //construct local info buffer to populate |
|
1819 TLogicalDeviceKernelInfoBuf* localInfoBuf = new TLogicalDeviceKernelInfoBuf; |
|
1820 if (!localInfoBuf) |
|
1821 { |
|
1822 err=KErrNoMemory; |
|
1823 } |
|
1824 else |
|
1825 { |
|
1826 //Get the standard DObject info |
|
1827 GetObjectInfo (aLogicalDevice, (*localInfoBuf)()); |
|
1828 //Get the logical device specific info |
|
1829 (*localInfoBuf)().iVersion = aLogicalDevice->iVersion; |
|
1830 (*localInfoBuf)().iParseMask = aLogicalDevice->iParseMask; |
|
1831 (*localInfoBuf)().iUnitsMask = aLogicalDevice->iUnitsMask; |
|
1832 (*localInfoBuf)().iOpenChannels = aLogicalDevice->iOpenChannels; |
|
1833 |
|
1834 //Copy the local info buffer into the client's address space |
|
1835 err = Kern::ThreadDesWrite(iClient, aLogicalDeviceInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1836 delete localInfoBuf; |
|
1837 } |
|
1838 return err; |
|
1839 } |
|
1840 |
|
1841 TInt DMemoryAccess::GetPhysicalDeviceInfo(DPhysicalDevice* aPhysicalDevice, TDes8* aPhysicalDeviceInfoBuf) |
|
1842 { |
|
1843 // Kern::Printf("[DMemoryAccess] ::GetPhysicalDeviceInfo"); |
|
1844 TInt err=KErrNone; |
|
1845 //construct local info buffer to populate |
|
1846 TPhysicalDeviceKernelInfoBuf* localInfoBuf = new TPhysicalDeviceKernelInfoBuf; |
|
1847 if (!localInfoBuf) |
|
1848 { |
|
1849 err=KErrNoMemory; |
|
1850 } |
|
1851 else |
|
1852 { |
|
1853 //Get the standard DObject info |
|
1854 GetObjectInfo (aPhysicalDevice, (*localInfoBuf)()); |
|
1855 //Get the physical device specific info |
|
1856 (*localInfoBuf)().iVersion = aPhysicalDevice->iVersion; |
|
1857 (*localInfoBuf)().iUnitsMask = aPhysicalDevice->iUnitsMask; |
|
1858 (*localInfoBuf)().iAddressOfCodeSeg = (TUint8*)aPhysicalDevice->iCodeSeg; |
|
1859 |
|
1860 //Copy the local info buffer into the client's address space |
|
1861 err = Kern::ThreadDesWrite(iClient, aPhysicalDeviceInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1862 delete localInfoBuf; |
|
1863 } |
|
1864 return err; |
|
1865 } |
|
1866 |
|
1867 TInt DMemoryAccess::GetLogicalChannelInfo(DLogicalChannel* aLogicalChannel, TDes8* aLogicalChannelInfoBuf) |
|
1868 { |
|
1869 // Kern::Printf("[DMemoryAccess] ::GetLogicalChannelInfo"); |
|
1870 TInt err=KErrNone; |
|
1871 //construct local info buffer to populate |
|
1872 TLogicalChannelKernelInfoBuf* localInfoBuf = new TLogicalChannelKernelInfoBuf; |
|
1873 if (!localInfoBuf) |
|
1874 { |
|
1875 err=KErrNoMemory; |
|
1876 } |
|
1877 else |
|
1878 { |
|
1879 //Get the standard DObject info |
|
1880 GetObjectInfo (aLogicalChannel, (*localInfoBuf)()); |
|
1881 //Get the logical channel info |
|
1882 |
|
1883 //Copy the local info buffer into the client's address space |
|
1884 err = Kern::ThreadDesWrite(iClient, aLogicalChannelInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1885 delete localInfoBuf; |
|
1886 } |
|
1887 return err; |
|
1888 } |
|
1889 |
|
1890 TInt DMemoryAccess::GetChangeNotifierInfo(DChangeNotifier* aChangeNotifier, TDes8* aChangeNotifierInfoBuf) |
|
1891 { |
|
1892 // Kern::Printf("[DMemoryAccess] ::GetChangeNotifierInfo"); |
|
1893 TInt err=KErrNone; |
|
1894 //construct local info buffer to populate |
|
1895 TChangeNotifierKernelInfoBuf* localInfoBuf = new TChangeNotifierKernelInfoBuf; |
|
1896 if (!localInfoBuf) |
|
1897 { |
|
1898 err=KErrNoMemory; |
|
1899 } |
|
1900 else |
|
1901 { |
|
1902 //Get the standard DObject info |
|
1903 GetObjectInfo (aChangeNotifier, (*localInfoBuf)()); |
|
1904 //Get the change notifier specific info |
|
1905 (*localInfoBuf)().iChanges = aChangeNotifier->iChanges; |
|
1906 (*localInfoBuf)().iAddressOfThread = (TUint8*)aChangeNotifier->iThread; |
|
1907 |
|
1908 //Copy the local info buffer into the client's address space |
|
1909 err = Kern::ThreadDesWrite(iClient, aChangeNotifierInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1910 delete localInfoBuf; |
|
1911 } |
|
1912 return err; |
|
1913 } |
|
1914 |
|
1915 TInt DMemoryAccess::GetMsgQueueInfo(DMsgQueue* aMsgQueue, TDes8* aMsgQueueInfoBuf) |
|
1916 { |
|
1917 // Kern::Printf("[DMemoryAccess] ::GetUndertakerInfo"); |
|
1918 TInt err=KErrNone; |
|
1919 //construct local info buffer to populate |
|
1920 TMsgQueueKernelInfoBuf* localInfoBuf = new TMsgQueueKernelInfoBuf; |
|
1921 if (!localInfoBuf) |
|
1922 { |
|
1923 err=KErrNoMemory; |
|
1924 } |
|
1925 else |
|
1926 { |
|
1927 //Get the standard DObject info |
|
1928 GetObjectInfo((DObject*)aMsgQueue, (*localInfoBuf)()); |
|
1929 //Get the specific info - highly fragile this! |
|
1930 const TInt KSizeOffset = sizeof(DObject)+(8*4); |
|
1931 (*localInfoBuf)().iMaxMsgLength = *(TUint16*)((TLinAddr)aMsgQueue + KSizeOffset); |
|
1932 |
|
1933 //Copy the local info buffer into the client's address space |
|
1934 err = Kern::ThreadDesWrite(iClient, aMsgQueueInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1935 delete localInfoBuf; |
|
1936 } |
|
1937 return err; |
|
1938 } |
|
1939 |
|
1940 TInt DMemoryAccess::GetUndertakerInfo(DUndertaker* aUndertaker, TDes8* aUndertakerInfoBuf) |
|
1941 { |
|
1942 // Kern::Printf("[DMemoryAccess] ::GetUndertakerInfo"); |
|
1943 TInt err=KErrNone; |
|
1944 //construct local info buffer to populate |
|
1945 TUndertakerKernelInfoBuf* localInfoBuf = new TUndertakerKernelInfoBuf; |
|
1946 if (!localInfoBuf) |
|
1947 { |
|
1948 err=KErrNoMemory; |
|
1949 } |
|
1950 else |
|
1951 { |
|
1952 //Get the standard DObject info |
|
1953 GetObjectInfo (aUndertaker, (*localInfoBuf)()); |
|
1954 //Get the thread specific info |
|
1955 (*localInfoBuf)().iOwningThread = (TUint8*)aUndertaker->iOwningThread; |
|
1956 |
|
1957 //Copy the local info buffer into the client's address space |
|
1958 err = Kern::ThreadDesWrite(iClient, aUndertakerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1959 delete localInfoBuf; |
|
1960 } |
|
1961 return err; |
|
1962 } |
|
1963 |
|
1964 TInt DMemoryAccess::GetCondVarInfo(DCondVar* aCondVar, TDes8* aCondVarInfoBuf) |
|
1965 { |
|
1966 // Kern::Printf("[DMemoryAccess] ::GetCondVarInfo"); |
|
1967 TInt err=KErrNone; |
|
1968 //construct local info buffer to populate |
|
1969 TCondVarKernelInfoBuf* localInfoBuf = new TCondVarKernelInfoBuf; |
|
1970 if (!localInfoBuf) |
|
1971 { |
|
1972 err=KErrNoMemory; |
|
1973 } |
|
1974 else |
|
1975 { |
|
1976 //Get the standard DObject info |
|
1977 GetObjectInfo (aCondVar, (*localInfoBuf)()); |
|
1978 //Get the cond var specific info |
|
1979 (*localInfoBuf)().iResetting = aCondVar->iResetting; |
|
1980 (*localInfoBuf)().iAddressOfMutex = (TUint8*)aCondVar->iMutex; |
|
1981 (*localInfoBuf)().iWaitCount = aCondVar->iWaitCount; |
|
1982 TInt ii=0; |
|
1983 SDblQueLink* pLink=aCondVar->iSuspendedQ.First(); |
|
1984 while ((pLink!=&aCondVar->iSuspendedQ.iA) && (ii<KQueBufferLength)) |
|
1985 { |
|
1986 DThread* pT=_LOFF(pLink,DThread,iWaitLink); |
|
1987 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT; |
|
1988 pLink=pLink->iNext; |
|
1989 ii++; |
|
1990 } |
|
1991 (*localInfoBuf)().iSuspendedQ.iStartFrom=0; |
|
1992 (*localInfoBuf)().iSuspendedQ.iCount=ii; |
|
1993 |
|
1994 //Copy the local info buffer into the client's address space |
|
1995 err = Kern::ThreadDesWrite(iClient, aCondVarInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL); |
|
1996 delete localInfoBuf; |
|
1997 } |
|
1998 return err; |
|
1999 } |
|
2000 |
|
2001 TInt DMemoryAccess::FindPtrInCodeSegments(TAny* aDllNamePtr, TAny* aPtr) |
|
2002 { |
|
2003 /* |
|
2004 // Iterate the code segments |
|
2005 TInt err = AcquireCodeSegMutex(); |
|
2006 if (err) return err; |
|
2007 DCodeSeg* currentCodeSeg = NULL; |
|
2008 |
|
2009 //BEGIN copied from GetNextCodeSegInfo |
|
2010 SDblQue* p = Kern::CodeSegList(); |
|
2011 SDblQueLink* anchor=&p->iA; |
|
2012 |
|
2013 currentCodeSeg = _LOFF(anchor->iNext, DCodeSeg, iLink); |
|
2014 |
|
2015 while (currentCodeSeg) |
|
2016 { |
|
2017 if (currentCodeSeg->iLink.iNext != anchor) |
|
2018 { |
|
2019 currentCodeSeg = _LOFF(currentCodeSeg->iLink.iNext, DCodeSeg, iLink); |
|
2020 if ((TUint)aPtr >= currentCodeSeg->iRunAddress && (TUint)aPtr < currentCodeSeg->iRunAddress + currentCodeSeg->iSize) |
|
2021 { |
|
2022 // Found it |
|
2023 break; |
|
2024 } |
|
2025 } |
|
2026 else |
|
2027 { |
|
2028 // Not found any code seg matching |
|
2029 currentCodeSeg = NULL; |
|
2030 err = KErrNotFound; |
|
2031 } |
|
2032 } |
|
2033 //END copied from GetNextCodeSegInfo |
|
2034 ReleaseCodeSegMutex(); |
|
2035 // End iterate |
|
2036 */ |
|
2037 |
|
2038 Kern::MutexWait(*Kern::CodeSegLock()); |
|
2039 DCodeSeg* currentCodeSeg = Kern::CodeSegFromAddress((TLinAddr)aPtr, iClient->iOwningProcess); |
|
2040 TInt err = KErrNone; |
|
2041 TInt offset = 0; |
|
2042 TBuf8<256> dllName; |
|
2043 if (currentCodeSeg) |
|
2044 { |
|
2045 dllName.Copy(*currentCodeSeg->iFileName); |
|
2046 offset = (TUint)aPtr - currentCodeSeg->iRunAddress; // This won't work on flexible memory model! |
|
2047 } |
|
2048 else |
|
2049 { |
|
2050 err = KErrNotFound; |
|
2051 } |
|
2052 Kern::MutexSignal(*Kern::CodeSegLock()); |
|
2053 |
|
2054 if (!err) |
|
2055 { |
|
2056 err = Kern::ThreadDesWrite(iClient, aDllNamePtr, dllName, 0, KTruncateToMaxLength, NULL); |
|
2057 } |
|
2058 return err ? err : offset; |
|
2059 } |
|
2060 |
|
2061 TInt DMemoryAccess::GetHandleOwners(TAny* aObj, TAny* aOwnersBuf) |
|
2062 { |
|
2063 #ifdef FSHELL_DOBJECTIX_SUPPORT |
|
2064 TBuf8<256> buf; |
|
2065 |
|
2066 // Code adapted from ExecHandler::HandleInfo |
|
2067 DObject* pO=(DObject*)aObj; |
|
2068 TInt r = KErrNone; |
|
2069 /* |
|
2070 DThread& t = *iClient; |
|
2071 //TInt r=K::OpenObjectFromHandle(aHandle,pO); |
|
2072 //BEGIN this bit copied from K::OpenObjectFromHandle |
|
2073 TInt r=KErrBadHandle; |
|
2074 NKern::ThreadEnterCS(); |
|
2075 NKern::LockSystem(); |
|
2076 pO=t.ObjectFromHandle(aHandle); |
|
2077 if (pO) |
|
2078 r=pO->Open(); |
|
2079 NKern::UnlockSystem(); |
|
2080 if (r!=KErrNone) |
|
2081 { |
|
2082 pO=NULL; |
|
2083 NKern::ThreadLeaveCS(); |
|
2084 } |
|
2085 //END |
|
2086 */ |
|
2087 |
|
2088 if (r==KErrNone) |
|
2089 { |
|
2090 //DObjectIx::Wait(); //TOMSCI I can't call this frmo a device driver, why did the code I copied do it but none of the DMemoryAccess stuff that uses containers do it?? |
|
2091 //DProcess* pCurrentProcess=TheCurrentThread->iOwningProcess; |
|
2092 //hinfo.iNumOpenInThread=TheCurrentThread->iHandles->Count(pO); |
|
2093 //hinfo.iNumOpenInProcess=pCurrentProcess->iHandles->Count(pO); |
|
2094 |
|
2095 DObjectCon* const * cons=Kern::Containers(); |
|
2096 DObjectCon& threads = *cons[EThread]; |
|
2097 threads.Wait(); |
|
2098 TInt c=threads.Count(); |
|
2099 TInt i=0; |
|
2100 for (;i<c;i++) |
|
2101 { |
|
2102 DThread *pT=(DThread *)threads[i]; |
|
2103 DObjectIx* handles = pT->iHandles; |
|
2104 if (handles) // maybe a nearly dead one hanging around |
|
2105 { |
|
2106 TInt rr=((DObjectIxNinePointTwoHack*)handles)->At(pO); |
|
2107 if (rr!=KErrNotFound) |
|
2108 { |
|
2109 TPckgBuf<TUint> idBuf(pT->iId); |
|
2110 if (buf.Length() + idBuf.Length() >= buf.MaxLength()) |
|
2111 { |
|
2112 r = KErrOverflow; |
|
2113 break; |
|
2114 } |
|
2115 else |
|
2116 { |
|
2117 buf.Append(idBuf); |
|
2118 } |
|
2119 //++hinfo.iNumThreads; |
|
2120 //if (pT->iOwningProcess==pCurrentProcess) |
|
2121 // ++hinfo.iNumOpenInProcess; |
|
2122 } |
|
2123 } |
|
2124 } |
|
2125 threads.Signal(); |
|
2126 |
|
2127 DObjectCon& processes = *cons[EProcess]; |
|
2128 processes.Wait(); |
|
2129 c=processes.Count(); |
|
2130 for (i=0;i<c;i++) |
|
2131 { |
|
2132 DProcess *pP=(DProcess *)processes[i]; |
|
2133 DObjectIx* handles = pP->iHandles; |
|
2134 if (handles) // maybe a nearly dead one hanging around |
|
2135 { |
|
2136 TInt rr=((DObjectIxNinePointTwoHack*)handles)->At(pO); |
|
2137 if (rr!=KErrNotFound) |
|
2138 { |
|
2139 //++hinfo.iNumProcesses; |
|
2140 TPckgBuf<TUint> idBuf(pP->iId); |
|
2141 if (buf.Length() + idBuf.Length() >= buf.MaxLength()) |
|
2142 { |
|
2143 r = KErrOverflow; |
|
2144 break; |
|
2145 } |
|
2146 else |
|
2147 { |
|
2148 buf.Append(idBuf); |
|
2149 } |
|
2150 } |
|
2151 } |
|
2152 } |
|
2153 processes.Signal(); |
|
2154 //DObjectIx::Signal(); |
|
2155 |
|
2156 |
|
2157 //DObjectIx::Signal(); |
|
2158 //pO->Close(NULL); |
|
2159 //NKern::ThreadLeaveCS(); |
|
2160 } |
|
2161 |
|
2162 TInt clientLen = Kern::ThreadGetDesMaxLength(iClient, aOwnersBuf); |
|
2163 if (clientLen < 0) return clientLen; |
|
2164 TInt writeErr = Kern::ThreadDesWrite(iClient, aOwnersBuf, buf, 0, KTruncateToMaxLength, NULL); |
|
2165 if (writeErr) return writeErr; |
|
2166 return (clientLen < buf.Length()) ? KErrOverflow : r; |
|
2167 #else |
|
2168 return KErrNotSupported; |
|
2169 #endif |
|
2170 } |
|
2171 |
|
2172 TInt DMemoryAccess::GetThreadHandles(TInt aThreadId, TAny* aHandlesBuf) |
|
2173 { |
|
2174 #ifdef FSHELL_DOBJECTIX_SUPPORT |
|
2175 TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); |
|
2176 TInt err = KErrNone; |
|
2177 |
|
2178 DObjectCon* const * cons = Kern::Containers(); |
|
2179 DObjectCon& container = *cons[EThread]; |
|
2180 container.Wait(); |
|
2181 NKern::ThreadEnterCS(); |
|
2182 DThread* thread = Kern::ThreadFromId(aThreadId); |
|
2183 //TOMSCI FIXME we don't increment thread's ref count |
|
2184 NKern::ThreadLeaveCS(); |
|
2185 container.Signal(); |
|
2186 if (thread == NULL) |
|
2187 { |
|
2188 return KErrNotFound; |
|
2189 } |
|
2190 |
|
2191 // Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex. |
|
2192 DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)thread->iHandles; |
|
2193 if (handles) |
|
2194 { |
|
2195 TInt offset = 0; |
|
2196 |
|
2197 for (TInt i = 0; i < handles->Count(); ++i) |
|
2198 { |
|
2199 if (offset >= maxLength) |
|
2200 { |
|
2201 err = KErrOverflow; |
|
2202 break; |
|
2203 } |
|
2204 NKern::LockSystem(); |
|
2205 DObject* obj = (*handles)[i]; |
|
2206 NKern::UnlockSystem(); |
|
2207 if (obj != NULL) |
|
2208 { |
|
2209 err = Kern::ThreadDesWrite(iClient, aHandlesBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient); |
|
2210 if (err) |
|
2211 { |
|
2212 break; |
|
2213 } |
|
2214 else |
|
2215 { |
|
2216 offset += sizeof(TAny*); |
|
2217 } |
|
2218 } |
|
2219 } |
|
2220 } |
|
2221 |
|
2222 //TOMSCI What is this unlock doing here? TODO FIXME!!! |
|
2223 NKern::UnlockSystem(); |
|
2224 return err; |
|
2225 #else |
|
2226 return KErrNotSupported; |
|
2227 #endif |
|
2228 } |
|
2229 |
|
2230 TInt DMemoryAccess::GetProcessHandles(TInt aProcessId, TAny* aHandlesBuf) |
|
2231 { |
|
2232 #ifdef FSHELL_DOBJECTIX_SUPPORT |
|
2233 TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf); |
|
2234 TInt err = KErrNone; |
|
2235 |
|
2236 DObjectCon* const * cons = Kern::Containers(); |
|
2237 DObjectCon& container = *cons[EProcess]; |
|
2238 container.Wait(); |
|
2239 NKern::ThreadEnterCS(); |
|
2240 DProcess* process = Kern::ProcessFromId(aProcessId); |
|
2241 NKern::ThreadLeaveCS(); |
|
2242 container.Signal(); |
|
2243 if (process == NULL) |
|
2244 { |
|
2245 return KErrNotFound; |
|
2246 } |
|
2247 |
|
2248 // Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex. |
|
2249 DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)process->iHandles; |
|
2250 if (handles) |
|
2251 { |
|
2252 TInt offset = 0; |
|
2253 |
|
2254 for (TInt i = 0; i < handles->Count(); ++i) |
|
2255 { |
|
2256 if (offset >= maxLength) |
|
2257 { |
|
2258 err = KErrOverflow; |
|
2259 break; |
|
2260 } |
|
2261 NKern::LockSystem(); |
|
2262 DObject* obj = (*handles)[i]; |
|
2263 NKern::UnlockSystem(); |
|
2264 if (obj != NULL) |
|
2265 { |
|
2266 err = Kern::ThreadDesWrite(iClient, aHandlesBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient); |
|
2267 if (err) |
|
2268 { |
|
2269 break; |
|
2270 } |
|
2271 else |
|
2272 { |
|
2273 offset += sizeof(TAny*); |
|
2274 } |
|
2275 } |
|
2276 } |
|
2277 } |
|
2278 |
|
2279 return err; |
|
2280 #else |
|
2281 return KErrNotSupported; |
|
2282 #endif |
|
2283 } |
|
2284 |
|
2285 TInt DMemoryAccess::SetCriticalFlags(TInt aThreadHandle, TUint aFlags) |
|
2286 { |
|
2287 NKern::LockSystem(); |
|
2288 DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aThreadHandle, EThread); |
|
2289 if (!thread) |
|
2290 { |
|
2291 NKern::UnlockSystem(); |
|
2292 return KErrNotFound; |
|
2293 } |
|
2294 |
|
2295 const TUint32 clear = KThreadFlagSystemPermanent | KThreadFlagSystemCritical | |
|
2296 KThreadFlagProcessPermanent | KThreadFlagProcessCritical; |
|
2297 |
|
2298 TUint newFlags = (thread->iFlags&~clear) | aFlags; |
|
2299 thread->iFlags = newFlags; |
|
2300 |
|
2301 NKern::UnlockSystem(); |
|
2302 return KErrNone; |
|
2303 } |
|
2304 |
|
2305 // Enter and exit with system lock held |
|
2306 TInt SetPri(DThread* aThread, TInt aPriority) |
|
2307 { |
|
2308 //Kern::SetThreadPriority(aPriority, aThread); |
|
2309 |
|
2310 // Bypass limitation of Kern::SetThreadPriority on specifying relative priorities |
|
2311 if (aPriority<EThrdPriorityIdle || aPriority==-1 || aPriority==0 || aPriority>=KNumPriorities) |
|
2312 return KErrArgument; |
|
2313 aThread->SetThreadPriority(aPriority); |
|
2314 return KErrNone; |
|
2315 } |
|
2316 |
|
2317 TInt DMemoryAccess::SetThreadPriority(TInt aThreadHandle, TInt aPriority) |
|
2318 { |
|
2319 NKern::LockSystem(); |
|
2320 DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aThreadHandle, EThread); |
|
2321 if (!thread) |
|
2322 { |
|
2323 NKern::UnlockSystem(); |
|
2324 return KErrNotFound; |
|
2325 } |
|
2326 |
|
2327 TInt err = SetPri(thread, aPriority); |
|
2328 NKern::UnlockSystem(); |
|
2329 return err; |
|
2330 } |
|
2331 |
|
2332 void DMemoryAccess::NotifyThreadCreation(TRequestStatus* aStatus) |
|
2333 { |
|
2334 // TODO: Have this migrate to the shared event handler |
|
2335 TInt err = KErrNone; |
|
2336 TBool supported = DKernelEventHandler::DebugSupportEnabled(); |
|
2337 if (!supported) err = KErrNotSupported; |
|
2338 if (!err && !iEventHandler) |
|
2339 { |
|
2340 iEventHandler = new DThreadChangeHandler(iClient); |
|
2341 if (iEventHandler) |
|
2342 { |
|
2343 iEventHandler->Add(DKernelEventHandler::EAppend); |
|
2344 } |
|
2345 else |
|
2346 { |
|
2347 err = KErrNoMemory; |
|
2348 } |
|
2349 } |
|
2350 |
|
2351 if (err) |
|
2352 { |
|
2353 Kern::RequestComplete(iClient, aStatus, err); |
|
2354 } |
|
2355 else |
|
2356 { |
|
2357 iEventHandler->SetStatus(aStatus); |
|
2358 } |
|
2359 } |
|
2360 |
|
2361 void DMemoryAccess::CancelNotifyThreadCreation() |
|
2362 { |
|
2363 if (iEventHandler) |
|
2364 { |
|
2365 iEventHandler->SetStatus(NULL); |
|
2366 } |
|
2367 } |
|
2368 |
|
2369 TInt DMemoryAccess::SetPriorityOverride(TInt aPriority, TAny* aMatchString) |
|
2370 { |
|
2371 // TODO: Have this migrate to the shared event handler |
|
2372 // Or... just remove it. It's really odd code that could probably achieve its end goals in a much more sensible way. |
|
2373 TInt err = KErrNone; |
|
2374 if (!iEventHandler) |
|
2375 { |
|
2376 iEventHandler = new DThreadChangeHandler(iClient); |
|
2377 if (iEventHandler) |
|
2378 { |
|
2379 iEventHandler->Add(DKernelEventHandler::EAppend); |
|
2380 } |
|
2381 else |
|
2382 { |
|
2383 err = KErrNoMemory; |
|
2384 } |
|
2385 } |
|
2386 |
|
2387 // TODO: this isn't thread safe, as iEventHandler is already added... meh. |
|
2388 |
|
2389 if (!err) |
|
2390 { |
|
2391 iEventHandler->iPriorityToSet = aPriority; |
|
2392 err = Kern::ThreadDesRead(iClient, aMatchString, iEventHandler->iMatch, 0); |
|
2393 } |
|
2394 return err; |
|
2395 } |
|
2396 |
|
2397 TInt DMemoryAccess::OpenThread(TUint aThreadId) |
|
2398 { |
|
2399 NKern::ThreadEnterCS(); |
|
2400 DObjectCon* threads = Kern::Containers()[EThread]; |
|
2401 threads->Wait(); |
|
2402 DThread* thread = Kern::ThreadFromId(aThreadId); |
|
2403 if (thread && thread->Open() != KErrNone) |
|
2404 { |
|
2405 // Failed to open |
|
2406 thread = NULL; |
|
2407 } |
|
2408 threads->Signal(); |
|
2409 |
|
2410 if (thread) |
|
2411 { |
|
2412 TInt res = Kern::MakeHandleAndOpen(iClient, thread); |
|
2413 thread->Close(NULL); |
|
2414 NKern::ThreadLeaveCS(); |
|
2415 return res; |
|
2416 } |
|
2417 else |
|
2418 { |
|
2419 NKern::ThreadLeaveCS(); |
|
2420 return KErrNotFound; |
|
2421 } |
|
2422 } |
|
2423 |
|
2424 DThreadChangeHandler::DThreadChangeHandler(DThread* aClientThread) |
|
2425 : DKernelEventHandler(&Event, this), iThread(aClientThread) |
|
2426 { |
|
2427 } |
|
2428 |
|
2429 DThreadChangeHandler::~DThreadChangeHandler() |
|
2430 { |
|
2431 } |
|
2432 |
|
2433 /*static*/ TUint DThreadChangeHandler::Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData) |
|
2434 { |
|
2435 DThreadChangeHandler* self = static_cast<DThreadChangeHandler*>(aPrivateData); |
|
2436 return self->DoEvent(aEvent, a1, a2); |
|
2437 } |
|
2438 |
|
2439 TUint DThreadChangeHandler::DoEvent(TKernelEvent aEvent, TAny* a1, TAny* /*a2*/) |
|
2440 { |
|
2441 if (aEvent == EEventAddThread) |
|
2442 { |
|
2443 TRequestStatus* nullstat = NULL; |
|
2444 TRequestStatus* stat = (TRequestStatus*)NKern::SafeSwap(nullstat, (TAny*&)iStatus); |
|
2445 DThread* thread = static_cast<DThread*>(a1); |
|
2446 TBool notify = ETrue; |
|
2447 |
|
2448 if (iPriorityToSet && iMatch.Length()) |
|
2449 { |
|
2450 TBuf8<256> name; |
|
2451 thread->AppendFullName(name); |
|
2452 if (name.MatchF(iMatch) >= 0) |
|
2453 { |
|
2454 //Kern::Printf("Matched %O", thread); |
|
2455 NKern::LockSystem(); |
|
2456 SetPri(thread, iPriorityToSet); |
|
2457 NKern::UnlockSystem(); |
|
2458 } |
|
2459 else |
|
2460 { |
|
2461 // Not a thread we're interested in |
|
2462 notify = EFalse; |
|
2463 } |
|
2464 } |
|
2465 if (stat && notify) |
|
2466 { |
|
2467 TInt res = Kern::MakeHandleAndOpen(iThread, thread); |
|
2468 Kern::RequestComplete(iThread, stat, res); |
|
2469 } |
|
2470 } |
|
2471 return ERunNext; |
|
2472 } |
|
2473 |
|
2474 void DThreadChangeHandler::SetStatus(TRequestStatus* aStatus) |
|
2475 { |
|
2476 TRequestStatus* oldStat = (TRequestStatus*)NKern::SafeSwap(aStatus, (TAny*&)iStatus); |
|
2477 if (oldStat) |
|
2478 { |
|
2479 Kern::RequestComplete(iThread, oldStat, KErrCancel); |
|
2480 } |
|
2481 } |
|
2482 |
|
2483 TInt DMemoryAccess::InPlaceObjectRename(TAny* aParamsBuf, TAny* aNewNamePtr) |
|
2484 { |
|
2485 TObjectInfoByPtrParams params; |
|
2486 TPckg<TObjectInfoByPtrParams> paramsPkg(params); |
|
2487 TInt err = Kern::ThreadDesRead(iClient, aParamsBuf, paramsPkg, 0); |
|
2488 if (err) return err; |
|
2489 |
|
2490 TKName newName; |
|
2491 err = Kern::ThreadDesRead(iClient, aNewNamePtr, newName, 0); |
|
2492 if (err) return err; |
|
2493 |
|
2494 TInt posInContainer = KErrNotFound; |
|
2495 DObjectCon* const * cons = Kern::Containers(); |
|
2496 DObjectCon& container = *cons[params.iObjectType]; |
|
2497 container.Wait(); |
|
2498 TBool alreadyHeld = iLocks[params.iObjectType]; |
|
2499 iLocks[params.iObjectType] = ETrue; |
|
2500 |
|
2501 err = GetObjectPositionInContainer(params.iObjectPtr, container, posInContainer); |
|
2502 |
|
2503 if (err == KErrNone) |
|
2504 { |
|
2505 DObject* obj = container[posInContainer]; |
|
2506 obj->iName->Copy(newName); |
|
2507 } |
|
2508 container.Signal(); |
|
2509 iLocks[params.iObjectType] = alreadyHeld; |
|
2510 return err; |
|
2511 } |
|
2512 |
|
2513 TInt DMemoryAccess::InPlaceSetProcessFileName(TAny* a1, TAny* aNewNamePtr) |
|
2514 { |
|
2515 NKern::LockSystem(); |
|
2516 DProcess* process = (DProcess*)Kern::ObjectFromHandle(iClient, (TUint)a1, EProcess); |
|
2517 NKern::UnlockSystem(); |
|
2518 if (!process) |
|
2519 { |
|
2520 return KErrNotFound; |
|
2521 } |
|
2522 TBuf<256> filename; |
|
2523 TInt err = Kern::ThreadDesRead(iClient, aNewNamePtr, filename, 0); |
|
2524 if (err) return err; |
|
2525 //thread->iName->Copy(buf); |
|
2526 #ifdef __WINS__ |
|
2527 // Wins does 'optimisations' on the file name meaning an in-place copy will never work |
|
2528 HBuf* newName = HBuf8::New(filename); |
|
2529 if (!newName) return KErrNoMemory; |
|
2530 HBuf* oldName = (HBuf*)NKern::SafeSwap(newName, (TAny*&)process->iCodeSeg->iFileName); |
|
2531 delete oldName; |
|
2532 #else |
|
2533 process->iCodeSeg->iFileName->Copy(filename); |
|
2534 #endif |
|
2535 return KErrNone; |
|
2536 } |
|
2537 |
|
2538 class RHackAllocator : public RAllocator |
|
2539 { |
|
2540 public: |
|
2541 using RAllocator::iFlags; |
|
2542 }; |
|
2543 |
|
2544 TInt DMemoryAccess::EnableHeapTracing(TUint aThreadId, TBool aEnable) |
|
2545 { |
|
2546 #ifndef FSHELL_BTRACE_SUPPORT |
|
2547 // If the kernel doesn't have btrace, the heap won't have instrumentation |
|
2548 (void)aThreadId; |
|
2549 (void)aEnable; |
|
2550 return KErrNotSupported; |
|
2551 #else |
|
2552 |
|
2553 DObjectCon* threads = Kern::Containers()[EThread]; |
|
2554 NKern::ThreadEnterCS(); |
|
2555 threads->Wait(); |
|
2556 DThread* thread = Kern::ThreadFromId(aThreadId); |
|
2557 if (thread) thread->Open(); |
|
2558 threads->Signal(); |
|
2559 NKern::ThreadLeaveCS(); |
|
2560 |
|
2561 if (!thread) return KErrNotFound; |
|
2562 TLinAddr allocatorAddr = DoGetAllocatorAddress(thread, EFalse); |
|
2563 if (!allocatorAddr) |
|
2564 { |
|
2565 thread->Close(NULL); |
|
2566 return KErrNotFound; |
|
2567 } |
|
2568 |
|
2569 TLinAddr flagsAddr = allocatorAddr + _FOFF(RHackAllocator, iFlags); |
|
2570 TUint flags = 0; |
|
2571 TInt err = Kern::ThreadRawRead(thread, (void*)flagsAddr, &flags, sizeof(TUint)); |
|
2572 if (!err) |
|
2573 { |
|
2574 if (aEnable) flags |= RAllocator::ETraceAllocs; |
|
2575 else flags &= ~(RAllocator::ETraceAllocs); |
|
2576 err = Kern::ThreadRawWrite(thread, (void*)flagsAddr, &flags, sizeof(TUint)); |
|
2577 } |
|
2578 NKern::ThreadEnterCS(); |
|
2579 thread->Close(NULL); |
|
2580 NKern::ThreadLeaveCS(); |
|
2581 return err; |
|
2582 #endif |
|
2583 } |
|
2584 |
|
2585 #if defined(FSHELL_RAMDEFRAG_SUPPORT) && !defined(__WINS__) // emulator platform.h doesn't have the ram defrag APIs |
|
2586 |
|
2587 TInt DMemoryAccess::DefragRam(TInt aPriority) |
|
2588 { |
|
2589 TInt priority = aPriority; |
|
2590 if (priority == -1) priority = TRamDefragRequest::KInheritPriority; // I know KInheritPriority is actually -1 anyway but better to be correctly typed |
|
2591 TRamDefragRequest request; |
|
2592 return request.DefragRam(priority); |
|
2593 } |
|
2594 |
|
2595 TInt DMemoryAccess::EmptyRamZone(TInt aPriority, TUint aZone) |
|
2596 { |
|
2597 TInt priority = aPriority; |
|
2598 if (priority == -1) priority = TRamDefragRequest::KInheritPriority; // I know KInheritPriority is actually -1 anyway but better to be correctly typed |
|
2599 TRamDefragRequest request; |
|
2600 return request.EmptyRamZone(aZone, priority); |
|
2601 } |
|
2602 |
|
2603 TInt DMemoryAccess::GetRamZoneInfo(TUint aZone, TAny* aInfoPkg) |
|
2604 { |
|
2605 SRamZonePageCount info; |
|
2606 TInt err = Epoc::GetRamZonePageCount(aZone, info); |
|
2607 if (err) return err; |
|
2608 |
|
2609 TRamZoneInfo clientInf; |
|
2610 clientInf.iFreePages = info.iFreePages; |
|
2611 clientInf.iUnknownPages = info.iUnknownPages; |
|
2612 clientInf.iFixedPages = info.iFixedPages; |
|
2613 clientInf.iMovablePages = info.iMovablePages; |
|
2614 clientInf.iDiscardablePages = info.iDiscardablePages; |
|
2615 TPckg<TRamZoneInfo> clientPkg(clientInf); |
|
2616 err = Kern::ThreadDesWrite(iClient, aInfoPkg, clientPkg, 0, KTruncateToMaxLength, NULL); |
|
2617 return err; |
|
2618 } |
|
2619 |
|
2620 #else |
|
2621 |
|
2622 TInt DMemoryAccess::DefragRam(TInt /*aPriority*/) |
|
2623 { |
|
2624 return KErrNotSupported; |
|
2625 } |
|
2626 |
|
2627 TInt DMemoryAccess::EmptyRamZone(TInt /*aPriority*/, TUint /*aZone*/) |
|
2628 { |
|
2629 return KErrNotSupported; |
|
2630 } |
|
2631 |
|
2632 TInt DMemoryAccess::GetRamZoneInfo(TUint /*aZone*/, TAny* /*aInfoPkg*/) |
|
2633 { |
|
2634 return KErrNotSupported; |
|
2635 } |
|
2636 |
|
2637 #endif |
|
2638 |
|
2639 TCapabilitySet StoT(const SCapabilitySet& aCaps) |
|
2640 { |
|
2641 TCapabilitySet result; |
|
2642 result.SetEmpty(); |
|
2643 memcpy(&result, &aCaps, sizeof(SCapabilitySet)); |
|
2644 return result; |
|
2645 } |
|
2646 |
|
2647 SCapabilitySet TtoS(const TCapabilitySet& aCaps) |
|
2648 { |
|
2649 SCapabilitySet result; |
|
2650 memcpy(&result, &aCaps, sizeof(SCapabilitySet)); |
|
2651 return result; |
|
2652 } |
|
2653 |
|
2654 // Copied from DProcess::ConvertPriority |
|
2655 TInt DProcessConvertPriority(TProcessPriority aPriority) |
|
2656 { |
|
2657 TInt p=-1; |
|
2658 switch(aPriority) |
|
2659 { |
|
2660 case EPriorityLow: p=EProcPriorityLow; break; |
|
2661 case EPriorityBackground: p=EProcPriorityBackground; break; |
|
2662 case EPriorityForeground: p=EProcPriorityForeground; break; |
|
2663 case EPriorityHigh: p=EProcPriorityHigh; break; |
|
2664 case EPriorityWindowServer: p=EProcPrioritySystemServer1; break; |
|
2665 case EPriorityFileServer: p=EProcPrioritySystemServer2; break; |
|
2666 case EPriorityRealTimeServer: p=EProcPriorityRealTimeServer; break; |
|
2667 case EPrioritySupervisor: p=EProcPrioritySystemServer3; break; |
|
2668 } |
|
2669 return p; |
|
2670 } |
|
2671 |
|
2672 TInt DMemoryAccess::SetProcessProperties(TInt aProcessHandle, TAny* aProperties) |
|
2673 { |
|
2674 TProcessProperties properties; |
|
2675 TPckg<TProcessProperties> pkg(properties); |
|
2676 TInt err = Kern::ThreadDesRead(iClient, aProperties, pkg, 0); |
|
2677 if (err) return err; |
|
2678 |
|
2679 NKern::LockSystem(); |
|
2680 DProcess* proc = (DProcess*)Kern::ObjectFromHandle(iClient, aProcessHandle, EProcess); |
|
2681 if (!proc) return KErrBadHandle; |
|
2682 proc->Open(); |
|
2683 NKern::UnlockSystem(); |
|
2684 |
|
2685 if (properties.iSid != 0xFFFFFFFFu) proc->iS.iSecureId = properties.iSid; |
|
2686 if (properties.iVid != 0xFFFFFFFFu) proc->iS.iVendorId = properties.iVid; |
|
2687 |
|
2688 // Why is there no way of converting from an SCapabilitySet to a TCapabilitySet? |
|
2689 TCapabilitySet caps = StoT(proc->iS.iCaps); |
|
2690 caps.Union(properties.iCapsToAdd); |
|
2691 caps.Remove(properties.iCapsToRemove); |
|
2692 SCapabilitySet newSet = TtoS(caps); |
|
2693 memcpy(&proc->iS.iCaps, &newSet, sizeof(SCapabilitySet)); |
|
2694 |
|
2695 if (properties.iProcessPriority) |
|
2696 { |
|
2697 TInt priority = DProcessConvertPriority((TProcessPriority)properties.iProcessPriority); |
|
2698 if (priority < 0) err = KErrArgument; |
|
2699 else proc->iPriority = priority; // Note this won't recalculate thread priorities |
|
2700 } |
|
2701 |
|
2702 proc->Close(NULL); |
|
2703 return err; |
|
2704 } |
|
2705 |
|
2706 #ifndef FSHELL_COPYTOSHADOWMEMORY_SUPPORT |
|
2707 // Not sure exactly when it was introduced. Somewhere between 9.1 and 9.3 or anywhere that used ARM7 |
|
2708 // If CopyToShadowMemory is available it MUST be used, on ARM7 or later, otherwise you'll get an exception |
|
2709 #define NO_COPYTOSHADOWMEMORY |
|
2710 #endif |
|
2711 |
|
2712 TInt DMemoryAccess::WriteShadowMemory(TLinAddr aAddress, TAny* aNewContents) |
|
2713 { |
|
2714 #ifdef __WINS__ |
|
2715 (void)aAddress; |
|
2716 (void)aNewContents; |
|
2717 return KErrNotSupported; // Shadowing not supported on emulator |
|
2718 #else |
|
2719 TBuf8<32> newMem; |
|
2720 TInt len = Kern::ThreadGetDesLength(iClient, aNewContents); |
|
2721 if (len < 0) return len; |
|
2722 if (len > 32) return KErrTooBig; // API for CopyToShadowMemory says max 32 bytes, who are we to argue with hard-coded magic numbers (that aren't actually enforced afaics) |
|
2723 |
|
2724 TInt err = Kern::ThreadDesRead(iClient, aNewContents, newMem, 0); |
|
2725 if (err) return err; |
|
2726 |
|
2727 #ifdef NO_COPYTOSHADOWMEMORY |
|
2728 // Can't check if the page is already shadowed, just error and go straight to trying to call AllocShadowPage |
|
2729 err = KErrArgument; |
|
2730 #else |
|
2731 err = Epoc::CopyToShadowMemory(aAddress, (TLinAddr)newMem.Ptr(), newMem.Size()); |
|
2732 #endif |
|
2733 if (err == KErrArgument || err == KErrNotFound) |
|
2734 { |
|
2735 // The documentation *says* it will always be KErrArgument but Flexible memory model actually returns KErrNotFound |
|
2736 // Page (or pages) hasn't been shadowed yet |
|
2737 TLinAddr pageForStart = aAddress & ~(Kern::RoundToPageSize(1)-1); |
|
2738 TLinAddr pageForEnd = (aAddress + newMem.Size()) & ~(Kern::RoundToPageSize(1)-1); |
|
2739 err = Epoc::AllocShadowPage(pageForStart); |
|
2740 if ((err == KErrNone || err == KErrAlreadyExists) && pageForEnd != pageForStart) |
|
2741 { |
|
2742 // Maybe the area spans a page boundary and that was why the copy failed, so try allocing the end bit too |
|
2743 err = Epoc::AllocShadowPage(pageForEnd); |
|
2744 } |
|
2745 |
|
2746 if (err == KErrNone || err == KErrAlreadyExists) |
|
2747 { |
|
2748 // Retry the copy |
|
2749 #ifdef NO_COPYTOSHADOWMEMORY |
|
2750 memcpy((TAny*)aAddress, newMem.Ptr(), newMem.Size()); |
|
2751 err = KErrNone; |
|
2752 #else |
|
2753 err = Epoc::CopyToShadowMemory(aAddress, (TLinAddr)newMem.Ptr(), newMem.Size()); |
|
2754 #endif |
|
2755 } |
|
2756 } |
|
2757 return err; |
|
2758 #endif // __WINS__ |
|
2759 } |
|
2760 |
|
2761 TInt DMemoryAccess::FreeShadowMemory(TLinAddr aAddress, TInt aLength) |
|
2762 { |
|
2763 #ifdef __WINS__ |
|
2764 (void)aAddress; |
|
2765 (void)aLength; |
|
2766 return KErrNotSupported; // Shadowing not supported on emulator |
|
2767 #else |
|
2768 const TInt pageSize = Kern::RoundToPageSize(1); |
|
2769 TLinAddr end = aAddress + aLength; |
|
2770 TLinAddr page = aAddress & ~(pageSize -1); |
|
2771 while (page < end) |
|
2772 { |
|
2773 Epoc::FreeShadowPage(page); |
|
2774 page += pageSize; |
|
2775 } |
|
2776 return KErrNone; // There aren't any errors that it's important or sensible to pass to the client |
|
2777 #endif // __WINS__ |
|
2778 } |
|
2779 |
|
2780 TInt DMemoryAccessFactory::GetEventHandler(DDebuggerEventHandler*& aResult) |
|
2781 { |
|
2782 if (!DKernelEventHandler::DebugSupportEnabled()) return KErrNotSupported; |
|
2783 |
|
2784 Lock(); |
|
2785 if (iSharedEventHandler) |
|
2786 { |
|
2787 aResult = iSharedEventHandler; |
|
2788 Unlock(); |
|
2789 return KErrNone; |
|
2790 } |
|
2791 Unlock(); // Can't hold fast mutex around allocs |
|
2792 |
|
2793 TDfcQue* q = NULL; |
|
2794 TInt err = GetDfcQue(q); |
|
2795 if (err) return err; |
|
2796 |
|
2797 DDebuggerEventHandler* handler = DDebuggerEventHandler::New(q); |
|
2798 if (!handler) return KErrNoMemory; |
|
2799 // We must NOT call anything that could fail from this point on - otherwise it is impossible to safely close the DDebuggerEventHandler (looks like a bug in constructing a DKernelEventHandler from DLogicalDevice::Install()) |
|
2800 if (err != KErrNone) |
|
2801 { |
|
2802 handler->Close(); |
|
2803 return err; |
|
2804 } |
|
2805 Lock(); |
|
2806 if (iSharedEventHandler) |
|
2807 { |
|
2808 // Someone beat us to it |
|
2809 Unlock(); |
|
2810 handler->Close(); |
|
2811 } |
|
2812 else |
|
2813 { |
|
2814 iSharedEventHandler = handler; |
|
2815 Unlock(); |
|
2816 } |
|
2817 aResult = iSharedEventHandler; |
|
2818 |
|
2819 return KErrNone; |
|
2820 } |
|
2821 |
|
2822 void DMemoryAccessFactory::Lock() |
|
2823 { |
|
2824 NKern::FMWait(&iLock); |
|
2825 } |
|
2826 |
|
2827 void DMemoryAccessFactory::Unlock() |
|
2828 { |
|
2829 NKern::FMSignal(&iLock); |
|
2830 } |
|
2831 |
|
2832 TInt DMemoryAccess::DebuggerFn(TInt aFn, TAny* a1, TAny* a2) |
|
2833 { |
|
2834 DDebuggerEventHandler* handler = NULL; |
|
2835 TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler); |
|
2836 if (err) return err; |
|
2837 |
|
2838 switch (aFn) |
|
2839 { |
|
2840 case RMemoryAccess::EControlGetZombieDebugMode: |
|
2841 return handler->GetZombieMode(); |
|
2842 case RMemoryAccess::EControlSetZombieDebugMode: |
|
2843 { |
|
2844 TInt newmode = (TInt)a1; |
|
2845 TInt oldmode = handler->GetZombieMode(); |
|
2846 if (newmode && !oldmode) iDevice->Open(); // Stops us getting unloaded |
|
2847 else if (!newmode && oldmode) iDevice->Close(NULL); |
|
2848 err = handler->SetZombieMode(newmode); |
|
2849 break; |
|
2850 } |
|
2851 case RMemoryAccess::EControlGetZombies: |
|
2852 { |
|
2853 HBuf* zoms = handler->GetZombieThreadIds(); |
|
2854 if (zoms) |
|
2855 { |
|
2856 err = Kern::ThreadDesWrite(iClient, a1, *zoms, 0, KTruncateToMaxLength, NULL); |
|
2857 if (err == KErrNone || err == KErrOverflow) err = zoms->Length(); |
|
2858 delete zoms; |
|
2859 } |
|
2860 else |
|
2861 { |
|
2862 err = KErrNoMemory; |
|
2863 } |
|
2864 break; |
|
2865 } |
|
2866 case RMemoryAccess::EControlReleaseZombie: |
|
2867 { |
|
2868 DThread* thread = ThreadFromHandle((TInt)a1); |
|
2869 if (!thread) return KErrBadHandle; |
|
2870 err = handler->ReleaseZombie(thread); |
|
2871 thread->Close(NULL); |
|
2872 break; |
|
2873 } |
|
2874 case RMemoryAccess::EControlSuspendThread: |
|
2875 { |
|
2876 DThread* thread = ThreadFromHandle((TInt)a1); |
|
2877 if (!thread) return KErrBadHandle; |
|
2878 err = handler->SuspendThread(thread); |
|
2879 thread->Close(NULL); |
|
2880 break; |
|
2881 } |
|
2882 case RMemoryAccess::EControlNotifyBreakpoint: |
|
2883 { |
|
2884 if (iClientBreakpointNotifyStatus) return KErrAlreadyExists; |
|
2885 iClientBreakpointNotifyPkg = a1; |
|
2886 iClientBreakpointNotifyStatus = (TRequestStatus*)a2; |
|
2887 err = handler->RegisterForBreakpointNotification(this); |
|
2888 if (err) |
|
2889 { |
|
2890 iClientBreakpointNotifyPkg = NULL; |
|
2891 iClientBreakpointNotifyStatus = NULL; |
|
2892 } |
|
2893 break; |
|
2894 } |
|
2895 case RMemoryAccess::EControlCancelNotifyBreakpoint: |
|
2896 { |
|
2897 iClientBreakpointNotifyPkg = NULL; |
|
2898 if (iClientBreakpointNotifyStatus) |
|
2899 { |
|
2900 handler->UnregisterForBreakpointNotification(this); |
|
2901 Kern::RequestComplete(iClient, iClientBreakpointNotifyStatus, KErrCancel); |
|
2902 } |
|
2903 break; |
|
2904 } |
|
2905 case RMemoryAccess::EControlSetBreakpoint: |
|
2906 { |
|
2907 DThread* thread = ThreadFromHandle((TInt)a1); |
|
2908 if (!thread) return KErrBadHandle; |
|
2909 TUint32 args[2]; |
|
2910 RMemoryAccess::TPredicate cond; |
|
2911 err = Kern::ThreadRawRead(iClient, a2, args, sizeof(args)); |
|
2912 if (!err && args[1]) err = Kern::ThreadRawRead(iClient, (TAny*)args[1], &cond, sizeof(RMemoryAccess::TPredicate)); |
|
2913 if (!err) err = handler->SetBreakpoint(thread, args[0], cond); |
|
2914 thread->Close(NULL); |
|
2915 break; |
|
2916 } |
|
2917 case RMemoryAccess::EControlSetSymbolicBreakpoint: |
|
2918 { |
|
2919 TUint32 args[3]; |
|
2920 err = Kern::ThreadRawRead(iClient, a1, args, sizeof(args)); |
|
2921 if (err) return err; |
|
2922 DThread* thread = ThreadFromHandle(args[0]); |
|
2923 if (!thread) return KErrBadHandle; |
|
2924 |
|
2925 RMemoryAccess::TPredicate cond; |
|
2926 if (args[2] != 0) err = Kern::ThreadRawRead(iClient, (TAny*)args[2], &cond, sizeof(RMemoryAccess::TPredicate)); |
|
2927 if (err) |
|
2928 { |
|
2929 thread->Close(NULL); |
|
2930 return err; |
|
2931 } |
|
2932 |
|
2933 TInt nameLen = Kern::ThreadGetDesLength(iClient, a2); |
|
2934 if (nameLen < 0) err = nameLen; |
|
2935 HBuf* codeseg = NULL; |
|
2936 if (!err) |
|
2937 { |
|
2938 codeseg = HBuf::New(nameLen); |
|
2939 if (!codeseg) err = KErrNoMemory; |
|
2940 } |
|
2941 if (!err) err = Kern::ThreadDesRead(iClient, a2, *codeseg, 0); |
|
2942 if (!err) err = handler->SetSymbolicBreakpoint(thread, codeseg, args[1], cond); |
|
2943 |
|
2944 if (err < 0) delete codeseg; |
|
2945 thread->Close(NULL); |
|
2946 break; |
|
2947 } |
|
2948 case RMemoryAccess::EControlSetBreakpointEnabled: |
|
2949 return handler->SetBreakpointEnabled((TInt)a1, (TBool)a2); |
|
2950 case RMemoryAccess::EControlClearBreakpoint: |
|
2951 return handler->ClearBreakpoint((TInt)a1); |
|
2952 case RMemoryAccess::EControlContinueFromBreakpoint: |
|
2953 { |
|
2954 DThread* thread = ThreadFromHandle((TInt)a1); |
|
2955 if (!thread) return KErrBadHandle; |
|
2956 err = handler->ContinueFromBreakpoint(thread, 0); |
|
2957 thread->Close(NULL); |
|
2958 break; |
|
2959 } |
|
2960 case RMemoryAccess::EControlGetBreakpoints: |
|
2961 { |
|
2962 HBuf* breakpoints = handler->GetBreakpoints(); |
|
2963 if (breakpoints) |
|
2964 { |
|
2965 err = Kern::ThreadDesWrite(iClient, a1, *breakpoints, 0, KTruncateToMaxLength, NULL); |
|
2966 if (err == KErrNone || err == KErrOverflow) err = breakpoints->Length(); |
|
2967 delete breakpoints; |
|
2968 } |
|
2969 else |
|
2970 { |
|
2971 err = KErrNoMemory; |
|
2972 } |
|
2973 break; |
|
2974 } |
|
2975 case RMemoryAccess::EControlRegisterPersistantBreakpoint: |
|
2976 return handler->RegisterPersistantBreakpoint(iClient, (TLinAddr)a1); |
|
2977 default: |
|
2978 err = KErrNotSupported; |
|
2979 } |
|
2980 return err; |
|
2981 } |
|
2982 |
|
2983 DThread* DMemoryAccess::ThreadFromHandle(TInt aHandle) |
|
2984 { |
|
2985 if (aHandle == KCurrentThreadHandle) |
|
2986 { |
|
2987 iClient->Open(); |
|
2988 return iClient; |
|
2989 } |
|
2990 else |
|
2991 { |
|
2992 NKern::LockSystem(); |
|
2993 DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aHandle, EThread); |
|
2994 if (thread) thread->Open(); |
|
2995 NKern::UnlockSystem(); |
|
2996 return thread; |
|
2997 } |
|
2998 } |
|
2999 |
|
3000 DMemoryAccessFactory::~DMemoryAccessFactory() |
|
3001 { |
|
3002 if (iSharedEventHandler) |
|
3003 { |
|
3004 iSharedEventHandler->SetZombieMode(0); // This is needed because its iAccessCount is incremented while threads are blocked in its Event function, therefore Close will otherwise never get to the destructor (Which is what otherwise calls CompleteZombies) |
|
3005 iSharedEventHandler->Close(); |
|
3006 iSharedEventHandler = NULL; |
|
3007 } |
|
3008 if (iDfcQueWrapper) |
|
3009 { |
|
3010 iDfcQueWrapper->Destroy(); |
|
3011 } |
|
3012 } |
|
3013 |
|
3014 TInt DMemoryAccess::GetRegisters(TAny* a1, TAny* /*a2*/) |
|
3015 { |
|
3016 TUint32 args[4]; |
|
3017 TInt err = Kern::ThreadRawRead(iClient, a1, &args[0], sizeof(args)); |
|
3018 if (err) return err; |
|
3019 TInt threadHandle = args[0]; |
|
3020 TBool userMode = args[1]; |
|
3021 TAny* regBuf = (TAny*)args[2]; |
|
3022 TAny* validPtr = (TAny*)args[3]; |
|
3023 |
|
3024 DThread* thread = ThreadFromHandle(threadHandle); |
|
3025 if (!thread) return KErrBadHandle; |
|
3026 TUint32 regs[32]; |
|
3027 TUint32 valid = 0; |
|
3028 |
|
3029 #if !defined(__WINS__) && !defined(FSHELL_9_1_SUPPORT) // win32 ekern doesn't even export this API let alone implement it |
|
3030 if (!thread->iSupervisorStack) |
|
3031 { |
|
3032 // Thread has not only died but has got as far as deallocating its supervisor stack - in which case we can't |
|
3033 // get the registers, and moreover NKern::ThreadGetXXXContext will crash if we try |
|
3034 thread->Close(NULL); |
|
3035 return KErrDied; |
|
3036 } |
|
3037 if (userMode) |
|
3038 { |
|
3039 NKern::ThreadGetUserContext(&thread->iNThread, ®s[0], valid); |
|
3040 } |
|
3041 else |
|
3042 { |
|
3043 NKern::ThreadGetSystemContext(&thread->iNThread, ®s[0], valid); |
|
3044 } |
|
3045 #else |
|
3046 (void)userMode; |
|
3047 #endif |
|
3048 |
|
3049 thread->Close(NULL); |
|
3050 TPckg<TUint32[32]> regsPkg(regs); |
|
3051 err = Kern::ThreadDesWrite(iClient, regBuf, regsPkg, 0); |
|
3052 if (err) return err; |
|
3053 err = Kern::ThreadRawWrite(iClient, validPtr, &valid, sizeof(TUint32)); |
|
3054 return err; |
|
3055 } |
|
3056 |
|
3057 void DMemoryAccess::BreakpointHit(TDes& aPkg) |
|
3058 { |
|
3059 TRequestStatus* stat = (TRequestStatus*)NKern::SafeSwap(NULL, (TAny*&)iClientBreakpointNotifyStatus); |
|
3060 if (stat) |
|
3061 { |
|
3062 // Can't see how we could get here with it being null, but still |
|
3063 TInt err = Kern::ThreadDesWrite(iClient, iClientBreakpointNotifyPkg, aPkg, 0); |
|
3064 Kern::RequestComplete(iClient, stat, err); |
|
3065 iClientBreakpointNotifyPkg = NULL; |
|
3066 } |
|
3067 } |