--- a/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp Wed Aug 18 11:08:29 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3791 +0,0 @@
-// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of the License "Eclipse Public License v1.0"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-// Device driver for kernel side debug assist
-//
-
-#ifdef __WINS__
-#error - this driver cannot be built for emulation
-#endif
-
-#include <e32def.h>
-#include <e32def_private.h>
-#include <e32cmn.h>
-#include <e32cmn_private.h>
-#include <e32ldr.h>
-#include <u32std.h>
-#include <kernel/kernel.h>
-#include <kernel/kern_priv.h>
-#include <nk_trace.h>
-#include <arm.h>
-#include <kernel/cache.h>
-#include <platform.h>
-#include <nkern.h>
-#include <u32hal.h>
-#include <kernel/kdebug.h>
-#include <rm_debug_api.h>
-
-#include "debug_logging.h"
-#include "d_rmd_breakpoints.h" // moved breakpoints code lives here
-#include "d_rmd_stepping.h" // moved stepping code lives here
-#include "rm_debug_kerneldriver.h"
-#include "d_list_manager.h"
-#include "rm_debug_driver.h"
-#include "rm_debug_eventhandler.h"
-#include "d_debug_functionality.h"
-#include "d_process_tracker.h"
-#include "debug_utils.h"
-#include "d_buffer_manager.h"
-
-using namespace Debug;
-
-/////////////////////////////////////////////////////////////////////////
-//
-// DRM_DebugDriverFactory implementation
-//
-/////////////////////////////////////////////////////////////////////////
-
-//
-// DRM_DebugDriverFactory constructor
-//
-DRM_DebugDriverFactory::DRM_DebugDriverFactory()
- {
- iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
- }
-
-//
-// DRM_DebugDriverFactory::Create
-//
-TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
- {
- if (iOpenChannels != 0)
- return KErrInUse; // a channel is already open
-
- aChannel = new DRM_DebugChannel(this);
-
- return aChannel ? KErrNone : KErrNoMemory;
- }
-
-//
-// DRM_DebugDriverFactory::Install
-//
-TInt DRM_DebugDriverFactory::Install()
- {
- return(SetName(&KRM_DebugDriverName));
- }
-
-//
-// DRM_DebugDriverFactory::Install
-//
-void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
- {
- TCapsRM_DebugDriver b;
- b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
-
- Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
- }
-
-/////////////////////////////////////////////////////////////////////////
-//
-// DRM_DebugChannel implementation
-//
-/////////////////////////////////////////////////////////////////////////
-
-//
-// DRM_DebugChannel constructor
-//
-DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
- : iExcludedROMAddressStart(ROM_LINEAR_BASE),
- iExcludedROMAddressEnd(0),
- iPageSize(0x1000),
- iBreakManager(0),
- iStepper(0),
- iStepLock(0),
- iDfcQ(NULL),
- iInitialisedCodeModifier(0),
- iAsyncGetValueRequest(NULL)
- {
- LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
-
- iDevice = aLogicalDevice;
-
- iClientThread = &Kern::CurrentThread();
- iClientThread->Open();
-
- LOG_MSG3("DRM_DebugChannel::DRM_DebugChannel() clientThread = 0x%08x, id=%d",
- iClientThread, iClientThread->iId );
-
-
- iPageSize = Kern::RoundToPageSize(1);
- }
-
-//
-// DRM_DebugChannel destructor
-//
-DRM_DebugChannel::~DRM_DebugChannel()
- {
- LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
-
- if (iAsyncGetValueRequest)
- {
- Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
- Kern::DestroyClientRequest(iAsyncGetValueRequest);
- }
-
- NKern::ThreadEnterCS();
- Kern::SafeClose((DObject*&)iClientThread, NULL);
- NKern::ThreadLeaveCS();
-
- // Close breakpoint manager
- if (iBreakManager)
- {
- NKern::ThreadEnterCS();
- delete iBreakManager;
- NKern::ThreadLeaveCS();
- }
-
- // Close stepping manager
- if (iStepper)
- {
- NKern::ThreadEnterCS();
- delete iStepper;
- NKern::ThreadLeaveCS();
- }
-
- //close the debug process list
- iDebugProcessList.Close();
-
- DestroyDfcQ();
-
- //close the code modifier
- if (iInitialisedCodeModifier)
- {
- DebugSupport::CloseCodeModifier();
- }
- }
-
-void DRM_DebugChannel::DestroyDfcQ()
- {
- LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
- if (iDfcQ)
- {
- NKern::ThreadEnterCS();
- iDfcQ->Destroy();
- NKern::ThreadLeaveCS();
- }
- }
-
-//
-// DRM_DebugChannel::DoCreate
-//
-TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
- {
- LOG_MSG("DRM_DebugChannel::DoCreate()");
- TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
- if(err != KErrNone)
- return err;
-
- if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
- return KErrNotSupported;
-
- // Do the security check here so that any arbitrary application doesn't make
- // use of Trk kernel driver.
- if (!DoSecurityCheck())
- {
- LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
- return KErrPermissionDenied;
- }
-
- if (anInfo)
- {
- // this is the end address of the user library.
- // this doesn't seem to be valid for EKA2.
- // right now we dont need this for EKA2 since we are not worried
- // about kernel being stopped as kernel is multithreaded.
- // just retaining this for future use.
- TBuf8<32> buf;
- TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
- if(err != KErrNone)
- return err;
- }
-
- // Allocate a D_RMD_Breakpoints class as a breakpoint manager
- NKern::ThreadEnterCS();
- iBreakManager = new D_RMD_Breakpoints(this);
- NKern::ThreadLeaveCS();
- if (iBreakManager == NULL)
- {
- LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
- return KErrNoMemory;
- }
-
- // Initialise the new breakpoint manager object
- iBreakManager->Init();
-
- // Allocate a DRMDStepping class as the stepping manager
- NKern::ThreadEnterCS();
- iStepper = new DRMDStepping(this);
- NKern::ThreadLeaveCS();
- if (iStepper == NULL)
- {
- LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
- return KErrNoMemory;
- }
-
- // Initialize the code modifier for managing breakpoints.
- TUint caps; //ignored for now
- err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
- //if code modifier initializer failed,
- //return here, since we can't set an breakpoints
- if(err != KErrNone)
- {
- return err;
- }
- else
- {
- iInitialisedCodeModifier = ETrue;
- }
-
- //create and set the driver's Dfc queue
- err = CreateDfcQ();
- if(err != KErrNone)
- {
- LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
- }
- SetDfcQ(iDfcQ);
-
- iMsgQ.Receive();
-
- iEventHandler = new DRM_DebugEventHandler;
- if (!iEventHandler)
- return KErrNoMemory;
- err = iEventHandler->Create(iDevice, this, iClientThread);
- if (err != KErrNone)
- return err;
-
- //return KErrNone;
- return iEventHandler->Start();
- }
-
-/**
-Forward call to either synch or asynch methods while serialising all calls via lock.
-
-Protect access via a the event handler lock to
-serialise all calls and protect concurrent access to data structures
-
-@param aMsg pointer to a TMessageBase object
-
-@return error returned by called methods
-
-@see DRM_DebugEventHandler::HandleSpecificEvent where lock is also used
-@see DRM_DebugEventHandler::iProtectionLock
-
-*/
-TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
- {
- DThread * currThread = &Kern::CurrentThread();
- LOG_MSG3("DRM_DebugChannel::SendMsg() currThread = 0x%08x, iClientThread=0x%08x", currThread, iClientThread );
-
- iEventHandler->LockDataAccess();
-
- TThreadMessage& m = *(TThreadMessage*)aMsg;
- TInt id = m.iValue;
- TInt err = KErrNone;
-
- if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
- {
- // DoRequest
- TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
- err = SendRequest(aMsg);
- if (err != KErrNone)
- Kern::RequestComplete(pStatus,err);
- }
- else
- {
- err = DLogicalChannel::SendMsg(aMsg);
- }
-
- iEventHandler->ReleaseDataAccess();
- return err;
- }
-
-//
-// DRM_DebugChannel::SendRequest
-//
-TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
- {
- LOG_MSG("DRM_DebugChannel::SendRequest()");
-
- TThreadMessage& m = *(TThreadMessage*)aMsg;
- TInt function = ~m.iValue;
- TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
- TAny* a1 = m.Ptr1();
-
- TInt err = KErrNotSupported;
- switch(function)
- {
- case RRM_DebugDriver::ERequestGetEvent:
- err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
- break;
- }
- if (err == KErrNone)
- err = DLogicalChannel::SendMsg(aMsg);
- return err;
- }
-
-//
-// DRM_DebugChannel::PreAsyncGetValue
-//
-TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
- {
- LOG_MSG3("DRM_DebugChannel::PreAsyncGetValue() TEventInfo=0x%08x, TRequestStatus=0x%08x",
- aValue, aStatus );
-
- iAsyncGetValueRequest->Reset();
-
- TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
- if (err != KErrNone)
- return err;
-
- iAsyncGetValueRequest->SetDestPtr(aValue);
- return KErrNone;
- }
-
-/**
- Create the Dfc queue for receiving messages
- */
-TInt DRM_DebugChannel::CreateDfcQ()
- {
- LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
- TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
- // Fix to stop t_rmdebug2 etc crashing the device.
- // This should be removed once the rm debug driver has been updated for WDP.
- if (r == KErrNone)
- iDfcQ->SetRealtimeState(ERealtimeStateOff);
- return r;
- }
-
-//
-// DRM_DebugChannel::DoCancel
-//
-// New: The cancel call does not take an enum parameter describing
-// the request to be cancelled. Rather it supplies a pointer
-// to a user-side struct defining the cancellation
-//
-void DRM_DebugChannel::DoCancel(TInt aReqNo)
- {
- LOG_MSG("DRM_DebugChannel::DoCancel()");
-
- TRMD_DebugCancelInfo info;
-
- TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
- if (err != KErrNone)
- {
- // How do we cancel something we know nothing about???
- LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
- return;
- }
-
- // Find the process
- DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
- if (pProcess == NULL)
- {
- // We are doomed. We don't know which event to cancel..
- LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
-
- return;
- }
-
- // Find the agent
- DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
- if (debugAgent == NULL)
- {
- // Bad agent means there is no tracking agent
- LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
- return;
- }
-
- // Agent completes/pends the request as appropriate.
- debugAgent->CancelGetEvent();
-
- }
-
-//
-// DRM_DebugChannel::DoRequest
-//
-void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
- {
- LOG_MSG4("DRM_DebugChannel::DoRequest(), iClientThread=0x%08x, tid=0x%08x, TRequestStatus=0x%08x",
- iClientThread, I64LOW(iClientThread->iId), aStatus);
-
- switch(aReqNo)
- {
- case RRM_DebugDriver::ERequestGetEvent:
- {
- TEventMetaData eventMetaData;
- TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
- if (err != KErrNone)
- {
- LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
-
- // We could not read information from the user, so the a2 argument is probably wrong
- Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
- return;
- }
-
- // Find the process
- DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
- if (pProcess == NULL)
- {
- LOG_MSG("Cannot identify process being debugged");
-
- // We could not locate the process, so the user asked for the wrong one.
- Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
- return;
- }
-
- // Find the agent
- DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
- LOG_MSG5(" For agent pid=%d, DTargetProcess=0x%08x, Agent=0x%08x, iAsyncGetValueRequest0x%08x",
- I64LOW(eventMetaData.iDebugAgentProcessId), pProcess, debugAgent, iAsyncGetValueRequest );
-
- if (debugAgent == NULL)
- {
- // Bad agent means there is no tracking agent
- LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
- return;
- }
- // Agent completes/pends the request as appropriate.
- debugAgent->GetEvent(iAsyncGetValueRequest, iClientThread);
-
- break;
- }
- default:
- {
- // Don't know what to do, should not get here!
- LOG_MSG("DRM_DebugChannel::DoRequest was passed an unsupported request aReqNo");
-
- Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
- }
- }
- }
-
-//
-// DRM_DebugChannel::DoControl
-//
-TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
- {
- LOG_MSG("DRM_DebugChannel::DoControl()");
-
- LOG_MSG2("DoControl Function %d", aFunction);
-
- TInt err = KErrBadHandle;
- DThread* threadObj = NULL;
-
- switch(aFunction)
- {
- /* Security first */
- case RRM_DebugDriver::EControlIsDebuggable:
- {
- err = IsDebuggable((TUint32)a1);
- break;
- }
- case RRM_DebugDriver::EControlSetBreak:
- {
- err = SetBreak((TSetBreakInfo*)a1);
- break;
- }
- case RRM_DebugDriver::EControlClearBreak:
- {
- err = iBreakManager->DoClearBreak((TInt32)a1);
- break;
- }
- case RRM_DebugDriver::EControlModifyBreak:
- {
- err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
- break;
- }
- case RRM_DebugDriver::EControlModifyProcessBreak:
- {
- err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
- break;
- }
- case RRM_DebugDriver::EControlBreakInfo:
- {
- err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
- break;
- }
- case RRM_DebugDriver::EControlSuspendThread:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = DoSuspendThread(threadObj);
- }
- break;
- }
- case RRM_DebugDriver::EControlResumeThread:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = DoResumeThread(threadObj);
- }
- break;
- }
- case RRM_DebugDriver::EControlStepRange:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlReadMemory:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlWriteMemory:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlReadRegistersLegacy:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlWriteRegistersLegacy:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlReadRegisters:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlWriteRegisters:
- {
- threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
- if (threadObj)
- {
- err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
- }
- break;
- }
- case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
- {
- LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
-
- TDebugFunctionality df;
-
- TUint size = df.GetDebugFunctionalityBufSize();
-
- // Return size to user-side in a safe manner
- err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
- break;
- }
- case RRM_DebugDriver::EControlGetDebugFunctionality:
- {
- LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
-
- TDebugFunctionality df;
-
- TUint32 dfsize = df.GetDebugFunctionalityBufSize();
-
- // Alloc tmp buffer for Debug Functionality data
- NKern::ThreadEnterCS();
- TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
- NKern::ThreadLeaveCS();
- if (dfbuffer==NULL)
- {
- LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
-
- // could not allocate memory
- return KErrNoMemory;
- }
-
- // Temporary descriptor to hold DF data
- TPtr8 tmpPtr(dfbuffer,0,dfsize);
-
- // Obtain the DF data
- if (df.GetDebugFunctionality(tmpPtr) )
- {
- // Return the DF data to the user-side
- err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
- }
- else
- {
- // Failed.
- err = KErrGeneral;
- }
-
- // Free tmp buffer
- NKern::ThreadEnterCS();
- Kern::Free(dfbuffer);
- NKern::ThreadLeaveCS();
- break;
- }
- case RRM_DebugDriver::EControlAttachProcess:
- {
- LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
-
- err = AttachProcess(a1,a2);
- break;
- }
- case RRM_DebugDriver::EControlDetachProcess:
- {
- LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
-
- err = DetachProcess(a1,a2);
- break;
- }
- case RRM_DebugDriver::EControlDetachAgent:
- {
- LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
-
- err = DetachAgent(a1,a2);
- break;
- }
- case RRM_DebugDriver::EControlSetEventAction:
- {
- LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
-
- err = SetEventAction(a1,a2);
- break;
- }
- case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
- {
- LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
-
- TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
-
- // Return size to user-side in a safe manner
- err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
- break;
- }
- case RRM_DebugDriver::EControlGetList:
- {
- LOG_MSG("RRM_DebugDriver::EControlGetList\n");
- err = GetList((TListInformation*)a1);
- break;
- }
- case RRM_DebugDriver::EControlStep:
- {
- LOG_MSG("RRM_DebugDriver::EControlStep\n");
-
- err = Step((TUint32)a1,(TUint32)a2);
- break;
- }
- case RRM_DebugDriver::EControlKillProcess:
- {
- LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
-
- err = KillProcess((TUint32)a1,(TUint32)a2);
- break;
- }
- default:
- {
- err = KErrGeneral;
- }
- }
-
- if (KErrNone != err)
- {
- LOG_MSG2("Error %d from control function", err);
- }
-
- if (threadObj)
- {
- // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
- threadObj->Close(NULL);
- }
-
- return err;
- }
-
-void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
- {
- LOG_MSG("DRM_DebugChannel::HandleMsg()");
-
- TThreadMessage& m = *(TThreadMessage*)aMsg;
- TInt id = m.iValue;
-
- if (id == (TInt)ECloseMsg)
- {
- if (iEventHandler)
- {
- iEventHandler->Stop();
- iEventHandler->Close();
- iEventHandler = NULL;
- }
- m.Complete(KErrNone, EFalse);
- return;
- }
-
- if (id == KMaxTInt)
- {
- // DoCancel
- DoCancel(m.Int0());
- m.Complete(KErrNone, ETrue);
- return;
- }
-
- if (id < 0)
- {
- // DoRequest
- TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
- DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
- m.Complete(KErrNone, ETrue);
- }
- else
- {
- // DoControl
- TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
- m.Complete(err, ETrue);
- }
- }
-
-//
-// DRM_DebugChannel::RemoveProcess
-//
-TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
- {
- LOG_MSG("DRM_DebugChannel::RemoveProcess()");
-
- DProcess *aProcess = (DProcess*)a1;
-
- // Sanity check
- if (!aProcess)
- {
- // No process was specified!
- LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
- return EFalse;
- }
-
- // this is called when a process dies. we want to mark any breakpoints in this
- // process space as obsolete. the main reason for this is so we don't return
- // an error when the host debugger tries to clear breakpoints for the process
-
- TUint32 codeAddress = 0;
- TUint32 codeSize = 0;
-
- LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
-
- DCodeSeg* codeSeg = aProcess->iCodeSeg;
-
- if (codeSeg)
- {
- TModuleMemoryInfo processMemoryInfo;
- TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
- if (err != KErrNone)
- {
- codeAddress = processMemoryInfo.iCodeBase;
- codeSize = processMemoryInfo.iCodeSize;
- }
- else
- {
- LOG_MSG2("Error in getting memory info: %d", err);
- }
- }
-
- if (!codeAddress || !codeSize)
- {
- LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
- // make sure there is not already a breakpoint at this address
- for (TInt i = 0; i < iDebugProcessList.Count(); i++)
- {
- if (iDebugProcessList[i].iId == aProcess->iId)
- {
- codeAddress = iDebugProcessList[i].iCodeAddress;
- codeSize = iDebugProcessList[i].iCodeSize;
-
- //now remove from the list
- iDebugProcessList.Remove(i);
- break;
- }
- }
- }
-
- if (!codeAddress || !codeSize)
- {
- return EFalse;
- }
-
- iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::StartThread
-//
-TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
-
- DThread *aThread = (DThread*)a1;
- if(!aThread)
- {
- LOG_MSG("Error getting DThread object");
- __NK_ASSERT_DEBUG(aThread);
- return EFalse;
- }
-
- //a2 points to the thread creating the new thread.
- //We have no use for it at the moment so just ignore it for now
-
- TDriverEventInfo info;
- info.iEventType = EEventsStartThread;
- info.iThreadId = aThread->iId;
- info.iThreadIdValid = ETrue;
- DProcess* owningProcess = aThread->iOwningProcess;
- if(owningProcess)
- {
- info.iProcessId = owningProcess->iId;
- info.iProcessIdValid = ETrue;
- DCodeSeg* p = owningProcess->iCodeSeg;
- if(p && p->iFileName)
- {
- info.iFileName.Copy(*(p->iFileName));
- DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
- if(foundProcess)
- {
- foundProcess->NotifyEvent(info);
- }
- else
- {
- LOG_EVENT_MSG2("Couldn't find process with name [%S]", p->iFileName);
- }
- }
- else
- {
- if(p)
- {
- LOG_EVENT_MSG("\tCode segment name missing");
- }
- else
- {
- LOG_EVENT_MSG("\tCode segment is NULL");
- }
- }
- }
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandleAddProcessEvent
-//
-TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
-
- DProcess *aProcess = (DProcess*)a1;
- // a2 points to the thread creating the new process.
- DThread *aThread = (DThread*)a2;
-
- if(!aProcess)
- {
- LOG_MSG("Error getting DProcess object");
- __NK_ASSERT_DEBUG(aProcess);
- return EFalse;
- }
-
- TDriverEventInfo info;
- info.iEventType = EEventsAddProcess;
- info.iProcessId = aProcess->iId;
-
- info.iCreatorThreadId = aThread ? aThread->iId : 0;
- info.iProcessIdValid = ETrue;
-
- // Copy TUids
- info.iUids = aProcess->iUids;
-
- info.iUidsValid = ETrue;
-
- // copy name of the process
- if (aProcess->iName)
- {
- // copy the name of the process
- info.iFileName.Copy(*aProcess->iName);
-
- DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
- if(foundProcess)
- {
- foundProcess->NotifyEvent(info);
- }
- else
- {
- // AddProcess event does not have fully-qualified path, it has "filename.exe"
- // So we try a less-precise match
- DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
- if(foundProcess)
- {
- foundProcess->NotifyEvent(info);
- }
- else
- {
- LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
- }
- }
- }
- else
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
- }
-
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandleRemoveProcessEvent
-//
-TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
-
- DProcess *aProcess = (DProcess*)a1;
- if(!aProcess)
- {
- LOG_MSG("Error getting DProcess object");
- __NK_ASSERT_DEBUG(aProcess);
- return EFalse;
- }
-
- // a2 points to the thread creating the new process.
- // We have no use for it at the moment so just ignore it for now
- // Also, it may not be known and therefore NULL
-
- TDriverEventInfo info;
- info.iEventType = EEventsRemoveProcess;
- info.iProcessId = aProcess->iId;
- info.iProcessIdValid = ETrue;
-
- // copy name of the process
- if (aProcess->iName)
- {
- // copy the name of the process
- info.iFileName.Copy(*aProcess->iName);
-
- DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
- if(foundProcess)
- {
- foundProcess->NotifyEvent(info);
- }
- else
- {
- // RemoveProcess event does not have fully-qualified path, it has "filename.exe"
- // So we try a less-precise match
- DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
- if(foundProcess)
- {
- foundProcess->NotifyEvent(info);
- }
- else
- {
- LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
- }
- }
-
- }
- else
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
- }
-
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::AddLibrary
-//
-TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
-
- DLibrary *aLibrary = (DLibrary*)a1;
- DThread *aThread = (DThread*)a2;
-
- // sanity check
- if (!aLibrary)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
- return EFalse;
- }
-
- if (!aThread)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
- return EFalse;
- }
-
- LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
-
- if (aThread)
- {
- // make sure this is not the debugger thread
- if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
- {
- TDriverEventInfo info;
-
- info.iEventType = EEventsAddLibrary;
- info.iProcessId = aThread->iOwningProcess->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = aThread->iId;
- info.iThreadIdValid = ETrue;
-
- //get the code address
- DCodeSeg* codeSeg = aLibrary->iCodeSeg;
- if (!codeSeg)
- {
- LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
- return EFalse;
- }
-
- // Uid3
- info.iUids = codeSeg->iUids;
- info.iUidsValid = ETrue;
-
- TModuleMemoryInfo memoryInfo;
- TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
- if (err != KErrNone)
- {
- LOG_EVENT_MSG2("Error in getting memory info: %d", err);
- return EFalse;
- }
-
- info.iCodeAddress = memoryInfo.iCodeBase;
- info.iDataAddress = memoryInfo.iInitialisedDataBase;
-
- info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
-
- //queue up or complete the event
- info.iArg1 = a1;
- info.iArg2 = a2;
- NotifyEvent(info);
- }
-
- }
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::RemoveLibrary
-//
-TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
- DLibrary *aLibrary = (DLibrary*)a1;
-
- // sanity check
- if (!aLibrary)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
- return EFalse;
- }
-
- LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
-
- // this is called when all handles to this library have been closed. this can happen when a process dies, or when a dll is
- // unloaded while the process lives on. in former case, we don't need to notify the host debugger because that process is
- // dying anyway. for the latter case, we do need to notify the host so it can unload the symbolics, etc.
-
- DThread* aThread = &Kern::CurrentThread();
-
- if ((aThread) &&
- (aThread != iClientThread) &&
- (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
- {
- //the library gets unloaded only when the mapcount is 0.
- if (aLibrary->iMapCount != 0)
- return EFalse;
-
- DCodeSeg* codeSeg = aLibrary->iCodeSeg;
- if (!codeSeg)
- {
- LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
- return EFalse;
- }
-
- TModuleMemoryInfo processMemoryInfo;
- TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
- if (err != KErrNone)
- {
- LOG_EVENT_MSG2("Error in getting memory info: %d", err);
- return EFalse;
- }
-
- TUint32 codeAddress = processMemoryInfo.iCodeBase;
- TUint32 codeSize = processMemoryInfo.iCodeSize;
-
- // first invalidate all breakpoints that were set in the library code
- iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
- DProcess *process = &Kern::CurrentProcess();
- RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
-
- for (TInt j=0; j<dynamicCode->Count(); j++)
- {
- if ((*dynamicCode)[j].iLib == aLibrary)
- {
- TDriverEventInfo info;
-
- info.iEventType = EEventsRemoveLibrary;
- info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
- //info.iFileName.ZeroTerminate();
- info.iProcessId = process->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = 0xFFFFFFFF; // don't care!
- info.iThreadIdValid = EFalse;
- // Uid3
- info.iUids = codeSeg->iUids;
- info.iUidsValid = ETrue;
-
- //queue up or complete the event
- info.iArg1 = a1;
- info.iArg2 = a2;
- NotifyEvent(info);
- }
- }
- }
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandleEventKillThread
-//
-TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
- {
-
- LOG_MSG2("DRM_DebugChannel::HandleEventKillThread(Thread a1=0x%08x)", a1 );
-
- DThread* currentThread = &Kern::CurrentThread();
- if (!currentThread)
- {
- LOG_MSG("Error getting current thread");
- __NK_ASSERT_DEBUG(currentThread);
- return EFalse;
- }
-
- // a1 should point to the current thread, check this to make sure it does
- __NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
-
- TDriverEventInfo info;
-
- info.iProcessId = currentThread->iOwningProcess->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = currentThread->iId;
- info.iThreadIdValid = ETrue;
- // 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
- TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
- if(err != KErrNone)
- {
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
- }
-
- if (currentThread->iExitType == EExitPanic)
- {
- info.iPanicCategory.Copy(currentThread->iExitCategory);
- }
- info.iExceptionNumber = currentThread->iExitReason;
- info.iExitType = currentThread->iExitType;
- info.iEventType = EEventsKillThread;
-
- // Are we debugging this process - decide based on iFileName
- DCodeSeg* codeSeg = currentThread->iOwningProcess->iCodeSeg;
-
- // remove all the breakpoints in this thread, whether we are debugging it or not.
- iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
-
- // if the code seg exists then get the file name from it and check we're debugging it
- if(codeSeg)
- {
- DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(codeSeg->iFileName));
- if(!foundProcess)
- {
- // not debugging this process so return false
- return EFalse;
- }
- }
- else
- {
- // can't validate that we are debugging the thread
- return EFalse;
- }
-
- info.iArg1 = a1;
- info.iArg2 = a2;
- NotifyEvent(info);
-
- return ETrue;
- }
-
-//
-// DRM_DebugChannel::HandleSwException
-//
-TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
- TExcType aExcType = (TExcType)(TInt)a1;
-
- TDriverEventInfo info;
-
- DThread* currentThread = &Kern::CurrentThread();
- if (!currentThread)
- {
- LOG_MSG("Error getting current thread");
- __NK_ASSERT_DEBUG(currentThread);
- return EFalse;
- }
-
- info.iProcessId = currentThread->iOwningProcess->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = currentThread->iId;
- info.iThreadIdValid = ETrue;
- TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
- if(err != KErrNone)
- {
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
- }
- info.iExceptionNumber = aExcType;
- info.iEventType = EEventsSwExc;
- info.iArg1 = a1;
- info.iArg2 = a2;
-
- NotifyEvent(info);
-
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandleHwException
-//
-TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
- {
- TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
-
- // sanity check
- if (!aExcInfo)
- {
- LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
- __NK_ASSERT_DEBUG(aExcInfo);
- return EFalse;
- }
-
- TDriverEventInfo info;
-
- DThread* currentThread = &Kern::CurrentThread();
-
- if (!currentThread)
- {
- LOG_MSG("Error getting current thread");
- __NK_ASSERT_DEBUG(currentThread);
- return EFalse;
- }
-
- info.iProcessId = currentThread->iOwningProcess->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = currentThread->iId;
- info.iThreadIdValid = ETrue;
- info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
- info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
-
- LOG_MSG5("DRM_DebugChannel::HandleHwException current thread = 0x%08x, CritSect count=%d,\n"
- " iFaultAddress=0x%08x, iFaultStatus=0x%08x",
- currentThread, currentThread->iNThread.iCsCount, aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
-
- info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
- info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
- info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
- info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
-
- info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
- info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
- info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
- info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
- info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
- info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
- info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
- info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
- info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
-
- info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
- info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
- info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
-
- info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
- info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
- info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
- info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
- LOG_MSG5(" iCpsr=0x%x, iExcCode=0x%x, R14=0x%x, R15=0x%x",
- aExcInfo->iCpsr, aExcInfo->iExcCode, aExcInfo->iR14, aExcInfo->iR15);
-
- switch (aExcInfo->iExcCode)
- {
- case 0:
- info.iExceptionNumber = EExcCodeAbort;
- LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
- break;
- case 1:
- info.iExceptionNumber = EExcDataAbort;
- LOG_EVENT_MSG(" iExcCode == 1 => EExcDataAbort");
- break;
- case 2:
- info.iExceptionNumber = EExcInvalidOpCode;
- LOG_EVENT_MSG(" iExcCode == 2 => EExcInvalidOpCode");
- break;
- default:
- // new event? Something gone wrong?
- __NK_ASSERT_DEBUG(EFalse);
- return EFalse;
- }
-
- info.iEventType = EEventsHwExc;
-
- info.iArg1 = a1;
- info.iArg2 = a2;
-
- if(EExcInvalidOpCode == info.iExceptionNumber)
- {
- return HandleInvalidOpCodeException(info, currentThread);
- }
-
- NotifyEvent(info);
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandUserTrace
-//
-TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
-
- DThread* currentThread = &Kern::CurrentThread();
- if (!currentThread)
- {
- LOG_EVENT_MSG("Error getting current thread");
- __NK_ASSERT_DEBUG(currentThread);
- return EFalse;
- }
-
- TDriverEventInfo info;
- info.iProcessId = currentThread->iOwningProcess->iId;
- info.iProcessIdValid = ETrue;
- info.iThreadId = currentThread->iId;
- info.iThreadIdValid = ETrue;
- info.iEventType = EEventsUserTrace;
- info.iArg1 = a1;
- info.iArg2 = a2;
-
- TInt err = KErrNone;
-
- //User Trace info
- XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
- if(KErrNone != err)
- {
- return EFalse;
- }
-
- info.iMessageStatus = ESingleMessage;
-
- NotifyEvent(info);
-
- return EFalse;
- }
-
-//
-// DRM_DebugChannel::HandleException
-//
-TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
-
- TInt err = KErrNone;
-
- TUint32 inst = KArmBreakPoint;
- TInt instSize = 4;
-
- // change these for thumb mode
- TUint32 regValue;
- err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
- if(err != KErrNone)
- {
- LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
- }
-
- if (regValue & ECpuThumb)
- {
- inst = KThumbBreakPoint;
- instSize = 2;
- }
-
- TUint32 instruction = 0;
- err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
-
- if (KErrNone != err)
- LOG_MSG2("Error reading instruction at currentpc: %d", err);
-
- if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
- {
- TInt err = DoSuspendThread(aCurrentThread);
- if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
- {
- LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
- return EFalse;
- }
-
- // the exception was a breakpoint instruction. see if we have a breakpoint at that address
- TBreakEntry* breakEntry = NULL;
- do
- {
- breakEntry = iBreakManager->GetNextBreak(breakEntry);
- if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
- {
- LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
-
- TBreakEntry tempBreakEntry = *breakEntry;
-
- //change the event type to breakpoint type
- aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
-
- // enable any breakpoints we had to disable for this thread
- err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
- if (KErrNone != err)
- LOG_MSG2("Error %d enabling disabled breakpoints", err);
-
- // see if this is a temp breakpoint
- if (iBreakManager->IsTemporaryBreak(*breakEntry))
- {
- // this was a temp breakpoint, so we need to clear it now
- err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
- if (KErrNone != err)
- LOG_MSG2("Error %d clearing temp breakpoint", err);
-
- // Find out how many steps remain to be done
-
- // reduce the number of steps to complete by 1
- tempBreakEntry.iNumSteps--;
-
- LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
-
- // New. If we have not finished do all the steps, continue stepping and don't notify event
- if (tempBreakEntry.iNumSteps)
- {
- LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
- err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
- if (err != KErrNone)
- {
- LOG_EVENT_MSG("Failed to continue stepping\n");
-
- // what do we do? might as well stop here and tell the user
- NotifyEvent(aEventInfo);
-
- return ETrue;
- }
-
- // continue as though no event occured. No need to suspend/resume anything...
- LOG_EVENT_MSG("Continuing to step\n");
- return ETrue;
- }
-
- // Is this a case where we just want to continue?
- if (tempBreakEntry.iResumeOnceOutOfRange)
- {
- LOG_EVENT_MSG("PC is out of range, continuing thread");
- DoResumeThread(aCurrentThread);
-
- return ETrue;
- }
- }
-
- // if the breakpoint is thread specific, make sure it's the right thread
- // if not, just continue the thread. take special care if it's the debugger
- // thread. if it hits a regular breakpoint, we NEVER want to stop at it. if
- // it hits a temp breakpoint, we're probably just stepping past a real breakpoint
- // and we do need to handle it.
- TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
- (!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
-
- if (needToResume)
- {
- LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
- err = DoResumeThread(aCurrentThread);
- if (KErrNone != err)
- LOG_MSG2("Error in DoResumeThread: %d", err);
-
- return EFalse;
- }
-
- //normal user break point, just notify the event
- break;
- }
- } while(breakEntry);
- }
-
- NotifyEvent(aEventInfo);
-
- return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
- }
-
-//
-// DRM_DebugChannel::SetBreak
-//
-TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
- {
- LOG_MSG("DRM_DebugChannel::SetBreak()");
-
- TInt err = KErrNone;
-
- if (!aBreakInfo)
- {
- LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
- return KErrArgument;
- }
-
- //User side memory is not accessible directly
- TSetBreakInfo info;
- err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
- if (err != KErrNone)
- {
- LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
- return err;
- }
-
- DProcess* process = NULL;
- if(info.iThreadSpecific)
- {
- // if the target thread is not suspended then return KErrInUse
- if(!TheDProcessTracker.CheckSuspended(info.iId))
- {
- LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not suspended.", info.iId);
- return KErrInUse;
- }
- DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
- if(!thread)
- {
- LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
- return KErrNotFound;
- }
- process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
- thread->Close(NULL);
- }
- else
- {
- process = DebugUtils::OpenProcessHandle(info.iId);
- }
-
- if(!process)
- {
- LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
- return KErrNotFound;
- }
-
- TBool found = EFalse;
- for(TInt i=0; i<iDebugProcessList.Count(); i++)
- {
- if(process->iId == iDebugProcessList[i].iId)
- {
- found = ETrue;
- }
- }
-
- if(!found)
- {
- DCodeSeg* codeSeg = process->iCodeSeg;
- if (!codeSeg)
- {
- LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
- return KErrNotFound;
- }
-
- TModuleMemoryInfo memoryInfo;
- TInt err = codeSeg->GetMemoryInfo(memoryInfo, process);
- if (err != KErrNone)
- {
- LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
- return err;
- }
-
- //add this process to the list of processes that we are debugging
- TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
- iDebugProcessList.Append(processInfo);
- process->Close(NULL);
- }
-
- if (!info.iBreakId) //first check if the iId address is valid
- return KErrArgument;
-
- if (err == KErrNone)
- {
- TInt32 iBreakId;
-
- err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
-
- if (err == KErrNone)
- {
- err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
- }
- }
-
- return err;
- }
-
-//
-// DRM_DebugChannel::StepRange
-//
-TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
- {
- LOG_MSG("DRM_DebugChannel::StepRange()");
-
- TInt err = KErrNone;
-
- if(!TheDProcessTracker.CheckSuspended(aThread))
- {
- LOG_MSG2("DRM_DebugChannel::StepRange() Thread with id 0x%08x not suspended.", aThread->iId);
- return KErrInUse;
- }
-
- if (!aStepInfo)
- return KErrArgument;
-
- TRM_DebugStepInfo info(0, 0, 0);
- err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
-
- if (err != KErrNone)
- return err;
-
- err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
-
- return err;
- }
-
-/**
-Read memory from a target thread and return the data to the client. If the
-memory block has breakpoints in it then the correct values are placed in the
-returned data
-
-@param aThread pointer to thread whose memory space the memory is to be read from
-@param aMemoryInfo information about what memory to read
-
-@return KErrNone if memory read successfully,
- KErrArgument if aMemoryInfo is not initialised correctly,
- KErrNoMemory if a temporary buffer could not be allocated,
- KErrBadHandle if aThread is invalid,
- or another of the system wide error codes
-*/
-TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
- {
- LOG_MSG("DRM_DebugChannel::ReadMemory()");
-
- TInt err = KErrNone;
-
- if (!aMemoryInfo)
- return KErrArgument;
-
- TRM_DebugMemoryInfo info(0, 0, 0);
- err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
- if (err != KErrNone)
- return err;
-
- if (!info.iData)
- return KErrArgument;
-
- NKern::ThreadEnterCS();
- TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
- NKern::ThreadLeaveCS();
- if (!data)
- {
- return KErrNoMemory;
- }
-
- TPtr8 dataDes(data, info.iLength);
-
- err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
- if (err == KErrNone)
- {
- err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
- }
-
- NKern::ThreadEnterCS();
- Kern::Free(data);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-Attempt to write memory to aThread's address space
-
-@param aThread thread to whose address space memory is to be written
-@param aMemoryInfo memory info object representing the data to write
-
-@return KErrNone if memory written successfully,
- KErrNoMemory if memory could not be allocated
- KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
- if aMemoryInfo.iLength is greater than than the length of the passed
- in descrptor
- KErrBadHandle if aThread is invalid,
- or another of the system wide error codes
-*/
-TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
- {
- LOG_MSG("DRM_DebugChannel::WriteMemory()");
-
- TInt err = KErrNone;
-
- if (!aMemoryInfo)
- return KErrArgument;
-
- TRM_DebugMemoryInfo info(0, 0, 0);
- err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
- if (err != KErrNone)
- return err;
-
- if (!info.iData)
- return KErrArgument;
-
- NKern::ThreadEnterCS();
- TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
- NKern::ThreadLeaveCS();
- if (!data)
- {
- return KErrNoMemory;
- }
-
- TPtr8 dataDes(data, info.iLength);
-
- err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
- if (err == KErrNone)
- {
- err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
- }
-
- NKern::ThreadEnterCS();
- Kern::Free(data);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-//
-// DRM_DebugChannel::ReadRegisters
-//
-TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
- {
- LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
-
- TInt err = KErrNone;
-
- if (!aRegisterInfo)
- return KErrArgument;
-
- TRM_DebugRegisterInfo info(0, 0, 0);
- err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
- if (err != KErrNone)
- return err;
-
- if (!info.iValues)
- return KErrArgument;
-
- TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
-
- NKern::ThreadEnterCS();
- TUint8 *values = (TUint8*)Kern::Alloc(length);
- NKern::ThreadLeaveCS();
- if (!values)
- {
- return KErrNoMemory;
- }
-
- TPtr8 valuesDes(values, length);
-
- err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
- if (err == KErrNone)
- {
- err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
- }
-
- NKern::ThreadEnterCS();
- Kern::Free(values);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-Get listing information.
-
-@param aListInformation pointer to a TListInformation object containing the
- user specified listings information
-
-@return KErrNone on success,
- KErrTooBig if the kernel's data is too big to fit in the passed buffer,
- KErrArgument if aListInformation is NULL,
- or one of the other system-wide error codes
-*/
-TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
- {
- LOG_MSG("DRM_DebugChannel::GetList()");
-
- TInt err = KErrNone;
-
- if(aListInformation == NULL)
- {
- return KErrArgument;
- }
-
- //read DSS' data into local structure
- TListInformation info;
- err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
- if(err != KErrNone)
- {
- return err;
- }
-
- //check arguments
- TPtr8 buffer(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
- if(err != KErrNone)
- {
- //need to free the buffer if it was allocated
- if(err != KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)buffer.Ptr());
- NKern::ThreadLeaveCS();
- }
- return err;
- }
-
- //get the list
- TUint32 dataSize = 0;
- TListManager manager;
- err = KErrArgument;
- switch(info.iType)
- {
- case EXipLibraries:
- if(Debug::EScopeGlobal == info.iListScope)
- {
- err = manager.GetXipLibrariesList(buffer, dataSize);
- }
- break;
-
- case EThreads:
- if(Debug::EScopeGlobal == info.iListScope)
- {
- err = manager.GetGlobalThreadList(buffer, dataSize);
- }
- else if(Debug::EScopeProcessSpecific == info.iListScope)
- {
- err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
- }
- else if(Debug::EScopeThreadSpecific == info.iListScope)
- {
- err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
- }
- break;
-
- case EProcesses:
- if(Debug::EScopeGlobal == info.iListScope)
- {
- err = manager.GetProcessList(buffer, dataSize);
- }
- break;
-
- case ECodeSegs:
- if(Debug::EScopeGlobal == info.iListScope)
- {
- err = manager.GetGlobalCodeSegList(buffer, dataSize);
- }
- else if(Debug::EScopeProcessSpecific == info.iListScope)
- {
- err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
- }
- else if(Debug::EScopeThreadSpecific == info.iListScope)
- {
- err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
- }
- break;
-
- default:
- err = KErrNotSupported;
- }
-
- if(err == KErrNone)
- {
- //if no error then write the buffer back
- err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
- }
-
- //write back the size of the data regardless of any error
- TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
- if(writeErr != KErrNone)
- {
- //if there was an error writing the size return that error instead
- err = writeErr;
- }
-
- //free the buffer
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)buffer.Ptr());
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-Read registers and store register data in aRegisterInfo
-
-@param aThread thread to read registers from
-@param aRegisterInfo structure specifying which registers to read and providing
- descriptors to write the register data into
-
-@return KErrNone if registers were read successfully. Note that this does not
- mean that all the registers could be read, the
- aRegisterInfo.iRegisterFlags array should be checked as to whether each
- individual register could be read,
- KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
- are members of aRegisterInfo are NULL, if an unknown register is
- specified or if the passed in register values buffer is too small
- KErrNoMemory if there is insufficient memory,
- KErrDied, if the thread with thread ID aThreadId is dead
-*/
-TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
- {
- LOG_MSG("DRM_DebugChannel::ReadRegisters()");
-
- TInt err = KErrNone;
-
- if (!aRegisterInfo)
- return KErrArgument;
-
- TRM_DebugRegisterInformation info;
- err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
- if (err != KErrNone)
- return err;
-
- if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
- return KErrArgument;
-
- //read ids from client thread
- TPtr8 ids(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- NKern::ThreadLeaveCS();
- }
- return err;
- }
-
- //read values from client thread
- TPtr8 values(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)values.Ptr());
- NKern::ThreadLeaveCS();
- }
-
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- NKern::ThreadLeaveCS();
- return err;
- }
-
- //read flags from client thread
- TPtr8 flags(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)flags.Ptr());
- NKern::ThreadLeaveCS();
- }
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- Kern::Free((TAny*)values.Ptr());
- NKern::ThreadLeaveCS();
- return err;
- }
-
- err = DoReadRegisters(aThread, ids, values, flags);
- if (err == KErrNone)
- {
- err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
- if(err == KErrNone)
- {
- err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
- }
- }
-
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- Kern::Free((TAny*)values.Ptr());
- Kern::Free((TAny*)flags.Ptr());
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-@deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
-*/
-TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
- {
- LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
-
- TInt err = KErrNone;
-
- if (!aRegisterInfo)
- return KErrArgument;
-
- TRM_DebugRegisterInfo info(0, 0, 0);
- err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
- if (err != KErrNone)
- return err;
-
- if (!info.iValues)
- return KErrArgument;
-
- TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
-
- NKern::ThreadEnterCS();
- TUint8 *values = (TUint8*)Kern::Alloc(length);
- NKern::ThreadLeaveCS();
- if (!values)
- {
- return KErrNoMemory;
- }
-
- TPtr8 valuesDes(values, length);
-
- err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
- if (err == KErrNone)
- {
- err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
- }
-
- NKern::ThreadEnterCS();
- Kern::Free(values);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-Write registers and store flags data in aRegisterInfo
-
-@param aThread thread to write registers to
-@param aRegisterInfo structure specifying which registers to write and providing
- descriptors to write the register flags data into
-
-@return KErrNone if registers were written successfully. Note that this does not
- mean that all the registers could be written, the flags array
- should be checked as to whether each individual register could be read,
- KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
- are members of aRegisterInfo are NULL, if an unknown register is
- specified or if the passed in register values buffer is too small, or
- if aThread is NULL,
- KErrGeneral if there was a problem initialising the register set,
- KErrNoMemory if there is insufficient memory,
- KErrDied, if the thread with thread ID aThreadId is dead
-*/
-TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
- {
- LOG_MSG("DRM_DebugChannel::WriteRegisters()");
-
- TInt err = KErrNone;
-
- if (!aRegisterInfo)
- return KErrArgument;
-
- TRM_DebugRegisterInformation info;
- err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
- if (err != KErrNone)
- return err;
-
- if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
- return KErrArgument;
-
- //read ids from client thread
- TPtr8 ids(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- NKern::ThreadLeaveCS();
- }
- return err;
- }
-
- //read values from client thread
- TPtr8 values(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)values.Ptr());
- NKern::ThreadLeaveCS();
- }
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- NKern::ThreadLeaveCS();
- return err;
- }
-
- //read flags from client thread
- TPtr8 flags(NULL, 0);
- err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
- if(err != KErrNone)
- {
- if(err == KErrNoMemory)
- {
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)flags.Ptr());
- NKern::ThreadLeaveCS();
- }
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- Kern::Free((TAny*)values.Ptr());
- NKern::ThreadLeaveCS();
- return err;
- }
-
- err = DoWriteRegisters(aThread, ids, values, flags);
- if(err == KErrNone)
- {
- err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
- }
-
- NKern::ThreadEnterCS();
- Kern::Free((TAny*)ids.Ptr());
- Kern::Free((TAny*)values.Ptr());
- Kern::Free((TAny*)flags.Ptr());
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/**
-Suspends execution of the specified thread.
-
-@param aThread thread to resume
-
-@return KErrNone if there were no problems or KErrArgument if aThread is NULL
-*/
-TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
- {
- LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
-
- if (!aThread)
- {
- LOG_MSG("Invalid dthread object");
- return KErrArgument;
- }
-
- return TheDProcessTracker.SuspendThread(aThread);
- }
-
-/**
-Resumes execution of the specified thread.
-
-@param aThread thread to resume
-
-@return KErrNone if there were no problems, KErrArgument if aThread is NULL
- or an error value returned from DoStepRange()
-*/
-TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
- {
- LOG_MSG("DRM_DebugChannel::DoResumeThread()");
-
- if (!aThread)
- return KErrArgument;
-
- // get the current PC
- TUint32 currentPC;
- TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
- if(err != KErrNone)
- {
- LOG_MSG2("DRM_DebugChannel::DoResumeThread - Non-zero error code discarded: %d", err);
- }
-
- // if there is a breakpoint at the current PC, we need to single step past it
- TBreakEntry* breakEntry = NULL;
- do
- {
- breakEntry = iBreakManager->GetNextBreak(breakEntry);
- if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
- {
- if (breakEntry->iAddress == currentPC)
- {
- return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
- }
- }
- } while(breakEntry);
-
- return TheDProcessTracker.ResumeThread(aThread);
- }
-
-//
-// DRM_DebugChannel::DoStepRange
-//
-TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
- {
- LOG_MSG("DRM_DebugChannel::DoStepRange()");
-
- if (!aThread)
- return KErrArgument;
-
- //check that the thread is suspended
- if(!TheDProcessTracker.CheckSuspended(aThread))
- {
- LOG_MSG2("DRM_DebugChannel::DoStepRange() Thread with id 0x%08x not suspended.", aThread->iId);
- return KErrInUse;
- }
-
- TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
- TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
-
- // don't allow the user to step in the excluded ROM region. this could be called
- // internally however. for example, the the special breakpoints we set to handle
- // panics, exceptions, and library loaded events are in the user library, and we
- // will need to step past the breakpoint before continuing the thread.
- //if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
- //{
- // return KErrNotSupported;
- //}
-
- // set the temp breakpoint, and disable the breakpoint at the current PC if necessary
- // if its not a user request, and we are just trying to resume from a breakpoint,
- // then we don't need to check for stubs. The last parameter aUserRequest tells
- // ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
- // is true even if its not a user request.For example, this is true in cases where
- // we are doing a step range and the instruction in the range modified PC.
- // in this case, DoStepRange will be called from the exception handler where
- // we need to check for the stubs for the valid behavior. So truly, we don't need to check
- // for stubs only when resuming from a breakpoint.
- ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
-
- LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
-
- return TheDProcessTracker.ResumeThread(aThread);
- }
-
-/**
-Read memory from the specified addres into the aData descriptor. If there is a
-breakpoint set in the region of memory returned then the correct data value is
-inserted into the descriptor
-
-@param aThread pointer to thread whose address space memory is to be read from
-@param aAddress address to start reading memory from
-@param aLength length of memory block to read
-@param aData descriptor to read memory into
-
-@return KErrNone if memory read successfully,
- KErrNotSupported if reading from the rom section is not supported,
- KErrBadHandle if aThread is invalid,
- or one of the other system wide error codes
-*/
-TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
- {
- LOG_MSG("DRM_DebugChannel::DoReadMemory()");
-
- // make sure the parameters are valid
- if (aLength > aData.MaxSize())
- return KErrArgument;
-
- TInt err = KErrNone;
-
- // trap exceptions in case the address is invalid
- XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
-
- err = (KErrNone == r) ? err : r;
-
- if (KErrNone == err)
- {
- aData.SetLength(aLength);
-
- TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
-
- // if we have any breakpoints in this range, put the actual instruction in the buffer
- TBreakEntry* breakEntry = NULL;
- do
- {
- breakEntry = iBreakManager->GetNextBreak(breakEntry);
- if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
- {
- if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
- {
- TInt instSize;
-
- switch(breakEntry->iMode)
- {
- case EArmMode:
- instSize = 4;
- break;
-
- case EThumbMode:
- instSize = 2;
- break;
-
- case EThumb2EEMode:
- default:
- LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
- return KErrNotSupported;
- }
- memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
- }
- }
- } while(breakEntry);
- }
-
- return err;
- }
-
-/**
-Attempt to write memory to aThread's address space
-
-@param aThread thread to whose address space memory is to be written
-@param aAddress memory location to write memory to
-@param aLength number of bytes of data to write
-@param aData descriptor containing memory to write
-
-@return KErrNone if memory written successfully,
- KErrArgument if aLength is greater than than the length of the aData
- KErrBadHandle if aThread is invalid,
- or another of the system wide error codes
-*/
-TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
- {
- LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
-
- // make sure the parameters are valid
- if (aLength > aData.Length())
- return KErrArgument;
-
- TInt err = KErrNone;
-
- // trap exceptions in case the address is invalid
- XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
-
- err = (KErrNone == r) ? err : r;
-
- // reset any breakpoints we may have just overwritten
- if (KErrNone == err)
- {
- TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
-
- TBreakEntry* breakEntry = NULL;
- do
- {
- breakEntry = iBreakManager->GetNextBreak(breakEntry);
- if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
- {
- if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
- {
- // default to arm mode
- TUint32 inst;
- TInt instSize;
-
- switch (breakEntry->iMode)
- {
- case EArmMode:
- inst = KArmBreakPoint;
- instSize = 4;
- break;
-
- case EThumbMode:
- inst = KThumbBreakPoint;
- instSize = 2;
- break;
-
- case EThumb2EEMode:
- default:
- LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
-
- return KErrNotSupported;
- }
-
- breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
- memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
- }
- }
-
- } while(breakEntry);
- }
- return err;
- }
-
-//
-// DRM_DebugChannel::DoReadRegisters
-//
-TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::DoReadRegisters()");
-
- // make sure the parameters are valid
- if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
- return KErrArgument;
-
- // make sure the descriptor is big enough to hold the requested data
- if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
- return KErrArgument;
-
- TArmRegSet regSet;
- TUint32 unused;
-
- NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
-
- LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
-
- TArmReg *reg = ®Set.iR0;
-
- if (!reg)
- return KErrGeneral;
-
- for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
- aValues.Append((TUint8 *)®[i], sizeof(TArmReg));
-
- return KErrNone;
-}
-
-/**
- @prototype
-
- Experimental function for determining whether a thread is suspended.
-
- @param aThread thread to check if suspended
-
- @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
- */
-TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
- {
- if(!aThread)
- {
- return EFalse;
- }
-
- if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
- {
- return ETrue;
- }
-
- if(aThread->iNThread.iSuspendCount > 0)
- {
- return ETrue;
- }
- return EFalse;
- }
-
-/**
-Read registers and store register values in aRegisterValues and the flags
-indicating which registers could be read in aRegisterFlags
-
-@param aThread thread to read registers from
-@param aRegisterIds array containing register IDs to read
-@param aRegisterValues array to store register values in
-@param aRegisterFlags array to store flags in
-
-@return KErrNone if registers were read successfully. Note that this does not
- mean that all the registers could be read, the aRegisterFlags array
- should be checked as to whether each individual register could be read,
- KErrArgument if aThread is NULL, if an unknown register is specified in
- aRegisterValues or if aRegisterValues is too small
- KErrGeneral if there was a problem initialising the register set
-*/
-TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
- {
- LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
-
- // make sure the parameters are valid
- if (!aThread)
- return KErrArgument;
-
- //Need to revisit this to determine whether there is a way to validate this
-#if 0
- if ( !CheckSuspended(aThread) )
- {
- LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
- return KErrInUse;
- }
-#endif
-
- //set lengths of output descriptors to 0 prior to filling
- aRegisterValues.SetLength(0);
- aRegisterFlags.SetLength(0);
-
- TArmRegSet regSet;
- TUint32 flags;
-
- NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
-
- LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
-
- TArmReg *regPtr = ®Set.iR0;
-
- if (!regPtr)
- return KErrGeneral;
-
- TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
-
- //iterate through registers setting the relevant aFlags value
- for(TUint i=0; i<numberOfRegisters; i++)
- {
- //get current register id
- TRegisterInfo reg;
- TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
- //exit with the error value if there was an error
- if(err != KErrNone)
- return err;
-
- //if unknown register then exit as can't know how many bytes this entry will
- //represent in aRegisterValues
- TTag registerTag;
- TDebugFunctionality::GetRegister(reg, registerTag);
- if(registerTag.iValue == EAccessUnknown)
- {
- return KErrArgument;
- }
-
- //get the current register id as a kernel register
- TArmReg armReg;
- err = GetKernelRegisterId(reg, armReg);
- if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
- {
- //reading this register is not supported
- aRegisterFlags.Append(ENotSupported);
- //just skip over this entry in the values buffer
- if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
- {
- //writing this value would cause overflow so exit
- return KErrArgument;
- }
- aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
- }
- else
- {
- if(registerTag.iSize == sizeof(TArmReg))
- {
- if(GetFlagAtOffset(flags, armReg))
- {
- //set flag as valid
- aRegisterFlags.Append(EValid);
- }
- else
- {
- // Even though the flag is invalid, we can return the value of the register
- // and let the user decide what to do
- aRegisterFlags.Append(EInValid);
- }
-
- if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
- {
- //writing this value would cause overflow so exit
- return KErrArgument;
- }
- //write value into register into regSet
- aRegisterValues.Append((TUint8 *)®Ptr[armReg], registerTag.iSize);
- }
- else
- {
- //currently all kernel supported registers are 4 bytes so
- //return EBadSize. Would need updating if/when other register
- //value sizes are supported
- aRegisterFlags.Append(EBadSize);
- aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
- }
- }
- }
- return KErrNone;
- }
-
-//
-// DRM_DebugChannel::DoWriteRegisters
-//
-TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
- {
- LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
-
- // make sure the parameters are valid
- if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
- return KErrArgument;
-
- // make sure the descriptor is big enough to hold the data to write
- if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
- return KErrArgument;
-
- TArmRegSet regSet;
- TUint32 unused;
-
- NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
-
- TArmReg *reg = ®Set.iR0;
-
- for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
- reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
-
- NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
-
- return KErrNone;
- }
-
-/**
-Write registers and store flags indicating which registers could be read in
-aRegisterFlags
-
-@param aThread thread to write registers to
-@param aRegisterIds array containing register IDs to write
-@param aRegisterValues array containing register values to write
-@param aRegisterFlags array to store flags in
-
-@return KErrNone if registers were written successfully. Note that this does not
- mean that all the registers could be written, the aRegisterFlags array
- should be checked as to whether each individual register could be read,
- KErrArgument if aThread is NULL, if the buffer passed in as
- aRegisterValue is too small, or if an unknown register is requested,
- KErrGeneral if there was a problem initialising the register set
-*/
-TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
- {
- LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
-
- // make sure the parameters are valid
- if (!aThread)
- return KErrArgument;
-
- //check that the thread is suspended before reading the registers
- if(!TheDProcessTracker.CheckSuspended(aThread))
- {
- LOG_MSG2("DRM_DebugChannel::DoWriteRegisters() thread with id 0x%08x is not suspended", aThread->iId);
- return KErrInUse;
- }
-
- //get register values from kernel
- TArmRegSet regSet;
- TUint32 flags;
- NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, flags);
-
- //set lengths of output descriptors to 0 prior to filling
- aRegisterFlags.SetLength(0);
-
- //pointer to first kernel register
- TArmReg *regPtr = ®Set.iR0;
-
- if (!regPtr)
- return KErrGeneral;
-
- //calculate number of registers
- TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
-
- //iterate through registers setting the relevant aRegisterFlags value and
- //setting the necessary value in regSet ready to write to kernel
- for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
- {
- //get current register id
- TRegisterInfo reg;
- TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
- //exit with the error value if there was an error
- if(err != KErrNone)
- {
- return err;
- }
-
- //if unknown register then exit as can't know how many bytes this entry will
- //represent in aRegisterValues
- TTag registerTag;
- TDebugFunctionality::GetRegister(reg, registerTag);
- if(registerTag.iValue == EAccessUnknown)
- {
- return KErrArgument;
- }
-
- //get the current register id as a kernel register
- TArmReg armReg;
- err = GetKernelRegisterId(reg, armReg);
- if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
- {
- //writing to this register is not supported
- aRegisterFlags.Append(ENotSupported);
- }
- else if(GetFlagAtOffset(flags, armReg))
- {
- if(registerTag.iSize == sizeof(TArmReg))
- {
- //set flag as valid
- aRegisterFlags.Append(EValid);
- if(offset + sizeof(TArmReg) > aRegisterValues.Length())
- {
- //getting this value would cause overflow so exit
- return KErrArgument;
- }
- //write value into register into regSet
- regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
- }
- else
- {
- //currently all kernel supported registers are 4 bytes so
- //return EBadSize. Would need updating if/when other register
- //value sizes are supported
- aRegisterFlags.Append(EBadSize);
- }
-
- }
- else
- {
- //set flag as invalid as register value couldn't be read
- aRegisterFlags.Append(EInValid);
- }
- offset+=registerTag.iSize;
- }
-
- //write the input data into the registers
- NKern::ThreadSetUserContext(&aThread->iNThread, ®Set);
-
- //return normally
- return KErrNone;
- }
-
-//
-// DRM_DebugChannel::DoSecurityCheck
-//
-TBool DRM_DebugChannel::DoSecurityCheck()
- {
- LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
- DProcess* clientProcess = iClientThread->iOwningProcess;
- if (clientProcess)
- {
- SSecurityInfo secureInfo = clientProcess->iS;
-
- LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
-
- // Ensure we really are communicating with the Debug Security Server
- if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
- {
- return ETrue;
- }
- }
- return EFalse;
- }
-
-/**
-Attempt to read memory from aThread's address space
-
-@param aThread thread from whose address space memory is to be read
-@param aSrc pointer to memory location to read memory from
-@param aDest pointer to memory location to write memory to
-@param aLength number of bytes of data to read
-
-@return KErrNone if memory read successfully,
- or another of the system wide error codes
-*/
-TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
- {
- LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
-
- // make sure the parameters are valid
- if (!aThread)
- return KErrArgument;
-
- //Need to revisit this to determine whether there is a way to validate this
-#if 0
- //check that the thread is suspended before reading the memory
- if ( !CheckSuspended(aThread) )
- {
- LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
- return KErrInUse;
- }
-#endif
-
- LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
- return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
- }
-
-/**
-Attempt to write memory to aThread's address space
-
-@param aThread thread to whose address space memory is to be written
-@param aDest pointer to memory location to write memory to
-@param aSrc pointer to memory location to read memory from
-@param aLength number of bytes of data to write
-
-@return KErrNone if memory written successfully, or another of the system wide
- error codes
-*/
-TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
- {
- LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
-
- //check that the thread is suspended before writing the memory
- if(!TheDProcessTracker.CheckSuspended((DThread*)aThread))
- {
- LOG_MSG2("DRM_DebugChannel::TryToWriteMemory() thread with id 0x%08x is not suspended", aThread->iId);
- return KErrInUse;
- }
-
- LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
- return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
- }
-
-/**
-@deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
-*/
-TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
- {
- LOG_MSG("DRM_DebugChannel::ReadRegister()");
-
- if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
- {
- LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
- return 0;
- }
-
- TArmRegSet regSet;
- TUint32 unused;
-
- NKern::ThreadGetUserContext(&aThread->iNThread, ®Set, unused);
-
- TArmReg *reg = ®Set.iR0;
-
- return ((TUint32 *)reg)[aNum];
- }
-
-/**
-Given a TArmReg register ID, read the value of the register. The register value
-will be stored in aValue if the register could be read.
-
-@param aThread thread to read register from
-@param aKernelRegisterId ID of register to read from
-@param aValue value read from register
-
-@return KErrNone if value was successfully stored in aValue,
- KErrNotSupported if aKernelRegister is not supported by the debug
- security server,
- or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
-*/
-TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
- {
- //get register ID as a TRegisterInfo ID
- TRegisterInfo regId;
- TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
- if(err != KErrNone)
- return err;
-
- //get the value for the register
- err = ReadDebugRegisterValue(aThread, regId, aValue);
- return err;
- }
-
-/**
-Given a TRegisterInfo register ID, read the value of this register. The
-register value will be stored in aValue if the register could be read.
-
-@param aThread thread to read register from
-@param aDebugRegisterId ID of register to read from
-@param aValue value read from register
-
-@return KErrNone if value was successfully stored in aValue,
- TRegisterFlag::EInValid if value could not be read from the register,
- TRegisterFlag::ENotSupported if the register is not supported,
- KErrNoMemory if temporary memory could not be allocated,
- or a return value from DRM_DebugChannel::DoReadRegisters
-*/
-TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
- {
- //allocate temporary buffers to store data
- NKern::ThreadEnterCS();
- TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
- NKern::ThreadLeaveCS();
- if(id == NULL)
- {
- return KErrNoMemory;
- }
-
- TPtr8 idPtr(id, sizeof(TRegisterInfo));
-
- NKern::ThreadEnterCS();
- TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
- NKern::ThreadLeaveCS();
- if(value == NULL)
- {
- return KErrNoMemory;
- }
- TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
-
- NKern::ThreadEnterCS();
- TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
- NKern::ThreadLeaveCS();
- if(flag == NULL)
- {
- return KErrNoMemory;
- }
- TPtr8 flagPtr(flag, sizeof(TUint8));
-
- //store register id in buffer
- idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
-
- //read registers
- TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
- if(err == KErrNone)
- {
- if(*flag == EValid)
- {
- //register could be read so store value
- aValue = *(T4ByteRegisterValue*)value;
- }
- else
- {
- //register couldn't be read for some reason
- err = *flag;
- }
- }
-
- //free memory
- NKern::ThreadEnterCS();
- Kern::Free(id);
- Kern::Free(value);
- Kern::Free(flag);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-//
-// DRM_DebugChannel::NotifyEvent
-//
-void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
-
- // Look for the relevant DTargetProcess
- // We can find out the relevant process id from aEventInfo
- TUint32 pid = aEventInfo.iProcessId;
-
- //opening handle to process
- DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
-
- if(!targetProcess)
- {
- LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - process does not exist!");
- return;
- }
-
- // Are we debugging this process - decide based on iFileName
- DCodeSeg* p = targetProcess->iCodeSeg;
- DTargetProcess* foundProcess;
- if (p)
- {
- foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
- }
- else
- {
- // special case: may not have a code seg in some cases. in which case we tell everyone!
- if (targetProcess->iName)
- {
- // copy the name of the process
- foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
- }
- else
- {
- foundProcess = NULL;
- }
- }
-
- //close the handle
- targetProcess->Close(NULL);
-
- if (!foundProcess)
- {
- // No: just ignore this exception
- LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - we are not debugging this process!");
- return;
- }
-
- foundProcess->NotifyEvent(aEventInfo);
- }
-
-#ifndef __LAUNCH_AS_EXTENSION__
-DECLARE_STANDARD_LDD()
- {
- return new DRM_DebugDriverFactory;
- }
-#else
-
-DStopModeExtension* TheStopModeExtension = NULL;
-
-DECLARE_EXTENSION_LDD()
- {
- return new DRM_DebugDriverFactory;
- }
-
-/**
- This value is used as an initialiser for the size of the Stop-Mode Debug API's
- default request buffer.
- */
-const TInt KRequestBufferSize = 0x200;
-/**
- This value is used as an initialiser for the size of the Stop-Mode Debug API's
- default response buffer.
- */
-const TInt KResponseBufferSize = 0x1000;
-
-DECLARE_STANDARD_EXTENSION()
- {
- __KTRACE_OPT(KBOOT,Kern::Printf("Starting RM_DEBUG extension"));
-
- // get a reference to the DDebuggerInfo and to the DStopModeExtension
- TSuperPage& superPage = Kern::SuperPage();
-
- if(!superPage.iDebuggerInfo)
- {
- //kdebug has not been installed so create DDebuggerInfo using our stub constructor
- superPage.iDebuggerInfo = new DDebuggerInfo();
- }
-
- if(!TheStopModeExtension)
- {
- TheStopModeExtension = new DStopModeExtension();
- }
-
- // create the request buffer and store a reference to it
- TTag tag;
- tag.iTagId = EBuffersRequest;
- tag.iType = ETagTypePointer;
- tag.iSize = KRequestBufferSize;
- TInt err = TheDBufferManager.CreateBuffer(tag);
- if(KErrNone != err)
- {
- return KErrNone;
- }
-
- // create the response buffer and store a reference to it
- tag.iTagId = EBuffersResponse;
- tag.iSize = KResponseBufferSize;
- err = TheDBufferManager.CreateBuffer(tag);
- if(KErrNone != err)
- {
- return KErrNone;
- }
- // create the debug functionality buffer and store a reference to it
- TDebugFunctionality df;
- TUint dfSize = df.GetStopModeFunctionalityBufSize();
- tag.iTagId = EBuffersFunctionality;
- tag.iSize = dfSize;
- err = TheDBufferManager.CreateBuffer(tag);
- if(KErrNone != err)
- {
- return KErrNone;
- }
-
- // fill the functionality buffer with the functionality data and store it in
- // the super page
- TPtr8 dfBlockPtr((TUint8*)tag.iValue, dfSize);
- if(!df.GetStopModeFunctionality(dfBlockPtr))
- {
- return KErrNone;
- }
- TheStopModeExtension->iFunctionalityBlock = (DFunctionalityBlock*)tag.iValue;
-
- DStopModeExtension::Install(TheStopModeExtension);
-
- return KErrNone;
- }
-
-/**
- * This stub constructor is intended to be used in the case where the old deprecated
- * stop mode api, kdebug, is not in place. It will initialise all values to NULL except
- * the pointer to the new stop mode api extension. This allows the new stop mode solution
- * to both co-exist and exist independantly of the existing one *
- */
-DDebuggerInfo::DDebuggerInfo():
- iObjectOffsetTable(NULL),
- iObjectOffsetTableCount(NULL),
- iThreadContextTable(NULL),
- iStopModeExtension(new DStopModeExtension()),
- iContainers(NULL),
- iCodeSegLock(NULL),
- iCodeSegGlobalList(NULL),
- iScheduler(NULL),
- iShadowPages(NULL),
- iShadowPageCount(0),
- iCurrentThread(NULL),
- iEventMask(),
- iEventHandlerBreakpoint(0),
- iMemModelObjectOffsetTable(NULL),
- iMemModelObjectOffsetTableCount(0)
- {
- }
-
-/**
- * Installs the stop-mode debugger extension
- * Make the stop-mode API visible to a JTAG debugger, by publishing its
- * existence in the superpage
-*/
-void DStopModeExtension::Install(DStopModeExtension* aExt)
- {
- Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
- }
-
-#endif
-
-/**
-Helper function
-
-Allocates memory in current thread with a max length the same as aSrcDes. If
-aReadFromClient is true (as it is by default) then the data from aSrdDes is
-copied into the allocated aDestDes buffer.
-
-Use of this function should be followed at a later time by a call such as
-Kern::Free(aDestDes.Ptr())
-
-@param aThread pointer to thread to read data from
-@param aSrcDes descriptor in aThread to read data from
-@param aDestDes location to read data to. Memory is allocated at this location,
- if memory is already allocated at this location then the function will
- return KErrArgument
-@param aReadFromClient if false then data is not actually read from the
- client, the memory is simply allocated
-@param aOffest offset into aSrcDes to start reading from. Default is 0.
-
-@return KErrNone if there were no problems,
- KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
- KErrNoMemory if could not allocate memory,
- or one of the other system wide error codes
-*/
-TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
- {
-
- //check thread is not null
- if(!aThread)
- {
- return KErrArgument;
- }
-
- //check aDestDes is empty
- if(aDestDes.Ptr() != NULL)
- {
- return KErrArgument;
- }
-
- //get the source descriptor's max length and exit if 0
- TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
- if(srcMaxLength == 0)
- {
- return KErrNone;
- }
-
- //allocate memory and return if none available
- NKern::ThreadEnterCS();
- TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
- NKern::ThreadLeaveCS();
- if (!destPtr)
- {
- return KErrNoMemory;
- }
-
- //point the TPtr8 at the target memory
- aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
-
- if(aReadFromClient)
- {
- //read data from the client thread and return status code
- return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
- }
- else
- {
- return KErrNone;
- }
- }
-
-/**
-Helper function to extract a TRegisterInfo value from a descriptor containing
-binary data.
-
-@param aRegisterIds descriptor containing register IDs
-@param aOffset offset in bytes into the descriptor to start reading data from.
- If this value is not a multiple of sizeof(TRegisterInfo) then a
- KErrArgument error is returned.
-@param aValue will contain the returned value
-
-@return KErrNone if aValue was set correctly, KErrArgument if bad arguments
- were passed in
-*/
-TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
- {
- TUint length = aRegisterIds.Length();
-
- TUint size = sizeof(TRegisterInfo);
-
- //check that not trying to read past end of descriptor
- if((aIndex + 1) * size > length)
- return KErrArgument;
-
- //get pointer to descriptor's data
- const TUint8 *dataPtr = aRegisterIds.Ptr();
- const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
-
- aValue = *registerId;
-
- return KErrNone;
- }
-
-/**
-Helper function to get the kernel register ID of the TRegisterInfo defined register.
-
-@param aDebugRegister the debug register ID to return the kernel ID for
-@param aKernelRegister corresponding value of register aDebugRegister
-
-@return KErrNone if translation occurred without problems
- KErrNotSupported if aDebugRegister is not supported by the kernel
-*/
-TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
- {
- if(Register::IsCoreReg(aDebugRegister))
- {
- TUint id = Register::GetCoreRegId(aDebugRegister);
- //first 17 registers match the first 17 kernel registers
- if(id < 17)
- {
- aKernelRegister = id;
- }
- else
- {
- return KErrNotSupported;
- }
- }
- else if(Register::IsCoproReg(aDebugRegister))
- {
- TUint32 crn = Register::GetCRn(aDebugRegister);
- TUint32 crm = Register::GetCRm(aDebugRegister);
- TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
- TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
- TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
-
- //each coprocessor register has potentially different characteristics
- //so need to identify each individually
-
- //this is the DACR, the ARM ARM specifies that the CRn and the
- //Opcodes are not relevant, section B3-24, point 3.7.3
- if((coproNum == 15) && (crm == 3))
- {
- aKernelRegister = EArmDacr;
- }
- else
- {
- return KErrNotSupported;
- }
- }
- else // might be supported at a later date
- {
- return KErrNotSupported;
- }
-
- return KErrNone;
- }
-
-/**
-Helper function to get the debug register ID of the kernel defined register.
-
-@param aKernelRegister the kernel register ID to return the debug ID for
-@param aDebugRegister corresponding value of register aKernelRegister
-
-@return KErrNone if translation occured without problems
- KErrNotSupported if aKernelRegister is not supported by the debug
- security server
-*/
-TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
- {
-
- // registers 0 - 15 and the CPSR share the same values as with the debug enums
- if(aKernelRegister < 17)
- {
- TUint32 id = aKernelRegister;
- aDebugRegister = id << 8;
- }
- //the DACR value is special and corresponds to EDF_Register_DACR
- else if(aKernelRegister == EArmDacr)
- {
- aDebugRegister = 0x00300f01;
- }
- // must be an unsupported register, return an error as such
- else
- {
- return KErrNotSupported;
- }
-
- //found a supported register so return KErrNone
- return KErrNone;
- }
-
-/**
-Helper function to find out whether the aIndex flag is set. This is equivalent
-to the aIndex bit of aFlags being non-zero.
-
-@param aFlags set of flags
-@param aIndex offset into aFlags to get flag from
-
-@return ETrue if bit is set, EFalse if not
-*/
-TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
- {
- return aFlags & (1<<aIndex);
- }
-
-/* Register the attachment of a debug agent to a process to be debugged
- *
- * @param a1 - TDes8 target process name
- * @param a2 - &TUint64 - Debug Agent Id
- *
- * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
- * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
- * if appropriate.
- */
-TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
- {
- LOG_MSG("DRM_DebugChannel::AttachProcess()");
-
- // Validate the supplied TDes8 target process name in a1
- TInt length, maxLength;
- TUint8* aPtr;
-
- TInt err = Kern::ThreadGetDesInfo(iClientThread,\
- a1,\
- length,\
- maxLength,\
- aPtr,\
- EFalse);
- if (err != KErrNone)
- {
- // Could not read the descriptor information
- return err;
- }
-
- // Check the processname is a valid size for a filepath
- if (length < 1 || length >= KMaxPath)
- {
- return KErrArgument;
- }
-
- if (maxLength < 1 || maxLength >= KMaxPath)
- {
- return KErrArgument;
- }
-
- // Allocate space to store the target process name in a kernel-side TPtr8
- NKern::ThreadEnterCS();
- TUint8* buffer = (TUint8*)Kern::AllocZ(length);
- NKern::ThreadLeaveCS();
- if (buffer==NULL)
- {
- // Out of memory
- return KErrNoMemory;
- }
-
- // A temporary descriptor to store the target process name
- TPtr8 targetProcessName(buffer,length,length);
-
- // Read the user-side data into targetProcessName
- err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
- if (err != KErrNone)
- {
- // Could not read the user-side descriptor containing the target process name
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
- // Obtain the Debug Agent Id
- TUint64 debugAgentId = 0;
-
- err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
- if (err != KErrNone)
- {
- // Something bad happened so free the memory and return
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
- return err;
- }
-
- // Add the target process to our list of tracked processes
- err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
-
- // Free the kernel-side memory containing targetProcessName data
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/* Register the detachment of a debug agent to a process to be debugged.
- *
- * @param - a1 TDes8 target process name in a1
- * @param a2 - &TUint64 - Debug Agent Id
- *
- * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
- * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
- * if appropriate.
- */
-TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
- {
- // Validate the supplied TDes8 target process name in a1
- TInt length, maxLength;
- TUint8* aPtr;
-
- TInt err = Kern::ThreadGetDesInfo(iClientThread,\
- a1,\
- length,\
- maxLength,\
- aPtr,\
- EFalse);
- if (err != KErrNone)
- {
- return err;
- }
-
- if (length < 1 || length >= KMaxPath)
- {
- return KErrArgument;
- }
-
- if (maxLength < 1 || maxLength >= KMaxPath)
- {
- return KErrArgument;
- }
-
- // Allocate space to store the target process name in a kernel-side TPtr8
- NKern::ThreadEnterCS();
- TUint8* buffer = (TUint8*)Kern::AllocZ(length);
- NKern::ThreadLeaveCS();
- if (buffer==NULL)
- {
- // Out of memory
- return KErrNoMemory;
- }
-
- TPtr8 targetProcessName(buffer,length,length);
-
- // Read the user-side data into targetProcessName
- err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
- if (err != KErrNone)
- {
- // Something bad happened so free the memory and return
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
- // Obtain the AgentId
- TUint64 debugAgentId = 0;
-
- err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
- if (err != KErrNone)
- {
- // Something bad happened so free the memory and return
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
- // Remove the process from our list of tracked processes
- err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
-
- // Free the kernel-side memory containing targetProcessName data
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-/* Register the detachment of a debug agent from all processes being debugged.
- *
- * @param - a1 - &TUint64 Debug Agent Id.
- * @return - KErrNone if successful. One of the system-wide error codes otherwise.
- */
-TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
- {
- // Obtain the AgentId
- TUint64 debugAgentId = 0;
-
- TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
- if (err != KErrNone)
- {
- return err;
- }
-
- // Remove the process from our list of tracked processes
- return TheDProcessTracker.DetachAgent(debugAgentId);
- }
-
-/* Set the action associated with a particular kernel event for a given agent and target process
- *
- * @param - a1 TDes8 target process name in a1
- * @param - a2 &TRM_DebugEventActionInfo
- * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
- * the other system wide error codes if appropriate.
- */
-TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
- {
- // Validate the supplied TDes8 target process name in a1
- TInt length, maxLength;
- TUint8* aPtr;
-
- TInt err = Kern::ThreadGetDesInfo(iClientThread,\
- a1,\
- length,\
- maxLength,\
- aPtr,\
- EFalse);
- if (err != KErrNone)
- {
- return err;
- }
-
- if (length < 1 || length >= KMaxPath)
- {
- return KErrArgument;
- }
-
- if (maxLength < 1 || maxLength >= KMaxPath)
- {
- return KErrArgument;
- }
-
- // Allocate space to store the target process name in a kernelspace TPtr8
- NKern::ThreadEnterCS();
- TUint8* buffer = (TUint8*)Kern::AllocZ(length);
- NKern::ThreadLeaveCS();
- if (buffer==NULL)
- {
- // Out of memory
- return KErrNoMemory;
- }
- TPtr8 targetProcessName(buffer,length,length);
-
- // Read the user-side data into targetProcessName
- err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
- if (err != KErrNone)
- {
- // Something bad happened so free the memory and return
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
- // Read the Event and Action from the user-side
- TRM_DebugEventActionInfo info(0,0,0);
-
- err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
- if (err != KErrNone)
- {
- // Could not read event action data from the user-side
-
- // Free memory used for targetProcessName
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
- // Find the target process
- DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
- if (pProcess == NULL)
- {
- // Could not find this process
-
- // Free memory used for targetProcessName
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return KErrArgument;
- }
-
- TUint64 debugAgentId = info.iAgentId;
-
- // Find the agent
- DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
- if (debugAgent == NULL)
- {
- // Bad agent means there is no tracking agent
- LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
-
- // Free memory used for targetProcessName
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return KErrGeneral;
- }
-
- // Set the event action
- debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
-
- // Free memory used for targetProcessName
- NKern::ThreadEnterCS();
- Kern::Free(buffer);
- NKern::ThreadLeaveCS();
-
- return KErrNone;
- }
-
-TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
- {
- LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
-
- DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
-
- if (thread == NULL)
- {
- // The thread terminated before we could open it.
- LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
-
- return KErrArgument;
- }
-
- // We simply repeat this for desired number of steps
- TInt err = KErrNone;
-
- // Need to step from the current location for 'n' steps
- TUint32 startAddress;
-
- // We always step from the current PC.
- err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
- if(err != KErrNone)
- {
- LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
-
- // Close the handle
- thread->Close(NULL);
-
- return err;
- }
-
- err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
-
- if (err != KErrNone)
- {
- // There was a problem, return straightaway
- LOG_MSG("DRM_DebugChannel::Step - failed to step");
- }
-
- // Close the handle
- thread->Close(NULL);
-
- return err;
- }
-
-TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
- {
- LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
-
- DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
-
- if (process == NULL)
- {
- // The process terminated before we could open it to kill it ourselves.
- LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
-
- return KErrArgument;
- }
-
- TInt err = KErrNone;
-
- DebugSupport::TerminateProcess(process,aReason);
-
- // Close the handle
- process->Close(NULL);
-
- return err;
- }
-
-/* Security critical - this checks whether the specified process is debuggable or not
- *
- * @param aProcessId - The process id of the process to check
- * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
- */
-TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
- {
- /* In order to ensure that only processes which are debuggable
- * can be debugged, this function enables the security server
- * to read the DProcess.iDebugAttributes field and ensure
- * the process was created from a debuggable executable.
- */
- LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
-
- TInt err = KErrPermissionDenied;
-
- DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
- if (process)
- {
- if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
- {
- // Yes this process exists and is debuggable
- err = KErrNone;
- }
- process->Close(NULL);
- }
-
- if (err == KErrNone)
- {
- LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
- }
-
- return err;
- }