Update contrib.
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Device driver for kernel side debug assist
18 #error - this driver cannot be built for emulation
22 #include <e32def_private.h>
24 #include <e32cmn_private.h>
27 #include <kernel/kernel.h>
28 #include <kernel/kern_priv.h>
31 #include <kernel/cache.h>
35 #include <kernel/kdebug.h>
36 #include <rm_debug_api.h>
38 #include "debug_logging.h"
39 #include "d_rmd_breakpoints.h" // moved breakpoints code lives here
40 #include "d_rmd_stepping.h" // moved stepping code lives here
41 #include "rm_debug_kerneldriver.h"
42 #include "d_list_manager.h"
43 #include "rm_debug_driver.h"
44 #include "rm_debug_eventhandler.h"
45 #include "d_debug_functionality.h"
46 #include "d_process_tracker.h"
47 #include "debug_utils.h"
48 #include "d_buffer_manager.h"
50 using namespace Debug;
52 /////////////////////////////////////////////////////////////////////////
54 // DRM_DebugDriverFactory implementation
56 /////////////////////////////////////////////////////////////////////////
59 // DRM_DebugDriverFactory constructor
61 DRM_DebugDriverFactory::DRM_DebugDriverFactory()
63 iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
67 // DRM_DebugDriverFactory::Create
69 TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
71 if (iOpenChannels != 0)
72 return KErrInUse; // a channel is already open
74 aChannel = new DRM_DebugChannel(this);
76 return aChannel ? KErrNone : KErrNoMemory;
80 // DRM_DebugDriverFactory::Install
82 TInt DRM_DebugDriverFactory::Install()
84 return(SetName(&KRM_DebugDriverName));
88 // DRM_DebugDriverFactory::Install
90 void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
92 TCapsRM_DebugDriver b;
93 b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
95 Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
98 /////////////////////////////////////////////////////////////////////////
100 // DRM_DebugChannel implementation
102 /////////////////////////////////////////////////////////////////////////
105 // DRM_DebugChannel constructor
107 DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
108 : iExcludedROMAddressStart(ROM_LINEAR_BASE),
109 iExcludedROMAddressEnd(0),
115 iInitialisedCodeModifier(0),
116 iAsyncGetValueRequest(NULL)
118 LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
120 iDevice = aLogicalDevice;
122 iClientThread = &Kern::CurrentThread();
123 iClientThread->Open();
125 iPageSize = Kern::RoundToPageSize(1);
129 // DRM_DebugChannel destructor
131 DRM_DebugChannel::~DRM_DebugChannel()
133 LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
135 if (iAsyncGetValueRequest)
137 Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
138 Kern::DestroyClientRequest(iAsyncGetValueRequest);
141 NKern::ThreadEnterCS();
142 Kern::SafeClose((DObject*&)iClientThread, NULL);
143 NKern::ThreadLeaveCS();
145 // Close breakpoint manager
148 NKern::ThreadEnterCS();
149 delete iBreakManager;
150 NKern::ThreadLeaveCS();
153 // Close stepping manager
156 NKern::ThreadEnterCS();
158 NKern::ThreadLeaveCS();
161 //close the debug process list
162 iDebugProcessList.Close();
166 //close the code modifier
167 if (iInitialisedCodeModifier)
169 DebugSupport::CloseCodeModifier();
173 void DRM_DebugChannel::DestroyDfcQ()
175 LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
178 NKern::ThreadEnterCS();
180 NKern::ThreadLeaveCS();
185 // DRM_DebugChannel::DoCreate
187 TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
189 LOG_MSG("DRM_DebugChannel::DoCreate()");
190 TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
194 if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
195 return KErrNotSupported;
197 // Do the security check here so that any arbitrary application doesn't make
198 // use of Trk kernel driver.
199 if (!DoSecurityCheck())
201 LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
202 return KErrPermissionDenied;
207 // this is the end address of the user library.
208 // this doesn't seem to be valid for EKA2.
209 // right now we dont need this for EKA2 since we are not worried
210 // about kernel being stopped as kernel is multithreaded.
211 // just retaining this for future use.
213 TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
217 //iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
220 // Allocate a D_RMD_Breakpoints class as a breakpoint manager
221 NKern::ThreadEnterCS();
222 iBreakManager = new D_RMD_Breakpoints(this);
223 NKern::ThreadLeaveCS();
224 if (iBreakManager == NULL)
226 LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
230 // Initialise the new breakpoint manager object
231 iBreakManager->Init();
233 // Allocate a DRMDStepping class as the stepping manager
234 NKern::ThreadEnterCS();
235 iStepper = new DRMDStepping(this);
236 NKern::ThreadLeaveCS();
237 if (iStepper == NULL)
239 LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
243 // Initialize the code modifier for managing breakpoints.
244 TUint caps; //ignored for now
245 err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
246 //if code modifier initializer failed,
247 //return here, since we can't set an breakpoints
254 iInitialisedCodeModifier = ETrue;
257 //create and set the driver's Dfc queue
261 LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
267 iEventHandler = new DRM_DebugEventHandler;
270 err = iEventHandler->Create(iDevice, this, iClientThread);
275 return iEventHandler->Start();
279 // DRM_DebugChannel::SendMsg
281 TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
283 LOG_MSG("DRM_DebugChannel::SendMsg()");
285 TThreadMessage& m = *(TThreadMessage*)aMsg;
289 if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
292 TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
293 err = SendRequest(aMsg);
295 Kern::RequestComplete(pStatus,err);
299 err = DLogicalChannel::SendMsg(aMsg);
305 // DRM_DebugChannel::SendRequest
307 TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
309 LOG_MSG("DRM_DebugChannel::SendRequest()");
311 TThreadMessage& m = *(TThreadMessage*)aMsg;
312 TInt function = ~m.iValue;
313 TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
316 TInt err = KErrNotSupported;
319 case RRM_DebugDriver::ERequestGetEvent:
320 err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
324 err = DLogicalChannel::SendMsg(aMsg);
329 // DRM_DebugChannel::PreAsyncGetValue
331 TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
333 LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
335 iAsyncGetValueRequest->Reset();
337 TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
341 iAsyncGetValueRequest->SetDestPtr(aValue);
346 Create the Dfc queue for receiving messages
348 TInt DRM_DebugChannel::CreateDfcQ()
350 LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
351 TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
352 // Fix to stop t_rmdebug2 etc crashing the device.
353 // This should be removed once the rm debug driver has been updated for WDP.
355 iDfcQ->SetRealtimeState(ERealtimeStateOff);
360 // DRM_DebugChannel::DoCancel
362 // New: The cancel call does not take an enum parameter describing
363 // the request to be cancelled. Rather it supplies a pointer
364 // to a user-side struct defining the cancellation
366 void DRM_DebugChannel::DoCancel(TInt aReqNo)
368 LOG_MSG("DRM_DebugChannel::DoCancel()");
370 TRMD_DebugCancelInfo info;
372 TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
375 // How do we cancel something we know nothing about???
376 LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
381 DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
382 if (pProcess == NULL)
384 // We are doomed. We don't know which event to cancel..
385 LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
391 DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
392 if (debugAgent == NULL)
394 // Bad agent means there is no tracking agent
395 LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
399 // Agent completes/pends the request as appropriate.
400 debugAgent->CancelGetEvent();
405 // DRM_DebugChannel::DoRequest
407 void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
409 LOG_MSG("DRM_DebugChannel::DoRequest()");
413 case RRM_DebugDriver::ERequestGetEvent:
415 TEventMetaData eventMetaData;
416 TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
419 LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
421 // We could not read information from the user, so the a2 argument is probably wrong
422 Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
427 DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
428 if (pProcess == NULL)
430 LOG_MSG("Cannot identify process being debugged");
432 // We could not locate the process, so the user asked for the wrong one.
433 Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
438 DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
439 if (debugAgent == NULL)
441 // Bad agent means there is no tracking agent
442 LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
445 // Agent completes/pends the request as appropriate.
446 debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
452 // Don't know what to do, should not get here!
453 LOG_MSG("DRM_DebugChannel::DoRequest was passed an unsupported request aReqNo");
455 Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
461 // DRM_DebugChannel::DoControl
463 TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
465 LOG_MSG("DRM_DebugChannel::DoControl()");
467 LOG_MSG2("DoControl Function %d", aFunction);
469 TInt err = KErrBadHandle;
470 DThread* threadObj = NULL;
475 case RRM_DebugDriver::EControlIsDebuggable:
477 err = IsDebuggable((TUint32)a1);
480 case RRM_DebugDriver::EControlSetBreak:
482 err = SetBreak((TSetBreakInfo*)a1);
485 case RRM_DebugDriver::EControlClearBreak:
487 err = iBreakManager->DoClearBreak((TInt32)a1);
490 case RRM_DebugDriver::EControlModifyBreak:
492 err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
495 case RRM_DebugDriver::EControlModifyProcessBreak:
497 err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
500 case RRM_DebugDriver::EControlBreakInfo:
502 err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
505 case RRM_DebugDriver::EControlSuspendThread:
507 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
510 err = DoSuspendThread(threadObj);
514 case RRM_DebugDriver::EControlResumeThread:
516 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
519 err = DoResumeThread(threadObj);
523 case RRM_DebugDriver::EControlStepRange:
525 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
528 err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
532 case RRM_DebugDriver::EControlReadMemory:
534 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
537 err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
541 case RRM_DebugDriver::EControlWriteMemory:
543 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
546 err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
550 case RRM_DebugDriver::EControlReadRegistersLegacy:
552 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
555 err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
559 case RRM_DebugDriver::EControlWriteRegistersLegacy:
561 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
564 err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
568 case RRM_DebugDriver::EControlReadRegisters:
570 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
573 err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
577 case RRM_DebugDriver::EControlWriteRegisters:
579 threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
582 err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
586 case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
588 LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
590 TDebugFunctionality df;
592 TUint size = df.GetDebugFunctionalityBufSize();
594 // Return size to user-side in a safe manner
595 err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
598 case RRM_DebugDriver::EControlGetDebugFunctionality:
600 LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
602 TDebugFunctionality df;
604 TUint32 dfsize = df.GetDebugFunctionalityBufSize();
606 // Alloc tmp buffer for Debug Functionality data
607 NKern::ThreadEnterCS();
608 TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
609 NKern::ThreadLeaveCS();
612 LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
614 // could not allocate memory
618 // Temporary descriptor to hold DF data
619 TPtr8 tmpPtr(dfbuffer,0,dfsize);
621 // Obtain the DF data
622 if (df.GetDebugFunctionality(tmpPtr) )
624 // Return the DF data to the user-side
625 err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
634 NKern::ThreadEnterCS();
635 Kern::Free(dfbuffer);
636 NKern::ThreadLeaveCS();
639 case RRM_DebugDriver::EControlAttachProcess:
641 LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
643 err = AttachProcess(a1,a2);
646 case RRM_DebugDriver::EControlDetachProcess:
648 LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
650 err = DetachProcess(a1,a2);
653 case RRM_DebugDriver::EControlDetachAgent:
655 LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
657 err = DetachAgent(a1,a2);
660 case RRM_DebugDriver::EControlSetEventAction:
662 LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
664 err = SetEventAction(a1,a2);
667 case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
669 LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
671 TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
673 // Return size to user-side in a safe manner
674 err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
677 case RRM_DebugDriver::EControlGetList:
679 LOG_MSG("RRM_DebugDriver::EControlGetList\n");
680 err = GetList((TListInformation*)a1);
683 case RRM_DebugDriver::EControlStep:
685 LOG_MSG("RRM_DebugDriver::EControlStep\n");
687 err = Step((TUint32)a1,(TUint32)a2);
690 case RRM_DebugDriver::EControlKillProcess:
692 LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
694 err = KillProcess((TUint32)a1,(TUint32)a2);
705 LOG_MSG2("Error %d from control function", err);
710 // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
711 threadObj->Close(NULL);
717 void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
719 LOG_MSG("DRM_DebugChannel::HandleMsg()");
721 TThreadMessage& m = *(TThreadMessage*)aMsg;
724 if (id == (TInt)ECloseMsg)
728 iEventHandler->Stop();
729 iEventHandler->Close();
730 iEventHandler = NULL;
732 m.Complete(KErrNone, EFalse);
740 m.Complete(KErrNone, ETrue);
747 TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
748 DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
749 m.Complete(KErrNone, ETrue);
754 TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
755 m.Complete(err, ETrue);
760 // DRM_DebugChannel::RemoveProcess
762 TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
764 LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
766 DProcess *aProcess = (DProcess*)a1;
771 // No process was specified!
772 LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
776 // this is called when a process dies. we want to mark any breakpoints in this
777 // process space as obsolete. the main reason for this is so we don't return
778 // an error when the host debugger tries to clear breakpoints for the process
780 TUint32 codeAddress = 0;
781 TUint32 codeSize = 0;
783 LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
785 DCodeSeg* codeSeg = aProcess->iCodeSeg;
789 TModuleMemoryInfo processMemoryInfo;
790 TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
793 codeAddress = processMemoryInfo.iCodeBase;
794 codeSize = processMemoryInfo.iCodeSize;
798 LOG_MSG2("Error in getting memory info: %d", err);
803 if (!codeAddress || !codeSize)
805 LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
806 // make sure there is not already a breakpoint at this address
807 for (TInt i = 0; i < iDebugProcessList.Count(); i++)
809 if (iDebugProcessList[i].iId == aProcess->iId)
811 codeAddress = iDebugProcessList[i].iCodeAddress;
812 codeSize = iDebugProcessList[i].iCodeSize;
814 //now remove from the list
815 iDebugProcessList.Remove(i);
821 if (!codeAddress || !codeSize)
826 iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
831 // DRM_DebugChannel::StartThread
833 TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
835 LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
837 DThread *aThread = (DThread*)a1;
840 LOG_MSG("Error getting DThread object");
841 __NK_ASSERT_DEBUG(aThread);
845 //a2 points to the thread creating the new thread.
846 //We have no use for it at the moment so just ignore it for now
848 TDriverEventInfo info;
849 info.iEventType = EEventsStartThread;
850 info.iThreadId = aThread->iId;
851 info.iThreadIdValid = ETrue;
852 DProcess* owningProcess = aThread->iOwningProcess;
855 info.iProcessId = owningProcess->iId;
856 info.iProcessIdValid = ETrue;
857 DCodeSeg* p = owningProcess->iCodeSeg;
858 if(p && p->iFileName)
860 info.iFileName.Copy(*(p->iFileName));
861 DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
864 foundProcess->NotifyEvent(info);
868 LOG_EVENT_MSG2("Couldn't find process with name [%S]", p->iFileName);
875 LOG_EVENT_MSG("\tCode segment name missing");
879 LOG_EVENT_MSG("\tCode segment is NULL");
887 // DRM_DebugChannel::HandleAddProcessEvent
889 TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
891 LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
893 DProcess *aProcess = (DProcess*)a1;
894 // a2 points to the thread creating the new process.
895 DThread *aThread = (DThread*)a2;
899 LOG_MSG("Error getting DProcess object");
900 __NK_ASSERT_DEBUG(aProcess);
904 TDriverEventInfo info;
905 info.iEventType = EEventsAddProcess;
906 info.iProcessId = aProcess->iId;
908 info.iCreatorThreadId = aThread ? aThread->iId : 0;
909 info.iProcessIdValid = ETrue;
912 info.iUids = aProcess->iUids;
914 info.iUidsValid = ETrue;
916 // copy name of the process
919 // copy the name of the process
920 info.iFileName.Copy(*aProcess->iName);
922 DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
925 foundProcess->NotifyEvent(info);
929 // AddProcess event does not have fully-qualified path, it has "filename.exe"
930 // So we try a less-precise match
931 DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
934 foundProcess->NotifyEvent(info);
938 LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
944 LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
951 // DRM_DebugChannel::HandleRemoveProcessEvent
953 TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
955 LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
957 DProcess *aProcess = (DProcess*)a1;
960 LOG_MSG("Error getting DProcess object");
961 __NK_ASSERT_DEBUG(aProcess);
965 // a2 points to the thread creating the new process.
966 // We have no use for it at the moment so just ignore it for now
967 // Also, it may not be known and therefore NULL
969 TDriverEventInfo info;
970 info.iEventType = EEventsRemoveProcess;
971 info.iProcessId = aProcess->iId;
972 info.iProcessIdValid = ETrue;
974 // copy name of the process
977 // copy the name of the process
978 info.iFileName.Copy(*aProcess->iName);
980 DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
983 foundProcess->NotifyEvent(info);
987 // RemoveProcess event does not have fully-qualified path, it has "filename.exe"
988 // So we try a less-precise match
989 DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
992 foundProcess->NotifyEvent(info);
996 LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
1003 LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
1010 // DRM_DebugChannel::AddLibrary
1012 TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
1014 LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
1016 DLibrary *aLibrary = (DLibrary*)a1;
1017 DThread *aThread = (DThread*)a2;
1022 LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
1028 LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
1032 LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
1036 // make sure this is not the debugger thread
1037 if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
1039 TDriverEventInfo info;
1041 info.iEventType = EEventsAddLibrary;
1042 info.iProcessId = aThread->iOwningProcess->iId;
1043 info.iProcessIdValid = ETrue;
1044 info.iThreadId = aThread->iId;
1045 info.iThreadIdValid = ETrue;
1047 //get the code address
1048 DCodeSeg* codeSeg = aLibrary->iCodeSeg;
1051 LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
1056 info.iUids = codeSeg->iUids;
1057 info.iUidsValid = ETrue;
1059 TModuleMemoryInfo memoryInfo;
1060 TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
1061 if (err != KErrNone)
1063 LOG_EVENT_MSG2("Error in getting memory info: %d", err);
1067 info.iCodeAddress = memoryInfo.iCodeBase;
1068 info.iDataAddress = memoryInfo.iInitialisedDataBase;
1070 info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
1072 //queue up or complete the event
1083 // DRM_DebugChannel::RemoveLibrary
1085 TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
1087 LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
1088 DLibrary *aLibrary = (DLibrary*)a1;
1093 LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
1097 LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
1099 // this is called when all handles to this library have been closed. this can happen when a process dies, or when a dll is
1100 // unloaded while the process lives on. in former case, we don't need to notify the host debugger because that process is
1101 // dying anyway. for the latter case, we do need to notify the host so it can unload the symbolics, etc.
1103 DThread* aThread = &Kern::CurrentThread();
1106 (aThread != iClientThread) &&
1107 (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
1109 //the library gets unloaded only when the mapcount is 0.
1110 if (aLibrary->iMapCount != 0)
1113 DCodeSeg* codeSeg = aLibrary->iCodeSeg;
1116 LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
1120 TModuleMemoryInfo processMemoryInfo;
1121 TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
1122 if (err != KErrNone)
1124 LOG_EVENT_MSG2("Error in getting memory info: %d", err);
1128 TUint32 codeAddress = processMemoryInfo.iCodeBase;
1129 TUint32 codeSize = processMemoryInfo.iCodeSize;
1131 // first invalidate all breakpoints that were set in the library code
1132 iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
1133 DProcess *process = &Kern::CurrentProcess();
1134 RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
1136 for (TInt j=0; j<dynamicCode->Count(); j++)
1138 if ((*dynamicCode)[j].iLib == aLibrary)
1140 TDriverEventInfo info;
1142 info.iEventType = EEventsRemoveLibrary;
1143 info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
1144 //info.iFileName.ZeroTerminate();
1145 info.iProcessId = process->iId;
1146 info.iProcessIdValid = ETrue;
1147 info.iThreadId = 0xFFFFFFFF; // don't care!
1148 info.iThreadIdValid = EFalse;
1150 info.iUids = codeSeg->iUids;
1151 info.iUidsValid = ETrue;
1153 //queue up or complete the event
1164 // DRM_DebugChannel::HandleEventKillThread
1166 TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
1168 LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
1170 DThread* currentThread = &Kern::CurrentThread();
1173 LOG_MSG("Error getting current thread");
1174 __NK_ASSERT_DEBUG(currentThread);
1178 // a1 should point to the current thread, check this to make sure it does
1179 __NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
1181 TDriverEventInfo info;
1183 info.iProcessId = currentThread->iOwningProcess->iId;
1184 info.iProcessIdValid = ETrue;
1185 info.iThreadId = currentThread->iId;
1186 info.iThreadIdValid = ETrue;
1187 // 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
1188 TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
1191 LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
1194 if (currentThread->iExitType == EExitPanic)
1196 info.iPanicCategory.Copy(currentThread->iExitCategory);
1198 info.iExceptionNumber = currentThread->iExitReason;
1199 info.iExitType = currentThread->iExitType;
1200 info.iEventType = EEventsKillThread;
1202 // Are we debugging this process - decide based on iFileName
1203 DCodeSeg* codeSeg = currentThread->iOwningProcess->iCodeSeg;
1205 // remove all the breakpoints in this thread, whether we are debugging it or not.
1206 iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
1208 // if the code seg exists then get the file name from it and check we're debugging it
1211 DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(codeSeg->iFileName));
1214 // not debugging this process so return false
1220 // can't validate that we are debugging the thread
1232 // DRM_DebugChannel::HandleSwException
1234 TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
1236 LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
1237 TExcType aExcType = (TExcType)(TInt)a1;
1239 TDriverEventInfo info;
1241 DThread* currentThread = &Kern::CurrentThread();
1244 LOG_MSG("Error getting current thread");
1245 __NK_ASSERT_DEBUG(currentThread);
1249 info.iProcessId = currentThread->iOwningProcess->iId;
1250 info.iProcessIdValid = ETrue;
1251 info.iThreadId = currentThread->iId;
1252 info.iThreadIdValid = ETrue;
1253 TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
1256 LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
1258 info.iExceptionNumber = aExcType;
1259 info.iEventType = EEventsSwExc;
1269 // DRM_DebugChannel::HandleHwException
1271 TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
1273 LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
1274 TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
1279 LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
1280 __NK_ASSERT_DEBUG(aExcInfo);
1284 TDriverEventInfo info;
1286 DThread* currentThread = &Kern::CurrentThread();
1287 LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
1291 LOG_MSG("Error getting current thread");
1292 __NK_ASSERT_DEBUG(currentThread);
1296 info.iProcessId = currentThread->iOwningProcess->iId;
1297 info.iProcessIdValid = ETrue;
1298 info.iThreadId = currentThread->iId;
1299 info.iThreadIdValid = ETrue;
1300 info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
1301 info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
1302 LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
1303 aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
1305 info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
1306 info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
1307 info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
1308 info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
1310 info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
1311 info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
1312 info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
1313 info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
1314 info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
1315 info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
1316 info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
1317 info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
1318 info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
1320 info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
1321 info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
1322 info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
1323 LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
1324 aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
1326 info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
1327 info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
1328 info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
1329 info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
1330 LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
1331 aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
1333 switch (aExcInfo->iExcCode)
1336 info.iExceptionNumber = EExcCodeAbort;
1337 LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
1340 info.iExceptionNumber = EExcDataAbort;
1341 LOG_EVENT_MSG(" iExcCode == 1 => EExcDataAbort");
1344 info.iExceptionNumber = EExcInvalidOpCode;
1345 LOG_EVENT_MSG(" iExcCode == 2 => EExcInvalidOpCode");
1348 // new event? Something gone wrong?
1349 __NK_ASSERT_DEBUG(EFalse);
1353 info.iEventType = EEventsHwExc;
1358 if(EExcInvalidOpCode == info.iExceptionNumber)
1360 return HandleInvalidOpCodeException(info, currentThread);
1368 // DRM_DebugChannel::HandUserTrace
1370 TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
1372 LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
1374 DThread* currentThread = &Kern::CurrentThread();
1377 LOG_EVENT_MSG("Error getting current thread");
1378 __NK_ASSERT_DEBUG(currentThread);
1382 TDriverEventInfo info;
1383 info.iProcessId = currentThread->iOwningProcess->iId;
1384 info.iProcessIdValid = ETrue;
1385 info.iThreadId = currentThread->iId;
1386 info.iThreadIdValid = ETrue;
1387 info.iEventType = EEventsUserTrace;
1391 TInt err = KErrNone;
1394 XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
1400 info.iMessageStatus = ESingleMessage;
1408 // DRM_DebugChannel::HandleException
1410 TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
1412 LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
1414 TInt err = KErrNone;
1416 TUint32 inst = KArmBreakPoint;
1419 // change these for thumb mode
1421 err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
1424 LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
1426 if (regValue & ECpuThumb)
1428 inst = KThumbBreakPoint;
1432 TUint32 instruction = 0;
1433 err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
1435 if (KErrNone != err)
1436 LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
1438 if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
1440 TInt err = DoSuspendThread(aCurrentThread);
1441 if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
1443 LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
1447 // the exception was a breakpoint instruction. see if we have a breakpoint at that address
1448 TBreakEntry* breakEntry = NULL;
1451 breakEntry = iBreakManager->GetNextBreak(breakEntry);
1452 if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
1454 LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
1456 TBreakEntry tempBreakEntry = *breakEntry;
1458 //change the event type to breakpoint type
1459 aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
1461 // enable any breakpoints we had to disable for this thread
1462 err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
1463 if (KErrNone != err)
1464 LOG_MSG2("Error %d enabling disabled breakpoints", err);
1466 // see if this is a temp breakpoint
1467 if (iBreakManager->IsTemporaryBreak(*breakEntry))
1469 // this was a temp breakpoint, so we need to clear it now
1470 err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
1471 if (KErrNone != err)
1472 LOG_MSG2("Error %d clearing temp breakpoint", err);
1474 // Find out how many steps remain to be done
1476 // reduce the number of steps to complete by 1
1477 tempBreakEntry.iNumSteps--;
1479 LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
1481 // New. If we have not finished do all the steps, continue stepping and don't notify event
1482 if (tempBreakEntry.iNumSteps)
1484 LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
1485 err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
1486 if (err != KErrNone)
1488 LOG_EVENT_MSG("Failed to continue stepping\n");
1490 // what do we do? might as well stop here and tell the user
1491 NotifyEvent(aEventInfo);
1496 // continue as though no event occured. No need to suspend/resume anything...
1497 LOG_EVENT_MSG("Continuing to step\n");
1501 // Is this a case where we just want to continue?
1502 if (tempBreakEntry.iResumeOnceOutOfRange)
1504 LOG_EVENT_MSG("PC is out of range, continuing thread");
1505 DoResumeThread(aCurrentThread);
1511 // if the breakpoint is thread specific, make sure it's the right thread
1512 // if not, just continue the thread. take special care if it's the debugger
1513 // thread. if it hits a regular breakpoint, we NEVER want to stop at it. if
1514 // it hits a temp breakpoint, we're probably just stepping past a real breakpoint
1515 // and we do need to handle it.
1516 TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
1517 (!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
1521 LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
1522 err = DoResumeThread(aCurrentThread);
1523 if (KErrNone != err)
1524 LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
1529 //normal user break point, just notify the event
1532 } while(breakEntry);
1535 NotifyEvent(aEventInfo);
1537 return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
1541 // DRM_DebugChannel::SetBreak
1543 TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
1545 LOG_MSG("DRM_DebugChannel::SetBreak()");
1547 TInt err = KErrNone;
1551 LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
1552 return KErrArgument;
1555 //User side memory is not accessible directly
1557 err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
1558 if (err != KErrNone)
1560 LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
1564 DProcess* process = NULL;
1565 if(info.iThreadSpecific)
1567 // if the target thread is not suspended then return KErrInUse
1568 if(!TheDProcessTracker.CheckSuspended(info.iId))
1570 LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not suspended.", info.iId);
1573 DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
1576 LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
1577 return KErrNotFound;
1579 process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
1580 thread->Close(NULL);
1584 process = DebugUtils::OpenProcessHandle(info.iId);
1588 LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
1589 return KErrNotFound;
1591 TBool found = EFalse;
1592 for(TInt i=0; i<iDebugProcessList.Count(); i++)
1594 if(process->iId == iDebugProcessList[i].iId)
1601 DCodeSeg* codeSeg = process->iCodeSeg;
1604 LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
1605 return KErrNotFound;
1608 TModuleMemoryInfo memoryInfo;
1609 TInt err = codeSeg->GetMemoryInfo(memoryInfo, process);
1610 if (err != KErrNone)
1612 LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
1616 //add this process to the list of processes that we are debugging
1617 TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
1618 iDebugProcessList.Append(processInfo);
1619 process->Close(NULL);
1622 if (!info.iBreakId) //first check if the iId address is valid
1623 return KErrArgument;
1625 if (err == KErrNone)
1629 err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
1631 if (err == KErrNone)
1633 err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
1640 // DRM_DebugChannel::StepRange
1642 TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
1644 LOG_MSG("DRM_DebugChannel::StepRange()");
1646 TInt err = KErrNone;
1648 if(!TheDProcessTracker.CheckSuspended(aThread))
1650 LOG_MSG2("DRM_DebugChannel::StepRange() Thread with id 0x%08x not suspended.", aThread->iId);
1655 return KErrArgument;
1657 TRM_DebugStepInfo info(0, 0, 0);
1658 err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
1660 if (err != KErrNone)
1663 err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
1669 Read memory from a target thread and return the data to the client. If the
1670 memory block has breakpoints in it then the correct values are placed in the
1673 @param aThread pointer to thread whose memory space the memory is to be read from
1674 @param aMemoryInfo information about what memory to read
1676 @return KErrNone if memory read successfully,
1677 KErrArgument if aMemoryInfo is not initialised correctly,
1678 KErrNoMemory if a temporary buffer could not be allocated,
1679 KErrBadHandle if aThread is invalid,
1680 or another of the system wide error codes
1682 TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
1684 LOG_MSG("DRM_DebugChannel::ReadMemory()");
1686 TInt err = KErrNone;
1689 return KErrArgument;
1691 TRM_DebugMemoryInfo info(0, 0, 0);
1692 err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
1693 if (err != KErrNone)
1697 return KErrArgument;
1699 NKern::ThreadEnterCS();
1700 TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
1701 NKern::ThreadLeaveCS();
1704 return KErrNoMemory;
1707 TPtr8 dataDes(data, info.iLength);
1709 err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
1710 if (err == KErrNone)
1712 err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
1715 NKern::ThreadEnterCS();
1717 NKern::ThreadLeaveCS();
1723 Attempt to write memory to aThread's address space
1725 @param aThread thread to whose address space memory is to be written
1726 @param aMemoryInfo memory info object representing the data to write
1728 @return KErrNone if memory written successfully,
1729 KErrNoMemory if memory could not be allocated
1730 KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
1731 if aMemoryInfo.iLength is greater than than the length of the passed
1733 KErrBadHandle if aThread is invalid,
1734 or another of the system wide error codes
1736 TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
1738 LOG_MSG("DRM_DebugChannel::WriteMemory()");
1740 TInt err = KErrNone;
1743 return KErrArgument;
1745 TRM_DebugMemoryInfo info(0, 0, 0);
1746 err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
1747 if (err != KErrNone)
1751 return KErrArgument;
1753 NKern::ThreadEnterCS();
1754 TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
1755 NKern::ThreadLeaveCS();
1758 return KErrNoMemory;
1761 TPtr8 dataDes(data, info.iLength);
1763 err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
1764 if (err == KErrNone)
1766 err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
1769 NKern::ThreadEnterCS();
1771 NKern::ThreadLeaveCS();
1777 // DRM_DebugChannel::ReadRegisters
1779 TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
1781 LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
1783 TInt err = KErrNone;
1786 return KErrArgument;
1788 TRM_DebugRegisterInfo info(0, 0, 0);
1789 err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
1790 if (err != KErrNone)
1794 return KErrArgument;
1796 TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
1798 NKern::ThreadEnterCS();
1799 TUint8 *values = (TUint8*)Kern::Alloc(length);
1800 NKern::ThreadLeaveCS();
1803 return KErrNoMemory;
1806 TPtr8 valuesDes(values, length);
1808 err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
1809 if (err == KErrNone)
1811 err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
1814 NKern::ThreadEnterCS();
1816 NKern::ThreadLeaveCS();
1822 Get listing information.
1824 @param aListInformation pointer to a TListInformation object containing the
1825 user specified listings information
1827 @return KErrNone on success,
1828 KErrTooBig if the kernel's data is too big to fit in the passed buffer,
1829 KErrArgument if aListInformation is NULL,
1830 or one of the other system-wide error codes
1832 TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
1834 LOG_MSG("DRM_DebugChannel::GetList()");
1836 TInt err = KErrNone;
1838 if(aListInformation == NULL)
1840 return KErrArgument;
1843 //read DSS' data into local structure
1844 TListInformation info;
1845 err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
1852 TPtr8 buffer(NULL, 0);
1853 err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
1856 //need to free the buffer if it was allocated
1857 if(err != KErrNoMemory)
1859 NKern::ThreadEnterCS();
1860 Kern::Free((TAny*)buffer.Ptr());
1861 NKern::ThreadLeaveCS();
1867 TUint32 dataSize = 0;
1868 TListManager manager;
1873 if(Debug::EScopeGlobal == info.iListScope)
1875 err = manager.GetXipLibrariesList(buffer, dataSize);
1880 if(Debug::EScopeGlobal == info.iListScope)
1882 err = manager.GetGlobalThreadList(buffer, dataSize);
1884 else if(Debug::EScopeProcessSpecific == info.iListScope)
1886 err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
1888 else if(Debug::EScopeThreadSpecific == info.iListScope)
1890 err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
1895 if(Debug::EScopeGlobal == info.iListScope)
1897 err = manager.GetProcessList(buffer, dataSize);
1902 if(Debug::EScopeGlobal == info.iListScope)
1904 err = manager.GetGlobalCodeSegList(buffer, dataSize);
1906 else if(Debug::EScopeProcessSpecific == info.iListScope)
1908 err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
1910 else if(Debug::EScopeThreadSpecific == info.iListScope)
1912 err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
1917 err = KErrNotSupported;
1922 //if no error then write the buffer back
1923 err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
1925 //write back the size of the data regardless of any error
1926 TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
1927 if(writeErr != KErrNone)
1929 //if there was an error writing the size return that error instead
1934 NKern::ThreadEnterCS();
1935 Kern::Free((TAny*)buffer.Ptr());
1936 NKern::ThreadLeaveCS();
1942 Read registers and store register data in aRegisterInfo
1944 @param aThread thread to read registers from
1945 @param aRegisterInfo structure specifying which registers to read and providing
1946 descriptors to write the register data into
1948 @return KErrNone if registers were read successfully. Note that this does not
1949 mean that all the registers could be read, the
1950 aRegisterInfo.iRegisterFlags array should be checked as to whether each
1951 individual register could be read,
1952 KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
1953 are members of aRegisterInfo are NULL, if an unknown register is
1954 specified or if the passed in register values buffer is too small
1955 KErrNoMemory if there is insufficient memory,
1956 KErrDied, if the thread with thread ID aThreadId is dead
1958 TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
1960 LOG_MSG("DRM_DebugChannel::ReadRegisters()");
1962 TInt err = KErrNone;
1965 return KErrArgument;
1967 TRM_DebugRegisterInformation info;
1968 err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
1969 if (err != KErrNone)
1972 if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
1973 return KErrArgument;
1975 //read ids from client thread
1977 err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
1980 if(err == KErrNoMemory)
1982 NKern::ThreadEnterCS();
1983 Kern::Free((TAny*)ids.Ptr());
1984 NKern::ThreadLeaveCS();
1989 //read values from client thread
1990 TPtr8 values(NULL, 0);
1991 err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
1994 if(err == KErrNoMemory)
1995 { NKern::ThreadEnterCS();
1996 Kern::Free((TAny*)values.Ptr());
1997 NKern::ThreadLeaveCS();
1999 NKern::ThreadEnterCS();
2000 Kern::Free((TAny*)ids.Ptr());
2001 NKern::ThreadLeaveCS();
2005 //read flags from client thread
2006 TPtr8 flags(NULL, 0);
2007 err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
2010 if(err == KErrNoMemory)
2012 NKern::ThreadEnterCS();
2013 Kern::Free((TAny*)flags.Ptr());
2014 NKern::ThreadLeaveCS();
2016 NKern::ThreadEnterCS();
2017 Kern::Free((TAny*)ids.Ptr());
2018 Kern::Free((TAny*)values.Ptr());
2019 NKern::ThreadLeaveCS();
2023 err = DoReadRegisters(aThread, ids, values, flags);
2024 if (err == KErrNone)
2026 err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
2029 err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
2033 NKern::ThreadEnterCS();
2034 Kern::Free((TAny*)ids.Ptr());
2035 Kern::Free((TAny*)values.Ptr());
2036 Kern::Free((TAny*)flags.Ptr());
2037 NKern::ThreadLeaveCS();
2043 @deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
2045 TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
2047 LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
2049 TInt err = KErrNone;
2052 return KErrArgument;
2054 TRM_DebugRegisterInfo info(0, 0, 0);
2055 err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
2056 if (err != KErrNone)
2060 return KErrArgument;
2062 TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
2064 NKern::ThreadEnterCS();
2065 TUint8 *values = (TUint8*)Kern::Alloc(length);
2066 NKern::ThreadLeaveCS();
2069 return KErrNoMemory;
2072 TPtr8 valuesDes(values, length);
2074 err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
2075 if (err == KErrNone)
2077 err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
2080 NKern::ThreadEnterCS();
2082 NKern::ThreadLeaveCS();
2088 Write registers and store flags data in aRegisterInfo
2090 @param aThread thread to write registers to
2091 @param aRegisterInfo structure specifying which registers to write and providing
2092 descriptors to write the register flags data into
2094 @return KErrNone if registers were written successfully. Note that this does not
2095 mean that all the registers could be written, the flags array
2096 should be checked as to whether each individual register could be read,
2097 KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
2098 are members of aRegisterInfo are NULL, if an unknown register is
2099 specified or if the passed in register values buffer is too small, or
2101 KErrGeneral if there was a problem initialising the register set,
2102 KErrNoMemory if there is insufficient memory,
2103 KErrDied, if the thread with thread ID aThreadId is dead
2105 TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
2107 LOG_MSG("DRM_DebugChannel::WriteRegisters()");
2109 TInt err = KErrNone;
2112 return KErrArgument;
2114 TRM_DebugRegisterInformation info;
2115 err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
2116 if (err != KErrNone)
2119 if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
2120 return KErrArgument;
2122 //read ids from client thread
2124 err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
2127 if(err == KErrNoMemory)
2129 NKern::ThreadEnterCS();
2130 Kern::Free((TAny*)ids.Ptr());
2131 NKern::ThreadLeaveCS();
2136 //read values from client thread
2137 TPtr8 values(NULL, 0);
2138 err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
2141 if(err == KErrNoMemory)
2143 NKern::ThreadEnterCS();
2144 Kern::Free((TAny*)values.Ptr());
2145 NKern::ThreadLeaveCS();
2147 NKern::ThreadEnterCS();
2148 Kern::Free((TAny*)ids.Ptr());
2149 NKern::ThreadLeaveCS();
2153 //read flags from client thread
2154 TPtr8 flags(NULL, 0);
2155 err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
2158 if(err == KErrNoMemory)
2160 NKern::ThreadEnterCS();
2161 Kern::Free((TAny*)flags.Ptr());
2162 NKern::ThreadLeaveCS();
2164 NKern::ThreadEnterCS();
2165 Kern::Free((TAny*)ids.Ptr());
2166 Kern::Free((TAny*)values.Ptr());
2167 NKern::ThreadLeaveCS();
2171 err = DoWriteRegisters(aThread, ids, values, flags);
2174 err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
2177 NKern::ThreadEnterCS();
2178 Kern::Free((TAny*)ids.Ptr());
2179 Kern::Free((TAny*)values.Ptr());
2180 Kern::Free((TAny*)flags.Ptr());
2181 NKern::ThreadLeaveCS();
2187 Suspends execution of the specified thread.
2189 @param aThread thread to resume
2191 @return KErrNone if there were no problems or KErrArgument if aThread is NULL
2193 TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
2195 LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
2199 LOG_MSG("Invalid dthread object");
2200 return KErrArgument;
2203 return TheDProcessTracker.SuspendThread(aThread);
2207 Resumes execution of the specified thread.
2209 @param aThread thread to resume
2211 @return KErrNone if there were no problems, KErrArgument if aThread is NULL
2212 or an error value returned from DoStepRange()
2214 TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
2216 LOG_MSG("DRM_DebugChannel::DoResumeThread()");
2219 return KErrArgument;
2221 // get the current PC
2223 TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
2226 LOG_MSG2("DRM_DebugChannel::DoResumeThread - Non-zero error code discarded: %d", err);
2229 // if there is a breakpoint at the current PC, we need to single step past it
2230 TBreakEntry* breakEntry = NULL;
2233 breakEntry = iBreakManager->GetNextBreak(breakEntry);
2234 if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
2236 if (breakEntry->iAddress == currentPC)
2238 return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
2241 } while(breakEntry);
2242 return TheDProcessTracker.ResumeThread(aThread);
2246 // DRM_DebugChannel::DoStepRange
2248 TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
2250 LOG_MSG("DRM_DebugChannel::DoStepRange()");
2253 return KErrArgument;
2255 //check that the thread is suspended
2256 if(!TheDProcessTracker.CheckSuspended(aThread))
2258 LOG_MSG2("DRM_DebugChannel::DoStepRange() Thread with id 0x%08x not suspended.", aThread->iId);
2262 TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
2263 TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
2265 // don't allow the user to step in the excluded ROM region. this could be called
2266 // internally however. for example, the the special breakpoints we set to handle
2267 // panics, exceptions, and library loaded events are in the user library, and we
2268 // will need to step past the breakpoint before continuing the thread.
2269 //if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
2271 // return KErrNotSupported;
2274 // set the temp breakpoint, and disable the breakpoint at the current PC if necessary
2275 // if its not a user request, and we are just trying to resume from a breakpoint,
2276 // then we don't need to check for stubs. The last parameter aUserRequest tells
2277 // ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
2278 // is true even if its not a user request.For example, this is true in cases where
2279 // we are doing a step range and the instruction in the range modified PC.
2280 // in this case, DoStepRange will be called from the exception handler where
2281 // we need to check for the stubs for the valid behavior. So truly, we don't need to check
2282 // for stubs only when resuming from a breakpoint.
2283 ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
2285 LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
2287 return TheDProcessTracker.ResumeThread(aThread);
2291 Read memory from the specified addres into the aData descriptor. If there is a
2292 breakpoint set in the region of memory returned then the correct data value is
2293 inserted into the descriptor
2295 @param aThread pointer to thread whose address space memory is to be read from
2296 @param aAddress address to start reading memory from
2297 @param aLength length of memory block to read
2298 @param aData descriptor to read memory into
2300 @return KErrNone if memory read successfully,
2301 KErrNotSupported if reading from the rom section is not supported,
2302 KErrBadHandle if aThread is invalid,
2303 or one of the other system wide error codes
2305 TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
2307 LOG_MSG("DRM_DebugChannel::DoReadMemory()");
2309 // make sure the parameters are valid
2310 if (aLength > aData.MaxSize())
2311 return KErrArgument;
2313 TInt err = KErrNone;
2315 // trap exceptions in case the address is invalid
2316 XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
2318 err = (KErrNone == r) ? err : r;
2320 if (KErrNone == err)
2322 aData.SetLength(aLength);
2324 TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
2326 // if we have any breakpoints in this range, put the actual instruction in the buffer
2327 TBreakEntry* breakEntry = NULL;
2330 breakEntry = iBreakManager->GetNextBreak(breakEntry);
2331 if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
2333 if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
2337 switch(breakEntry->iMode)
2349 LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
2350 return KErrNotSupported;
2352 memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
2355 } while(breakEntry);
2362 Attempt to write memory to aThread's address space
2364 @param aThread thread to whose address space memory is to be written
2365 @param aAddress memory location to write memory to
2366 @param aLength number of bytes of data to write
2367 @param aData descriptor containing memory to write
2369 @return KErrNone if memory written successfully,
2370 KErrArgument if aLength is greater than than the length of the aData
2371 KErrBadHandle if aThread is invalid,
2372 or another of the system wide error codes
2374 TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
2376 LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
2378 // make sure the parameters are valid
2379 if (aLength > aData.Length())
2380 return KErrArgument;
2382 TInt err = KErrNone;
2384 // trap exceptions in case the address is invalid
2385 XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
2387 err = (KErrNone == r) ? err : r;
2389 // reset any breakpoints we may have just overwritten
2390 if (KErrNone == err)
2392 TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
2394 TBreakEntry* breakEntry = NULL;
2397 breakEntry = iBreakManager->GetNextBreak(breakEntry);
2398 if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
2400 if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
2402 // default to arm mode
2406 switch (breakEntry->iMode)
2409 inst = KArmBreakPoint;
2414 inst = KThumbBreakPoint;
2420 LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
2422 return KErrNotSupported;
2425 breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
2426 memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
2430 } while(breakEntry);
2436 // DRM_DebugChannel::DoReadRegisters
2438 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
2440 LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
2442 // make sure the parameters are valid
2443 if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
2444 return KErrArgument;
2446 // make sure the descriptor is big enough to hold the requested data
2447 if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
2448 return KErrArgument;
2453 NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
2455 LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
2457 TArmReg *reg = ®Set.iR0;
2462 for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
2463 aValues.Append((TUint8 *)®[i], sizeof(TArmReg));
2471 Experimental function for determining whether a thread is suspended.
2473 @param aThread thread to check if suspended
2475 @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
2477 TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
2484 if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
2489 if(aThread->iNThread.iSuspendCount > 0)
2497 Read registers and store register values in aRegisterValues and the flags
2498 indicating which registers could be read in aRegisterFlags
2500 @param aThread thread to read registers from
2501 @param aRegisterIds array containing register IDs to read
2502 @param aRegisterValues array to store register values in
2503 @param aRegisterFlags array to store flags in
2505 @return KErrNone if registers were read successfully. Note that this does not
2506 mean that all the registers could be read, the aRegisterFlags array
2507 should be checked as to whether each individual register could be read,
2508 KErrArgument if aThread is NULL, if an unknown register is specified in
2509 aRegisterValues or if aRegisterValues is too small
2510 KErrGeneral if there was a problem initialising the register set
2512 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
2514 LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
2516 // make sure the parameters are valid
2518 return KErrArgument;
2520 //Need to revisit this to determine whether there is a way to validate this
2522 if ( !CheckSuspended(aThread) )
2524 LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
2529 //set lengths of output descriptors to 0 prior to filling
2530 aRegisterValues.SetLength(0);
2531 aRegisterFlags.SetLength(0);
2536 NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
2538 LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
2540 TArmReg *regPtr = ®Set.iR0;
2545 TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
2547 //iterate through registers setting the relevant aFlags value
2548 for(TUint i=0; i<numberOfRegisters; i++)
2550 //get current register id
2552 TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
2553 //exit with the error value if there was an error
2557 //if unknown register then exit as can't know how many bytes this entry will
2558 //represent in aRegisterValues
2560 TDebugFunctionality::GetRegister(reg, registerTag);
2561 if(registerTag.iValue == EAccessUnknown)
2563 return KErrArgument;
2566 //get the current register id as a kernel register
2568 err = GetKernelRegisterId(reg, armReg);
2569 if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
2571 //reading this register is not supported
2572 aRegisterFlags.Append(ENotSupported);
2573 //just skip over this entry in the values buffer
2574 if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
2576 //writing this value would cause overflow so exit
2577 return KErrArgument;
2579 aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
2583 if(registerTag.iSize == sizeof(TArmReg))
2585 if(GetFlagAtOffset(flags, armReg))
2588 aRegisterFlags.Append(EValid);
2592 // Even though the flag is invalid, we can return the value of the register
2593 // and let the user decide what to do
2594 aRegisterFlags.Append(EInValid);
2597 if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
2599 //writing this value would cause overflow so exit
2600 return KErrArgument;
2602 //write value into register into regSet
2603 aRegisterValues.Append((TUint8 *)®Ptr[armReg], registerTag.iSize);
2607 //currently all kernel supported registers are 4 bytes so
2608 //return EBadSize. Would need updating if/when other register
2609 //value sizes are supported
2610 aRegisterFlags.Append(EBadSize);
2611 aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
2619 // DRM_DebugChannel::DoWriteRegisters
2621 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
2623 LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
2625 // make sure the parameters are valid
2626 if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
2627 return KErrArgument;
2629 // make sure the descriptor is big enough to hold the data to write
2630 if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
2631 return KErrArgument;
2636 NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
2638 TArmReg *reg = ®Set.iR0;
2640 for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
2641 reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
2643 NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
2649 Write registers and store flags indicating which registers could be read in
2652 @param aThread thread to write registers to
2653 @param aRegisterIds array containing register IDs to write
2654 @param aRegisterValues array containing register values to write
2655 @param aRegisterFlags array to store flags in
2657 @return KErrNone if registers were written successfully. Note that this does not
2658 mean that all the registers could be written, the aRegisterFlags array
2659 should be checked as to whether each individual register could be read,
2660 KErrArgument if aThread is NULL, if the buffer passed in as
2661 aRegisterValue is too small, or if an unknown register is requested,
2662 KErrGeneral if there was a problem initialising the register set
2664 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
2666 LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
2668 // make sure the parameters are valid
2670 return KErrArgument;
2672 //check that the thread is suspended before reading the registers
2673 if(!TheDProcessTracker.CheckSuspended(aThread))
2675 LOG_MSG2("DRM_DebugChannel::DoWriteRegisters() thread with id 0x%08x is not suspended", aThread->iId);
2679 //get register values from kernel
2682 NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
2684 //set lengths of output descriptors to 0 prior to filling
2685 aRegisterFlags.SetLength(0);
2687 //pointer to first kernel register
2688 TArmReg *regPtr = ®Set.iR0;
2693 //calculate number of registers
2694 TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
2696 //iterate through registers setting the relevant aRegisterFlags value and
2697 //setting the necessary value in regSet ready to write to kernel
2698 for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
2700 //get current register id
2702 TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
2703 //exit with the error value if there was an error
2709 //if unknown register then exit as can't know how many bytes this entry will
2710 //represent in aRegisterValues
2712 TDebugFunctionality::GetRegister(reg, registerTag);
2713 if(registerTag.iValue == EAccessUnknown)
2715 return KErrArgument;
2718 //get the current register id as a kernel register
2720 err = GetKernelRegisterId(reg, armReg);
2721 if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
2723 //writing to this register is not supported
2724 aRegisterFlags.Append(ENotSupported);
2726 else if(GetFlagAtOffset(flags, armReg))
2728 if(registerTag.iSize == sizeof(TArmReg))
2731 aRegisterFlags.Append(EValid);
2732 if(offset + sizeof(TArmReg) > aRegisterValues.Length())
2734 //getting this value would cause overflow so exit
2735 return KErrArgument;
2737 //write value into register into regSet
2738 regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
2742 //currently all kernel supported registers are 4 bytes so
2743 //return EBadSize. Would need updating if/when other register
2744 //value sizes are supported
2745 aRegisterFlags.Append(EBadSize);
2751 //set flag as invalid as register value couldn't be read
2752 aRegisterFlags.Append(EInValid);
2754 offset+=registerTag.iSize;
2757 //write the input data into the registers
2758 NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
2765 // DRM_DebugChannel::DoSecurityCheck
2767 TBool DRM_DebugChannel::DoSecurityCheck()
2769 LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
2770 DProcess* clientProcess = iClientThread->iOwningProcess;
2773 SSecurityInfo secureInfo = clientProcess->iS;
2775 LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
2777 // Ensure we really are communicating with the Debug Security Server
2778 if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
2787 Attempt to read memory from aThread's address space
2789 @param aThread thread from whose address space memory is to be read
2790 @param aSrc pointer to memory location to read memory from
2791 @param aDest pointer to memory location to write memory to
2792 @param aLength number of bytes of data to read
2794 @return KErrNone if memory read successfully,
2795 or another of the system wide error codes
2797 TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
2799 LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
2801 // make sure the parameters are valid
2803 return KErrArgument;
2805 //Need to revisit this to determine whether there is a way to validate this
2807 //check that the thread is suspended before reading the memory
2808 if ( !CheckSuspended(aThread) )
2810 LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
2815 LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
2816 return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
2820 Attempt to write memory to aThread's address space
2822 @param aThread thread to whose address space memory is to be written
2823 @param aDest pointer to memory location to write memory to
2824 @param aSrc pointer to memory location to read memory from
2825 @param aLength number of bytes of data to write
2827 @return KErrNone if memory written successfully, or another of the system wide
2830 TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
2832 LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
2834 //check that the thread is suspended before writing the memory
2835 if(!TheDProcessTracker.CheckSuspended((DThread*)aThread))
2837 LOG_MSG2("DRM_DebugChannel::TryToWriteMemory() thread with id 0x%08x is not suspended", aThread->iId);
2841 LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
2842 return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
2846 @deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
2848 TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
2850 LOG_MSG("DRM_DebugChannel::ReadRegister()");
2852 if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
2854 LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
2861 NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
2863 TArmReg *reg = ®Set.iR0;
2865 return ((TUint32 *)reg)[aNum];
2869 Given a TArmReg register ID, read the value of the register. The register value
2870 will be stored in aValue if the register could be read.
2872 @param aThread thread to read register from
2873 @param aKernelRegisterId ID of register to read from
2874 @param aValue value read from register
2876 @return KErrNone if value was successfully stored in aValue,
2877 KErrNotSupported if aKernelRegister is not supported by the debug
2879 or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
2881 TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
2883 //get register ID as a TRegisterInfo ID
2884 TRegisterInfo regId;
2885 TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
2889 //get the value for the register
2890 err = ReadDebugRegisterValue(aThread, regId, aValue);
2895 Given a TRegisterInfo register ID, read the value of this register. The
2896 register value will be stored in aValue if the register could be read.
2898 @param aThread thread to read register from
2899 @param aDebugRegisterId ID of register to read from
2900 @param aValue value read from register
2902 @return KErrNone if value was successfully stored in aValue,
2903 TRegisterFlag::EInValid if value could not be read from the register,
2904 TRegisterFlag::ENotSupported if the register is not supported,
2905 KErrNoMemory if temporary memory could not be allocated,
2906 or a return value from DRM_DebugChannel::DoReadRegisters
2908 TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
2910 //allocate temporary buffers to store data
2911 NKern::ThreadEnterCS();
2912 TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
2913 NKern::ThreadLeaveCS();
2916 return KErrNoMemory;
2918 TPtr8 idPtr(id, sizeof(TRegisterInfo));
2920 NKern::ThreadEnterCS();
2921 TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
2922 NKern::ThreadLeaveCS();
2925 return KErrNoMemory;
2927 TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
2929 NKern::ThreadEnterCS();
2930 TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
2931 NKern::ThreadLeaveCS();
2934 return KErrNoMemory;
2936 TPtr8 flagPtr(flag, sizeof(TUint8));
2938 //store register id in buffer
2939 idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
2942 TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
2947 //register could be read so store value
2948 aValue = *(T4ByteRegisterValue*)value;
2952 //register couldn't be read for some reason
2958 NKern::ThreadEnterCS();
2962 NKern::ThreadLeaveCS();
2968 // DRM_DebugChannel::NotifyEvent
2970 void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
2972 LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
2974 // Look for the relevant DTargetProcess
2975 // We can find out the relevant process id from aEventInfo
2976 TUint32 pid = aEventInfo.iProcessId;
2978 //opening handle to process
2979 DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
2983 LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - process does not exist!");
2987 // Are we debugging this process - decide based on iFileName
2988 DCodeSeg* p = targetProcess->iCodeSeg;
2989 DTargetProcess* foundProcess;
2992 foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
2996 // special case: may not have a code seg in some cases. in which case we tell everyone!
2997 if (targetProcess->iName)
2999 // copy the name of the process
3000 foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
3004 foundProcess = NULL;
3009 targetProcess->Close(NULL);
3013 // No: just ignore this exception
3014 LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - we are not debugging this process!");
3018 foundProcess->NotifyEvent(aEventInfo);
3021 #ifndef __LAUNCH_AS_EXTENSION__
3022 DECLARE_STANDARD_LDD()
3024 return new DRM_DebugDriverFactory;
3028 DStopModeExtension* TheStopModeExtension = NULL;
3030 DECLARE_EXTENSION_LDD()
3032 return new DRM_DebugDriverFactory;
3036 This value is used as an initialiser for the size of the Stop-Mode Debug API's
3037 default request buffer.
3039 const TInt KRequestBufferSize = 0x200;
3041 This value is used as an initialiser for the size of the Stop-Mode Debug API's
3042 default response buffer.
3044 const TInt KResponseBufferSize = 0x1000;
3046 DECLARE_STANDARD_EXTENSION()
3048 __KTRACE_OPT(KBOOT,Kern::Printf("Starting RM_DEBUG extension"));
3050 // get a reference to the DDebuggerInfo and to the DStopModeExtension
3051 TSuperPage& superPage = Kern::SuperPage();
3053 if(!superPage.iDebuggerInfo)
3055 //kdebug has not been installed so create DDebuggerInfo using our stub constructor
3056 superPage.iDebuggerInfo = new DDebuggerInfo();
3059 if(!TheStopModeExtension)
3061 TheStopModeExtension = new DStopModeExtension();
3064 // create the request buffer and store a reference to it
3066 tag.iTagId = EBuffersRequest;
3067 tag.iType = ETagTypePointer;
3068 tag.iSize = KRequestBufferSize;
3069 TInt err = TheDBufferManager.CreateBuffer(tag);
3075 // create the response buffer and store a reference to it
3076 tag.iTagId = EBuffersResponse;
3077 tag.iSize = KResponseBufferSize;
3078 err = TheDBufferManager.CreateBuffer(tag);
3083 // create the debug functionality buffer and store a reference to it
3084 TDebugFunctionality df;
3085 TUint dfSize = df.GetStopModeFunctionalityBufSize();
3086 tag.iTagId = EBuffersFunctionality;
3088 err = TheDBufferManager.CreateBuffer(tag);
3094 // fill the functionality buffer with the functionality data and store it in
3096 TPtr8 dfBlockPtr((TUint8*)tag.iValue, dfSize);
3097 if(!df.GetStopModeFunctionality(dfBlockPtr))
3101 TheStopModeExtension->iFunctionalityBlock = (DFunctionalityBlock*)tag.iValue;
3103 DStopModeExtension::Install(TheStopModeExtension);
3109 * This stub constructor is intended to be used in the case where the old deprecated
3110 * stop mode api, kdebug, is not in place. It will initialise all values to NULL except
3111 * the pointer to the new stop mode api extension. This allows the new stop mode solution
3112 * to both co-exist and exist independantly of the existing one *
3114 DDebuggerInfo::DDebuggerInfo():
3115 iObjectOffsetTable(NULL),
3116 iObjectOffsetTableCount(NULL),
3117 iThreadContextTable(NULL),
3118 iStopModeExtension(new DStopModeExtension()),
3121 iCodeSegGlobalList(NULL),
3124 iShadowPageCount(0),
3125 iCurrentThread(NULL),
3127 iEventHandlerBreakpoint(0),
3128 iMemModelObjectOffsetTable(NULL),
3129 iMemModelObjectOffsetTableCount(0)
3134 * Installs the stop-mode debugger extension
3135 * Make the stop-mode API visible to a JTAG debugger, by publishing its
3136 * existence in the superpage
3138 void DStopModeExtension::Install(DStopModeExtension* aExt)
3140 Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
3148 Allocates memory in current thread with a max length the same as aSrcDes. If
3149 aReadFromClient is true (as it is by default) then the data from aSrdDes is
3150 copied into the allocated aDestDes buffer.
3152 Use of this function should be followed at a later time by a call such as
3153 Kern::Free(aDestDes.Ptr())
3155 @param aThread pointer to thread to read data from
3156 @param aSrcDes descriptor in aThread to read data from
3157 @param aDestDes location to read data to. Memory is allocated at this location,
3158 if memory is already allocated at this location then the function will
3160 @param aReadFromClient if false then data is not actually read from the
3161 client, the memory is simply allocated
3162 @param aOffest offset into aSrcDes to start reading from. Default is 0.
3164 @return KErrNone if there were no problems,
3165 KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
3166 KErrNoMemory if could not allocate memory,
3167 or one of the other system wide error codes
3169 TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
3172 //check thread is not null
3175 return KErrArgument;
3178 //check aDestDes is empty
3179 if(aDestDes.Ptr() != NULL)
3181 return KErrArgument;
3184 //get the source descriptor's max length and exit if 0
3185 TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
3186 if(srcMaxLength == 0)
3191 //allocate memory and return if none available
3192 NKern::ThreadEnterCS();
3193 TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
3194 NKern::ThreadLeaveCS();
3197 return KErrNoMemory;
3200 //point the TPtr8 at the target memory
3201 aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
3205 //read data from the client thread and return status code
3206 return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
3215 Helper function to extract a TRegisterInfo value from a descriptor containing
3218 @param aRegisterIds descriptor containing register IDs
3219 @param aOffset offset in bytes into the descriptor to start reading data from.
3220 If this value is not a multiple of sizeof(TRegisterInfo) then a
3221 KErrArgument error is returned.
3222 @param aValue will contain the returned value
3224 @return KErrNone if aValue was set correctly, KErrArgument if bad arguments
3227 TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
3229 TUint length = aRegisterIds.Length();
3231 TUint size = sizeof(TRegisterInfo);
3233 //check that not trying to read past end of descriptor
3234 if((aIndex + 1) * size > length)
3235 return KErrArgument;
3237 //get pointer to descriptor's data
3238 const TUint8 *dataPtr = aRegisterIds.Ptr();
3239 const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
3241 aValue = *registerId;
3247 Helper function to get the kernel register ID of the TRegisterInfo defined register.
3249 @param aDebugRegister the debug register ID to return the kernel ID for
3250 @param aKernelRegister corresponding value of register aDebugRegister
3252 @return KErrNone if translation occurred without problems
3253 KErrNotSupported if aDebugRegister is not supported by the kernel
3255 TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
3257 if(Register::IsCoreReg(aDebugRegister))
3259 TUint id = Register::GetCoreRegId(aDebugRegister);
3260 //first 17 registers match the first 17 kernel registers
3263 aKernelRegister = id;
3267 return KErrNotSupported;
3270 else if(Register::IsCoproReg(aDebugRegister))
3272 TUint32 crn = Register::GetCRn(aDebugRegister);
3273 TUint32 crm = Register::GetCRm(aDebugRegister);
3274 TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
3275 TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
3276 TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
3278 //each coprocessor register has potentially different characteristics
3279 //so need to identify each individually
3281 //this is the DACR, the ARM ARM specifies that the CRn and the
3282 //Opcodes are not relevant, section B3-24, point 3.7.3
3283 if((coproNum == 15) && (crm == 3))
3285 aKernelRegister = EArmDacr;
3289 return KErrNotSupported;
3292 else // might be supported at a later date
3294 return KErrNotSupported;
3301 Helper function to get the debug register ID of the kernel defined register.
3303 @param aKernelRegister the kernel register ID to return the debug ID for
3304 @param aDebugRegister corresponding value of register aKernelRegister
3306 @return KErrNone if translation occured without problems
3307 KErrNotSupported if aKernelRegister is not supported by the debug
3310 TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
3313 // registers 0 - 15 and the CPSR share the same values as with the debug enums
3314 if(aKernelRegister < 17)
3316 TUint32 id = aKernelRegister;
3317 aDebugRegister = id << 8;
3319 //the DACR value is special and corresponds to EDF_Register_DACR
3320 else if(aKernelRegister == EArmDacr)
3322 aDebugRegister = 0x00300f01;
3324 // must be an unsupported register, return an error as such
3327 return KErrNotSupported;
3330 //found a supported register so return KErrNone
3335 Helper function to find out whether the aIndex flag is set. This is equivalent
3336 to the aIndex bit of aFlags being non-zero.
3338 @param aFlags set of flags
3339 @param aIndex offset into aFlags to get flag from
3341 @return ETrue if bit is set, EFalse if not
3343 TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
3345 return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
3348 /* Register the attachment of a debug agent to a process to be debugged
3350 * @param a1 - TDes8 target process name
3351 * @param a2 - &TUint64 - Debug Agent Id
3353 * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
3354 * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
3357 TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
3359 LOG_MSG("DRM_DebugChannel::AttachProcess()");
3361 // Validate the supplied TDes8 target process name in a1
3362 TInt length, maxLength;
3365 TInt err = Kern::ThreadGetDesInfo(iClientThread,\
3371 if (err != KErrNone)
3373 // Could not read the descriptor information
3377 // Check the processname is a valid size for a filepath
3378 if (length < 1 || length >= KMaxPath)
3380 return KErrArgument;
3383 if (maxLength < 1 || maxLength >= KMaxPath)
3385 return KErrArgument;
3388 // Allocate space to store the target process name in a kernel-side TPtr8
3389 NKern::ThreadEnterCS();
3390 TUint8* buffer = (TUint8*)Kern::AllocZ(length);
3391 NKern::ThreadLeaveCS();
3395 return KErrNoMemory;
3398 // A temporary descriptor to store the target process name
3399 TPtr8 targetProcessName(buffer,length,length);
3401 // Read the user-side data into targetProcessName
3402 err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
3403 if (err != KErrNone)
3405 // Could not read the user-side descriptor containing the target process name
3406 NKern::ThreadEnterCS();
3408 NKern::ThreadLeaveCS();
3413 // Obtain the Debug Agent Id
3414 TUint64 debugAgentId = 0;
3416 err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
3417 if (err != KErrNone)
3419 // Something bad happened so free the memory and return
3420 NKern::ThreadEnterCS();
3422 NKern::ThreadLeaveCS();
3426 // Add the target process to our list of tracked processes
3427 err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
3429 // Free the kernel-side memory containing targetProcessName data
3430 NKern::ThreadEnterCS();
3432 NKern::ThreadLeaveCS();
3437 /* Register the detachment of a debug agent to a process to be debugged.
3439 * @param - a1 TDes8 target process name in a1
3440 * @param a2 - &TUint64 - Debug Agent Id
3442 * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
3443 * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
3446 TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
3448 // Validate the supplied TDes8 target process name in a1
3449 TInt length, maxLength;
3452 TInt err = Kern::ThreadGetDesInfo(iClientThread,\
3458 if (err != KErrNone)
3463 if (length < 1 || length >= KMaxPath)
3465 return KErrArgument;
3468 if (maxLength < 1 || maxLength >= KMaxPath)
3470 return KErrArgument;
3473 // Allocate space to store the target process name in a kernel-side TPtr8
3474 NKern::ThreadEnterCS();
3475 TUint8* buffer = (TUint8*)Kern::AllocZ(length);
3476 NKern::ThreadLeaveCS();
3480 return KErrNoMemory;
3483 TPtr8 targetProcessName(buffer,length,length);
3485 // Read the user-side data into targetProcessName
3486 err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
3487 if (err != KErrNone)
3489 // Something bad happened so free the memory and return
3490 NKern::ThreadEnterCS();
3492 NKern::ThreadLeaveCS();
3497 // Obtain the AgentId
3498 TUint64 debugAgentId = 0;
3500 err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
3501 if (err != KErrNone)
3503 // Something bad happened so free the memory and return
3504 NKern::ThreadEnterCS();
3506 NKern::ThreadLeaveCS();
3511 // Remove the process from our list of tracked processes
3512 err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
3514 // Free the kernel-side memory containing targetProcessName data
3515 NKern::ThreadEnterCS();
3517 NKern::ThreadLeaveCS();
3522 /* Register the detachment of a debug agent from all processes being debugged.
3524 * @param - a1 - &TUint64 Debug Agent Id.
3525 * @return - KErrNone if successful. One of the system-wide error codes otherwise.
3527 TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
3529 // Obtain the AgentId
3530 TUint64 debugAgentId = 0;
3532 TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
3533 if (err != KErrNone)
3538 // Remove the process from our list of tracked processes
3539 return TheDProcessTracker.DetachAgent(debugAgentId);
3542 /* Set the action associated with a particular kernel event for a given agent and target process
3544 * @param - a1 TDes8 target process name in a1
3545 * @param - a2 &TRM_DebugEventActionInfo
3546 * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
3547 * the other system wide error codes if appropriate.
3549 TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
3551 // Validate the supplied TDes8 target process name in a1
3552 TInt length, maxLength;
3555 TInt err = Kern::ThreadGetDesInfo(iClientThread,\
3561 if (err != KErrNone)
3566 if (length < 1 || length >= KMaxPath)
3568 return KErrArgument;
3571 if (maxLength < 1 || maxLength >= KMaxPath)
3573 return KErrArgument;
3576 // Allocate space to store the target process name in a kernelspace TPtr8
3577 NKern::ThreadEnterCS();
3578 TUint8* buffer = (TUint8*)Kern::AllocZ(length);
3579 NKern::ThreadLeaveCS();
3583 return KErrNoMemory;
3585 TPtr8 targetProcessName(buffer,length,length);
3587 // Read the user-side data into targetProcessName
3588 err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
3589 if (err != KErrNone)
3591 // Something bad happened so free the memory and return
3592 NKern::ThreadEnterCS();
3594 NKern::ThreadLeaveCS();
3599 // Read the Event and Action from the user-side
3600 TRM_DebugEventActionInfo info(0,0,0);
3602 err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
3603 if (err != KErrNone)
3605 // Could not read event action data from the user-side
3607 // Free memory used for targetProcessName
3608 NKern::ThreadEnterCS();
3610 NKern::ThreadLeaveCS();
3615 // Find the target process
3616 DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
3617 if (pProcess == NULL)
3619 // Could not find this process
3621 // Free memory used for targetProcessName
3622 NKern::ThreadEnterCS();
3624 NKern::ThreadLeaveCS();
3626 return KErrArgument;
3629 TUint64 debugAgentId = info.iAgentId;
3632 DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
3633 if (debugAgent == NULL)
3635 // Bad agent means there is no tracking agent
3636 LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
3638 // Free memory used for targetProcessName
3639 NKern::ThreadEnterCS();
3641 NKern::ThreadLeaveCS();
3646 // Set the event action
3647 debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
3649 // Free memory used for targetProcessName
3650 NKern::ThreadEnterCS();
3652 NKern::ThreadLeaveCS();
3657 TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
3659 LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
3661 DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
3665 // The thread terminated before we could open it.
3666 LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
3668 return KErrArgument;
3671 // We simply repeat this for desired number of steps
3672 TInt err = KErrNone;
3674 // Need to step from the current location for 'n' steps
3675 TUint32 startAddress;
3677 // We always step from the current PC.
3678 err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
3681 LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
3684 thread->Close(NULL);
3689 err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
3691 if (err != KErrNone)
3693 // There was a problem, return straightaway
3694 LOG_MSG("DRM_DebugChannel::Step - failed to step");
3698 thread->Close(NULL);
3703 TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
3705 LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
3707 DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
3709 if (process == NULL)
3711 // The process terminated before we could open it to kill it ourselves.
3712 LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
3714 return KErrArgument;
3717 TInt err = KErrNone;
3719 DebugSupport::TerminateProcess(process,aReason);
3722 process->Close(NULL);
3727 /* Security critical - this checks whether the specified process is debuggable or not
3729 * @param aProcessId - The process id of the process to check
3730 * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
3732 TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
3734 /* In order to ensure that only processes which are debuggable
3735 * can be debugged, this function enables the security server
3736 * to read the DProcess.iDebugAttributes field and ensure
3737 * the process was created from a debuggable executable.
3739 LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
3741 TInt err = KErrPermissionDenied;
3743 DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
3746 if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
3748 // Yes this process exists and is debuggable
3751 process->Close(NULL);
3754 if (err == KErrNone)
3756 LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);