os/kernelhwsrv/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // Device driver for kernel side debug assist
    15 //
    16 
    17 #ifdef __WINS__
    18 #error - this driver cannot be built for emulation
    19 #endif
    20 
    21 #include <e32def.h>
    22 #include <e32def_private.h>
    23 #include <e32cmn.h>
    24 #include <e32cmn_private.h>
    25 #include <e32ldr.h>
    26 #include <u32std.h>
    27 #include <kernel/kernel.h>
    28 #include <kernel/kern_priv.h>
    29 #include <nk_trace.h>
    30 #include <arm.h>
    31 #include <kernel/cache.h>
    32 #include <platform.h>
    33 #include <nkern.h>
    34 #include <u32hal.h>
    35 #include <kernel/kdebug.h>
    36 #include <rm_debug_api.h>
    37 
    38 #include "debug_logging.h"
    39 #include "d_rmd_breakpoints.h"	// moved breakpoints code lives here
    40 #include "d_rmd_stepping.h"		// moved stepping code lives here
    41 #include "rm_debug_kerneldriver.h"
    42 #include "d_list_manager.h"
    43 #include "rm_debug_driver.h"
    44 #include "rm_debug_eventhandler.h"
    45 #include "d_debug_functionality.h"
    46 #include "d_process_tracker.h"
    47 #include "debug_utils.h"
    48 #include "d_buffer_manager.h"
    49 
    50 using namespace Debug;
    51 
    52 /////////////////////////////////////////////////////////////////////////
    53 //
    54 // DRM_DebugDriverFactory implementation
    55 //
    56 /////////////////////////////////////////////////////////////////////////
    57 
    58 //
    59 // DRM_DebugDriverFactory constructor
    60 //
    61 DRM_DebugDriverFactory::DRM_DebugDriverFactory()
    62 {
    63 	iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
    64 }
    65 
    66 //
    67 // DRM_DebugDriverFactory::Create
    68 //
    69 TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
    70 {
    71 	if (iOpenChannels != 0)
    72 		return KErrInUse; // a channel is already open
    73 
    74 	aChannel = new DRM_DebugChannel(this);
    75 
    76 	return aChannel ? KErrNone : KErrNoMemory;
    77 }
    78 
    79 //
    80 // DRM_DebugDriverFactory::Install
    81 //
    82 TInt DRM_DebugDriverFactory::Install()
    83 {
    84     return(SetName(&KRM_DebugDriverName));
    85 }
    86 
    87 //
    88 // DRM_DebugDriverFactory::Install
    89 //
    90 void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
    91 {
    92     TCapsRM_DebugDriver b;
    93     b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
    94 
    95 	Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
    96 }
    97 
    98 /////////////////////////////////////////////////////////////////////////
    99 //
   100 // DRM_DebugChannel implementation
   101 //
   102 /////////////////////////////////////////////////////////////////////////
   103 
   104 //
   105 // DRM_DebugChannel constructor
   106 //
   107 DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
   108 	: iExcludedROMAddressStart(ROM_LINEAR_BASE),
   109       iExcludedROMAddressEnd(0),
   110    	  iPageSize(0x1000),
   111 	  iBreakManager(0),
   112 	  iStepper(0),
   113 	  iStepLock(0),
   114   	  iDfcQ(NULL),
   115 	  iInitialisedCodeModifier(0),
   116 	  iAsyncGetValueRequest(NULL)
   117 {
   118 	LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
   119 
   120 	iDevice = aLogicalDevice;
   121 
   122 	iClientThread = &Kern::CurrentThread();
   123 	iClientThread->Open();
   124 
   125 	iPageSize = Kern::RoundToPageSize(1);
   126 }
   127 
   128 //
   129 // DRM_DebugChannel destructor
   130 //
   131 DRM_DebugChannel::~DRM_DebugChannel()
   132 {
   133 	LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
   134 
   135 	if (iAsyncGetValueRequest)
   136 	{
   137 		Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
   138 		Kern::DestroyClientRequest(iAsyncGetValueRequest);
   139 	}
   140 
   141 	NKern::ThreadEnterCS();
   142 	Kern::SafeClose((DObject*&)iClientThread, NULL);
   143 	NKern::ThreadLeaveCS();
   144 
   145 	// Close breakpoint manager
   146 	if (iBreakManager)
   147 	{
   148 		NKern::ThreadEnterCS();
   149 		delete iBreakManager;
   150 		NKern::ThreadLeaveCS();
   151 	}
   152 
   153 	// Close stepping manager
   154 	if (iStepper)
   155 	{
   156 		NKern::ThreadEnterCS();
   157 		delete iStepper;
   158 		NKern::ThreadLeaveCS();
   159 	}
   160 
   161 	//close the debug process list
   162 	iDebugProcessList.Close();
   163 
   164 	DestroyDfcQ();
   165 
   166 	//close the code modifier
   167 	if (iInitialisedCodeModifier)
   168 	{
   169 		DebugSupport::CloseCodeModifier();
   170 	}
   171 }
   172 
   173 void DRM_DebugChannel::DestroyDfcQ()
   174 	{
   175 	LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
   176 	if (iDfcQ)
   177 		{
   178 		NKern::ThreadEnterCS();
   179 		iDfcQ->Destroy();
   180 		NKern::ThreadLeaveCS();
   181 		}
   182 	}
   183 
   184 //
   185 // DRM_DebugChannel::DoCreate
   186 //
   187 TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
   188 {
   189 	LOG_MSG("DRM_DebugChannel::DoCreate()");
   190 	TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
   191 	if(err != KErrNone)
   192 		return err;
   193 
   194   	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
   195 		return KErrNotSupported;
   196 
   197   	// Do the security check here so that any arbitrary application doesn't make
   198   	// use of Trk kernel driver.
   199   	if (!DoSecurityCheck())
   200   	{
   201 		LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
   202   		return KErrPermissionDenied;
   203   	}
   204 
   205   	if (anInfo)
   206   	{
   207   		// this is the end address of the user library.
   208   		// this doesn't seem to be valid for EKA2.
   209   		// right now we dont need this for EKA2 since we are not worried
   210   		// about kernel being stopped as kernel is multithreaded.
   211   		// just retaining this for future use.
   212 		TBuf8<32> buf;
   213 		TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
   214 		if(err != KErrNone)
   215 			return err;
   216 
   217 		//iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
   218 	}
   219 
   220 	// Allocate a D_RMD_Breakpoints class as a breakpoint manager
   221 	NKern::ThreadEnterCS();
   222 	iBreakManager = new D_RMD_Breakpoints(this);
   223 	NKern::ThreadLeaveCS();
   224 	if (iBreakManager == NULL)
   225 	{
   226 		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
   227 		return KErrNoMemory;
   228 	}
   229 
   230 	// Initialise the new breakpoint manager object
   231 	iBreakManager->Init();
   232 
   233 	// Allocate a DRMDStepping class as the stepping manager
   234 	NKern::ThreadEnterCS();
   235 	iStepper = new DRMDStepping(this);
   236 	NKern::ThreadLeaveCS();
   237 	if (iStepper == NULL)
   238 	{
   239 		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
   240 		return KErrNoMemory;
   241 	}
   242 
   243 	// Initialize the code modifier for managing breakpoints.
   244 	TUint caps; //ignored for now
   245 	err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
   246 	//if code modifier initializer failed,
   247 	//return here, since we can't set an breakpoints
   248 	if(err != KErrNone)
   249 	{
   250 		return err;
   251 	}
   252 	else
   253 	{
   254 		iInitialisedCodeModifier = ETrue;
   255 	}
   256 
   257 	//create and set the driver's Dfc queue
   258 	err = CreateDfcQ();
   259 	if(err != KErrNone)
   260 		{
   261 		LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
   262 		}
   263 	SetDfcQ(iDfcQ);
   264 
   265 	iMsgQ.Receive();
   266 
   267 	iEventHandler = new DRM_DebugEventHandler;
   268 	if (!iEventHandler)
   269 		return KErrNoMemory;
   270 	err = iEventHandler->Create(iDevice, this, iClientThread);
   271 	if (err != KErrNone)
   272 		return err;
   273 
   274 	//return KErrNone;
   275 	return iEventHandler->Start();
   276 }
   277 
   278 //
   279 // DRM_DebugChannel::SendMsg
   280 //
   281 TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
   282 	{
   283 	LOG_MSG("DRM_DebugChannel::SendMsg()");
   284 
   285 	TThreadMessage& m = *(TThreadMessage*)aMsg;
   286 	TInt id = m.iValue;
   287 	TInt err = KErrNone;
   288 
   289 	if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
   290 		{
   291 		// DoRequest
   292 		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   293 		err = SendRequest(aMsg);
   294 		if (err != KErrNone)
   295 			Kern::RequestComplete(pStatus,err);
   296 		}
   297 	else
   298 		{
   299 		err = DLogicalChannel::SendMsg(aMsg);
   300 		}
   301 	return err;
   302 	}
   303 
   304 //
   305 // DRM_DebugChannel::SendRequest
   306 //
   307 TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
   308 	{
   309 	LOG_MSG("DRM_DebugChannel::SendRequest()");
   310 
   311 	TThreadMessage& m = *(TThreadMessage*)aMsg;
   312 	TInt function = ~m.iValue;
   313 	TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   314 	TAny* a1 = m.Ptr1();
   315 
   316 	TInt err = KErrNotSupported;
   317 	switch(function)
   318 		{
   319 		case RRM_DebugDriver::ERequestGetEvent:
   320 			err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
   321 			break;
   322 		}
   323 	if (err == KErrNone)
   324 		err = DLogicalChannel::SendMsg(aMsg);
   325 	return err;
   326 	}
   327 
   328 //
   329 // DRM_DebugChannel::PreAsyncGetValue
   330 //
   331 TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
   332 	{
   333 	LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
   334 	
   335 	iAsyncGetValueRequest->Reset();
   336 	
   337 	TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
   338 	if (err != KErrNone)
   339 		return err;
   340 	
   341 	iAsyncGetValueRequest->SetDestPtr(aValue);
   342 	return KErrNone;
   343 	}
   344 
   345 /**
   346   Create the Dfc queue for receiving messages
   347   */
   348 TInt DRM_DebugChannel::CreateDfcQ()
   349 	{
   350 	LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
   351 	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
   352 	// Fix to stop t_rmdebug2 etc crashing the device.
   353 	// This should be removed once the rm debug driver has been updated for WDP.
   354 	if (r == KErrNone)
   355 		iDfcQ->SetRealtimeState(ERealtimeStateOff);
   356 	return r;
   357 	}
   358 
   359 //
   360 // DRM_DebugChannel::DoCancel
   361 //
   362 // New: The cancel call does not take an enum parameter describing
   363 // the request to be cancelled. Rather it supplies a pointer
   364 // to a user-side struct defining the cancellation
   365 //
   366 void DRM_DebugChannel::DoCancel(TInt aReqNo)
   367 {
   368 	LOG_MSG("DRM_DebugChannel::DoCancel()");
   369 
   370 	TRMD_DebugCancelInfo info;
   371 
   372 	TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
   373 	if (err != KErrNone)
   374 	{
   375 		// How do we cancel something we know nothing about???
   376 		LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
   377 		return;
   378 	}
   379 
   380 	// Find the process
   381 	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
   382 	if (pProcess == NULL)
   383 	{
   384 		// We are doomed. We don't know which event to cancel..
   385 		LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
   386 
   387 		return;
   388 	}
   389 
   390 	// Find the agent
   391 	DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
   392 	if (debugAgent == NULL)
   393 	{
   394 		// Bad agent means there is no tracking agent
   395 		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
   396 		return;
   397 	}
   398 
   399 	// Agent completes/pends the request as appropriate.
   400 	debugAgent->CancelGetEvent();
   401 
   402 }
   403 
   404 //
   405 // DRM_DebugChannel::DoRequest
   406 //
   407 void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   408 {
   409 	LOG_MSG("DRM_DebugChannel::DoRequest()");
   410 
   411 	switch(aReqNo)
   412 	{
   413 		case RRM_DebugDriver::ERequestGetEvent:
   414 		{
   415 			TEventMetaData eventMetaData;
   416 			TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
   417 			if (err != KErrNone)
   418 			{
   419 				LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
   420 
   421 				// We could not read information from the user, so the a2 argument is probably wrong
   422 				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
   423 				return;
   424 			}
   425 
   426 			// Find the process
   427 			DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
   428 			if (pProcess == NULL)
   429 			{
   430 				LOG_MSG("Cannot identify process being debugged");
   431 
   432 				// We could not locate the process, so the user asked for the wrong one.
   433 				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
   434 				return;
   435 			}
   436 
   437 			// Find the agent
   438 			DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
   439 			if (debugAgent == NULL)
   440 			{
   441 				// Bad agent means there is no tracking agent
   442 				LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
   443 				return;
   444 			}
   445 			// Agent completes/pends the request as appropriate.
   446 			debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
   447 
   448 			break;
   449 		}
   450 		default:
   451 			{
   452 			// Don't know what to do, should not get here!
   453 			LOG_MSG("DRM_DebugChannel::DoRequest was passed an unsupported request aReqNo");
   454 
   455 			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
   456 			}
   457 	}
   458 }
   459 
   460 //
   461 // DRM_DebugChannel::DoControl
   462 //
   463 TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   464 {
   465 	LOG_MSG("DRM_DebugChannel::DoControl()");
   466 
   467 	LOG_MSG2("DoControl Function %d", aFunction);
   468 
   469 	TInt err = KErrBadHandle;
   470 	DThread* threadObj = NULL;
   471 
   472 	switch(aFunction)
   473 	{
   474 		/* Security first */
   475 		case RRM_DebugDriver::EControlIsDebuggable:
   476 		{
   477 			err = IsDebuggable((TUint32)a1);
   478 			break;
   479 		}
   480 		case RRM_DebugDriver::EControlSetBreak:
   481 		{
   482 			err = SetBreak((TSetBreakInfo*)a1);
   483 			break;
   484 		}
   485 		case RRM_DebugDriver::EControlClearBreak:
   486 		{
   487 			err = iBreakManager->DoClearBreak((TInt32)a1);
   488 			break;
   489 		}
   490 		case RRM_DebugDriver::EControlModifyBreak:
   491 		{
   492 			err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
   493 			break;
   494 		}
   495 		case RRM_DebugDriver::EControlModifyProcessBreak:
   496 		{
   497 			err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
   498 			break;
   499 		}
   500 		case RRM_DebugDriver::EControlBreakInfo:
   501 		{
   502 			err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
   503 			break;
   504 		}
   505 		case RRM_DebugDriver::EControlSuspendThread:
   506 		{
   507 			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   508 			if (threadObj)
   509 			{
   510 				err = DoSuspendThread(threadObj);
   511 			}
   512 			break;
   513 		}
   514 		case RRM_DebugDriver::EControlResumeThread:
   515 		{
   516 			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   517 			if (threadObj)
   518 			{
   519 				err = DoResumeThread(threadObj);
   520 			}
   521 			break;
   522 		}
   523 		case RRM_DebugDriver::EControlStepRange:
   524 		{
   525            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   526            if (threadObj)
   527            {
   528    			err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
   529            }
   530 			break;
   531 		}
   532 		case RRM_DebugDriver::EControlReadMemory:
   533 		{
   534            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   535            if (threadObj)
   536            {
   537    			err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
   538            }
   539 			break;
   540 		}
   541 		case RRM_DebugDriver::EControlWriteMemory:
   542 		{
   543            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   544            if (threadObj)
   545            {
   546    			err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
   547            }
   548 			break;
   549 		}
   550 		case RRM_DebugDriver::EControlReadRegistersLegacy:
   551 		{
   552            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   553            if (threadObj)
   554            {
   555    			err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
   556            }
   557 			break;
   558 		}
   559 		case RRM_DebugDriver::EControlWriteRegistersLegacy:
   560 		{
   561            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   562            if (threadObj)
   563            {
   564    			err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
   565            }
   566 			break;
   567 		}
   568 		case RRM_DebugDriver::EControlReadRegisters:
   569 		{
   570            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   571            if (threadObj)
   572            {
   573    			err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
   574            }
   575 			break;
   576 		}
   577 		case RRM_DebugDriver::EControlWriteRegisters:
   578 		{
   579            threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   580            if (threadObj)
   581            {
   582    			err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
   583            }
   584 			break;
   585 		}
   586 		case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
   587 		{
   588 			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
   589 
   590 			TDebugFunctionality df;
   591 
   592 			TUint size = df.GetDebugFunctionalityBufSize();
   593 
   594 			// Return size to user-side in a safe manner
   595 			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
   596 			break;
   597 		}
   598 		case RRM_DebugDriver::EControlGetDebugFunctionality:
   599 		{
   600 			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
   601 
   602 			TDebugFunctionality df;
   603 
   604 			TUint32 dfsize = df.GetDebugFunctionalityBufSize();
   605 
   606 			// Alloc tmp buffer for Debug Functionality data
   607 			NKern::ThreadEnterCS();
   608 			TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
   609 			NKern::ThreadLeaveCS();
   610 			if (dfbuffer==NULL)
   611 			{
   612 				LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
   613 
   614 				// could not allocate memory
   615 				return KErrNoMemory;
   616 			}
   617 
   618 			// Temporary descriptor to hold DF data
   619 			TPtr8 tmpPtr(dfbuffer,0,dfsize);
   620 
   621 			// Obtain the DF data
   622 			if (df.GetDebugFunctionality(tmpPtr) )
   623 			{
   624 				// Return the DF data to the user-side
   625 				err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
   626 			}
   627 			else
   628 			{
   629 				// Failed.
   630 				err = KErrGeneral;
   631 			}
   632 
   633 			// Free tmp buffer
   634 			NKern::ThreadEnterCS();
   635 			Kern::Free(dfbuffer);
   636 			NKern::ThreadLeaveCS();
   637 			break;
   638 		}
   639 		case RRM_DebugDriver::EControlAttachProcess:
   640 		{
   641 			LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
   642 
   643 			err = AttachProcess(a1,a2);
   644 			break;
   645 		}
   646 		case RRM_DebugDriver::EControlDetachProcess:
   647 		{
   648 			LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
   649 
   650 			err = DetachProcess(a1,a2);
   651 			break;
   652 		}
   653 		case RRM_DebugDriver::EControlDetachAgent:
   654 		{
   655 			LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
   656 
   657 			err = DetachAgent(a1,a2);
   658 			break;
   659 		}
   660 		case RRM_DebugDriver::EControlSetEventAction:
   661 		{
   662 			LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
   663 
   664 			err = SetEventAction(a1,a2);
   665 			break;
   666 		}
   667 		case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
   668 		{
   669 			LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
   670 
   671 			TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
   672 
   673 			// Return size to user-side in a safe manner
   674 			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
   675 			break;
   676 		}
   677 		case RRM_DebugDriver::EControlGetList:
   678 		{
   679 			LOG_MSG("RRM_DebugDriver::EControlGetList\n");
   680 			err = GetList((TListInformation*)a1);
   681 			break;
   682 		}
   683 		case RRM_DebugDriver::EControlStep:
   684 		{
   685 			LOG_MSG("RRM_DebugDriver::EControlStep\n");
   686 
   687 			err = Step((TUint32)a1,(TUint32)a2);
   688 			break;
   689 		}
   690 		case RRM_DebugDriver::EControlKillProcess:
   691 		{
   692 			LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
   693 
   694 			err = KillProcess((TUint32)a1,(TUint32)a2);
   695 			break;
   696 		}
   697 		default:
   698 		{
   699 			err = KErrGeneral;
   700 		}
   701 	}
   702 
   703 	if (KErrNone != err)
   704 	{
   705 		LOG_MSG2("Error %d from control function", err);
   706 	}
   707 
   708    if (threadObj)
   709    {
   710        // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
   711        threadObj->Close(NULL);
   712    }
   713 
   714 	return err;
   715 }
   716 
   717 void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
   718 {
   719 	LOG_MSG("DRM_DebugChannel::HandleMsg()");
   720 
   721 	TThreadMessage& m = *(TThreadMessage*)aMsg;
   722 	TInt id = m.iValue;
   723 
   724 	if (id == (TInt)ECloseMsg)
   725 	{
   726 		if (iEventHandler)
   727 		{
   728 			iEventHandler->Stop();
   729 			iEventHandler->Close();
   730 			iEventHandler = NULL;
   731 		}
   732 		m.Complete(KErrNone, EFalse);
   733 		return;
   734 	}
   735 
   736 	if (id == KMaxTInt)
   737 	{
   738 		// DoCancel
   739 		DoCancel(m.Int0());
   740 		m.Complete(KErrNone, ETrue);
   741 		return;
   742 	}
   743 
   744 	if (id < 0)
   745 	{
   746 		// DoRequest
   747 		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   748 		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
   749 		m.Complete(KErrNone, ETrue);
   750 	}
   751 	else
   752 	{
   753 		// DoControl
   754 		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
   755 		m.Complete(err, ETrue);
   756 	}
   757 }
   758 
   759 //
   760 // DRM_DebugChannel::RemoveProcess
   761 //
   762 TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
   763 	{
   764 	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
   765 
   766 	DProcess *aProcess = (DProcess*)a1;
   767 
   768 	// Sanity check
   769 	if (!aProcess)
   770 		{
   771 		// No process was specified!
   772 		LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
   773 		return EFalse;
   774 		}
   775 
   776 	// this is called when a process dies.  we want to mark any breakpoints in this
   777 	// process space as obsolete.  the main reason for this is so we don't return
   778 	// an error when the host debugger tries to clear breakpoints for the process
   779 
   780 	TUint32 codeAddress = 0;
   781 	TUint32 codeSize = 0;
   782 
   783 	LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
   784 
   785 	DCodeSeg* codeSeg = aProcess->iCodeSeg;
   786 
   787 	if (codeSeg)
   788 		{
   789 		TModuleMemoryInfo processMemoryInfo;
   790 		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
   791 		if (err != KErrNone)
   792 			{
   793 			codeAddress = processMemoryInfo.iCodeBase;
   794 			codeSize = processMemoryInfo.iCodeSize;
   795 			}
   796 		else
   797 			{
   798 			LOG_MSG2("Error in getting memory info: %d", err);
   799 			}
   800 
   801 		}
   802 
   803 	if (!codeAddress || !codeSize)
   804 		{
   805 		LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
   806 		// make sure there is not already a breakpoint at this address
   807 		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
   808 			{
   809 			if (iDebugProcessList[i].iId == aProcess->iId)
   810 				{
   811 				codeAddress = iDebugProcessList[i].iCodeAddress;
   812 				codeSize = iDebugProcessList[i].iCodeSize;
   813 
   814 				//now remove from the list
   815 				iDebugProcessList.Remove(i);
   816 				break;
   817 				}
   818 			}
   819 		}
   820 
   821 	if (!codeAddress || !codeSize)
   822 		{
   823 		return EFalse;
   824 		}
   825 
   826 	iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
   827 	return EFalse;
   828 	}
   829 
   830 //
   831 // DRM_DebugChannel::StartThread
   832 //
   833 TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
   834 {
   835 	LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
   836 
   837 	DThread *aThread = (DThread*)a1;
   838 	if(!aThread)
   839 		{
   840 		LOG_MSG("Error getting DThread object");
   841 		__NK_ASSERT_DEBUG(aThread);
   842 		return EFalse;
   843 		}
   844 
   845 	//a2 points to the thread creating the new thread.
   846 	//We have no use for it at the moment so just ignore it for now
   847 
   848 	TDriverEventInfo info;
   849 	info.iEventType = EEventsStartThread;
   850 	info.iThreadId = aThread->iId;
   851 	info.iThreadIdValid = ETrue;
   852 	DProcess* owningProcess = aThread->iOwningProcess;
   853 	if(owningProcess)
   854 		{
   855 		info.iProcessId = owningProcess->iId;
   856 		info.iProcessIdValid = ETrue;
   857 		DCodeSeg* p = owningProcess->iCodeSeg;
   858 		if(p && p->iFileName)
   859 			{
   860 			info.iFileName.Copy(*(p->iFileName));
   861 			DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
   862 			if(foundProcess)
   863 				{
   864 				foundProcess->NotifyEvent(info);
   865 				}
   866 			else
   867 				{
   868 				LOG_EVENT_MSG2("Couldn't find process with name [%S]", p->iFileName);
   869 				}
   870 			}
   871 		else
   872 			{
   873 			if(p)
   874 				{
   875 				LOG_EVENT_MSG("\tCode segment name missing");
   876 				}
   877 			else
   878 				{
   879 				LOG_EVENT_MSG("\tCode segment is NULL");
   880 				}
   881 			}
   882 		}
   883 	return EFalse;
   884 }
   885 
   886 //
   887 // DRM_DebugChannel::HandleAddProcessEvent
   888 //
   889 TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
   890 {
   891 	LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
   892 
   893 	DProcess *aProcess = (DProcess*)a1;
   894 	// a2 points to the thread creating the new process.
   895 	DThread *aThread = (DThread*)a2;
   896 
   897 	if(!aProcess)
   898 		{
   899 		LOG_MSG("Error getting DProcess object");
   900 		__NK_ASSERT_DEBUG(aProcess);
   901 		return EFalse;
   902 		}
   903 
   904 	TDriverEventInfo info;
   905 	info.iEventType = EEventsAddProcess;
   906 	info.iProcessId = aProcess->iId;
   907 
   908     info.iCreatorThreadId  = aThread ? aThread->iId : 0;
   909 	info.iProcessIdValid = ETrue;
   910 
   911 	// Copy TUids
   912 	info.iUids = aProcess->iUids;
   913 
   914 	info.iUidsValid = ETrue;
   915 
   916 	// copy name of the process
   917 	if (aProcess->iName)
   918 		{
   919 		// copy the name of the process
   920 		info.iFileName.Copy(*aProcess->iName);
   921 
   922 		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
   923 		if(foundProcess)
   924 			{
   925 			foundProcess->NotifyEvent(info);
   926 			}
   927 		else
   928 			{
   929 			// AddProcess event does not have fully-qualified path, it has "filename.exe"
   930 			// So we try a less-precise match
   931 			DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
   932 			if(foundProcess)
   933 				{
   934 				foundProcess->NotifyEvent(info);
   935 				}
   936 			else
   937 				{
   938 				LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
   939 				}
   940 			}
   941 		}
   942 	else
   943 		{
   944 		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
   945 		}
   946 
   947 	return EFalse;
   948 }
   949 
   950 //
   951 // DRM_DebugChannel::HandleRemoveProcessEvent
   952 //
   953 TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
   954 {
   955 	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
   956 
   957 	DProcess *aProcess = (DProcess*)a1;
   958 	if(!aProcess)
   959 		{
   960 		LOG_MSG("Error getting DProcess object");
   961 		__NK_ASSERT_DEBUG(aProcess);
   962 		return EFalse;
   963 		}
   964 
   965 	// a2 points to the thread creating the new process.
   966 	// We have no use for it at the moment so just ignore it for now
   967 	// Also, it may not be known and therefore NULL
   968 
   969 	TDriverEventInfo info;
   970 	info.iEventType = EEventsRemoveProcess;
   971 	info.iProcessId = aProcess->iId;
   972 	info.iProcessIdValid = ETrue;
   973 
   974 	// copy name of the process
   975 	if (aProcess->iName)
   976 		{
   977 		// copy the name of the process
   978 		info.iFileName.Copy(*aProcess->iName);
   979 
   980 		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
   981 		if(foundProcess)
   982 			{
   983 			foundProcess->NotifyEvent(info);
   984 			}
   985 		else
   986 			{
   987 			// RemoveProcess event does not have fully-qualified path, it has "filename.exe"
   988 			// So we try a less-precise match
   989 			DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
   990 			if(foundProcess)
   991 				{
   992 				foundProcess->NotifyEvent(info);
   993 				}
   994 			else
   995 				{
   996 				LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
   997 				}
   998 			}
   999 
  1000 		}
  1001 	else
  1002 		{
  1003 		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
  1004 		}
  1005 
  1006 	return EFalse;
  1007 }
  1008 
  1009 //
  1010 // DRM_DebugChannel::AddLibrary
  1011 //
  1012 TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
  1013 {
  1014 	LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
  1015 
  1016 	DLibrary *aLibrary = (DLibrary*)a1;
  1017 	DThread *aThread = (DThread*)a2;
  1018 
  1019 	// sanity check
  1020 	if (!aLibrary)
  1021 	{
  1022 		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
  1023 		return EFalse;
  1024 	}
  1025 
  1026 	if (!aThread)
  1027 	{
  1028 		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
  1029 		return EFalse;
  1030 	}
  1031 
  1032 	LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
  1033 
  1034 	if (aThread)
  1035 	{
  1036 		// make sure this is not the debugger thread
  1037 		if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
  1038 		{
  1039 			TDriverEventInfo info;
  1040 
  1041 			info.iEventType = EEventsAddLibrary;
  1042 			info.iProcessId = aThread->iOwningProcess->iId;
  1043 			info.iProcessIdValid = ETrue;
  1044 			info.iThreadId = aThread->iId;
  1045 			info.iThreadIdValid = ETrue;
  1046 
  1047 			//get the code address
  1048 			DCodeSeg* codeSeg = aLibrary->iCodeSeg;
  1049 			if (!codeSeg)
  1050 			{
  1051 				LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
  1052 				return EFalse;
  1053 			}
  1054 
  1055 			// Uid3
  1056 			info.iUids = codeSeg->iUids;
  1057 			info.iUidsValid = ETrue;
  1058 
  1059 			TModuleMemoryInfo memoryInfo;
  1060 			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
  1061 			if (err != KErrNone)
  1062 			{
  1063 				LOG_EVENT_MSG2("Error in getting memory info: %d", err);
  1064 				return EFalse;
  1065 			}
  1066 
  1067 			info.iCodeAddress = memoryInfo.iCodeBase;
  1068 			info.iDataAddress = memoryInfo.iInitialisedDataBase;
  1069 
  1070 			info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
  1071 
  1072 			//queue up or complete the event
  1073 			info.iArg1 = a1;
  1074 			info.iArg2 = a2;
  1075 			NotifyEvent(info);
  1076 		}
  1077 
  1078 	}
  1079 	return EFalse;
  1080 }
  1081 
  1082 //
  1083 // DRM_DebugChannel::RemoveLibrary
  1084 //
  1085 TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
  1086 	{
  1087 	LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
  1088 	DLibrary *aLibrary = (DLibrary*)a1;
  1089 
  1090 	// sanity check
  1091 	if (!aLibrary)
  1092 		{
  1093 		LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
  1094 		return EFalse;
  1095 		}
  1096 
  1097 	LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
  1098 
  1099 	// this is called when all handles to this library have been closed.  this can happen when a process dies, or when a dll is
  1100 	// unloaded while the process lives on.  in former case, we don't need to notify the host debugger because that process is
  1101 	// dying anyway.  for the latter case, we do need to notify the host so it can unload the symbolics, etc.
  1102 
  1103 	DThread* aThread = &Kern::CurrentThread();
  1104 
  1105 	if ((aThread) &&
  1106 			(aThread != iClientThread) &&
  1107 			(aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
  1108 		{
  1109 		//the library gets unloaded only when the mapcount is 0.
  1110 		if (aLibrary->iMapCount != 0)
  1111 			return EFalse;
  1112 
  1113 		DCodeSeg* codeSeg = aLibrary->iCodeSeg;
  1114 		if (!codeSeg)
  1115 			{
  1116 			LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
  1117 			return EFalse;
  1118 			}
  1119 
  1120 		TModuleMemoryInfo processMemoryInfo;
  1121 		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
  1122 		if (err != KErrNone)
  1123 			{
  1124 			LOG_EVENT_MSG2("Error in getting memory info: %d", err);
  1125 			return EFalse;
  1126 			}
  1127 
  1128 		TUint32 codeAddress = processMemoryInfo.iCodeBase;
  1129 		TUint32 codeSize = processMemoryInfo.iCodeSize;
  1130 
  1131 		// first invalidate all breakpoints that were set in the library code
  1132 		iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
  1133 		DProcess *process = &Kern::CurrentProcess();
  1134 		RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
  1135 
  1136 		for (TInt j=0; j<dynamicCode->Count(); j++)
  1137 			{
  1138 			if ((*dynamicCode)[j].iLib == aLibrary)
  1139 				{
  1140 				TDriverEventInfo info;
  1141 
  1142 				info.iEventType = EEventsRemoveLibrary;
  1143 				info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
  1144 				//info.iFileName.ZeroTerminate();
  1145 				info.iProcessId = process->iId;
  1146 				info.iProcessIdValid = ETrue;
  1147 				info.iThreadId = 0xFFFFFFFF; // don't care!
  1148 				info.iThreadIdValid = EFalse;
  1149 				// Uid3
  1150 				info.iUids = codeSeg->iUids;
  1151 				info.iUidsValid = ETrue;
  1152 
  1153 				//queue up or complete the event
  1154 				info.iArg1 = a1;
  1155 				info.iArg2 = a2;
  1156 				NotifyEvent(info);
  1157 				}
  1158 			}
  1159 		}
  1160 	return EFalse;
  1161 	}
  1162 
  1163 //
  1164 // DRM_DebugChannel::HandleEventKillThread
  1165 //
  1166 TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
  1167 {
  1168 	LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
  1169 
  1170 	DThread* currentThread = &Kern::CurrentThread();
  1171 	if (!currentThread)
  1172 	{
  1173 		LOG_MSG("Error getting current thread");
  1174 		__NK_ASSERT_DEBUG(currentThread);
  1175 		return EFalse;
  1176 	}
  1177 
  1178 	// a1 should point to the current thread, check this to make sure it does
  1179 	__NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
  1180 
  1181 	TDriverEventInfo info;
  1182 
  1183 	info.iProcessId = currentThread->iOwningProcess->iId;
  1184 	info.iProcessIdValid = ETrue;
  1185 	info.iThreadId = currentThread->iId;
  1186 	info.iThreadIdValid = ETrue;
  1187 	// 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
  1188 	TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
  1189 	if(err != KErrNone)
  1190 	{
  1191 		LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
  1192 	}
  1193 
  1194 	if (currentThread->iExitType == EExitPanic)
  1195 	{
  1196 		info.iPanicCategory.Copy(currentThread->iExitCategory);
  1197 	}
  1198 	info.iExceptionNumber = currentThread->iExitReason;
  1199 	info.iExitType = currentThread->iExitType;
  1200 	info.iEventType = EEventsKillThread;
  1201 
  1202 	// Are we debugging this process - decide based on iFileName
  1203 	DCodeSeg* codeSeg = currentThread->iOwningProcess->iCodeSeg;
  1204 
  1205 	// remove all the breakpoints in this thread, whether we are debugging it or not.
  1206 	iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
  1207 
  1208 	// if the code seg exists then get the file name from it and check we're debugging it
  1209 	if(codeSeg)
  1210 		{
  1211 		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(codeSeg->iFileName));
  1212 		if(!foundProcess)
  1213 			{
  1214 			// not debugging this process so return false
  1215 			return EFalse;
  1216 			}
  1217 		}
  1218 	else
  1219 		{
  1220 		// can't validate that we are debugging the thread
  1221 		return EFalse;
  1222 		}
  1223 
  1224 	info.iArg1 = a1;
  1225 	info.iArg2 = a2;
  1226 	NotifyEvent(info);
  1227 
  1228 	return ETrue;
  1229 }
  1230 
  1231 //
  1232 // DRM_DebugChannel::HandleSwException
  1233 //
  1234 TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
  1235 {
  1236 	LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
  1237 	TExcType aExcType = (TExcType)(TInt)a1;
  1238 
  1239 	TDriverEventInfo info;
  1240 
  1241 	DThread* currentThread = &Kern::CurrentThread();
  1242 	if (!currentThread)
  1243 	{
  1244 		LOG_MSG("Error getting current thread");
  1245 		__NK_ASSERT_DEBUG(currentThread);
  1246 		return EFalse;
  1247 	}
  1248 
  1249 	info.iProcessId = currentThread->iOwningProcess->iId;
  1250 	info.iProcessIdValid = ETrue;
  1251 	info.iThreadId = currentThread->iId;
  1252 	info.iThreadIdValid = ETrue;
  1253 	TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
  1254 	if(err != KErrNone)
  1255 	{
  1256 		LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
  1257 	}
  1258 	info.iExceptionNumber = aExcType;
  1259 	info.iEventType = EEventsSwExc;
  1260 	info.iArg1 = a1;
  1261 	info.iArg2 = a2;
  1262 
  1263 	NotifyEvent(info);
  1264 
  1265 	return EFalse;
  1266 }
  1267 
  1268 //
  1269 // DRM_DebugChannel::HandleHwException
  1270 //
  1271 TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
  1272 {
  1273 	LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
  1274 	TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
  1275 
  1276 	// sanity check
  1277 	if (!aExcInfo)
  1278 	{
  1279 		LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
  1280 		__NK_ASSERT_DEBUG(aExcInfo);
  1281 		return EFalse;
  1282 	}
  1283 
  1284 	TDriverEventInfo info;
  1285 
  1286 	DThread* currentThread = &Kern::CurrentThread();
  1287 	LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
  1288 
  1289 	if (!currentThread)
  1290 	{
  1291 		LOG_MSG("Error getting current thread");
  1292 		__NK_ASSERT_DEBUG(currentThread);
  1293 		return EFalse;
  1294 	}
  1295 
  1296 	info.iProcessId = currentThread->iOwningProcess->iId;
  1297 	info.iProcessIdValid = ETrue;
  1298 	info.iThreadId = currentThread->iId;
  1299 	info.iThreadIdValid = ETrue;
  1300 	info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
  1301 	info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
  1302 	LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
  1303 			aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
  1304 
  1305 	info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
  1306 	info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
  1307 	info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
  1308 	info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
  1309 
  1310 	info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
  1311 	info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
  1312 	info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
  1313 	info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
  1314 	info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
  1315 	info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
  1316 	info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
  1317 	info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
  1318 	info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
  1319 
  1320 	info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
  1321 	info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
  1322 	info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
  1323 	LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
  1324 			aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
  1325 
  1326 	info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
  1327 	info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
  1328 	info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
  1329 	info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
  1330 	LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
  1331 			aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
  1332 
  1333 	switch (aExcInfo->iExcCode)
  1334 	{
  1335 		case 0:
  1336 			info.iExceptionNumber = EExcCodeAbort;
  1337 			LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
  1338 			break;
  1339 		case 1:
  1340 			info.iExceptionNumber = EExcDataAbort;
  1341 			LOG_EVENT_MSG(" iExcCode == 1 => EExcDataAbort");
  1342 			break;
  1343 		case 2:
  1344 			info.iExceptionNumber = EExcInvalidOpCode;
  1345 			LOG_EVENT_MSG(" iExcCode == 2 => EExcInvalidOpCode");
  1346 			break;
  1347 		default:
  1348 			// new event? Something gone wrong?
  1349 			__NK_ASSERT_DEBUG(EFalse);
  1350 			return EFalse;
  1351 
  1352 	}
  1353 	info.iEventType = EEventsHwExc;
  1354 
  1355 	info.iArg1 = a1;
  1356 	info.iArg2 = a2;
  1357 
  1358 	if(EExcInvalidOpCode == info.iExceptionNumber)
  1359 		{
  1360 		return HandleInvalidOpCodeException(info, currentThread);
  1361 		}
  1362 
  1363 	NotifyEvent(info);
  1364 	return EFalse;
  1365 }
  1366 
  1367 //
  1368 // DRM_DebugChannel::HandUserTrace
  1369 //
  1370 TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
  1371 {
  1372 	LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
  1373 
  1374 	DThread* currentThread = &Kern::CurrentThread();
  1375 	if (!currentThread)
  1376 	{
  1377 		LOG_EVENT_MSG("Error getting current thread");
  1378 		__NK_ASSERT_DEBUG(currentThread);
  1379 		return EFalse;
  1380 	}
  1381 
  1382 	TDriverEventInfo info;
  1383 	info.iProcessId = currentThread->iOwningProcess->iId;
  1384 	info.iProcessIdValid = ETrue;
  1385 	info.iThreadId = currentThread->iId;
  1386 	info.iThreadIdValid = ETrue;
  1387 	info.iEventType = EEventsUserTrace;
  1388 	info.iArg1 = a1;
  1389 	info.iArg2 = a2;
  1390 
  1391 	TInt err = KErrNone;
  1392 
  1393 	//User Trace info
  1394 	XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
  1395 	if(KErrNone != err)
  1396 		{
  1397 		return EFalse;
  1398 		}
  1399 
  1400 	info.iMessageStatus = ESingleMessage;
  1401 
  1402 	NotifyEvent(info);
  1403 
  1404 	return EFalse;
  1405 }
  1406 
  1407 //
  1408 // DRM_DebugChannel::HandleException
  1409 //
  1410 TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
  1411 {
  1412 	LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
  1413 
  1414 	TInt err = KErrNone;
  1415 
  1416 	TUint32 inst = KArmBreakPoint;
  1417 	TInt instSize = 4;
  1418 
  1419 	// change these for thumb mode
  1420 	TUint32 regValue;
  1421 	err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
  1422 	if(err != KErrNone)
  1423 	{
  1424 		LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
  1425 	}
  1426 	if (regValue & ECpuThumb)
  1427 	{
  1428 		inst = KThumbBreakPoint;
  1429 		instSize = 2;
  1430 	}
  1431 
  1432 	TUint32 instruction = 0;
  1433 	err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
  1434 
  1435 	if (KErrNone != err)
  1436 		LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
  1437 
  1438 	if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
  1439 	{
  1440 		TInt err = DoSuspendThread(aCurrentThread);
  1441 		if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
  1442 			{
  1443 			LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
  1444 			return EFalse;
  1445 			}
  1446 
  1447 		// the exception was a breakpoint instruction.  see if we have a breakpoint at that address
  1448 		TBreakEntry* breakEntry = NULL;
  1449 		do
  1450 		{
  1451 			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  1452 			if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
  1453 			{
  1454 				LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
  1455 
  1456 				TBreakEntry tempBreakEntry = *breakEntry;
  1457 
  1458 				//change the event type to breakpoint type
  1459 				aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
  1460 
  1461 				// enable any breakpoints we had to disable for this thread
  1462 				err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
  1463 				if (KErrNone != err)
  1464 					LOG_MSG2("Error %d enabling disabled breakpoints", err);
  1465 
  1466 				// see if this is a temp breakpoint
  1467 				if (iBreakManager->IsTemporaryBreak(*breakEntry))
  1468 				{
  1469 					// this was a temp breakpoint, so we need to clear it now
  1470 					err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
  1471 					if (KErrNone != err)
  1472 						LOG_MSG2("Error %d clearing temp breakpoint", err);
  1473 
  1474 					// Find out how many steps remain to be done
  1475 
  1476 					// reduce the number of steps to complete by 1
  1477 					tempBreakEntry.iNumSteps--;
  1478 
  1479 					LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
  1480 
  1481 					// New. If we have not finished do all the steps, continue stepping and don't notify event
  1482 					if (tempBreakEntry.iNumSteps)
  1483 					{
  1484 						LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
  1485 						err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
  1486 						if (err != KErrNone)
  1487 						{
  1488 							LOG_EVENT_MSG("Failed to continue stepping\n");
  1489 
  1490 							// what do we do? might as well stop here and tell the user
  1491 							NotifyEvent(aEventInfo);
  1492 
  1493 							return ETrue;
  1494 						}
  1495 
  1496 						// continue as though no event occured. No need to suspend/resume anything...
  1497 						LOG_EVENT_MSG("Continuing to step\n");
  1498 						return ETrue;
  1499 					}
  1500 
  1501 					// Is this a case where we just want to continue?
  1502 					if (tempBreakEntry.iResumeOnceOutOfRange)
  1503 					{
  1504 					LOG_EVENT_MSG("PC is out of range, continuing thread");
  1505 						DoResumeThread(aCurrentThread);
  1506 
  1507 						return ETrue;
  1508     					}
  1509 					}
  1510 
  1511 				// if the breakpoint is thread specific, make sure it's the right thread
  1512 				// if not, just continue the thread.  take special care if it's the debugger
  1513 				// thread.  if it hits a regular breakpoint, we NEVER want to stop at it.  if
  1514 				// it hits a temp breakpoint, we're probably just stepping past a real breakpoint
  1515 				// and we do need to handle it.
  1516 				TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
  1517 					(!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
  1518 
  1519 				if (needToResume)
  1520 				{
  1521 					LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
  1522 					err = DoResumeThread(aCurrentThread);
  1523 					if (KErrNone != err)
  1524 						LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
  1525 
  1526 					return EFalse;
  1527 				}
  1528 
  1529 				//normal user break point, just notify the event
  1530 				break;
  1531 			}
  1532 		} while(breakEntry);
  1533 	}
  1534 
  1535 	NotifyEvent(aEventInfo);
  1536 
  1537 	return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
  1538 }
  1539 
  1540 //
  1541 // DRM_DebugChannel::SetBreak
  1542 //
  1543 TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
  1544 {
  1545 	LOG_MSG("DRM_DebugChannel::SetBreak()");
  1546 
  1547 	TInt err = KErrNone;
  1548 
  1549 	if (!aBreakInfo)
  1550 	{
  1551 		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
  1552 		return KErrArgument;
  1553 	}
  1554 
  1555 	//User side memory is not accessible directly
  1556 	TSetBreakInfo info;
  1557 	err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
  1558 	if (err != KErrNone)
  1559 	{
  1560 		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
  1561 		return err;
  1562 	}
  1563 
  1564 	DProcess* process = NULL;
  1565 	if(info.iThreadSpecific)
  1566 		{
  1567 		// if the target thread is not suspended then return KErrInUse
  1568 		if(!TheDProcessTracker.CheckSuspended(info.iId))
  1569 			{
  1570 			LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not suspended.", info.iId);
  1571 			return KErrInUse;
  1572 			}
  1573 		DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
  1574 		if(!thread)
  1575 			{
  1576 			LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
  1577 			return KErrNotFound;
  1578 			}
  1579 		process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
  1580 		thread->Close(NULL);
  1581 		}
  1582 	else
  1583 		{
  1584 		process = DebugUtils::OpenProcessHandle(info.iId);
  1585 		}
  1586 	if(!process)
  1587 		{
  1588 		LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
  1589 		return KErrNotFound;
  1590 		}
  1591 	TBool found = EFalse;
  1592 	for(TInt i=0; i<iDebugProcessList.Count(); i++)
  1593 		{
  1594 		if(process->iId == iDebugProcessList[i].iId)
  1595 			{
  1596 			found = ETrue;
  1597 			}
  1598 		}
  1599 	if(!found)
  1600 		{
  1601 		DCodeSeg* codeSeg = process->iCodeSeg;
  1602 		if (!codeSeg)
  1603 			{
  1604 			LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
  1605 			return KErrNotFound;
  1606 			}
  1607 
  1608 		TModuleMemoryInfo memoryInfo;
  1609 		TInt err = codeSeg->GetMemoryInfo(memoryInfo, process);
  1610 		if (err != KErrNone)
  1611 			{
  1612 			LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
  1613 			return err;
  1614 			}
  1615 
  1616 		//add this process to the list of processes that we are debugging
  1617 		TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
  1618 		iDebugProcessList.Append(processInfo);
  1619 		process->Close(NULL);
  1620 		}
  1621 
  1622 	if (!info.iBreakId) //first check if the iId address is valid
  1623 		return KErrArgument;
  1624 
  1625 	if (err == KErrNone)
  1626 	{
  1627 		TInt32 iBreakId;
  1628 
  1629 		err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
  1630 
  1631 		if (err == KErrNone)
  1632 		{
  1633 			err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
  1634 		}
  1635 	}
  1636 	return err;
  1637 }
  1638 
  1639 //
  1640 // DRM_DebugChannel::StepRange
  1641 //
  1642 TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
  1643 {
  1644 	LOG_MSG("DRM_DebugChannel::StepRange()");
  1645 
  1646 	TInt err = KErrNone;
  1647 
  1648 	if(!TheDProcessTracker.CheckSuspended(aThread))
  1649 		{
  1650 		LOG_MSG2("DRM_DebugChannel::StepRange() Thread with id 0x%08x not suspended.", aThread->iId);
  1651 		return KErrInUse;
  1652 		}
  1653 
  1654 	if (!aStepInfo)
  1655 		return KErrArgument;
  1656 
  1657 	TRM_DebugStepInfo info(0, 0, 0);
  1658 	err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
  1659 
  1660 	if (err != KErrNone)
  1661 		return err;
  1662 
  1663 	err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
  1664 
  1665 	return err;
  1666 }
  1667 
  1668 /**
  1669 Read memory from a target thread and return the data to the client. If the
  1670 memory block has breakpoints in it then the correct values are placed in the
  1671 returned data
  1672 
  1673 @param aThread pointer to thread whose memory space the memory is to be read from
  1674 @param aMemoryInfo information about what memory to read
  1675 
  1676 @return KErrNone if memory read successfully,
  1677         KErrArgument if aMemoryInfo is not initialised correctly,
  1678         KErrNoMemory if a temporary buffer could not be allocated,
  1679         KErrBadHandle if aThread is invalid,
  1680         or another of the system wide error codes
  1681 */
  1682 TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
  1683 {
  1684 	LOG_MSG("DRM_DebugChannel::ReadMemory()");
  1685 
  1686 	TInt err = KErrNone;
  1687 
  1688 	if (!aMemoryInfo)
  1689 		return KErrArgument;
  1690 
  1691 	TRM_DebugMemoryInfo info(0, 0, 0);
  1692 	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
  1693 	if (err != KErrNone)
  1694 		return err;
  1695 
  1696 	if (!info.iData)
  1697 		return KErrArgument;
  1698 
  1699 	NKern::ThreadEnterCS();
  1700 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
  1701 	NKern::ThreadLeaveCS();
  1702 	if (!data)
  1703 	{
  1704 		return KErrNoMemory;
  1705 	}
  1706 
  1707 	TPtr8 dataDes(data, info.iLength);
  1708 
  1709 	err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
  1710 	if (err == KErrNone)
  1711 		{
  1712 		err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
  1713 		}
  1714 
  1715 	NKern::ThreadEnterCS();
  1716 	Kern::Free(data);
  1717 	NKern::ThreadLeaveCS();
  1718 
  1719 	return err;
  1720 }
  1721 
  1722 /**
  1723 Attempt to write memory to aThread's address space
  1724 
  1725 @param aThread thread to whose address space memory is to be written
  1726 @param aMemoryInfo memory info object representing the data to write
  1727 
  1728 @return KErrNone if memory written successfully,
  1729         KErrNoMemory if memory could not be allocated
  1730         KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
  1731         if aMemoryInfo.iLength is greater than than the length of the passed
  1732         in descrptor
  1733         KErrBadHandle if aThread is invalid,
  1734 	or another of the system wide error codes
  1735 */
  1736 TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
  1737 {
  1738 	LOG_MSG("DRM_DebugChannel::WriteMemory()");
  1739 
  1740 	TInt err = KErrNone;
  1741 
  1742 	if (!aMemoryInfo)
  1743 		return KErrArgument;
  1744 
  1745 	TRM_DebugMemoryInfo info(0, 0, 0);
  1746 	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
  1747 	if (err != KErrNone)
  1748 		return err;
  1749 
  1750 	if (!info.iData)
  1751 		return KErrArgument;
  1752 
  1753 	NKern::ThreadEnterCS();
  1754 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
  1755 	NKern::ThreadLeaveCS();
  1756 	if (!data)
  1757 	{
  1758 		return KErrNoMemory;
  1759 	}
  1760 
  1761 	TPtr8 dataDes(data, info.iLength);
  1762 
  1763 	err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
  1764 	if (err == KErrNone)
  1765 	{
  1766 		err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
  1767 	}
  1768 
  1769 	NKern::ThreadEnterCS();
  1770 	Kern::Free(data);
  1771 	NKern::ThreadLeaveCS();
  1772 
  1773 	return err;
  1774 }
  1775 
  1776 //
  1777 // DRM_DebugChannel::ReadRegisters
  1778 //
  1779 TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
  1780 {
  1781 	LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
  1782 
  1783 	TInt err = KErrNone;
  1784 
  1785 	if (!aRegisterInfo)
  1786 		return KErrArgument;
  1787 
  1788 	TRM_DebugRegisterInfo info(0, 0, 0);
  1789 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
  1790 	if (err != KErrNone)
  1791 		return err;
  1792 
  1793 	if (!info.iValues)
  1794 		return KErrArgument;
  1795 
  1796 	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
  1797 
  1798 	NKern::ThreadEnterCS();
  1799 	TUint8 *values = (TUint8*)Kern::Alloc(length);
  1800 	NKern::ThreadLeaveCS();
  1801 	if (!values)
  1802 	{
  1803 		return KErrNoMemory;
  1804 	}
  1805 
  1806 	TPtr8 valuesDes(values, length);
  1807 
  1808 	err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
  1809 	if (err == KErrNone)
  1810 	{
  1811 		err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
  1812 	}
  1813 
  1814 	NKern::ThreadEnterCS();
  1815 	Kern::Free(values);
  1816 	NKern::ThreadLeaveCS();
  1817 
  1818 	return err;
  1819 }
  1820 
  1821 /**
  1822 Get listing information.
  1823 
  1824 @param aListInformation pointer to a TListInformation object containing the
  1825        user specified listings information
  1826 
  1827 @return KErrNone on success,
  1828         KErrTooBig if the kernel's data is too big to fit in the passed buffer,
  1829         KErrArgument if aListInformation is NULL,
  1830 	or one of the other system-wide error codes
  1831 */
  1832 TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
  1833 	{
  1834 	LOG_MSG("DRM_DebugChannel::GetList()");
  1835 
  1836 	TInt err = KErrNone;
  1837 
  1838 	if(aListInformation == NULL)
  1839 		{
  1840 		return KErrArgument;
  1841 		}
  1842 
  1843 	//read DSS' data into local structure
  1844 	TListInformation info;
  1845 	err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
  1846 	if(err != KErrNone)
  1847 		{
  1848 		return err;
  1849 		}
  1850 
  1851 	//check arguments
  1852 	TPtr8 buffer(NULL, 0);
  1853 	err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
  1854 	if(err != KErrNone)
  1855 		{
  1856 		//need to free the buffer if it was allocated
  1857 		if(err != KErrNoMemory)
  1858 			{
  1859 			NKern::ThreadEnterCS();
  1860 			Kern::Free((TAny*)buffer.Ptr());
  1861 			NKern::ThreadLeaveCS();
  1862 			}
  1863 		return err;
  1864 		}
  1865 
  1866 	//get the list
  1867 	TUint32 dataSize = 0;
  1868 	TListManager manager;
  1869 	err = KErrArgument;
  1870 	switch(info.iType)
  1871 		{
  1872 		case EXipLibraries:
  1873 			if(Debug::EScopeGlobal == info.iListScope)
  1874 				{
  1875 				err = manager.GetXipLibrariesList(buffer, dataSize);
  1876 				}
  1877 			break;
  1878 
  1879 		case EThreads:
  1880 			if(Debug::EScopeGlobal == info.iListScope)
  1881 				{
  1882 				err = manager.GetGlobalThreadList(buffer, dataSize);
  1883 				}
  1884 			else if(Debug::EScopeProcessSpecific == info.iListScope)
  1885 				{
  1886 				err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
  1887 				}
  1888 			else if(Debug::EScopeThreadSpecific == info.iListScope)
  1889 				{
  1890 				err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
  1891 				}
  1892 			break;
  1893 
  1894 		case EProcesses:
  1895 			if(Debug::EScopeGlobal == info.iListScope)
  1896 				{
  1897 				err = manager.GetProcessList(buffer, dataSize);
  1898 				}
  1899 			break;
  1900 
  1901 		case ECodeSegs:
  1902 			if(Debug::EScopeGlobal == info.iListScope)
  1903 				{
  1904 				err = manager.GetGlobalCodeSegList(buffer, dataSize);
  1905 				}
  1906 			else if(Debug::EScopeProcessSpecific == info.iListScope)
  1907 				{
  1908 				err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
  1909 				}
  1910 			else if(Debug::EScopeThreadSpecific == info.iListScope)
  1911 				{
  1912 				err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
  1913 				}
  1914 			break;
  1915 
  1916 		default:
  1917 			err = KErrNotSupported;
  1918 		}
  1919 
  1920 	if(err == KErrNone)
  1921 		{
  1922 		//if no error then write the buffer back
  1923 		err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
  1924 		}
  1925 	//write back the size of the data regardless of any error
  1926 	TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
  1927 	if(writeErr != KErrNone)
  1928 		{
  1929 		//if there was an error writing the size return that error instead
  1930 		err = writeErr;
  1931 		}
  1932 
  1933 	//free the buffer
  1934 	NKern::ThreadEnterCS();
  1935 	Kern::Free((TAny*)buffer.Ptr());
  1936 	NKern::ThreadLeaveCS();
  1937 
  1938 	return err;
  1939 	}
  1940 
  1941 /**
  1942 Read registers and store register data in aRegisterInfo
  1943 
  1944 @param aThread thread to read registers from
  1945 @param aRegisterInfo structure specifying which registers to read and providing
  1946        descriptors to write the register data into
  1947 
  1948 @return KErrNone if registers were read successfully. Note that this does not
  1949         mean that all the registers could be read, the
  1950         aRegisterInfo.iRegisterFlags array should be checked as to whether each
  1951         individual register could be read,
  1952         KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
  1953         are members of aRegisterInfo are NULL, if an unknown register is
  1954         specified or if the passed in register values buffer is too small
  1955         KErrNoMemory if there is insufficient memory,
  1956         KErrDied, if the thread with thread ID aThreadId is dead
  1957 */
  1958 TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
  1959 {
  1960 	LOG_MSG("DRM_DebugChannel::ReadRegisters()");
  1961 
  1962 	TInt err = KErrNone;
  1963 
  1964 	if (!aRegisterInfo)
  1965 		return KErrArgument;
  1966 
  1967 	TRM_DebugRegisterInformation info;
  1968 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
  1969 	if (err != KErrNone)
  1970 		return err;
  1971 
  1972 	if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
  1973 		return KErrArgument;
  1974 
  1975 	//read ids from client thread
  1976 	TPtr8 ids(NULL, 0);
  1977 	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
  1978 	if(err != KErrNone)
  1979 		{
  1980 		if(err == KErrNoMemory)
  1981 		{
  1982 			NKern::ThreadEnterCS();
  1983 			Kern::Free((TAny*)ids.Ptr());
  1984 			NKern::ThreadLeaveCS();
  1985 		}
  1986 		return err;
  1987 		}
  1988 
  1989 	//read values from client thread
  1990 	TPtr8 values(NULL, 0);
  1991 	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
  1992 	if(err != KErrNone)
  1993 		{
  1994 		if(err == KErrNoMemory)
  1995 		{	NKern::ThreadEnterCS();
  1996 			Kern::Free((TAny*)values.Ptr());
  1997 			NKern::ThreadLeaveCS();
  1998 		}
  1999 		NKern::ThreadEnterCS();
  2000 		Kern::Free((TAny*)ids.Ptr());
  2001 		NKern::ThreadLeaveCS();
  2002 		return err;
  2003 		}
  2004 
  2005 	//read flags from client thread
  2006 	TPtr8 flags(NULL, 0);
  2007 	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
  2008 	if(err != KErrNone)
  2009 		{
  2010 		if(err == KErrNoMemory)
  2011 		{
  2012 			NKern::ThreadEnterCS();
  2013 			Kern::Free((TAny*)flags.Ptr());
  2014 			NKern::ThreadLeaveCS();
  2015 		}
  2016 		NKern::ThreadEnterCS();
  2017 		Kern::Free((TAny*)ids.Ptr());
  2018 		Kern::Free((TAny*)values.Ptr());
  2019 		NKern::ThreadLeaveCS();
  2020 		return err;
  2021 		}
  2022 
  2023 	err = DoReadRegisters(aThread, ids, values, flags);
  2024 	if (err == KErrNone)
  2025 		{
  2026 		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
  2027 		if(err == KErrNone)
  2028 			{
  2029 			err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
  2030 			}
  2031 		}
  2032 
  2033 	NKern::ThreadEnterCS();
  2034 	Kern::Free((TAny*)ids.Ptr());
  2035 	Kern::Free((TAny*)values.Ptr());
  2036 	Kern::Free((TAny*)flags.Ptr());
  2037 	NKern::ThreadLeaveCS();
  2038 
  2039 	return err;
  2040 }
  2041 
  2042 /**
  2043 @deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
  2044 */
  2045 TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
  2046 {
  2047 	LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
  2048 
  2049 	TInt err = KErrNone;
  2050 
  2051 	if (!aRegisterInfo)
  2052 		return KErrArgument;
  2053 
  2054 	TRM_DebugRegisterInfo info(0, 0, 0);
  2055 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
  2056 	if (err != KErrNone)
  2057 		return err;
  2058 
  2059 	if (!info.iValues)
  2060 		return KErrArgument;
  2061 
  2062 	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
  2063 
  2064 	NKern::ThreadEnterCS();
  2065 	TUint8 *values = (TUint8*)Kern::Alloc(length);
  2066 	NKern::ThreadLeaveCS();
  2067 	if (!values)
  2068 	{
  2069 		return KErrNoMemory;
  2070 	}
  2071 
  2072 	TPtr8 valuesDes(values, length);
  2073 
  2074 	err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
  2075 	if (err == KErrNone)
  2076 	{
  2077 		err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
  2078 	}
  2079 
  2080 	NKern::ThreadEnterCS();
  2081 	Kern::Free(values);
  2082 	NKern::ThreadLeaveCS();
  2083 
  2084 	return err;
  2085 }
  2086 
  2087 /**
  2088 Write registers and store flags data in aRegisterInfo
  2089 
  2090 @param aThread thread to write registers to
  2091 @param aRegisterInfo structure specifying which registers to write and providing
  2092        descriptors to write the register flags data into
  2093 
  2094 @return KErrNone if registers were written successfully. Note that this does not
  2095         mean that all the registers could be written, the flags array
  2096         should be checked as to whether each individual register could be read,
  2097         KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
  2098         are members of aRegisterInfo are NULL, if an unknown register is
  2099         specified or if the passed in register values buffer is too small, or
  2100         if aThread is NULL,
  2101         KErrGeneral if there was a problem initialising the register set,
  2102         KErrNoMemory if there is insufficient memory,
  2103         KErrDied, if the thread with thread ID aThreadId is dead
  2104 */
  2105 TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
  2106 {
  2107 	LOG_MSG("DRM_DebugChannel::WriteRegisters()");
  2108 
  2109 	TInt err = KErrNone;
  2110 
  2111 	if (!aRegisterInfo)
  2112 		return KErrArgument;
  2113 
  2114 	TRM_DebugRegisterInformation info;
  2115 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
  2116 	if (err != KErrNone)
  2117 		return err;
  2118 
  2119 	if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
  2120 		return KErrArgument;
  2121 
  2122 	//read ids from client thread
  2123 	TPtr8 ids(NULL, 0);
  2124 	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
  2125 	if(err != KErrNone)
  2126 		{
  2127 		if(err == KErrNoMemory)
  2128 			{
  2129 			NKern::ThreadEnterCS();
  2130 			Kern::Free((TAny*)ids.Ptr());
  2131 			NKern::ThreadLeaveCS();
  2132 			}
  2133 		return err;
  2134 		}
  2135 
  2136 	//read values from client thread
  2137 	TPtr8 values(NULL, 0);
  2138 	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
  2139 	if(err != KErrNone)
  2140 		{
  2141 		if(err == KErrNoMemory)
  2142 			{
  2143 			NKern::ThreadEnterCS();
  2144 			Kern::Free((TAny*)values.Ptr());
  2145 			NKern::ThreadLeaveCS();
  2146 			}
  2147 		NKern::ThreadEnterCS();
  2148 		Kern::Free((TAny*)ids.Ptr());
  2149 		NKern::ThreadLeaveCS();
  2150 		return err;
  2151 		}
  2152 
  2153 	//read flags from client thread
  2154 	TPtr8 flags(NULL, 0);
  2155 	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
  2156 	if(err != KErrNone)
  2157 		{
  2158 		if(err == KErrNoMemory)
  2159 			{
  2160 			NKern::ThreadEnterCS();
  2161 			Kern::Free((TAny*)flags.Ptr());
  2162 			NKern::ThreadLeaveCS();
  2163 			}
  2164 		NKern::ThreadEnterCS();
  2165 		Kern::Free((TAny*)ids.Ptr());
  2166 		Kern::Free((TAny*)values.Ptr());
  2167 		NKern::ThreadLeaveCS();
  2168 		return err;
  2169 		}
  2170 
  2171 	err = DoWriteRegisters(aThread, ids, values, flags);
  2172 	if(err == KErrNone)
  2173 		{
  2174 		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
  2175 		}
  2176 
  2177 	NKern::ThreadEnterCS();
  2178 	Kern::Free((TAny*)ids.Ptr());
  2179 	Kern::Free((TAny*)values.Ptr());
  2180 	Kern::Free((TAny*)flags.Ptr());
  2181 	NKern::ThreadLeaveCS();
  2182 
  2183 	return err;
  2184 }
  2185 
  2186 /**
  2187 Suspends execution of the specified thread.
  2188 
  2189 @param aThread thread to resume
  2190 
  2191 @return KErrNone if there were no problems or KErrArgument if aThread is NULL
  2192 */
  2193 TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
  2194 	{
  2195 	LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
  2196 
  2197 	if (!aThread)
  2198 		{
  2199 		LOG_MSG("Invalid dthread object");
  2200 		return KErrArgument;
  2201 		}
  2202 
  2203 	return TheDProcessTracker.SuspendThread(aThread);
  2204 	}
  2205 
  2206 /**
  2207 Resumes execution of the specified thread.
  2208 
  2209 @param aThread thread to resume
  2210 
  2211 @return KErrNone if there were no problems, KErrArgument if aThread is NULL
  2212         or an error value returned from DoStepRange()
  2213 */
  2214 TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
  2215 	{
  2216 	LOG_MSG("DRM_DebugChannel::DoResumeThread()");
  2217 
  2218 	if (!aThread)
  2219 		return KErrArgument;
  2220 
  2221 	// get the current PC
  2222 	TUint32 currentPC;
  2223 	TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
  2224 	if(err != KErrNone)
  2225 		{
  2226 		LOG_MSG2("DRM_DebugChannel::DoResumeThread - Non-zero error code discarded: %d", err);
  2227 		}
  2228 
  2229 	// if there is a breakpoint at the current PC, we need to single step past it
  2230 	TBreakEntry* breakEntry = NULL;
  2231 	do
  2232 		{
  2233 		breakEntry = iBreakManager->GetNextBreak(breakEntry);
  2234 		if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  2235 			{
  2236 			if (breakEntry->iAddress == currentPC)
  2237 				{
  2238 				return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
  2239 				}
  2240 			}
  2241 		} while(breakEntry);
  2242 	return TheDProcessTracker.ResumeThread(aThread);
  2243 	}
  2244 
  2245 //
  2246 // DRM_DebugChannel::DoStepRange
  2247 //
  2248 TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
  2249 {
  2250 	LOG_MSG("DRM_DebugChannel::DoStepRange()");
  2251 
  2252 	if (!aThread)
  2253 		return KErrArgument;
  2254 
  2255 	//check that the thread is suspended
  2256 	if(!TheDProcessTracker.CheckSuspended(aThread))
  2257 		{
  2258 		LOG_MSG2("DRM_DebugChannel::DoStepRange() Thread with id 0x%08x not suspended.", aThread->iId);
  2259 		return KErrInUse;
  2260 		}
  2261 
  2262 	TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
  2263 	TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
  2264 
  2265 	// don't allow the user to step in the excluded ROM region.  this could be called
  2266 	// internally however.  for example, the the special breakpoints we set to handle
  2267 	// panics, exceptions, and library loaded events are in the user library, and we
  2268 	// will need to step past the breakpoint before continuing the thread.
  2269 	//if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
  2270 	//{
  2271 	//	return KErrNotSupported;
  2272 	//}
  2273 
  2274 	// set the temp breakpoint, and disable the breakpoint at the current PC if necessary
  2275 	// if its not a user request, and we are just trying to resume from a breakpoint,
  2276 	// then we don't need to check for stubs. The last parameter aUserRequest tells
  2277 	// ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
  2278 	// is true even if its not a user request.For example, this is true in cases where
  2279 	// we are doing a step range and the instruction in the range modified PC.
  2280 	// in this case, DoStepRange will be called from the exception handler where
  2281 	// we need to check for the stubs for the valid behavior. So truly, we don't need to check
  2282 	// for stubs only when resuming from  a breakpoint.
  2283 	ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
  2284 
  2285 	LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
  2286 
  2287 	return TheDProcessTracker.ResumeThread(aThread);
  2288 }
  2289 
  2290 /**
  2291 Read memory from the specified addres into the aData descriptor. If there is a
  2292 breakpoint set in the region of memory returned then the correct data value is
  2293 inserted into the descriptor
  2294 
  2295 @param aThread pointer to thread whose address space memory is to be read from
  2296 @param aAddress address to start reading memory from
  2297 @param aLength length of memory block to read
  2298 @param aData descriptor to read memory into
  2299 
  2300 @return KErrNone if memory read successfully,
  2301         KErrNotSupported if reading from the rom section is not supported,
  2302         KErrBadHandle if aThread is invalid,
  2303         or one of the other system wide error codes
  2304 */
  2305 TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
  2306 	{
  2307 	LOG_MSG("DRM_DebugChannel::DoReadMemory()");
  2308 
  2309 	// make sure the parameters are valid
  2310 	if (aLength > aData.MaxSize())
  2311 		return KErrArgument;
  2312 
  2313 	TInt err = KErrNone;
  2314 
  2315 	// trap exceptions in case the address is invalid
  2316 	XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
  2317 
  2318 	err = (KErrNone == r) ? err : r;
  2319 
  2320 	if (KErrNone == err)
  2321 		{
  2322 		aData.SetLength(aLength);
  2323 
  2324 		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
  2325 
  2326 		// if we have any breakpoints in this range, put the actual instruction in the buffer
  2327 		TBreakEntry* breakEntry = NULL;
  2328 		do
  2329 			{
  2330 			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  2331 			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  2332 				{
  2333 				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
  2334 					{
  2335 					TInt instSize;
  2336 
  2337 					switch(breakEntry->iMode)
  2338 						{
  2339 						case EArmMode:
  2340 							instSize = 4;
  2341 							break;
  2342 
  2343 						case EThumbMode:
  2344 							instSize = 2;
  2345 							break;
  2346 
  2347 						case EThumb2EEMode:
  2348 						default:
  2349 							LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
  2350 							return KErrNotSupported;
  2351 						}
  2352 					memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
  2353 					}
  2354 				}
  2355 			} while(breakEntry);
  2356 		}
  2357 
  2358 	return err;
  2359 	}
  2360 
  2361 /**
  2362 Attempt to write memory to aThread's address space
  2363 
  2364 @param aThread thread to whose address space memory is to be written
  2365 @param aAddress memory location to write memory to
  2366 @param aLength number of bytes of data to write
  2367 @param aData descriptor containing memory to write
  2368 
  2369 @return KErrNone if memory written successfully,
  2370         KErrArgument if aLength is greater than than the length of the aData
  2371         KErrBadHandle if aThread is invalid,
  2372 	or another of the system wide error codes
  2373 */
  2374 TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
  2375 	{
  2376 	LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
  2377 
  2378 	// make sure the parameters are valid
  2379 	if (aLength > aData.Length())
  2380 		return KErrArgument;
  2381 
  2382 	TInt err = KErrNone;
  2383 
  2384 	// trap exceptions in case the address is invalid
  2385 	XTRAPD(r, XT_DEFAULT,  err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
  2386 
  2387 	err = (KErrNone == r) ? err : r;
  2388 
  2389 	// reset any breakpoints we may have just overwritten
  2390 	if (KErrNone == err)
  2391 		{
  2392 		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
  2393 
  2394 		TBreakEntry* breakEntry = NULL;
  2395 		do
  2396 			{
  2397 			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  2398 			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  2399 				{
  2400 				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
  2401 					{
  2402 					// default to arm mode
  2403 					TUint32 inst;
  2404 					TInt instSize;
  2405 
  2406 					switch (breakEntry->iMode)
  2407 						{
  2408 						case EArmMode:
  2409 							inst = KArmBreakPoint;
  2410 							instSize = 4;
  2411 							break;
  2412 
  2413 						case EThumbMode:
  2414 							inst = KThumbBreakPoint;
  2415 							instSize = 2;
  2416 							break;
  2417 
  2418 						case EThumb2EEMode:
  2419 						default:
  2420 							LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
  2421 
  2422 							return KErrNotSupported;
  2423 						}
  2424 
  2425 					breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
  2426 					memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
  2427 					}
  2428 				}
  2429 
  2430 			} while(breakEntry);
  2431 		}
  2432 	return err;
  2433 	}
  2434 
  2435 //
  2436 // DRM_DebugChannel::DoReadRegisters
  2437 //
  2438 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
  2439 {
  2440 	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
  2441 
  2442 	// make sure the parameters are valid
  2443 	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  2444 		return KErrArgument;
  2445 
  2446 	// make sure the descriptor is big enough to hold the requested data
  2447 	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
  2448 		return KErrArgument;
  2449 
  2450 	TArmRegSet regSet;
  2451     TUint32 unused;
  2452 
  2453 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  2454 
  2455 	LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
  2456 
  2457     TArmReg *reg = &regSet.iR0;
  2458 
  2459 	if (!reg)
  2460 		return KErrGeneral;
  2461 
  2462     for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
  2463     	aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
  2464 
  2465 	return KErrNone;
  2466 }
  2467 
  2468 /**
  2469   @prototype
  2470 
  2471   Experimental function for determining whether a thread is suspended.
  2472 
  2473   @param aThread thread to check if suspended
  2474 
  2475   @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
  2476   */
  2477 TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
  2478 	{
  2479 	if(!aThread)
  2480 		{
  2481 		return EFalse;
  2482 		}
  2483 
  2484 	if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
  2485 		{
  2486 		return ETrue;
  2487 		}
  2488 
  2489 	if(aThread->iNThread.iSuspendCount > 0)
  2490 		{
  2491 		return ETrue;
  2492 		}
  2493 	return EFalse;
  2494 	}
  2495 
  2496 /**
  2497 Read registers and store register values in aRegisterValues and the flags
  2498 indicating which registers could be read in aRegisterFlags
  2499 
  2500 @param aThread thread to read registers from
  2501 @param aRegisterIds array containing register IDs to read
  2502 @param aRegisterValues array to store register values in
  2503 @param aRegisterFlags array to store flags in
  2504 
  2505 @return KErrNone if registers were read successfully. Note that this does not
  2506         mean that all the registers could be read, the aRegisterFlags array
  2507         should be checked as to whether each individual register could be read,
  2508         KErrArgument if aThread is NULL, if an unknown register is specified in
  2509         aRegisterValues or if aRegisterValues is too small
  2510         KErrGeneral if there was a problem initialising the register set
  2511 */
  2512 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
  2513 {
  2514 	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
  2515 
  2516 	// make sure the parameters are valid
  2517 	if (!aThread)
  2518 		return KErrArgument;
  2519 
  2520 	//Need to revisit this to determine whether there is a way to validate this
  2521 #if 0
  2522 	if ( !CheckSuspended(aThread) )
  2523 		{
  2524 		LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
  2525 		return KErrInUse;
  2526 		}
  2527 #endif
  2528 
  2529 	//set lengths of output descriptors to 0 prior to filling
  2530 	aRegisterValues.SetLength(0);
  2531 	aRegisterFlags.SetLength(0);
  2532 
  2533 	TArmRegSet regSet;
  2534 	TUint32 flags;
  2535 
  2536 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
  2537 
  2538 	LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
  2539 
  2540 	TArmReg *regPtr = &regSet.iR0;
  2541 
  2542 	if (!regPtr)
  2543 		return KErrGeneral;
  2544 
  2545 	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
  2546 
  2547 	//iterate through registers setting the relevant aFlags value
  2548 	for(TUint i=0; i<numberOfRegisters; i++)
  2549 		{
  2550 		//get current register id
  2551 		TRegisterInfo reg;
  2552 		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
  2553 		//exit with the error value if there was an error
  2554 		if(err != KErrNone)
  2555 			return err;
  2556 
  2557 		//if unknown register then exit as can't know how many bytes this entry will
  2558 		//represent in aRegisterValues
  2559 		TTag registerTag;
  2560 		TDebugFunctionality::GetRegister(reg, registerTag);
  2561 		if(registerTag.iValue == EAccessUnknown)
  2562 			{
  2563 			return KErrArgument;
  2564 			}
  2565 
  2566 		//get the current register id as a kernel register
  2567 		TArmReg armReg;
  2568 		err = GetKernelRegisterId(reg, armReg);
  2569 		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
  2570 			{
  2571 			//reading this register is not supported
  2572 			aRegisterFlags.Append(ENotSupported);
  2573 			//just skip over this entry in the values buffer
  2574 			if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
  2575 				{
  2576 				//writing this value would cause overflow so exit
  2577 				return KErrArgument;
  2578 				}
  2579 			aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
  2580 			}
  2581 		else
  2582 			{
  2583 			if(registerTag.iSize == sizeof(TArmReg))
  2584 				{
  2585 				if(GetFlagAtOffset(flags, armReg))
  2586 					{
  2587 					//set flag as valid
  2588 					aRegisterFlags.Append(EValid);
  2589 					}
  2590 				else
  2591 					{
  2592 					// Even though the flag is invalid, we can return the value of the register
  2593 					// and let the user decide what to do
  2594 					aRegisterFlags.Append(EInValid);
  2595 					}
  2596 
  2597 				if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
  2598 					{
  2599 					//writing this value would cause overflow so exit
  2600 					return KErrArgument;
  2601 					}
  2602 				//write value into register into regSet
  2603 				aRegisterValues.Append((TUint8 *)&regPtr[armReg], registerTag.iSize);
  2604 				}
  2605 			else
  2606 				{
  2607 				//currently all kernel supported registers are 4 bytes so
  2608 				//return EBadSize. Would need updating if/when other register
  2609 				//value sizes are supported
  2610 				aRegisterFlags.Append(EBadSize);
  2611 				aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
  2612 				}
  2613 			}
  2614 		}
  2615 	return KErrNone;
  2616 }
  2617 
  2618 //
  2619 // DRM_DebugChannel::DoWriteRegisters
  2620 //
  2621 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
  2622 {
  2623 	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
  2624 
  2625 	// make sure the parameters are valid
  2626 	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  2627 		return KErrArgument;
  2628 
  2629 	// make sure the descriptor is big enough to hold the data to write
  2630 	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
  2631 		return KErrArgument;
  2632 
  2633 	TArmRegSet regSet;
  2634 	TUint32 unused;
  2635 
  2636 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  2637 
  2638 	TArmReg *reg = &regSet.iR0;
  2639 
  2640 	for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
  2641 		reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
  2642 
  2643 	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
  2644 
  2645 	return KErrNone;
  2646 }
  2647 
  2648 /**
  2649 Write registers and store flags indicating which registers could be read in
  2650 aRegisterFlags
  2651 
  2652 @param aThread thread to write registers to
  2653 @param aRegisterIds array containing register IDs to write
  2654 @param aRegisterValues array containing register values to write
  2655 @param aRegisterFlags array to store flags in
  2656 
  2657 @return KErrNone if registers were written successfully. Note that this does not
  2658         mean that all the registers could be written, the aRegisterFlags array
  2659         should be checked as to whether each individual register could be read,
  2660         KErrArgument if aThread is NULL, if the buffer passed in as
  2661         aRegisterValue is too small, or if an unknown register is requested,
  2662         KErrGeneral if there was a problem initialising the register set
  2663 */
  2664 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
  2665 {
  2666 	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
  2667 
  2668 	// make sure the parameters are valid
  2669 	if (!aThread)
  2670 		return KErrArgument;
  2671 
  2672 	//check that the thread is suspended before reading the registers
  2673 	if(!TheDProcessTracker.CheckSuspended(aThread))
  2674 		{
  2675 		LOG_MSG2("DRM_DebugChannel::DoWriteRegisters() thread with id 0x%08x is not suspended", aThread->iId);
  2676 		return KErrInUse;
  2677 		}
  2678 
  2679 	//get register values from kernel
  2680 	TArmRegSet regSet;
  2681 	TUint32 flags;
  2682 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
  2683 
  2684 	//set lengths of output descriptors to 0 prior to filling
  2685 	aRegisterFlags.SetLength(0);
  2686 
  2687 	//pointer to first kernel register
  2688 	TArmReg *regPtr = &regSet.iR0;
  2689 
  2690 	if (!regPtr)
  2691 		return KErrGeneral;
  2692 
  2693 	//calculate number of registers
  2694 	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
  2695 
  2696 	//iterate through registers setting the relevant aRegisterFlags value and
  2697 	//setting the necessary value in regSet ready to write to kernel
  2698 	for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
  2699 		{
  2700 		//get current register id
  2701 		TRegisterInfo reg;
  2702 		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
  2703 		//exit with the error value if there was an error
  2704 		if(err != KErrNone)
  2705 			{
  2706 			return err;
  2707 			}
  2708 
  2709 		//if unknown register then exit as can't know how many bytes this entry will
  2710 		//represent in aRegisterValues
  2711 		TTag registerTag;
  2712 		TDebugFunctionality::GetRegister(reg, registerTag);
  2713 		if(registerTag.iValue == EAccessUnknown)
  2714 			{
  2715 			return KErrArgument;
  2716 			}
  2717 
  2718 		//get the current register id as a kernel register
  2719 		TArmReg armReg;
  2720 		err = GetKernelRegisterId(reg, armReg);
  2721 		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
  2722 			{
  2723 			//writing to this register is not supported
  2724 			aRegisterFlags.Append(ENotSupported);
  2725 			}
  2726 		else if(GetFlagAtOffset(flags, armReg))
  2727 			{
  2728 			if(registerTag.iSize == sizeof(TArmReg))
  2729 				{
  2730 				//set flag as valid
  2731 				aRegisterFlags.Append(EValid);
  2732 				if(offset + sizeof(TArmReg) > aRegisterValues.Length())
  2733 					{
  2734 					//getting this value would cause overflow so exit
  2735 					return KErrArgument;
  2736 					}
  2737 				//write value into register into regSet
  2738 				regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
  2739 				}
  2740 			else
  2741 				{
  2742 				//currently all kernel supported registers are 4 bytes so
  2743 				//return EBadSize. Would need updating if/when other register
  2744 				//value sizes are supported
  2745 				aRegisterFlags.Append(EBadSize);
  2746 				}
  2747 
  2748 			}
  2749 		else
  2750 			{
  2751 			//set flag as invalid as register value couldn't be read
  2752 			aRegisterFlags.Append(EInValid);
  2753 			}
  2754 		offset+=registerTag.iSize;
  2755 		}
  2756 
  2757 	//write the input data into the registers
  2758 	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
  2759 
  2760 	//return normally
  2761 	return KErrNone;
  2762 	}
  2763 
  2764 //
  2765 // DRM_DebugChannel::DoSecurityCheck
  2766 //
  2767 TBool DRM_DebugChannel::DoSecurityCheck()
  2768 {
  2769 	LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
  2770 	DProcess* clientProcess = iClientThread->iOwningProcess;
  2771 	if (clientProcess)
  2772 	{
  2773 		SSecurityInfo secureInfo = clientProcess->iS;
  2774 
  2775 		LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
  2776 
  2777 		// Ensure we really are communicating with the Debug Security Server
  2778 		if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
  2779 		{
  2780 			return ETrue;
  2781 		}
  2782 	}
  2783 	return EFalse;
  2784 }
  2785 
  2786 /**
  2787 Attempt to read memory from aThread's address space
  2788 
  2789 @param aThread thread from whose address space memory is to be read
  2790 @param aSrc pointer to memory location to read memory from
  2791 @param aDest pointer to memory location to write memory to
  2792 @param aLength number of bytes of data to read
  2793 
  2794 @return KErrNone if memory read successfully,
  2795 	or another of the system wide error codes
  2796 */
  2797 TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
  2798 {
  2799 	LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
  2800 
  2801 	// make sure the parameters are valid
  2802 	if (!aThread)
  2803 		return KErrArgument;
  2804 
  2805 	//Need to revisit this to determine whether there is a way to validate this
  2806 #if 0
  2807 	//check that the thread is suspended before reading the memory
  2808 	if ( !CheckSuspended(aThread) )
  2809 		{
  2810 		LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
  2811 		return KErrInUse;
  2812 		}
  2813 #endif
  2814 
  2815 	LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
  2816 	return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
  2817 }
  2818 
  2819 /**
  2820 Attempt to write memory to aThread's address space
  2821 
  2822 @param aThread thread to whose address space memory is to be written
  2823 @param aDest pointer to memory location to write memory to
  2824 @param aSrc pointer to memory location to read memory from
  2825 @param aLength number of bytes of data to write
  2826 
  2827 @return KErrNone if memory written successfully, or another of the system wide
  2828         error codes
  2829 */
  2830 TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
  2831 {
  2832 	LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
  2833 
  2834 	//check that the thread is suspended before writing the memory
  2835 	if(!TheDProcessTracker.CheckSuspended((DThread*)aThread))
  2836 		{
  2837 		LOG_MSG2("DRM_DebugChannel::TryToWriteMemory() thread with id 0x%08x is not suspended", aThread->iId);
  2838 		return KErrInUse;
  2839 		}
  2840 
  2841 	LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
  2842 	return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
  2843 }
  2844 
  2845 /**
  2846 @deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
  2847 */
  2848 TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
  2849 {
  2850 	LOG_MSG("DRM_DebugChannel::ReadRegister()");
  2851 
  2852 	if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  2853 	{
  2854 		LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
  2855 		return 0;
  2856 	}
  2857 
  2858 	TArmRegSet regSet;
  2859     TUint32 unused;
  2860 
  2861 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  2862 
  2863     TArmReg *reg = &regSet.iR0;
  2864 
  2865 	return ((TUint32 *)reg)[aNum];
  2866 }
  2867 
  2868 /**
  2869 Given a TArmReg register ID, read the value of the register. The register value
  2870 will be stored in aValue if the register could be read.
  2871 
  2872 @param aThread thread to read register from
  2873 @param aKernelRegisterId ID of register to read from
  2874 @param aValue value read from register
  2875 
  2876 @return KErrNone if value was successfully stored in aValue,
  2877         KErrNotSupported if aKernelRegister is not supported by the debug
  2878 	security server,
  2879         or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
  2880 */
  2881 TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
  2882 {
  2883 	//get register ID as a TRegisterInfo ID
  2884 	TRegisterInfo regId;
  2885 	TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
  2886 	if(err != KErrNone)
  2887 		return err;
  2888 
  2889 	//get the value for the register
  2890 	err = ReadDebugRegisterValue(aThread, regId, aValue);
  2891 	return err;
  2892 	}
  2893 
  2894 /**
  2895 Given a TRegisterInfo register ID, read the value of this register. The
  2896 register value will be stored in aValue if the register could be read.
  2897 
  2898 @param aThread thread to read register from
  2899 @param aDebugRegisterId ID of register to read from
  2900 @param aValue value read from register
  2901 
  2902 @return KErrNone if value was successfully stored in aValue,
  2903         TRegisterFlag::EInValid if value could not be read from the register,
  2904         TRegisterFlag::ENotSupported if the register is not supported,
  2905         KErrNoMemory if temporary memory could not be allocated,
  2906         or a return value from DRM_DebugChannel::DoReadRegisters
  2907 */
  2908 TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
  2909 {
  2910 	//allocate temporary buffers to store data
  2911 	NKern::ThreadEnterCS();
  2912 	TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
  2913 	NKern::ThreadLeaveCS();
  2914 	if(id == NULL)
  2915 	{
  2916 		return KErrNoMemory;
  2917 	}
  2918 	TPtr8 idPtr(id, sizeof(TRegisterInfo));
  2919 
  2920 	NKern::ThreadEnterCS();
  2921 	TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
  2922 	NKern::ThreadLeaveCS();
  2923 	if(value == NULL)
  2924 	{
  2925 		return KErrNoMemory;
  2926 	}
  2927 	TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
  2928 
  2929 	NKern::ThreadEnterCS();
  2930 	TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
  2931 	NKern::ThreadLeaveCS();
  2932 	if(flag == NULL)
  2933 	{
  2934 		return KErrNoMemory;
  2935 	}
  2936 	TPtr8 flagPtr(flag, sizeof(TUint8));
  2937 
  2938 	//store register id in buffer
  2939 	idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
  2940 
  2941 	//read registers
  2942 	TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
  2943 	if(err == KErrNone)
  2944 	{
  2945 		if(*flag == EValid)
  2946 		{
  2947 			//register could be read so store value
  2948 			aValue = *(T4ByteRegisterValue*)value;
  2949 		}
  2950 		else
  2951 		{
  2952 			//register couldn't be read for some reason
  2953 			err = *flag;
  2954 		}
  2955 	}
  2956 
  2957 	//free memory
  2958 	NKern::ThreadEnterCS();
  2959 	Kern::Free(id);
  2960 	Kern::Free(value);
  2961 	Kern::Free(flag);
  2962 	NKern::ThreadLeaveCS();
  2963 
  2964 	return err;
  2965 }
  2966 
  2967 //
  2968 // DRM_DebugChannel::NotifyEvent
  2969 //
  2970 void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
  2971 {
  2972 	LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
  2973 
  2974 	// Look for the relevant DTargetProcess
  2975 	// We can find out the relevant process id from aEventInfo
  2976 	TUint32 pid = aEventInfo.iProcessId;
  2977 
  2978 	//opening handle to process
  2979 	DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
  2980 
  2981 	if(!targetProcess)
  2982 		{
  2983 		LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - process does not exist!");
  2984 		return;
  2985 		}
  2986 
  2987 	// Are we debugging this process - decide based on iFileName
  2988 	DCodeSeg* p = targetProcess->iCodeSeg;
  2989 	DTargetProcess* foundProcess;
  2990 	if (p)
  2991 		{
  2992 		 foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
  2993 		}
  2994 	else
  2995 		{
  2996 		// special case: may not have a code seg in some cases. in which case we tell everyone!
  2997 		if (targetProcess->iName)
  2998 			{
  2999 			// copy the name of the process
  3000 			foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
  3001 			}
  3002 		else
  3003 			{
  3004 			foundProcess = NULL;
  3005 			}
  3006 		}
  3007 
  3008 	//close the handle
  3009 	targetProcess->Close(NULL);
  3010 
  3011 	if (!foundProcess)
  3012 		{
  3013 		// No: just ignore this exception
  3014 		LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - we are not debugging this process!");
  3015 		return;
  3016 		}
  3017 
  3018 	foundProcess->NotifyEvent(aEventInfo);
  3019 }
  3020 
  3021 #ifndef __LAUNCH_AS_EXTENSION__
  3022 DECLARE_STANDARD_LDD()
  3023 	{
  3024 	return new DRM_DebugDriverFactory;
  3025 	}
  3026 #else
  3027 
  3028 DStopModeExtension* TheStopModeExtension = NULL;
  3029 
  3030 DECLARE_EXTENSION_LDD()
  3031 	{
  3032 	return new DRM_DebugDriverFactory;
  3033 	}
  3034 
  3035 /**
  3036   This value is used as an initialiser for the size of the Stop-Mode Debug API's
  3037   default request buffer.
  3038   */
  3039 const TInt KRequestBufferSize = 0x200;
  3040 /**
  3041   This value is used as an initialiser for the size of the Stop-Mode Debug API's
  3042   default response buffer.
  3043   */
  3044 const TInt KResponseBufferSize = 0x1000;
  3045 
  3046 DECLARE_STANDARD_EXTENSION()
  3047 	{
  3048 	__KTRACE_OPT(KBOOT,Kern::Printf("Starting RM_DEBUG extension"));
  3049 
  3050 	// get a reference to the DDebuggerInfo and to the DStopModeExtension
  3051 	TSuperPage& superPage = Kern::SuperPage();
  3052 
  3053 	if(!superPage.iDebuggerInfo)
  3054 		{
  3055 		//kdebug has not been installed so create DDebuggerInfo using our stub constructor
  3056 		superPage.iDebuggerInfo = new DDebuggerInfo();
  3057 		}
  3058 
  3059 	if(!TheStopModeExtension)
  3060 		{
  3061 		TheStopModeExtension = new DStopModeExtension();
  3062 		}
  3063 
  3064 	// create the request buffer and store a reference to it
  3065 	TTag tag;
  3066 	tag.iTagId = EBuffersRequest;
  3067 	tag.iType = ETagTypePointer;
  3068 	tag.iSize = KRequestBufferSize;
  3069 	TInt err = TheDBufferManager.CreateBuffer(tag);
  3070 	if(KErrNone != err)
  3071 		{
  3072 		return KErrNone;
  3073 		}
  3074 
  3075 	// create the response buffer and store a reference to it
  3076 	tag.iTagId = EBuffersResponse;
  3077 	tag.iSize = KResponseBufferSize;
  3078 	err = TheDBufferManager.CreateBuffer(tag);
  3079 	if(KErrNone != err)
  3080 		{
  3081 		return KErrNone;
  3082 		}
  3083 	// create the debug functionality buffer and store a reference to it
  3084 	TDebugFunctionality df;
  3085 	TUint dfSize = df.GetStopModeFunctionalityBufSize();
  3086 	tag.iTagId = EBuffersFunctionality;
  3087 	tag.iSize = dfSize;
  3088 	err = TheDBufferManager.CreateBuffer(tag);
  3089 	if(KErrNone != err)
  3090 		{
  3091 		return KErrNone;
  3092 		}
  3093 
  3094 	// fill the functionality buffer with the functionality data and store it in
  3095 	// the super page
  3096 	TPtr8 dfBlockPtr((TUint8*)tag.iValue, dfSize);
  3097 	if(!df.GetStopModeFunctionality(dfBlockPtr))
  3098 		{
  3099 		return KErrNone;
  3100 		}
  3101 	TheStopModeExtension->iFunctionalityBlock = (DFunctionalityBlock*)tag.iValue;
  3102 
  3103 	DStopModeExtension::Install(TheStopModeExtension);
  3104 
  3105 	return KErrNone;
  3106 	}
  3107 
  3108 /**
  3109  * This stub constructor is intended to be used in the case where the old deprecated
  3110  * stop mode api, kdebug, is not in place. It will initialise all values to NULL except
  3111  * the pointer to the new stop mode api extension. This allows the new stop mode solution
  3112  * to both co-exist and exist independantly of the existing one *
  3113  */
  3114 DDebuggerInfo::DDebuggerInfo():
  3115     iObjectOffsetTable(NULL),
  3116     iObjectOffsetTableCount(NULL),
  3117     iThreadContextTable(NULL),
  3118     iStopModeExtension(new DStopModeExtension()),
  3119     iContainers(NULL),
  3120     iCodeSegLock(NULL),
  3121     iCodeSegGlobalList(NULL),
  3122     iScheduler(NULL),
  3123     iShadowPages(NULL),
  3124     iShadowPageCount(0),
  3125     iCurrentThread(NULL),
  3126     iEventMask(),
  3127     iEventHandlerBreakpoint(0),
  3128     iMemModelObjectOffsetTable(NULL),
  3129     iMemModelObjectOffsetTableCount(0)
  3130     {
  3131     }
  3132 
  3133 /**
  3134  * Installs the stop-mode debugger extension
  3135  * Make the stop-mode API visible to a JTAG debugger, by publishing its
  3136  * existence in the superpage
  3137 */
  3138 void DStopModeExtension::Install(DStopModeExtension* aExt)
  3139     {
  3140     Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
  3141     }
  3142 
  3143 #endif
  3144 
  3145 /**
  3146 Helper function
  3147 
  3148 Allocates memory in current thread with a max length the same as aSrcDes. If
  3149 aReadFromClient is true (as it is by default) then the data from aSrdDes is
  3150 copied into the allocated aDestDes buffer.
  3151 
  3152 Use of this function should be followed at a later time by a call such as
  3153 Kern::Free(aDestDes.Ptr())
  3154 
  3155 @param aThread pointer to thread to read data from
  3156 @param aSrcDes descriptor in aThread to read data from
  3157 @param aDestDes location to read data to. Memory is allocated at this location,
  3158        if memory is already allocated at this location then the function will
  3159        return KErrArgument
  3160 @param aReadFromClient if false then data is not actually read from the
  3161        client, the memory is simply allocated
  3162 @param aOffest offset into aSrcDes to start reading from. Default is 0.
  3163 
  3164 @return KErrNone if there were no problems,
  3165         KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
  3166         KErrNoMemory if could not allocate memory,
  3167         or one of the other system wide error codes
  3168 */
  3169 TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
  3170 	{
  3171 
  3172 	//check thread is not null
  3173 	if(!aThread)
  3174 		{
  3175 		return KErrArgument;
  3176 		}
  3177 
  3178 	//check aDestDes is empty
  3179 	if(aDestDes.Ptr() != NULL)
  3180 		{
  3181 		return KErrArgument;
  3182 		}
  3183 
  3184 	//get the source descriptor's max length and exit if 0
  3185 	TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
  3186 	if(srcMaxLength == 0)
  3187 		{
  3188 		return KErrNone;
  3189 		}
  3190 
  3191 	//allocate memory and return if none available
  3192 	NKern::ThreadEnterCS();
  3193 	TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
  3194 	NKern::ThreadLeaveCS();
  3195 	if (!destPtr)
  3196 		{
  3197 		return KErrNoMemory;
  3198 		}
  3199 
  3200 	//point the TPtr8 at the target memory
  3201 	aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
  3202 
  3203 	if(aReadFromClient)
  3204 		{
  3205 		//read data from the client thread and return status code
  3206 		return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
  3207 		}
  3208 	else
  3209 		{
  3210 		return KErrNone;
  3211 		}
  3212 	}
  3213 
  3214 /**
  3215 Helper function to extract a TRegisterInfo value from a descriptor containing
  3216 binary data.
  3217 
  3218 @param aRegisterIds descriptor containing register IDs
  3219 @param aOffset offset in bytes into the descriptor to start reading data from.
  3220        If this value is not a multiple of sizeof(TRegisterInfo) then a
  3221        KErrArgument error is returned.
  3222 @param aValue will contain the returned value
  3223 
  3224 @return KErrNone if aValue was set correctly, KErrArgument if bad arguments
  3225         were passed in
  3226 */
  3227 TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
  3228 	{
  3229 	TUint length = aRegisterIds.Length();
  3230 
  3231 	TUint size = sizeof(TRegisterInfo);
  3232 
  3233 	//check that not trying to read past end of descriptor
  3234 	if((aIndex + 1) * size > length)
  3235 		return KErrArgument;
  3236 
  3237 	//get pointer to descriptor's data
  3238 	const TUint8 *dataPtr = aRegisterIds.Ptr();
  3239 	const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
  3240 
  3241 	aValue = *registerId;
  3242 
  3243 	return KErrNone;
  3244 	}
  3245 
  3246 /**
  3247 Helper function to get the kernel register ID of the TRegisterInfo defined register.
  3248 
  3249 @param aDebugRegister the debug register ID to return the kernel ID for
  3250 @param aKernelRegister corresponding value of register aDebugRegister
  3251 
  3252 @return KErrNone if translation occurred without problems
  3253         KErrNotSupported if aDebugRegister is not supported by the kernel
  3254 */
  3255 TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
  3256 	{
  3257 	if(Register::IsCoreReg(aDebugRegister))
  3258 		{
  3259 		TUint id = Register::GetCoreRegId(aDebugRegister);
  3260 		//first 17 registers match the first 17 kernel registers
  3261 		if(id < 17)
  3262 			{
  3263 			aKernelRegister = id;
  3264 			}
  3265 		else
  3266 			{
  3267 			return KErrNotSupported;
  3268 			}
  3269 		}
  3270 	else if(Register::IsCoproReg(aDebugRegister))
  3271 		{
  3272 		TUint32 crn = Register::GetCRn(aDebugRegister);
  3273 		TUint32 crm = Register::GetCRm(aDebugRegister);
  3274 		TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
  3275 		TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
  3276 		TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
  3277 
  3278 		//each coprocessor register has potentially different characteristics
  3279 		//so need to identify each individually
  3280 
  3281 		//this is the DACR, the ARM ARM specifies that the CRn and the
  3282 		//Opcodes are not relevant, section B3-24, point 3.7.3
  3283 		if((coproNum == 15) && (crm == 3))
  3284 			{
  3285 			aKernelRegister = EArmDacr;
  3286 			}
  3287 		else
  3288 			{
  3289 			return KErrNotSupported;
  3290 			}
  3291 		}
  3292 	else // might be supported at a later date
  3293 		{
  3294 		return KErrNotSupported;
  3295 		}
  3296 
  3297 	return KErrNone;
  3298 	}
  3299 
  3300 /**
  3301 Helper function to get the debug register ID of the kernel defined register.
  3302 
  3303 @param aKernelRegister the kernel register ID to return the debug ID for
  3304 @param aDebugRegister corresponding value of register aKernelRegister
  3305 
  3306 @return KErrNone if translation occured without problems
  3307         KErrNotSupported if aKernelRegister is not supported by the debug
  3308 	security server
  3309 */
  3310 TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
  3311 	{
  3312 
  3313 	// registers 0 - 15 and the CPSR share the same values as with the debug enums
  3314 	if(aKernelRegister < 17)
  3315 		{
  3316 		TUint32 id = aKernelRegister;
  3317 		aDebugRegister = id << 8;
  3318 		}
  3319 	//the DACR value is special and corresponds to EDF_Register_DACR
  3320 	else if(aKernelRegister == EArmDacr)
  3321 		{
  3322 		aDebugRegister = 0x00300f01;
  3323 		}
  3324 	// must be an unsupported register, return an error as such
  3325 	else
  3326 		{
  3327 		return KErrNotSupported;
  3328 		}
  3329 
  3330 	//found a supported register so return KErrNone
  3331 	return KErrNone;
  3332 	}
  3333 
  3334 /**
  3335 Helper function to find out whether the aIndex flag is set. This is equivalent
  3336 to the aIndex bit of aFlags being non-zero.
  3337 
  3338 @param aFlags set of flags
  3339 @param aIndex offset into aFlags to get flag from
  3340 
  3341 @return ETrue if bit is set, EFalse if not
  3342 */
  3343 TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
  3344 	{
  3345 	return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
  3346 	}
  3347 
  3348 /* Register the attachment of a debug agent to a process to be debugged
  3349  *
  3350  * @param a1 - TDes8 target process name
  3351  * @param a2 - &TUint64 - Debug Agent Id
  3352  *
  3353  * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
  3354  * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
  3355  * if appropriate.
  3356  */
  3357 TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
  3358 	{
  3359 	LOG_MSG("DRM_DebugChannel::AttachProcess()");
  3360 
  3361 	// Validate the supplied TDes8 target process name in a1
  3362 	TInt length, maxLength;
  3363 	TUint8* aPtr;
  3364 
  3365 	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  3366 		a1,\
  3367 		length,\
  3368 		maxLength,\
  3369 		aPtr,\
  3370 		EFalse);
  3371 	if (err != KErrNone)
  3372 		{
  3373 		// Could not read the descriptor information
  3374 		return err;
  3375 		}
  3376 
  3377 	// Check the processname is a valid size for a filepath
  3378 	if (length < 1 || length >= KMaxPath)
  3379 		{
  3380 		return KErrArgument;
  3381 		}
  3382 
  3383 	if (maxLength < 1 || maxLength >= KMaxPath)
  3384 		{
  3385 		return KErrArgument;
  3386 		}
  3387 
  3388 	// Allocate space to store the target process name in a kernel-side TPtr8
  3389 	NKern::ThreadEnterCS();
  3390 	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  3391 	NKern::ThreadLeaveCS();
  3392 	if (buffer==NULL)
  3393 		{
  3394 		// Out of memory
  3395 		return KErrNoMemory;
  3396 		}
  3397 
  3398 	// A temporary descriptor to store the target process name
  3399 	TPtr8 targetProcessName(buffer,length,length);
  3400 
  3401 	// Read the user-side data into targetProcessName
  3402 	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  3403 	if (err != KErrNone)
  3404 		{
  3405 		// Could not read the user-side descriptor containing the target process name
  3406 		NKern::ThreadEnterCS();
  3407 		Kern::Free(buffer);
  3408 		NKern::ThreadLeaveCS();
  3409 
  3410 		return err;
  3411 		}
  3412 
  3413 	// Obtain the Debug Agent Id
  3414 	TUint64 debugAgentId = 0;
  3415 
  3416 	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
  3417 	if (err != KErrNone)
  3418 		{
  3419 		// Something bad happened so free the memory and return
  3420 		NKern::ThreadEnterCS();
  3421 		Kern::Free(buffer);
  3422 		NKern::ThreadLeaveCS();
  3423 		return err;
  3424 		}
  3425 
  3426 	// Add the target process to our list of tracked processes
  3427 	err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
  3428 
  3429 	// Free the kernel-side memory containing targetProcessName data
  3430 	NKern::ThreadEnterCS();
  3431 	Kern::Free(buffer);
  3432 	NKern::ThreadLeaveCS();
  3433 
  3434 	return err;
  3435 	}
  3436 
  3437 /* Register the detachment of a debug agent to a process to be debugged.
  3438  *
  3439  * @param - a1 TDes8 target process name in a1
  3440  * @param a2 - &TUint64 - Debug Agent Id
  3441  *
  3442  * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
  3443  * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
  3444  * if appropriate.
  3445  */
  3446 TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
  3447 	{
  3448 	// Validate the supplied TDes8 target process name in a1
  3449 	TInt length, maxLength;
  3450 	TUint8* aPtr;
  3451 
  3452 	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  3453 		a1,\
  3454 		length,\
  3455 		maxLength,\
  3456 		aPtr,\
  3457 		EFalse);
  3458 	if (err != KErrNone)
  3459 		{
  3460 		return err;
  3461 		}
  3462 
  3463 	if (length < 1 || length >= KMaxPath)
  3464 		{
  3465 		return KErrArgument;
  3466 		}
  3467 
  3468 	if (maxLength < 1 || maxLength >= KMaxPath)
  3469 		{
  3470 		return KErrArgument;
  3471 		}
  3472 
  3473 	// Allocate space to store the target process name in a kernel-side TPtr8
  3474 	NKern::ThreadEnterCS();
  3475 	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  3476 	NKern::ThreadLeaveCS();
  3477 	if (buffer==NULL)
  3478 	{
  3479 		// Out of memory
  3480 		return KErrNoMemory;
  3481 	}
  3482 
  3483 	TPtr8 targetProcessName(buffer,length,length);
  3484 
  3485 	// Read the user-side data into targetProcessName
  3486 	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  3487 	if (err != KErrNone)
  3488 	{
  3489 		// Something bad happened so free the memory and return
  3490 		NKern::ThreadEnterCS();
  3491 		Kern::Free(buffer);
  3492 		NKern::ThreadLeaveCS();
  3493 
  3494 		return err;
  3495 	}
  3496 
  3497 	// Obtain the AgentId
  3498 	TUint64 debugAgentId = 0;
  3499 
  3500 	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
  3501 	if (err != KErrNone)
  3502 	{
  3503 		// Something bad happened so free the memory and return
  3504 		NKern::ThreadEnterCS();
  3505 		Kern::Free(buffer);
  3506 		NKern::ThreadLeaveCS();
  3507 
  3508 		return err;
  3509 	}
  3510 
  3511 	// Remove the process from our list of tracked processes
  3512 	err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
  3513 
  3514 	// Free the kernel-side memory containing targetProcessName data
  3515 	NKern::ThreadEnterCS();
  3516 	Kern::Free(buffer);
  3517 	NKern::ThreadLeaveCS();
  3518 
  3519 	return err;
  3520 	}
  3521 
  3522 /* Register the detachment of a debug agent from all processes being debugged.
  3523  *
  3524  * @param - a1 - &TUint64 Debug Agent Id.
  3525  * @return - KErrNone if successful. One of the system-wide error codes otherwise.
  3526  */
  3527 TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
  3528 	{
  3529 	// Obtain the AgentId
  3530 	TUint64 debugAgentId = 0;
  3531 
  3532 	TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
  3533 	if (err != KErrNone)
  3534 	{
  3535 		return err;
  3536 	}
  3537 
  3538 	// Remove the process from our list of tracked processes
  3539 	return TheDProcessTracker.DetachAgent(debugAgentId);
  3540 	}
  3541 
  3542 /* Set the action associated with a particular kernel event for a given agent and target process
  3543  *
  3544  * @param - a1 TDes8 target process name in a1
  3545  * @param - a2 &TRM_DebugEventActionInfo
  3546  * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
  3547  * the other system wide error codes if appropriate.
  3548  */
  3549 TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
  3550 	{
  3551 	// Validate the supplied TDes8 target process name in a1
  3552 	TInt length, maxLength;
  3553 	TUint8* aPtr;
  3554 
  3555 	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  3556 		a1,\
  3557 		length,\
  3558 		maxLength,\
  3559 		aPtr,\
  3560 		EFalse);
  3561 	if (err != KErrNone)
  3562 		{
  3563 		return err;
  3564 		}
  3565 
  3566 	if (length < 1 || length >= KMaxPath)
  3567 		{
  3568 		return KErrArgument;
  3569 		}
  3570 
  3571 	if (maxLength < 1 || maxLength >= KMaxPath)
  3572 		{
  3573 		return KErrArgument;
  3574 		}
  3575 
  3576 	// Allocate space to store the target process name in a kernelspace TPtr8
  3577 	NKern::ThreadEnterCS();
  3578 	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  3579 	NKern::ThreadLeaveCS();
  3580 	if (buffer==NULL)
  3581 	{
  3582 		// Out of memory
  3583 		return KErrNoMemory;
  3584 	}
  3585 	TPtr8 targetProcessName(buffer,length,length);
  3586 
  3587 	// Read the user-side data into targetProcessName
  3588 	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  3589 	if (err != KErrNone)
  3590 	{
  3591 		// Something bad happened so free the memory and return
  3592 		NKern::ThreadEnterCS();
  3593 		Kern::Free(buffer);
  3594 		NKern::ThreadLeaveCS();
  3595 
  3596 		return err;
  3597 	}
  3598 
  3599 	// Read the Event and Action from the user-side
  3600 	TRM_DebugEventActionInfo info(0,0,0);
  3601 
  3602 	err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
  3603 	if (err != KErrNone)
  3604 	{
  3605 		// Could not read event action data from the user-side
  3606 
  3607 		// Free memory used for targetProcessName
  3608 		NKern::ThreadEnterCS();
  3609 		Kern::Free(buffer);
  3610 		NKern::ThreadLeaveCS();
  3611 
  3612 		return err;
  3613 	}
  3614 
  3615 	// Find the target process
  3616 	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
  3617 	if (pProcess == NULL)
  3618 	{
  3619 		// Could not find this process
  3620 
  3621 		// Free memory used for targetProcessName
  3622 		NKern::ThreadEnterCS();
  3623 		Kern::Free(buffer);
  3624 		NKern::ThreadLeaveCS();
  3625 
  3626 		return KErrArgument;
  3627 	}
  3628 
  3629 	TUint64 debugAgentId = info.iAgentId;
  3630 
  3631 	// Find the agent
  3632 	DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
  3633 	if (debugAgent == NULL)
  3634 	{
  3635 		// Bad agent means there is no tracking agent
  3636 		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
  3637 
  3638 		// Free memory used for targetProcessName
  3639 		NKern::ThreadEnterCS();
  3640 		Kern::Free(buffer);
  3641 		NKern::ThreadLeaveCS();
  3642 
  3643 		return KErrGeneral;
  3644 	}
  3645 
  3646 	// Set the event action
  3647 	debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
  3648 
  3649 	// Free memory used for targetProcessName
  3650 	NKern::ThreadEnterCS();
  3651 	Kern::Free(buffer);
  3652 	NKern::ThreadLeaveCS();
  3653 
  3654 	return KErrNone;
  3655 	}
  3656 
  3657 TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
  3658 	{
  3659 	LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
  3660 
  3661 	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
  3662 
  3663 	if (thread == NULL)
  3664 		{
  3665 		// The thread terminated before we could open it.
  3666 		LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
  3667 
  3668 		return KErrArgument;
  3669 		}
  3670 
  3671 	// We simply repeat this for desired number of steps
  3672 	TInt err = KErrNone;
  3673 
  3674 	// Need to step from the current location for 'n' steps
  3675 	TUint32 startAddress;
  3676 
  3677 	// We always step from the current PC.
  3678 	err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
  3679 	if(err != KErrNone)
  3680 		{
  3681 		LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
  3682 
  3683 		// Close the handle
  3684 		thread->Close(NULL);
  3685 
  3686 		return err;
  3687 		}
  3688 
  3689 	err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
  3690 
  3691 	if (err != KErrNone)
  3692 		{
  3693 		// There was a problem, return straightaway
  3694 		LOG_MSG("DRM_DebugChannel::Step - failed to step");
  3695 		}
  3696 
  3697 	// Close the handle
  3698 	thread->Close(NULL);
  3699 
  3700 	return err;
  3701 	}
  3702 
  3703 TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
  3704 	{
  3705 	LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
  3706 
  3707 	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
  3708 
  3709 	if (process == NULL)
  3710 		{
  3711 		// The process terminated before we could open it to kill it ourselves.
  3712 		LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
  3713 
  3714 		return KErrArgument;
  3715 		}
  3716 
  3717 	TInt err = KErrNone;
  3718 
  3719 	DebugSupport::TerminateProcess(process,aReason);
  3720 
  3721 	// Close the handle
  3722 	process->Close(NULL);
  3723 
  3724 	return err;
  3725 	}
  3726 
  3727 /* Security critical - this checks whether the specified process is debuggable or not
  3728  *
  3729  * @param aProcessId - The process id of the process to check
  3730  * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
  3731  */
  3732 TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
  3733 	{
  3734 	/* In order to ensure that only processes which are debuggable
  3735 	 * can be debugged, this function enables the security server
  3736 	 * to read the DProcess.iDebugAttributes field and ensure
  3737 	 * the process was created from a debuggable executable.
  3738 	 */
  3739 	LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
  3740 
  3741 	TInt err = KErrPermissionDenied;
  3742 
  3743 	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
  3744 	if (process)
  3745 		{
  3746 		if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
  3747 			{
  3748 			// Yes this process exists and is debuggable
  3749 			err = KErrNone;
  3750 			}
  3751 		process->Close(NULL);
  3752 		}
  3753 
  3754 	if (err == KErrNone)
  3755 	{
  3756 		LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
  3757 	}
  3758 
  3759 	return err;
  3760 	}