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