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