os/kernelhwsrv/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,3760 @@
     1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// Device driver for kernel side debug assist
    1.18 +//
    1.19 +
    1.20 +#ifdef __WINS__
    1.21 +#error - this driver cannot be built for emulation
    1.22 +#endif
    1.23 +
    1.24 +#include <e32def.h>
    1.25 +#include <e32def_private.h>
    1.26 +#include <e32cmn.h>
    1.27 +#include <e32cmn_private.h>
    1.28 +#include <e32ldr.h>
    1.29 +#include <u32std.h>
    1.30 +#include <kernel/kernel.h>
    1.31 +#include <kernel/kern_priv.h>
    1.32 +#include <nk_trace.h>
    1.33 +#include <arm.h>
    1.34 +#include <kernel/cache.h>
    1.35 +#include <platform.h>
    1.36 +#include <nkern.h>
    1.37 +#include <u32hal.h>
    1.38 +#include <kernel/kdebug.h>
    1.39 +#include <rm_debug_api.h>
    1.40 +
    1.41 +#include "debug_logging.h"
    1.42 +#include "d_rmd_breakpoints.h"	// moved breakpoints code lives here
    1.43 +#include "d_rmd_stepping.h"		// moved stepping code lives here
    1.44 +#include "rm_debug_kerneldriver.h"
    1.45 +#include "d_list_manager.h"
    1.46 +#include "rm_debug_driver.h"
    1.47 +#include "rm_debug_eventhandler.h"
    1.48 +#include "d_debug_functionality.h"
    1.49 +#include "d_process_tracker.h"
    1.50 +#include "debug_utils.h"
    1.51 +#include "d_buffer_manager.h"
    1.52 +
    1.53 +using namespace Debug;
    1.54 +
    1.55 +/////////////////////////////////////////////////////////////////////////
    1.56 +//
    1.57 +// DRM_DebugDriverFactory implementation
    1.58 +//
    1.59 +/////////////////////////////////////////////////////////////////////////
    1.60 +
    1.61 +//
    1.62 +// DRM_DebugDriverFactory constructor
    1.63 +//
    1.64 +DRM_DebugDriverFactory::DRM_DebugDriverFactory()
    1.65 +{
    1.66 +	iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
    1.67 +}
    1.68 +
    1.69 +//
    1.70 +// DRM_DebugDriverFactory::Create
    1.71 +//
    1.72 +TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
    1.73 +{
    1.74 +	if (iOpenChannels != 0)
    1.75 +		return KErrInUse; // a channel is already open
    1.76 +
    1.77 +	aChannel = new DRM_DebugChannel(this);
    1.78 +
    1.79 +	return aChannel ? KErrNone : KErrNoMemory;
    1.80 +}
    1.81 +
    1.82 +//
    1.83 +// DRM_DebugDriverFactory::Install
    1.84 +//
    1.85 +TInt DRM_DebugDriverFactory::Install()
    1.86 +{
    1.87 +    return(SetName(&KRM_DebugDriverName));
    1.88 +}
    1.89 +
    1.90 +//
    1.91 +// DRM_DebugDriverFactory::Install
    1.92 +//
    1.93 +void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
    1.94 +{
    1.95 +    TCapsRM_DebugDriver b;
    1.96 +    b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
    1.97 +
    1.98 +	Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
    1.99 +}
   1.100 +
   1.101 +/////////////////////////////////////////////////////////////////////////
   1.102 +//
   1.103 +// DRM_DebugChannel implementation
   1.104 +//
   1.105 +/////////////////////////////////////////////////////////////////////////
   1.106 +
   1.107 +//
   1.108 +// DRM_DebugChannel constructor
   1.109 +//
   1.110 +DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
   1.111 +	: iExcludedROMAddressStart(ROM_LINEAR_BASE),
   1.112 +      iExcludedROMAddressEnd(0),
   1.113 +   	  iPageSize(0x1000),
   1.114 +	  iBreakManager(0),
   1.115 +	  iStepper(0),
   1.116 +	  iStepLock(0),
   1.117 +  	  iDfcQ(NULL),
   1.118 +	  iInitialisedCodeModifier(0),
   1.119 +	  iAsyncGetValueRequest(NULL)
   1.120 +{
   1.121 +	LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
   1.122 +
   1.123 +	iDevice = aLogicalDevice;
   1.124 +
   1.125 +	iClientThread = &Kern::CurrentThread();
   1.126 +	iClientThread->Open();
   1.127 +
   1.128 +	iPageSize = Kern::RoundToPageSize(1);
   1.129 +}
   1.130 +
   1.131 +//
   1.132 +// DRM_DebugChannel destructor
   1.133 +//
   1.134 +DRM_DebugChannel::~DRM_DebugChannel()
   1.135 +{
   1.136 +	LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
   1.137 +
   1.138 +	if (iAsyncGetValueRequest)
   1.139 +	{
   1.140 +		Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
   1.141 +		Kern::DestroyClientRequest(iAsyncGetValueRequest);
   1.142 +	}
   1.143 +
   1.144 +	NKern::ThreadEnterCS();
   1.145 +	Kern::SafeClose((DObject*&)iClientThread, NULL);
   1.146 +	NKern::ThreadLeaveCS();
   1.147 +
   1.148 +	// Close breakpoint manager
   1.149 +	if (iBreakManager)
   1.150 +	{
   1.151 +		NKern::ThreadEnterCS();
   1.152 +		delete iBreakManager;
   1.153 +		NKern::ThreadLeaveCS();
   1.154 +	}
   1.155 +
   1.156 +	// Close stepping manager
   1.157 +	if (iStepper)
   1.158 +	{
   1.159 +		NKern::ThreadEnterCS();
   1.160 +		delete iStepper;
   1.161 +		NKern::ThreadLeaveCS();
   1.162 +	}
   1.163 +
   1.164 +	//close the debug process list
   1.165 +	iDebugProcessList.Close();
   1.166 +
   1.167 +	DestroyDfcQ();
   1.168 +
   1.169 +	//close the code modifier
   1.170 +	if (iInitialisedCodeModifier)
   1.171 +	{
   1.172 +		DebugSupport::CloseCodeModifier();
   1.173 +	}
   1.174 +}
   1.175 +
   1.176 +void DRM_DebugChannel::DestroyDfcQ()
   1.177 +	{
   1.178 +	LOG_MSG("DRM_DebugChannel::DestroyDfcQ()");
   1.179 +	if (iDfcQ)
   1.180 +		{
   1.181 +		NKern::ThreadEnterCS();
   1.182 +		iDfcQ->Destroy();
   1.183 +		NKern::ThreadLeaveCS();
   1.184 +		}
   1.185 +	}
   1.186 +
   1.187 +//
   1.188 +// DRM_DebugChannel::DoCreate
   1.189 +//
   1.190 +TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
   1.191 +{
   1.192 +	LOG_MSG("DRM_DebugChannel::DoCreate()");
   1.193 +	TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
   1.194 +	if(err != KErrNone)
   1.195 +		return err;
   1.196 +
   1.197 +  	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
   1.198 +		return KErrNotSupported;
   1.199 +
   1.200 +  	// Do the security check here so that any arbitrary application doesn't make
   1.201 +  	// use of Trk kernel driver.
   1.202 +  	if (!DoSecurityCheck())
   1.203 +  	{
   1.204 +		LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
   1.205 +  		return KErrPermissionDenied;
   1.206 +  	}
   1.207 +
   1.208 +  	if (anInfo)
   1.209 +  	{
   1.210 +  		// this is the end address of the user library.
   1.211 +  		// this doesn't seem to be valid for EKA2.
   1.212 +  		// right now we dont need this for EKA2 since we are not worried
   1.213 +  		// about kernel being stopped as kernel is multithreaded.
   1.214 +  		// just retaining this for future use.
   1.215 +		TBuf8<32> buf;
   1.216 +		TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
   1.217 +		if(err != KErrNone)
   1.218 +			return err;
   1.219 +
   1.220 +		//iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
   1.221 +	}
   1.222 +
   1.223 +	// Allocate a D_RMD_Breakpoints class as a breakpoint manager
   1.224 +	NKern::ThreadEnterCS();
   1.225 +	iBreakManager = new D_RMD_Breakpoints(this);
   1.226 +	NKern::ThreadLeaveCS();
   1.227 +	if (iBreakManager == NULL)
   1.228 +	{
   1.229 +		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
   1.230 +		return KErrNoMemory;
   1.231 +	}
   1.232 +
   1.233 +	// Initialise the new breakpoint manager object
   1.234 +	iBreakManager->Init();
   1.235 +
   1.236 +	// Allocate a DRMDStepping class as the stepping manager
   1.237 +	NKern::ThreadEnterCS();
   1.238 +	iStepper = new DRMDStepping(this);
   1.239 +	NKern::ThreadLeaveCS();
   1.240 +	if (iStepper == NULL)
   1.241 +	{
   1.242 +		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
   1.243 +		return KErrNoMemory;
   1.244 +	}
   1.245 +
   1.246 +	// Initialize the code modifier for managing breakpoints.
   1.247 +	TUint caps; //ignored for now
   1.248 +	err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
   1.249 +	//if code modifier initializer failed,
   1.250 +	//return here, since we can't set an breakpoints
   1.251 +	if(err != KErrNone)
   1.252 +	{
   1.253 +		return err;
   1.254 +	}
   1.255 +	else
   1.256 +	{
   1.257 +		iInitialisedCodeModifier = ETrue;
   1.258 +	}
   1.259 +
   1.260 +	//create and set the driver's Dfc queue
   1.261 +	err = CreateDfcQ();
   1.262 +	if(err != KErrNone)
   1.263 +		{
   1.264 +		LOG_MSG("DRM_DebugChannel::DoCreate() Creating Dfc queue failed.");
   1.265 +		}
   1.266 +	SetDfcQ(iDfcQ);
   1.267 +
   1.268 +	iMsgQ.Receive();
   1.269 +
   1.270 +	iEventHandler = new DRM_DebugEventHandler;
   1.271 +	if (!iEventHandler)
   1.272 +		return KErrNoMemory;
   1.273 +	err = iEventHandler->Create(iDevice, this, iClientThread);
   1.274 +	if (err != KErrNone)
   1.275 +		return err;
   1.276 +
   1.277 +	//return KErrNone;
   1.278 +	return iEventHandler->Start();
   1.279 +}
   1.280 +
   1.281 +//
   1.282 +// DRM_DebugChannel::SendMsg
   1.283 +//
   1.284 +TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
   1.285 +	{
   1.286 +	LOG_MSG("DRM_DebugChannel::SendMsg()");
   1.287 +
   1.288 +	TThreadMessage& m = *(TThreadMessage*)aMsg;
   1.289 +	TInt id = m.iValue;
   1.290 +	TInt err = KErrNone;
   1.291 +
   1.292 +	if (id != (TInt)ECloseMsg && id != KMaxTInt && id < 0)
   1.293 +		{
   1.294 +		// DoRequest
   1.295 +		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   1.296 +		err = SendRequest(aMsg);
   1.297 +		if (err != KErrNone)
   1.298 +			Kern::RequestComplete(pStatus,err);
   1.299 +		}
   1.300 +	else
   1.301 +		{
   1.302 +		err = DLogicalChannel::SendMsg(aMsg);
   1.303 +		}
   1.304 +	return err;
   1.305 +	}
   1.306 +
   1.307 +//
   1.308 +// DRM_DebugChannel::SendRequest
   1.309 +//
   1.310 +TInt DRM_DebugChannel::SendRequest(TMessageBase* aMsg)
   1.311 +	{
   1.312 +	LOG_MSG("DRM_DebugChannel::SendRequest()");
   1.313 +
   1.314 +	TThreadMessage& m = *(TThreadMessage*)aMsg;
   1.315 +	TInt function = ~m.iValue;
   1.316 +	TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   1.317 +	TAny* a1 = m.Ptr1();
   1.318 +
   1.319 +	TInt err = KErrNotSupported;
   1.320 +	switch(function)
   1.321 +		{
   1.322 +		case RRM_DebugDriver::ERequestGetEvent:
   1.323 +			err = PreAsyncGetValue((TEventInfo*)a1,pStatus);
   1.324 +			break;
   1.325 +		}
   1.326 +	if (err == KErrNone)
   1.327 +		err = DLogicalChannel::SendMsg(aMsg);
   1.328 +	return err;
   1.329 +	}
   1.330 +
   1.331 +//
   1.332 +// DRM_DebugChannel::PreAsyncGetValue
   1.333 +//
   1.334 +TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
   1.335 +	{
   1.336 +	LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
   1.337 +	
   1.338 +	iAsyncGetValueRequest->Reset();
   1.339 +	
   1.340 +	TInt err = iAsyncGetValueRequest->SetStatus(aStatus);
   1.341 +	if (err != KErrNone)
   1.342 +		return err;
   1.343 +	
   1.344 +	iAsyncGetValueRequest->SetDestPtr(aValue);
   1.345 +	return KErrNone;
   1.346 +	}
   1.347 +
   1.348 +/**
   1.349 +  Create the Dfc queue for receiving messages
   1.350 +  */
   1.351 +TInt DRM_DebugChannel::CreateDfcQ()
   1.352 +	{
   1.353 +	LOG_MSG("DRM_DebugChannel::CreateDfcQ()");
   1.354 +	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KRmDebugDriverThreadPriority, KRM_DebugDriverName);
   1.355 +	// Fix to stop t_rmdebug2 etc crashing the device.
   1.356 +	// This should be removed once the rm debug driver has been updated for WDP.
   1.357 +	if (r == KErrNone)
   1.358 +		iDfcQ->SetRealtimeState(ERealtimeStateOff);
   1.359 +	return r;
   1.360 +	}
   1.361 +
   1.362 +//
   1.363 +// DRM_DebugChannel::DoCancel
   1.364 +//
   1.365 +// New: The cancel call does not take an enum parameter describing
   1.366 +// the request to be cancelled. Rather it supplies a pointer
   1.367 +// to a user-side struct defining the cancellation
   1.368 +//
   1.369 +void DRM_DebugChannel::DoCancel(TInt aReqNo)
   1.370 +{
   1.371 +	LOG_MSG("DRM_DebugChannel::DoCancel()");
   1.372 +
   1.373 +	TRMD_DebugCancelInfo info;
   1.374 +
   1.375 +	TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
   1.376 +	if (err != KErrNone)
   1.377 +	{
   1.378 +		// How do we cancel something we know nothing about???
   1.379 +		LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
   1.380 +		return;
   1.381 +	}
   1.382 +
   1.383 +	// Find the process
   1.384 +	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
   1.385 +	if (pProcess == NULL)
   1.386 +	{
   1.387 +		// We are doomed. We don't know which event to cancel..
   1.388 +		LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
   1.389 +
   1.390 +		return;
   1.391 +	}
   1.392 +
   1.393 +	// Find the agent
   1.394 +	DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
   1.395 +	if (debugAgent == NULL)
   1.396 +	{
   1.397 +		// Bad agent means there is no tracking agent
   1.398 +		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
   1.399 +		return;
   1.400 +	}
   1.401 +
   1.402 +	// Agent completes/pends the request as appropriate.
   1.403 +	debugAgent->CancelGetEvent();
   1.404 +
   1.405 +}
   1.406 +
   1.407 +//
   1.408 +// DRM_DebugChannel::DoRequest
   1.409 +//
   1.410 +void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   1.411 +{
   1.412 +	LOG_MSG("DRM_DebugChannel::DoRequest()");
   1.413 +
   1.414 +	switch(aReqNo)
   1.415 +	{
   1.416 +		case RRM_DebugDriver::ERequestGetEvent:
   1.417 +		{
   1.418 +			TEventMetaData eventMetaData;
   1.419 +			TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
   1.420 +			if (err != KErrNone)
   1.421 +			{
   1.422 +				LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
   1.423 +
   1.424 +				// We could not read information from the user, so the a2 argument is probably wrong
   1.425 +				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
   1.426 +				return;
   1.427 +			}
   1.428 +
   1.429 +			// Find the process
   1.430 +			DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
   1.431 +			if (pProcess == NULL)
   1.432 +			{
   1.433 +				LOG_MSG("Cannot identify process being debugged");
   1.434 +
   1.435 +				// We could not locate the process, so the user asked for the wrong one.
   1.436 +				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
   1.437 +				return;
   1.438 +			}
   1.439 +
   1.440 +			// Find the agent
   1.441 +			DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
   1.442 +			if (debugAgent == NULL)
   1.443 +			{
   1.444 +				// Bad agent means there is no tracking agent
   1.445 +				LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
   1.446 +				return;
   1.447 +			}
   1.448 +			// Agent completes/pends the request as appropriate.
   1.449 +			debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
   1.450 +
   1.451 +			break;
   1.452 +		}
   1.453 +		default:
   1.454 +			{
   1.455 +			// Don't know what to do, should not get here!
   1.456 +			LOG_MSG("DRM_DebugChannel::DoRequest was passed an unsupported request aReqNo");
   1.457 +
   1.458 +			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
   1.459 +			}
   1.460 +	}
   1.461 +}
   1.462 +
   1.463 +//
   1.464 +// DRM_DebugChannel::DoControl
   1.465 +//
   1.466 +TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   1.467 +{
   1.468 +	LOG_MSG("DRM_DebugChannel::DoControl()");
   1.469 +
   1.470 +	LOG_MSG2("DoControl Function %d", aFunction);
   1.471 +
   1.472 +	TInt err = KErrBadHandle;
   1.473 +	DThread* threadObj = NULL;
   1.474 +
   1.475 +	switch(aFunction)
   1.476 +	{
   1.477 +		/* Security first */
   1.478 +		case RRM_DebugDriver::EControlIsDebuggable:
   1.479 +		{
   1.480 +			err = IsDebuggable((TUint32)a1);
   1.481 +			break;
   1.482 +		}
   1.483 +		case RRM_DebugDriver::EControlSetBreak:
   1.484 +		{
   1.485 +			err = SetBreak((TSetBreakInfo*)a1);
   1.486 +			break;
   1.487 +		}
   1.488 +		case RRM_DebugDriver::EControlClearBreak:
   1.489 +		{
   1.490 +			err = iBreakManager->DoClearBreak((TInt32)a1);
   1.491 +			break;
   1.492 +		}
   1.493 +		case RRM_DebugDriver::EControlModifyBreak:
   1.494 +		{
   1.495 +			err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
   1.496 +			break;
   1.497 +		}
   1.498 +		case RRM_DebugDriver::EControlModifyProcessBreak:
   1.499 +		{
   1.500 +			err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
   1.501 +			break;
   1.502 +		}
   1.503 +		case RRM_DebugDriver::EControlBreakInfo:
   1.504 +		{
   1.505 +			err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
   1.506 +			break;
   1.507 +		}
   1.508 +		case RRM_DebugDriver::EControlSuspendThread:
   1.509 +		{
   1.510 +			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.511 +			if (threadObj)
   1.512 +			{
   1.513 +				err = DoSuspendThread(threadObj);
   1.514 +			}
   1.515 +			break;
   1.516 +		}
   1.517 +		case RRM_DebugDriver::EControlResumeThread:
   1.518 +		{
   1.519 +			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.520 +			if (threadObj)
   1.521 +			{
   1.522 +				err = DoResumeThread(threadObj);
   1.523 +			}
   1.524 +			break;
   1.525 +		}
   1.526 +		case RRM_DebugDriver::EControlStepRange:
   1.527 +		{
   1.528 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.529 +           if (threadObj)
   1.530 +           {
   1.531 +   			err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
   1.532 +           }
   1.533 +			break;
   1.534 +		}
   1.535 +		case RRM_DebugDriver::EControlReadMemory:
   1.536 +		{
   1.537 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.538 +           if (threadObj)
   1.539 +           {
   1.540 +   			err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
   1.541 +           }
   1.542 +			break;
   1.543 +		}
   1.544 +		case RRM_DebugDriver::EControlWriteMemory:
   1.545 +		{
   1.546 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.547 +           if (threadObj)
   1.548 +           {
   1.549 +   			err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
   1.550 +           }
   1.551 +			break;
   1.552 +		}
   1.553 +		case RRM_DebugDriver::EControlReadRegistersLegacy:
   1.554 +		{
   1.555 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.556 +           if (threadObj)
   1.557 +           {
   1.558 +   			err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
   1.559 +           }
   1.560 +			break;
   1.561 +		}
   1.562 +		case RRM_DebugDriver::EControlWriteRegistersLegacy:
   1.563 +		{
   1.564 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.565 +           if (threadObj)
   1.566 +           {
   1.567 +   			err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
   1.568 +           }
   1.569 +			break;
   1.570 +		}
   1.571 +		case RRM_DebugDriver::EControlReadRegisters:
   1.572 +		{
   1.573 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.574 +           if (threadObj)
   1.575 +           {
   1.576 +   			err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
   1.577 +           }
   1.578 +			break;
   1.579 +		}
   1.580 +		case RRM_DebugDriver::EControlWriteRegisters:
   1.581 +		{
   1.582 +           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
   1.583 +           if (threadObj)
   1.584 +           {
   1.585 +   			err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
   1.586 +           }
   1.587 +			break;
   1.588 +		}
   1.589 +		case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
   1.590 +		{
   1.591 +			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
   1.592 +
   1.593 +			TDebugFunctionality df;
   1.594 +
   1.595 +			TUint size = df.GetDebugFunctionalityBufSize();
   1.596 +
   1.597 +			// Return size to user-side in a safe manner
   1.598 +			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
   1.599 +			break;
   1.600 +		}
   1.601 +		case RRM_DebugDriver::EControlGetDebugFunctionality:
   1.602 +		{
   1.603 +			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
   1.604 +
   1.605 +			TDebugFunctionality df;
   1.606 +
   1.607 +			TUint32 dfsize = df.GetDebugFunctionalityBufSize();
   1.608 +
   1.609 +			// Alloc tmp buffer for Debug Functionality data
   1.610 +			NKern::ThreadEnterCS();
   1.611 +			TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
   1.612 +			NKern::ThreadLeaveCS();
   1.613 +			if (dfbuffer==NULL)
   1.614 +			{
   1.615 +				LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
   1.616 +
   1.617 +				// could not allocate memory
   1.618 +				return KErrNoMemory;
   1.619 +			}
   1.620 +
   1.621 +			// Temporary descriptor to hold DF data
   1.622 +			TPtr8 tmpPtr(dfbuffer,0,dfsize);
   1.623 +
   1.624 +			// Obtain the DF data
   1.625 +			if (df.GetDebugFunctionality(tmpPtr) )
   1.626 +			{
   1.627 +				// Return the DF data to the user-side
   1.628 +				err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
   1.629 +			}
   1.630 +			else
   1.631 +			{
   1.632 +				// Failed.
   1.633 +				err = KErrGeneral;
   1.634 +			}
   1.635 +
   1.636 +			// Free tmp buffer
   1.637 +			NKern::ThreadEnterCS();
   1.638 +			Kern::Free(dfbuffer);
   1.639 +			NKern::ThreadLeaveCS();
   1.640 +			break;
   1.641 +		}
   1.642 +		case RRM_DebugDriver::EControlAttachProcess:
   1.643 +		{
   1.644 +			LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
   1.645 +
   1.646 +			err = AttachProcess(a1,a2);
   1.647 +			break;
   1.648 +		}
   1.649 +		case RRM_DebugDriver::EControlDetachProcess:
   1.650 +		{
   1.651 +			LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
   1.652 +
   1.653 +			err = DetachProcess(a1,a2);
   1.654 +			break;
   1.655 +		}
   1.656 +		case RRM_DebugDriver::EControlDetachAgent:
   1.657 +		{
   1.658 +			LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
   1.659 +
   1.660 +			err = DetachAgent(a1,a2);
   1.661 +			break;
   1.662 +		}
   1.663 +		case RRM_DebugDriver::EControlSetEventAction:
   1.664 +		{
   1.665 +			LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
   1.666 +
   1.667 +			err = SetEventAction(a1,a2);
   1.668 +			break;
   1.669 +		}
   1.670 +		case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
   1.671 +		{
   1.672 +			LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
   1.673 +
   1.674 +			TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
   1.675 +
   1.676 +			// Return size to user-side in a safe manner
   1.677 +			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
   1.678 +			break;
   1.679 +		}
   1.680 +		case RRM_DebugDriver::EControlGetList:
   1.681 +		{
   1.682 +			LOG_MSG("RRM_DebugDriver::EControlGetList\n");
   1.683 +			err = GetList((TListInformation*)a1);
   1.684 +			break;
   1.685 +		}
   1.686 +		case RRM_DebugDriver::EControlStep:
   1.687 +		{
   1.688 +			LOG_MSG("RRM_DebugDriver::EControlStep\n");
   1.689 +
   1.690 +			err = Step((TUint32)a1,(TUint32)a2);
   1.691 +			break;
   1.692 +		}
   1.693 +		case RRM_DebugDriver::EControlKillProcess:
   1.694 +		{
   1.695 +			LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
   1.696 +
   1.697 +			err = KillProcess((TUint32)a1,(TUint32)a2);
   1.698 +			break;
   1.699 +		}
   1.700 +		default:
   1.701 +		{
   1.702 +			err = KErrGeneral;
   1.703 +		}
   1.704 +	}
   1.705 +
   1.706 +	if (KErrNone != err)
   1.707 +	{
   1.708 +		LOG_MSG2("Error %d from control function", err);
   1.709 +	}
   1.710 +
   1.711 +   if (threadObj)
   1.712 +   {
   1.713 +       // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
   1.714 +       threadObj->Close(NULL);
   1.715 +   }
   1.716 +
   1.717 +	return err;
   1.718 +}
   1.719 +
   1.720 +void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
   1.721 +{
   1.722 +	LOG_MSG("DRM_DebugChannel::HandleMsg()");
   1.723 +
   1.724 +	TThreadMessage& m = *(TThreadMessage*)aMsg;
   1.725 +	TInt id = m.iValue;
   1.726 +
   1.727 +	if (id == (TInt)ECloseMsg)
   1.728 +	{
   1.729 +		if (iEventHandler)
   1.730 +		{
   1.731 +			iEventHandler->Stop();
   1.732 +			iEventHandler->Close();
   1.733 +			iEventHandler = NULL;
   1.734 +		}
   1.735 +		m.Complete(KErrNone, EFalse);
   1.736 +		return;
   1.737 +	}
   1.738 +
   1.739 +	if (id == KMaxTInt)
   1.740 +	{
   1.741 +		// DoCancel
   1.742 +		DoCancel(m.Int0());
   1.743 +		m.Complete(KErrNone, ETrue);
   1.744 +		return;
   1.745 +	}
   1.746 +
   1.747 +	if (id < 0)
   1.748 +	{
   1.749 +		// DoRequest
   1.750 +		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
   1.751 +		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
   1.752 +		m.Complete(KErrNone, ETrue);
   1.753 +	}
   1.754 +	else
   1.755 +	{
   1.756 +		// DoControl
   1.757 +		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
   1.758 +		m.Complete(err, ETrue);
   1.759 +	}
   1.760 +}
   1.761 +
   1.762 +//
   1.763 +// DRM_DebugChannel::RemoveProcess
   1.764 +//
   1.765 +TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
   1.766 +	{
   1.767 +	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
   1.768 +
   1.769 +	DProcess *aProcess = (DProcess*)a1;
   1.770 +
   1.771 +	// Sanity check
   1.772 +	if (!aProcess)
   1.773 +		{
   1.774 +		// No process was specified!
   1.775 +		LOG_MSG("DRM_DebugChannel::RemoveProcess was called with an invalid process ID");
   1.776 +		return EFalse;
   1.777 +		}
   1.778 +
   1.779 +	// this is called when a process dies.  we want to mark any breakpoints in this
   1.780 +	// process space as obsolete.  the main reason for this is so we don't return
   1.781 +	// an error when the host debugger tries to clear breakpoints for the process
   1.782 +
   1.783 +	TUint32 codeAddress = 0;
   1.784 +	TUint32 codeSize = 0;
   1.785 +
   1.786 +	LOG_EVENT_MSG2("Process being removed, Name %S", aProcess->iName);
   1.787 +
   1.788 +	DCodeSeg* codeSeg = aProcess->iCodeSeg;
   1.789 +
   1.790 +	if (codeSeg)
   1.791 +		{
   1.792 +		TModuleMemoryInfo processMemoryInfo;
   1.793 +		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
   1.794 +		if (err != KErrNone)
   1.795 +			{
   1.796 +			codeAddress = processMemoryInfo.iCodeBase;
   1.797 +			codeSize = processMemoryInfo.iCodeSize;
   1.798 +			}
   1.799 +		else
   1.800 +			{
   1.801 +			LOG_MSG2("Error in getting memory info: %d", err);
   1.802 +			}
   1.803 +
   1.804 +		}
   1.805 +
   1.806 +	if (!codeAddress || !codeSize)
   1.807 +		{
   1.808 +		LOG_EVENT_MSG2("Code segment not available for process %d", aProcess->iId);
   1.809 +		// make sure there is not already a breakpoint at this address
   1.810 +		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
   1.811 +			{
   1.812 +			if (iDebugProcessList[i].iId == aProcess->iId)
   1.813 +				{
   1.814 +				codeAddress = iDebugProcessList[i].iCodeAddress;
   1.815 +				codeSize = iDebugProcessList[i].iCodeSize;
   1.816 +
   1.817 +				//now remove from the list
   1.818 +				iDebugProcessList.Remove(i);
   1.819 +				break;
   1.820 +				}
   1.821 +			}
   1.822 +		}
   1.823 +
   1.824 +	if (!codeAddress || !codeSize)
   1.825 +		{
   1.826 +		return EFalse;
   1.827 +		}
   1.828 +
   1.829 +	iBreakManager->RemoveBreaksForProcess(aProcess->iId, codeAddress, codeSize);
   1.830 +	return EFalse;
   1.831 +	}
   1.832 +
   1.833 +//
   1.834 +// DRM_DebugChannel::StartThread
   1.835 +//
   1.836 +TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
   1.837 +{
   1.838 +	LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
   1.839 +
   1.840 +	DThread *aThread = (DThread*)a1;
   1.841 +	if(!aThread)
   1.842 +		{
   1.843 +		LOG_MSG("Error getting DThread object");
   1.844 +		__NK_ASSERT_DEBUG(aThread);
   1.845 +		return EFalse;
   1.846 +		}
   1.847 +
   1.848 +	//a2 points to the thread creating the new thread.
   1.849 +	//We have no use for it at the moment so just ignore it for now
   1.850 +
   1.851 +	TDriverEventInfo info;
   1.852 +	info.iEventType = EEventsStartThread;
   1.853 +	info.iThreadId = aThread->iId;
   1.854 +	info.iThreadIdValid = ETrue;
   1.855 +	DProcess* owningProcess = aThread->iOwningProcess;
   1.856 +	if(owningProcess)
   1.857 +		{
   1.858 +		info.iProcessId = owningProcess->iId;
   1.859 +		info.iProcessIdValid = ETrue;
   1.860 +		DCodeSeg* p = owningProcess->iCodeSeg;
   1.861 +		if(p && p->iFileName)
   1.862 +			{
   1.863 +			info.iFileName.Copy(*(p->iFileName));
   1.864 +			DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
   1.865 +			if(foundProcess)
   1.866 +				{
   1.867 +				foundProcess->NotifyEvent(info);
   1.868 +				}
   1.869 +			else
   1.870 +				{
   1.871 +				LOG_EVENT_MSG2("Couldn't find process with name [%S]", p->iFileName);
   1.872 +				}
   1.873 +			}
   1.874 +		else
   1.875 +			{
   1.876 +			if(p)
   1.877 +				{
   1.878 +				LOG_EVENT_MSG("\tCode segment name missing");
   1.879 +				}
   1.880 +			else
   1.881 +				{
   1.882 +				LOG_EVENT_MSG("\tCode segment is NULL");
   1.883 +				}
   1.884 +			}
   1.885 +		}
   1.886 +	return EFalse;
   1.887 +}
   1.888 +
   1.889 +//
   1.890 +// DRM_DebugChannel::HandleAddProcessEvent
   1.891 +//
   1.892 +TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
   1.893 +{
   1.894 +	LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
   1.895 +
   1.896 +	DProcess *aProcess = (DProcess*)a1;
   1.897 +	// a2 points to the thread creating the new process.
   1.898 +	DThread *aThread = (DThread*)a2;
   1.899 +
   1.900 +	if(!aProcess)
   1.901 +		{
   1.902 +		LOG_MSG("Error getting DProcess object");
   1.903 +		__NK_ASSERT_DEBUG(aProcess);
   1.904 +		return EFalse;
   1.905 +		}
   1.906 +
   1.907 +	TDriverEventInfo info;
   1.908 +	info.iEventType = EEventsAddProcess;
   1.909 +	info.iProcessId = aProcess->iId;
   1.910 +
   1.911 +    info.iCreatorThreadId  = aThread ? aThread->iId : 0;
   1.912 +	info.iProcessIdValid = ETrue;
   1.913 +
   1.914 +	// Copy TUids
   1.915 +	info.iUids = aProcess->iUids;
   1.916 +
   1.917 +	info.iUidsValid = ETrue;
   1.918 +
   1.919 +	// copy name of the process
   1.920 +	if (aProcess->iName)
   1.921 +		{
   1.922 +		// copy the name of the process
   1.923 +		info.iFileName.Copy(*aProcess->iName);
   1.924 +
   1.925 +		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
   1.926 +		if(foundProcess)
   1.927 +			{
   1.928 +			foundProcess->NotifyEvent(info);
   1.929 +			}
   1.930 +		else
   1.931 +			{
   1.932 +			// AddProcess event does not have fully-qualified path, it has "filename.exe"
   1.933 +			// So we try a less-precise match
   1.934 +			DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
   1.935 +			if(foundProcess)
   1.936 +				{
   1.937 +				foundProcess->NotifyEvent(info);
   1.938 +				}
   1.939 +			else
   1.940 +				{
   1.941 +				LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
   1.942 +				}
   1.943 +			}
   1.944 +		}
   1.945 +	else
   1.946 +		{
   1.947 +		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
   1.948 +		}
   1.949 +
   1.950 +	return EFalse;
   1.951 +}
   1.952 +
   1.953 +//
   1.954 +// DRM_DebugChannel::HandleRemoveProcessEvent
   1.955 +//
   1.956 +TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
   1.957 +{
   1.958 +	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
   1.959 +
   1.960 +	DProcess *aProcess = (DProcess*)a1;
   1.961 +	if(!aProcess)
   1.962 +		{
   1.963 +		LOG_MSG("Error getting DProcess object");
   1.964 +		__NK_ASSERT_DEBUG(aProcess);
   1.965 +		return EFalse;
   1.966 +		}
   1.967 +
   1.968 +	// a2 points to the thread creating the new process.
   1.969 +	// We have no use for it at the moment so just ignore it for now
   1.970 +	// Also, it may not be known and therefore NULL
   1.971 +
   1.972 +	TDriverEventInfo info;
   1.973 +	info.iEventType = EEventsRemoveProcess;
   1.974 +	info.iProcessId = aProcess->iId;
   1.975 +	info.iProcessIdValid = ETrue;
   1.976 +
   1.977 +	// copy name of the process
   1.978 +	if (aProcess->iName)
   1.979 +		{
   1.980 +		// copy the name of the process
   1.981 +		info.iFileName.Copy(*aProcess->iName);
   1.982 +
   1.983 +		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(aProcess->iName));
   1.984 +		if(foundProcess)
   1.985 +			{
   1.986 +			foundProcess->NotifyEvent(info);
   1.987 +			}
   1.988 +		else
   1.989 +			{
   1.990 +			// RemoveProcess event does not have fully-qualified path, it has "filename.exe"
   1.991 +			// So we try a less-precise match
   1.992 +			DTargetProcess* foundProcess = TheDProcessTracker.FuzzyFindProcess(*(aProcess->iName));
   1.993 +			if(foundProcess)
   1.994 +				{
   1.995 +				foundProcess->NotifyEvent(info);
   1.996 +				}
   1.997 +			else
   1.998 +				{
   1.999 +				LOG_EVENT_MSG2("Couldn't find process with name [%S]", aProcess->iName);
  1.1000 +				}
  1.1001 +			}
  1.1002 +
  1.1003 +		}
  1.1004 +	else
  1.1005 +		{
  1.1006 +		LOG_EVENT_MSG("DRM_DebugChannel::AddProcess - No iName for this process");
  1.1007 +		}
  1.1008 +
  1.1009 +	return EFalse;
  1.1010 +}
  1.1011 +
  1.1012 +//
  1.1013 +// DRM_DebugChannel::AddLibrary
  1.1014 +//
  1.1015 +TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
  1.1016 +{
  1.1017 +	LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
  1.1018 +
  1.1019 +	DLibrary *aLibrary = (DLibrary*)a1;
  1.1020 +	DThread *aThread = (DThread*)a2;
  1.1021 +
  1.1022 +	// sanity check
  1.1023 +	if (!aLibrary)
  1.1024 +	{
  1.1025 +		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
  1.1026 +		return EFalse;
  1.1027 +	}
  1.1028 +
  1.1029 +	if (!aThread)
  1.1030 +	{
  1.1031 +		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
  1.1032 +		return EFalse;
  1.1033 +	}
  1.1034 +
  1.1035 +	LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
  1.1036 +
  1.1037 +	if (aThread)
  1.1038 +	{
  1.1039 +		// make sure this is not the debugger thread
  1.1040 +		if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
  1.1041 +		{
  1.1042 +			TDriverEventInfo info;
  1.1043 +
  1.1044 +			info.iEventType = EEventsAddLibrary;
  1.1045 +			info.iProcessId = aThread->iOwningProcess->iId;
  1.1046 +			info.iProcessIdValid = ETrue;
  1.1047 +			info.iThreadId = aThread->iId;
  1.1048 +			info.iThreadIdValid = ETrue;
  1.1049 +
  1.1050 +			//get the code address
  1.1051 +			DCodeSeg* codeSeg = aLibrary->iCodeSeg;
  1.1052 +			if (!codeSeg)
  1.1053 +			{
  1.1054 +				LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
  1.1055 +				return EFalse;
  1.1056 +			}
  1.1057 +
  1.1058 +			// Uid3
  1.1059 +			info.iUids = codeSeg->iUids;
  1.1060 +			info.iUidsValid = ETrue;
  1.1061 +
  1.1062 +			TModuleMemoryInfo memoryInfo;
  1.1063 +			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
  1.1064 +			if (err != KErrNone)
  1.1065 +			{
  1.1066 +				LOG_EVENT_MSG2("Error in getting memory info: %d", err);
  1.1067 +				return EFalse;
  1.1068 +			}
  1.1069 +
  1.1070 +			info.iCodeAddress = memoryInfo.iCodeBase;
  1.1071 +			info.iDataAddress = memoryInfo.iInitialisedDataBase;
  1.1072 +
  1.1073 +			info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
  1.1074 +
  1.1075 +			//queue up or complete the event
  1.1076 +			info.iArg1 = a1;
  1.1077 +			info.iArg2 = a2;
  1.1078 +			NotifyEvent(info);
  1.1079 +		}
  1.1080 +
  1.1081 +	}
  1.1082 +	return EFalse;
  1.1083 +}
  1.1084 +
  1.1085 +//
  1.1086 +// DRM_DebugChannel::RemoveLibrary
  1.1087 +//
  1.1088 +TBool DRM_DebugChannel::RemoveLibrary(TAny* a1, TAny* a2)
  1.1089 +	{
  1.1090 +	LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary()");
  1.1091 +	DLibrary *aLibrary = (DLibrary*)a1;
  1.1092 +
  1.1093 +	// sanity check
  1.1094 +	if (!aLibrary)
  1.1095 +		{
  1.1096 +		LOG_EVENT_MSG("DRM_DebugChannel::RemoveLibrary called with no library specified");
  1.1097 +		return EFalse;
  1.1098 +		}
  1.1099 +
  1.1100 +	LOG_EVENT_MSG2(("Lib unloaded: %S"), aLibrary->iName);
  1.1101 +
  1.1102 +	// this is called when all handles to this library have been closed.  this can happen when a process dies, or when a dll is
  1.1103 +	// unloaded while the process lives on.  in former case, we don't need to notify the host debugger because that process is
  1.1104 +	// dying anyway.  for the latter case, we do need to notify the host so it can unload the symbolics, etc.
  1.1105 +
  1.1106 +	DThread* aThread = &Kern::CurrentThread();
  1.1107 +
  1.1108 +	if ((aThread) &&
  1.1109 +			(aThread != iClientThread) &&
  1.1110 +			(aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
  1.1111 +		{
  1.1112 +		//the library gets unloaded only when the mapcount is 0.
  1.1113 +		if (aLibrary->iMapCount != 0)
  1.1114 +			return EFalse;
  1.1115 +
  1.1116 +		DCodeSeg* codeSeg = aLibrary->iCodeSeg;
  1.1117 +		if (!codeSeg)
  1.1118 +			{
  1.1119 +			LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
  1.1120 +			return EFalse;
  1.1121 +			}
  1.1122 +
  1.1123 +		TModuleMemoryInfo processMemoryInfo;
  1.1124 +		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
  1.1125 +		if (err != KErrNone)
  1.1126 +			{
  1.1127 +			LOG_EVENT_MSG2("Error in getting memory info: %d", err);
  1.1128 +			return EFalse;
  1.1129 +			}
  1.1130 +
  1.1131 +		TUint32 codeAddress = processMemoryInfo.iCodeBase;
  1.1132 +		TUint32 codeSize = processMemoryInfo.iCodeSize;
  1.1133 +
  1.1134 +		// first invalidate all breakpoints that were set in the library code
  1.1135 +		iBreakManager->InvalidateLibraryBreakPoints(codeAddress, codeSize);
  1.1136 +		DProcess *process = &Kern::CurrentProcess();
  1.1137 +		RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);
  1.1138 +
  1.1139 +		for (TInt j=0; j<dynamicCode->Count(); j++)
  1.1140 +			{
  1.1141 +			if ((*dynamicCode)[j].iLib == aLibrary)
  1.1142 +				{
  1.1143 +				TDriverEventInfo info;
  1.1144 +
  1.1145 +				info.iEventType = EEventsRemoveLibrary;
  1.1146 +				info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
  1.1147 +				//info.iFileName.ZeroTerminate();
  1.1148 +				info.iProcessId = process->iId;
  1.1149 +				info.iProcessIdValid = ETrue;
  1.1150 +				info.iThreadId = 0xFFFFFFFF; // don't care!
  1.1151 +				info.iThreadIdValid = EFalse;
  1.1152 +				// Uid3
  1.1153 +				info.iUids = codeSeg->iUids;
  1.1154 +				info.iUidsValid = ETrue;
  1.1155 +
  1.1156 +				//queue up or complete the event
  1.1157 +				info.iArg1 = a1;
  1.1158 +				info.iArg2 = a2;
  1.1159 +				NotifyEvent(info);
  1.1160 +				}
  1.1161 +			}
  1.1162 +		}
  1.1163 +	return EFalse;
  1.1164 +	}
  1.1165 +
  1.1166 +//
  1.1167 +// DRM_DebugChannel::HandleEventKillThread
  1.1168 +//
  1.1169 +TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
  1.1170 +{
  1.1171 +	LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
  1.1172 +
  1.1173 +	DThread* currentThread = &Kern::CurrentThread();
  1.1174 +	if (!currentThread)
  1.1175 +	{
  1.1176 +		LOG_MSG("Error getting current thread");
  1.1177 +		__NK_ASSERT_DEBUG(currentThread);
  1.1178 +		return EFalse;
  1.1179 +	}
  1.1180 +
  1.1181 +	// a1 should point to the current thread, check this to make sure it does
  1.1182 +	__NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
  1.1183 +
  1.1184 +	TDriverEventInfo info;
  1.1185 +
  1.1186 +	info.iProcessId = currentThread->iOwningProcess->iId;
  1.1187 +	info.iProcessIdValid = ETrue;
  1.1188 +	info.iThreadId = currentThread->iId;
  1.1189 +	info.iThreadIdValid = ETrue;
  1.1190 +	// 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
  1.1191 +	TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
  1.1192 +	if(err != KErrNone)
  1.1193 +	{
  1.1194 +		LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
  1.1195 +	}
  1.1196 +
  1.1197 +	if (currentThread->iExitType == EExitPanic)
  1.1198 +	{
  1.1199 +		info.iPanicCategory.Copy(currentThread->iExitCategory);
  1.1200 +	}
  1.1201 +	info.iExceptionNumber = currentThread->iExitReason;
  1.1202 +	info.iExitType = currentThread->iExitType;
  1.1203 +	info.iEventType = EEventsKillThread;
  1.1204 +
  1.1205 +	// Are we debugging this process - decide based on iFileName
  1.1206 +	DCodeSeg* codeSeg = currentThread->iOwningProcess->iCodeSeg;
  1.1207 +
  1.1208 +	// remove all the breakpoints in this thread, whether we are debugging it or not.
  1.1209 +	iBreakManager->DoRemoveThreadBreaks(info.iThreadId);
  1.1210 +
  1.1211 +	// if the code seg exists then get the file name from it and check we're debugging it
  1.1212 +	if(codeSeg)
  1.1213 +		{
  1.1214 +		DTargetProcess* foundProcess = TheDProcessTracker.FindProcess(*(codeSeg->iFileName));
  1.1215 +		if(!foundProcess)
  1.1216 +			{
  1.1217 +			// not debugging this process so return false
  1.1218 +			return EFalse;
  1.1219 +			}
  1.1220 +		}
  1.1221 +	else
  1.1222 +		{
  1.1223 +		// can't validate that we are debugging the thread
  1.1224 +		return EFalse;
  1.1225 +		}
  1.1226 +
  1.1227 +	info.iArg1 = a1;
  1.1228 +	info.iArg2 = a2;
  1.1229 +	NotifyEvent(info);
  1.1230 +
  1.1231 +	return ETrue;
  1.1232 +}
  1.1233 +
  1.1234 +//
  1.1235 +// DRM_DebugChannel::HandleSwException
  1.1236 +//
  1.1237 +TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
  1.1238 +{
  1.1239 +	LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
  1.1240 +	TExcType aExcType = (TExcType)(TInt)a1;
  1.1241 +
  1.1242 +	TDriverEventInfo info;
  1.1243 +
  1.1244 +	DThread* currentThread = &Kern::CurrentThread();
  1.1245 +	if (!currentThread)
  1.1246 +	{
  1.1247 +		LOG_MSG("Error getting current thread");
  1.1248 +		__NK_ASSERT_DEBUG(currentThread);
  1.1249 +		return EFalse;
  1.1250 +	}
  1.1251 +
  1.1252 +	info.iProcessId = currentThread->iOwningProcess->iId;
  1.1253 +	info.iProcessIdValid = ETrue;
  1.1254 +	info.iThreadId = currentThread->iId;
  1.1255 +	info.iThreadIdValid = ETrue;
  1.1256 +	TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
  1.1257 +	if(err != KErrNone)
  1.1258 +	{
  1.1259 +		LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
  1.1260 +	}
  1.1261 +	info.iExceptionNumber = aExcType;
  1.1262 +	info.iEventType = EEventsSwExc;
  1.1263 +	info.iArg1 = a1;
  1.1264 +	info.iArg2 = a2;
  1.1265 +
  1.1266 +	NotifyEvent(info);
  1.1267 +
  1.1268 +	return EFalse;
  1.1269 +}
  1.1270 +
  1.1271 +//
  1.1272 +// DRM_DebugChannel::HandleHwException
  1.1273 +//
  1.1274 +TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
  1.1275 +{
  1.1276 +	LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
  1.1277 +	TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
  1.1278 +
  1.1279 +	// sanity check
  1.1280 +	if (!aExcInfo)
  1.1281 +	{
  1.1282 +		LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
  1.1283 +		__NK_ASSERT_DEBUG(aExcInfo);
  1.1284 +		return EFalse;
  1.1285 +	}
  1.1286 +
  1.1287 +	TDriverEventInfo info;
  1.1288 +
  1.1289 +	DThread* currentThread = &Kern::CurrentThread();
  1.1290 +	LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
  1.1291 +
  1.1292 +	if (!currentThread)
  1.1293 +	{
  1.1294 +		LOG_MSG("Error getting current thread");
  1.1295 +		__NK_ASSERT_DEBUG(currentThread);
  1.1296 +		return EFalse;
  1.1297 +	}
  1.1298 +
  1.1299 +	info.iProcessId = currentThread->iOwningProcess->iId;
  1.1300 +	info.iProcessIdValid = ETrue;
  1.1301 +	info.iThreadId = currentThread->iId;
  1.1302 +	info.iThreadIdValid = ETrue;
  1.1303 +	info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
  1.1304 +	info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
  1.1305 +	LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
  1.1306 +			aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
  1.1307 +
  1.1308 +	info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
  1.1309 +	info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
  1.1310 +	info.iRmdArmExcInfo.iR2= aExcInfo->iR2;
  1.1311 +	info.iRmdArmExcInfo.iR3= aExcInfo->iR3;
  1.1312 +
  1.1313 +	info.iRmdArmExcInfo.iR4= aExcInfo->iR4;
  1.1314 +	info.iRmdArmExcInfo.iR5= aExcInfo->iR5;
  1.1315 +	info.iRmdArmExcInfo.iR6= aExcInfo->iR6;
  1.1316 +	info.iRmdArmExcInfo.iR7= aExcInfo->iR7;
  1.1317 +	info.iRmdArmExcInfo.iR8= aExcInfo->iR8;
  1.1318 +	info.iRmdArmExcInfo.iR9= aExcInfo->iR9;
  1.1319 +	info.iRmdArmExcInfo.iR10= aExcInfo->iR10;
  1.1320 +	info.iRmdArmExcInfo.iR11= aExcInfo->iR11;
  1.1321 +	info.iRmdArmExcInfo.iR12= aExcInfo->iR12;
  1.1322 +
  1.1323 +	info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
  1.1324 +	info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
  1.1325 +	info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
  1.1326 +	LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
  1.1327 +			aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
  1.1328 +
  1.1329 +	info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
  1.1330 +	info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
  1.1331 +	info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
  1.1332 +	info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
  1.1333 +	LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
  1.1334 +			aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
  1.1335 +
  1.1336 +	switch (aExcInfo->iExcCode)
  1.1337 +	{
  1.1338 +		case 0:
  1.1339 +			info.iExceptionNumber = EExcCodeAbort;
  1.1340 +			LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
  1.1341 +			break;
  1.1342 +		case 1:
  1.1343 +			info.iExceptionNumber = EExcDataAbort;
  1.1344 +			LOG_EVENT_MSG(" iExcCode == 1 => EExcDataAbort");
  1.1345 +			break;
  1.1346 +		case 2:
  1.1347 +			info.iExceptionNumber = EExcInvalidOpCode;
  1.1348 +			LOG_EVENT_MSG(" iExcCode == 2 => EExcInvalidOpCode");
  1.1349 +			break;
  1.1350 +		default:
  1.1351 +			// new event? Something gone wrong?
  1.1352 +			__NK_ASSERT_DEBUG(EFalse);
  1.1353 +			return EFalse;
  1.1354 +
  1.1355 +	}
  1.1356 +	info.iEventType = EEventsHwExc;
  1.1357 +
  1.1358 +	info.iArg1 = a1;
  1.1359 +	info.iArg2 = a2;
  1.1360 +
  1.1361 +	if(EExcInvalidOpCode == info.iExceptionNumber)
  1.1362 +		{
  1.1363 +		return HandleInvalidOpCodeException(info, currentThread);
  1.1364 +		}
  1.1365 +
  1.1366 +	NotifyEvent(info);
  1.1367 +	return EFalse;
  1.1368 +}
  1.1369 +
  1.1370 +//
  1.1371 +// DRM_DebugChannel::HandUserTrace
  1.1372 +//
  1.1373 +TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
  1.1374 +{
  1.1375 +	LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
  1.1376 +
  1.1377 +	DThread* currentThread = &Kern::CurrentThread();
  1.1378 +	if (!currentThread)
  1.1379 +	{
  1.1380 +		LOG_EVENT_MSG("Error getting current thread");
  1.1381 +		__NK_ASSERT_DEBUG(currentThread);
  1.1382 +		return EFalse;
  1.1383 +	}
  1.1384 +
  1.1385 +	TDriverEventInfo info;
  1.1386 +	info.iProcessId = currentThread->iOwningProcess->iId;
  1.1387 +	info.iProcessIdValid = ETrue;
  1.1388 +	info.iThreadId = currentThread->iId;
  1.1389 +	info.iThreadIdValid = ETrue;
  1.1390 +	info.iEventType = EEventsUserTrace;
  1.1391 +	info.iArg1 = a1;
  1.1392 +	info.iArg2 = a2;
  1.1393 +
  1.1394 +	TInt err = KErrNone;
  1.1395 +
  1.1396 +	//User Trace info
  1.1397 +	XTRAP(err, XT_DEFAULT, kumemget(info.iUserTraceText, info.iArg1, (TInt)a2));
  1.1398 +	if(KErrNone != err)
  1.1399 +		{
  1.1400 +		return EFalse;
  1.1401 +		}
  1.1402 +
  1.1403 +	info.iMessageStatus = ESingleMessage;
  1.1404 +
  1.1405 +	NotifyEvent(info);
  1.1406 +
  1.1407 +	return EFalse;
  1.1408 +}
  1.1409 +
  1.1410 +//
  1.1411 +// DRM_DebugChannel::HandleException
  1.1412 +//
  1.1413 +TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
  1.1414 +{
  1.1415 +	LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
  1.1416 +
  1.1417 +	TInt err = KErrNone;
  1.1418 +
  1.1419 +	TUint32 inst = KArmBreakPoint;
  1.1420 +	TInt instSize = 4;
  1.1421 +
  1.1422 +	// change these for thumb mode
  1.1423 +	TUint32 regValue;
  1.1424 +	err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
  1.1425 +	if(err != KErrNone)
  1.1426 +	{
  1.1427 +		LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
  1.1428 +	}
  1.1429 +	if (regValue & ECpuThumb)
  1.1430 +	{
  1.1431 +		inst = KThumbBreakPoint;
  1.1432 +		instSize = 2;
  1.1433 +	}
  1.1434 +
  1.1435 +	TUint32 instruction = 0;
  1.1436 +	err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
  1.1437 +
  1.1438 +	if (KErrNone != err)
  1.1439 +		LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
  1.1440 +
  1.1441 +	if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
  1.1442 +	{
  1.1443 +		TInt err = DoSuspendThread(aCurrentThread);
  1.1444 +		if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
  1.1445 +			{
  1.1446 +			LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
  1.1447 +			return EFalse;
  1.1448 +			}
  1.1449 +
  1.1450 +		// the exception was a breakpoint instruction.  see if we have a breakpoint at that address
  1.1451 +		TBreakEntry* breakEntry = NULL;
  1.1452 +		do
  1.1453 +		{
  1.1454 +			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  1.1455 +			if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
  1.1456 +			{
  1.1457 +				LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
  1.1458 +
  1.1459 +				TBreakEntry tempBreakEntry = *breakEntry;
  1.1460 +
  1.1461 +				//change the event type to breakpoint type
  1.1462 +				aEventInfo.iEventType = breakEntry->iThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint;
  1.1463 +
  1.1464 +				// enable any breakpoints we had to disable for this thread
  1.1465 +				err = iBreakManager->DoEnableDisabledBreak(aEventInfo.iThreadId);
  1.1466 +				if (KErrNone != err)
  1.1467 +					LOG_MSG2("Error %d enabling disabled breakpoints", err);
  1.1468 +
  1.1469 +				// see if this is a temp breakpoint
  1.1470 +				if (iBreakManager->IsTemporaryBreak(*breakEntry))
  1.1471 +				{
  1.1472 +					// this was a temp breakpoint, so we need to clear it now
  1.1473 +					err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
  1.1474 +					if (KErrNone != err)
  1.1475 +						LOG_MSG2("Error %d clearing temp breakpoint", err);
  1.1476 +
  1.1477 +					// Find out how many steps remain to be done
  1.1478 +
  1.1479 +					// reduce the number of steps to complete by 1
  1.1480 +					tempBreakEntry.iNumSteps--;
  1.1481 +
  1.1482 +					LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
  1.1483 +
  1.1484 +					// New. If we have not finished do all the steps, continue stepping and don't notify event
  1.1485 +					if (tempBreakEntry.iNumSteps)
  1.1486 +					{
  1.1487 +						LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
  1.1488 +						err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
  1.1489 +						if (err != KErrNone)
  1.1490 +						{
  1.1491 +							LOG_EVENT_MSG("Failed to continue stepping\n");
  1.1492 +
  1.1493 +							// what do we do? might as well stop here and tell the user
  1.1494 +							NotifyEvent(aEventInfo);
  1.1495 +
  1.1496 +							return ETrue;
  1.1497 +						}
  1.1498 +
  1.1499 +						// continue as though no event occured. No need to suspend/resume anything...
  1.1500 +						LOG_EVENT_MSG("Continuing to step\n");
  1.1501 +						return ETrue;
  1.1502 +					}
  1.1503 +
  1.1504 +					// Is this a case where we just want to continue?
  1.1505 +					if (tempBreakEntry.iResumeOnceOutOfRange)
  1.1506 +					{
  1.1507 +					LOG_EVENT_MSG("PC is out of range, continuing thread");
  1.1508 +						DoResumeThread(aCurrentThread);
  1.1509 +
  1.1510 +						return ETrue;
  1.1511 +    					}
  1.1512 +					}
  1.1513 +
  1.1514 +				// if the breakpoint is thread specific, make sure it's the right thread
  1.1515 +				// if not, just continue the thread.  take special care if it's the debugger
  1.1516 +				// thread.  if it hits a regular breakpoint, we NEVER want to stop at it.  if
  1.1517 +				// it hits a temp breakpoint, we're probably just stepping past a real breakpoint
  1.1518 +				// and we do need to handle it.
  1.1519 +				TBool needToResume = (tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iThreadId) ||
  1.1520 +					(!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
  1.1521 +
  1.1522 +				if (needToResume)
  1.1523 +				{
  1.1524 +					LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
  1.1525 +					err = DoResumeThread(aCurrentThread);
  1.1526 +					if (KErrNone != err)
  1.1527 +						LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
  1.1528 +
  1.1529 +					return EFalse;
  1.1530 +				}
  1.1531 +
  1.1532 +				//normal user break point, just notify the event
  1.1533 +				break;
  1.1534 +			}
  1.1535 +		} while(breakEntry);
  1.1536 +	}
  1.1537 +
  1.1538 +	NotifyEvent(aEventInfo);
  1.1539 +
  1.1540 +	return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
  1.1541 +}
  1.1542 +
  1.1543 +//
  1.1544 +// DRM_DebugChannel::SetBreak
  1.1545 +//
  1.1546 +TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
  1.1547 +{
  1.1548 +	LOG_MSG("DRM_DebugChannel::SetBreak()");
  1.1549 +
  1.1550 +	TInt err = KErrNone;
  1.1551 +
  1.1552 +	if (!aBreakInfo)
  1.1553 +	{
  1.1554 +		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
  1.1555 +		return KErrArgument;
  1.1556 +	}
  1.1557 +
  1.1558 +	//User side memory is not accessible directly
  1.1559 +	TSetBreakInfo info;
  1.1560 +	err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
  1.1561 +	if (err != KErrNone)
  1.1562 +	{
  1.1563 +		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
  1.1564 +		return err;
  1.1565 +	}
  1.1566 +
  1.1567 +	DProcess* process = NULL;
  1.1568 +	if(info.iThreadSpecific)
  1.1569 +		{
  1.1570 +		// if the target thread is not suspended then return KErrInUse
  1.1571 +		if(!TheDProcessTracker.CheckSuspended(info.iId))
  1.1572 +			{
  1.1573 +			LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not suspended.", info.iId);
  1.1574 +			return KErrInUse;
  1.1575 +			}
  1.1576 +		DThread* thread = DebugUtils::OpenThreadHandle(info.iId);
  1.1577 +		if(!thread)
  1.1578 +			{
  1.1579 +			LOG_MSG2("DRM_DebugChannel::SetBreak() Thread with id 0x%08x not found", info.iId);
  1.1580 +			return KErrNotFound;
  1.1581 +			}
  1.1582 +		process = DebugUtils::OpenProcessHandle(thread->iOwningProcess->iId);
  1.1583 +		thread->Close(NULL);
  1.1584 +		}
  1.1585 +	else
  1.1586 +		{
  1.1587 +		process = DebugUtils::OpenProcessHandle(info.iId);
  1.1588 +		}
  1.1589 +	if(!process)
  1.1590 +		{
  1.1591 +		LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
  1.1592 +		return KErrNotFound;
  1.1593 +		}
  1.1594 +	TBool found = EFalse;
  1.1595 +	for(TInt i=0; i<iDebugProcessList.Count(); i++)
  1.1596 +		{
  1.1597 +		if(process->iId == iDebugProcessList[i].iId)
  1.1598 +			{
  1.1599 +			found = ETrue;
  1.1600 +			}
  1.1601 +		}
  1.1602 +	if(!found)
  1.1603 +		{
  1.1604 +		DCodeSeg* codeSeg = process->iCodeSeg;
  1.1605 +		if (!codeSeg)
  1.1606 +			{
  1.1607 +			LOG_MSG2("DRM_DebugChannel::SetBreak() Code seg for process with id 0x%08x not found", process->iId);
  1.1608 +			return KErrNotFound;
  1.1609 +			}
  1.1610 +
  1.1611 +		TModuleMemoryInfo memoryInfo;
  1.1612 +		TInt err = codeSeg->GetMemoryInfo(memoryInfo, process);
  1.1613 +		if (err != KErrNone)
  1.1614 +			{
  1.1615 +			LOG_MSG2("DRM_DebugChannel::SetBreak() Error getting memory info for process with id 0x%08x", process->iId);
  1.1616 +			return err;
  1.1617 +			}
  1.1618 +
  1.1619 +		//add this process to the list of processes that we are debugging
  1.1620 +		TProcessInfo processInfo(process->iId, memoryInfo.iCodeBase, memoryInfo.iCodeSize, memoryInfo.iInitialisedDataBase);
  1.1621 +		iDebugProcessList.Append(processInfo);
  1.1622 +		process->Close(NULL);
  1.1623 +		}
  1.1624 +
  1.1625 +	if (!info.iBreakId) //first check if the iId address is valid
  1.1626 +		return KErrArgument;
  1.1627 +
  1.1628 +	if (err == KErrNone)
  1.1629 +	{
  1.1630 +		TInt32 iBreakId;
  1.1631 +
  1.1632 +		err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
  1.1633 +
  1.1634 +		if (err == KErrNone)
  1.1635 +		{
  1.1636 +			err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
  1.1637 +		}
  1.1638 +	}
  1.1639 +	return err;
  1.1640 +}
  1.1641 +
  1.1642 +//
  1.1643 +// DRM_DebugChannel::StepRange
  1.1644 +//
  1.1645 +TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
  1.1646 +{
  1.1647 +	LOG_MSG("DRM_DebugChannel::StepRange()");
  1.1648 +
  1.1649 +	TInt err = KErrNone;
  1.1650 +
  1.1651 +	if(!TheDProcessTracker.CheckSuspended(aThread))
  1.1652 +		{
  1.1653 +		LOG_MSG2("DRM_DebugChannel::StepRange() Thread with id 0x%08x not suspended.", aThread->iId);
  1.1654 +		return KErrInUse;
  1.1655 +		}
  1.1656 +
  1.1657 +	if (!aStepInfo)
  1.1658 +		return KErrArgument;
  1.1659 +
  1.1660 +	TRM_DebugStepInfo info(0, 0, 0);
  1.1661 +	err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TRM_DebugStepInfo));
  1.1662 +
  1.1663 +	if (err != KErrNone)
  1.1664 +		return err;
  1.1665 +
  1.1666 +	err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
  1.1667 +
  1.1668 +	return err;
  1.1669 +}
  1.1670 +
  1.1671 +/**
  1.1672 +Read memory from a target thread and return the data to the client. If the
  1.1673 +memory block has breakpoints in it then the correct values are placed in the
  1.1674 +returned data
  1.1675 +
  1.1676 +@param aThread pointer to thread whose memory space the memory is to be read from
  1.1677 +@param aMemoryInfo information about what memory to read
  1.1678 +
  1.1679 +@return KErrNone if memory read successfully,
  1.1680 +        KErrArgument if aMemoryInfo is not initialised correctly,
  1.1681 +        KErrNoMemory if a temporary buffer could not be allocated,
  1.1682 +        KErrBadHandle if aThread is invalid,
  1.1683 +        or another of the system wide error codes
  1.1684 +*/
  1.1685 +TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
  1.1686 +{
  1.1687 +	LOG_MSG("DRM_DebugChannel::ReadMemory()");
  1.1688 +
  1.1689 +	TInt err = KErrNone;
  1.1690 +
  1.1691 +	if (!aMemoryInfo)
  1.1692 +		return KErrArgument;
  1.1693 +
  1.1694 +	TRM_DebugMemoryInfo info(0, 0, 0);
  1.1695 +	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
  1.1696 +	if (err != KErrNone)
  1.1697 +		return err;
  1.1698 +
  1.1699 +	if (!info.iData)
  1.1700 +		return KErrArgument;
  1.1701 +
  1.1702 +	NKern::ThreadEnterCS();
  1.1703 +	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
  1.1704 +	NKern::ThreadLeaveCS();
  1.1705 +	if (!data)
  1.1706 +	{
  1.1707 +		return KErrNoMemory;
  1.1708 +	}
  1.1709 +
  1.1710 +	TPtr8 dataDes(data, info.iLength);
  1.1711 +
  1.1712 +	err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
  1.1713 +	if (err == KErrNone)
  1.1714 +		{
  1.1715 +		err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
  1.1716 +		}
  1.1717 +
  1.1718 +	NKern::ThreadEnterCS();
  1.1719 +	Kern::Free(data);
  1.1720 +	NKern::ThreadLeaveCS();
  1.1721 +
  1.1722 +	return err;
  1.1723 +}
  1.1724 +
  1.1725 +/**
  1.1726 +Attempt to write memory to aThread's address space
  1.1727 +
  1.1728 +@param aThread thread to whose address space memory is to be written
  1.1729 +@param aMemoryInfo memory info object representing the data to write
  1.1730 +
  1.1731 +@return KErrNone if memory written successfully,
  1.1732 +        KErrNoMemory if memory could not be allocated
  1.1733 +        KErrArgument if aMemoryInfo is NULL, if aMemoryInfo.iData is NULL,
  1.1734 +        if aMemoryInfo.iLength is greater than than the length of the passed
  1.1735 +        in descrptor
  1.1736 +        KErrBadHandle if aThread is invalid,
  1.1737 +	or another of the system wide error codes
  1.1738 +*/
  1.1739 +TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
  1.1740 +{
  1.1741 +	LOG_MSG("DRM_DebugChannel::WriteMemory()");
  1.1742 +
  1.1743 +	TInt err = KErrNone;
  1.1744 +
  1.1745 +	if (!aMemoryInfo)
  1.1746 +		return KErrArgument;
  1.1747 +
  1.1748 +	TRM_DebugMemoryInfo info(0, 0, 0);
  1.1749 +	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TRM_DebugMemoryInfo));
  1.1750 +	if (err != KErrNone)
  1.1751 +		return err;
  1.1752 +
  1.1753 +	if (!info.iData)
  1.1754 +		return KErrArgument;
  1.1755 +
  1.1756 +	NKern::ThreadEnterCS();
  1.1757 +	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
  1.1758 +	NKern::ThreadLeaveCS();
  1.1759 +	if (!data)
  1.1760 +	{
  1.1761 +		return KErrNoMemory;
  1.1762 +	}
  1.1763 +
  1.1764 +	TPtr8 dataDes(data, info.iLength);
  1.1765 +
  1.1766 +	err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
  1.1767 +	if (err == KErrNone)
  1.1768 +	{
  1.1769 +		err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
  1.1770 +	}
  1.1771 +
  1.1772 +	NKern::ThreadEnterCS();
  1.1773 +	Kern::Free(data);
  1.1774 +	NKern::ThreadLeaveCS();
  1.1775 +
  1.1776 +	return err;
  1.1777 +}
  1.1778 +
  1.1779 +//
  1.1780 +// DRM_DebugChannel::ReadRegisters
  1.1781 +//
  1.1782 +TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
  1.1783 +{
  1.1784 +	LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
  1.1785 +
  1.1786 +	TInt err = KErrNone;
  1.1787 +
  1.1788 +	if (!aRegisterInfo)
  1.1789 +		return KErrArgument;
  1.1790 +
  1.1791 +	TRM_DebugRegisterInfo info(0, 0, 0);
  1.1792 +	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
  1.1793 +	if (err != KErrNone)
  1.1794 +		return err;
  1.1795 +
  1.1796 +	if (!info.iValues)
  1.1797 +		return KErrArgument;
  1.1798 +
  1.1799 +	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
  1.1800 +
  1.1801 +	NKern::ThreadEnterCS();
  1.1802 +	TUint8 *values = (TUint8*)Kern::Alloc(length);
  1.1803 +	NKern::ThreadLeaveCS();
  1.1804 +	if (!values)
  1.1805 +	{
  1.1806 +		return KErrNoMemory;
  1.1807 +	}
  1.1808 +
  1.1809 +	TPtr8 valuesDes(values, length);
  1.1810 +
  1.1811 +	err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
  1.1812 +	if (err == KErrNone)
  1.1813 +	{
  1.1814 +		err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
  1.1815 +	}
  1.1816 +
  1.1817 +	NKern::ThreadEnterCS();
  1.1818 +	Kern::Free(values);
  1.1819 +	NKern::ThreadLeaveCS();
  1.1820 +
  1.1821 +	return err;
  1.1822 +}
  1.1823 +
  1.1824 +/**
  1.1825 +Get listing information.
  1.1826 +
  1.1827 +@param aListInformation pointer to a TListInformation object containing the
  1.1828 +       user specified listings information
  1.1829 +
  1.1830 +@return KErrNone on success,
  1.1831 +        KErrTooBig if the kernel's data is too big to fit in the passed buffer,
  1.1832 +        KErrArgument if aListInformation is NULL,
  1.1833 +	or one of the other system-wide error codes
  1.1834 +*/
  1.1835 +TInt DRM_DebugChannel::GetList(TListInformation* aListInformation) const
  1.1836 +	{
  1.1837 +	LOG_MSG("DRM_DebugChannel::GetList()");
  1.1838 +
  1.1839 +	TInt err = KErrNone;
  1.1840 +
  1.1841 +	if(aListInformation == NULL)
  1.1842 +		{
  1.1843 +		return KErrArgument;
  1.1844 +		}
  1.1845 +
  1.1846 +	//read DSS' data into local structure
  1.1847 +	TListInformation info;
  1.1848 +	err = Kern::ThreadRawRead(iClientThread, aListInformation, (TUint8*)&info, sizeof(TListInformation));
  1.1849 +	if(err != KErrNone)
  1.1850 +		{
  1.1851 +		return err;
  1.1852 +		}
  1.1853 +
  1.1854 +	//check arguments
  1.1855 +	TPtr8 buffer(NULL, 0);
  1.1856 +	err = AllocAndReadDes(iClientThread, *info.iBuffer, buffer);
  1.1857 +	if(err != KErrNone)
  1.1858 +		{
  1.1859 +		//need to free the buffer if it was allocated
  1.1860 +		if(err != KErrNoMemory)
  1.1861 +			{
  1.1862 +			NKern::ThreadEnterCS();
  1.1863 +			Kern::Free((TAny*)buffer.Ptr());
  1.1864 +			NKern::ThreadLeaveCS();
  1.1865 +			}
  1.1866 +		return err;
  1.1867 +		}
  1.1868 +
  1.1869 +	//get the list
  1.1870 +	TUint32 dataSize = 0;
  1.1871 +	TListManager manager;
  1.1872 +	err = KErrArgument;
  1.1873 +	switch(info.iType)
  1.1874 +		{
  1.1875 +		case EXipLibraries:
  1.1876 +			if(Debug::EScopeGlobal == info.iListScope)
  1.1877 +				{
  1.1878 +				err = manager.GetXipLibrariesList(buffer, dataSize);
  1.1879 +				}
  1.1880 +			break;
  1.1881 +
  1.1882 +		case EThreads:
  1.1883 +			if(Debug::EScopeGlobal == info.iListScope)
  1.1884 +				{
  1.1885 +				err = manager.GetGlobalThreadList(buffer, dataSize);
  1.1886 +				}
  1.1887 +			else if(Debug::EScopeProcessSpecific == info.iListScope)
  1.1888 +				{
  1.1889 +				err = manager.GetThreadListForProcess(buffer, dataSize, info.iTargetId);
  1.1890 +				}
  1.1891 +			else if(Debug::EScopeThreadSpecific == info.iListScope)
  1.1892 +				{
  1.1893 +				err = manager.GetThreadListForThread(buffer, dataSize, info.iTargetId);
  1.1894 +				}
  1.1895 +			break;
  1.1896 +
  1.1897 +		case EProcesses:
  1.1898 +			if(Debug::EScopeGlobal == info.iListScope)
  1.1899 +				{
  1.1900 +				err = manager.GetProcessList(buffer, dataSize);
  1.1901 +				}
  1.1902 +			break;
  1.1903 +
  1.1904 +		case ECodeSegs:
  1.1905 +			if(Debug::EScopeGlobal == info.iListScope)
  1.1906 +				{
  1.1907 +				err = manager.GetGlobalCodeSegList(buffer, dataSize);
  1.1908 +				}
  1.1909 +			else if(Debug::EScopeProcessSpecific == info.iListScope)
  1.1910 +				{
  1.1911 +				err = manager.GetCodeSegListForProcess(buffer, dataSize, info.iTargetId);
  1.1912 +				}
  1.1913 +			else if(Debug::EScopeThreadSpecific == info.iListScope)
  1.1914 +				{
  1.1915 +				err = manager.GetCodeSegListForThread(buffer, dataSize, info.iTargetId);
  1.1916 +				}
  1.1917 +			break;
  1.1918 +
  1.1919 +		default:
  1.1920 +			err = KErrNotSupported;
  1.1921 +		}
  1.1922 +
  1.1923 +	if(err == KErrNone)
  1.1924 +		{
  1.1925 +		//if no error then write the buffer back
  1.1926 +		err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
  1.1927 +		}
  1.1928 +	//write back the size of the data regardless of any error
  1.1929 +	TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
  1.1930 +	if(writeErr != KErrNone)
  1.1931 +		{
  1.1932 +		//if there was an error writing the size return that error instead
  1.1933 +		err = writeErr;
  1.1934 +		}
  1.1935 +
  1.1936 +	//free the buffer
  1.1937 +	NKern::ThreadEnterCS();
  1.1938 +	Kern::Free((TAny*)buffer.Ptr());
  1.1939 +	NKern::ThreadLeaveCS();
  1.1940 +
  1.1941 +	return err;
  1.1942 +	}
  1.1943 +
  1.1944 +/**
  1.1945 +Read registers and store register data in aRegisterInfo
  1.1946 +
  1.1947 +@param aThread thread to read registers from
  1.1948 +@param aRegisterInfo structure specifying which registers to read and providing
  1.1949 +       descriptors to write the register data into
  1.1950 +
  1.1951 +@return KErrNone if registers were read successfully. Note that this does not
  1.1952 +        mean that all the registers could be read, the
  1.1953 +        aRegisterInfo.iRegisterFlags array should be checked as to whether each
  1.1954 +        individual register could be read,
  1.1955 +        KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
  1.1956 +        are members of aRegisterInfo are NULL, if an unknown register is
  1.1957 +        specified or if the passed in register values buffer is too small
  1.1958 +        KErrNoMemory if there is insufficient memory,
  1.1959 +        KErrDied, if the thread with thread ID aThreadId is dead
  1.1960 +*/
  1.1961 +TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
  1.1962 +{
  1.1963 +	LOG_MSG("DRM_DebugChannel::ReadRegisters()");
  1.1964 +
  1.1965 +	TInt err = KErrNone;
  1.1966 +
  1.1967 +	if (!aRegisterInfo)
  1.1968 +		return KErrArgument;
  1.1969 +
  1.1970 +	TRM_DebugRegisterInformation info;
  1.1971 +	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
  1.1972 +	if (err != KErrNone)
  1.1973 +		return err;
  1.1974 +
  1.1975 +	if ((!info.iRegisterIds) || (!info.iRegisterValues) || (!info.iRegisterFlags))
  1.1976 +		return KErrArgument;
  1.1977 +
  1.1978 +	//read ids from client thread
  1.1979 +	TPtr8 ids(NULL, 0);
  1.1980 +	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
  1.1981 +	if(err != KErrNone)
  1.1982 +		{
  1.1983 +		if(err == KErrNoMemory)
  1.1984 +		{
  1.1985 +			NKern::ThreadEnterCS();
  1.1986 +			Kern::Free((TAny*)ids.Ptr());
  1.1987 +			NKern::ThreadLeaveCS();
  1.1988 +		}
  1.1989 +		return err;
  1.1990 +		}
  1.1991 +
  1.1992 +	//read values from client thread
  1.1993 +	TPtr8 values(NULL, 0);
  1.1994 +	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values, EFalse);
  1.1995 +	if(err != KErrNone)
  1.1996 +		{
  1.1997 +		if(err == KErrNoMemory)
  1.1998 +		{	NKern::ThreadEnterCS();
  1.1999 +			Kern::Free((TAny*)values.Ptr());
  1.2000 +			NKern::ThreadLeaveCS();
  1.2001 +		}
  1.2002 +		NKern::ThreadEnterCS();
  1.2003 +		Kern::Free((TAny*)ids.Ptr());
  1.2004 +		NKern::ThreadLeaveCS();
  1.2005 +		return err;
  1.2006 +		}
  1.2007 +
  1.2008 +	//read flags from client thread
  1.2009 +	TPtr8 flags(NULL, 0);
  1.2010 +	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
  1.2011 +	if(err != KErrNone)
  1.2012 +		{
  1.2013 +		if(err == KErrNoMemory)
  1.2014 +		{
  1.2015 +			NKern::ThreadEnterCS();
  1.2016 +			Kern::Free((TAny*)flags.Ptr());
  1.2017 +			NKern::ThreadLeaveCS();
  1.2018 +		}
  1.2019 +		NKern::ThreadEnterCS();
  1.2020 +		Kern::Free((TAny*)ids.Ptr());
  1.2021 +		Kern::Free((TAny*)values.Ptr());
  1.2022 +		NKern::ThreadLeaveCS();
  1.2023 +		return err;
  1.2024 +		}
  1.2025 +
  1.2026 +	err = DoReadRegisters(aThread, ids, values, flags);
  1.2027 +	if (err == KErrNone)
  1.2028 +		{
  1.2029 +		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterValues, values, 0, KChunkShiftBy0, iClientThread);
  1.2030 +		if(err == KErrNone)
  1.2031 +			{
  1.2032 +			err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
  1.2033 +			}
  1.2034 +		}
  1.2035 +
  1.2036 +	NKern::ThreadEnterCS();
  1.2037 +	Kern::Free((TAny*)ids.Ptr());
  1.2038 +	Kern::Free((TAny*)values.Ptr());
  1.2039 +	Kern::Free((TAny*)flags.Ptr());
  1.2040 +	NKern::ThreadLeaveCS();
  1.2041 +
  1.2042 +	return err;
  1.2043 +}
  1.2044 +
  1.2045 +/**
  1.2046 +@deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
  1.2047 +*/
  1.2048 +TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
  1.2049 +{
  1.2050 +	LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
  1.2051 +
  1.2052 +	TInt err = KErrNone;
  1.2053 +
  1.2054 +	if (!aRegisterInfo)
  1.2055 +		return KErrArgument;
  1.2056 +
  1.2057 +	TRM_DebugRegisterInfo info(0, 0, 0);
  1.2058 +	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInfo));
  1.2059 +	if (err != KErrNone)
  1.2060 +		return err;
  1.2061 +
  1.2062 +	if (!info.iValues)
  1.2063 +		return KErrArgument;
  1.2064 +
  1.2065 +	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
  1.2066 +
  1.2067 +	NKern::ThreadEnterCS();
  1.2068 +	TUint8 *values = (TUint8*)Kern::Alloc(length);
  1.2069 +	NKern::ThreadLeaveCS();
  1.2070 +	if (!values)
  1.2071 +	{
  1.2072 +		return KErrNoMemory;
  1.2073 +	}
  1.2074 +
  1.2075 +	TPtr8 valuesDes(values, length);
  1.2076 +
  1.2077 +	err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
  1.2078 +	if (err == KErrNone)
  1.2079 +	{
  1.2080 +		err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
  1.2081 +	}
  1.2082 +
  1.2083 +	NKern::ThreadEnterCS();
  1.2084 +	Kern::Free(values);
  1.2085 +	NKern::ThreadLeaveCS();
  1.2086 +
  1.2087 +	return err;
  1.2088 +}
  1.2089 +
  1.2090 +/**
  1.2091 +Write registers and store flags data in aRegisterInfo
  1.2092 +
  1.2093 +@param aThread thread to write registers to
  1.2094 +@param aRegisterInfo structure specifying which registers to write and providing
  1.2095 +       descriptors to write the register flags data into
  1.2096 +
  1.2097 +@return KErrNone if registers were written successfully. Note that this does not
  1.2098 +        mean that all the registers could be written, the flags array
  1.2099 +        should be checked as to whether each individual register could be read,
  1.2100 +        KErrArgument if aRegisterInfo is NULL, or if any of the pointers that
  1.2101 +        are members of aRegisterInfo are NULL, if an unknown register is
  1.2102 +        specified or if the passed in register values buffer is too small, or
  1.2103 +        if aThread is NULL,
  1.2104 +        KErrGeneral if there was a problem initialising the register set,
  1.2105 +        KErrNoMemory if there is insufficient memory,
  1.2106 +        KErrDied, if the thread with thread ID aThreadId is dead
  1.2107 +*/
  1.2108 +TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
  1.2109 +{
  1.2110 +	LOG_MSG("DRM_DebugChannel::WriteRegisters()");
  1.2111 +
  1.2112 +	TInt err = KErrNone;
  1.2113 +
  1.2114 +	if (!aRegisterInfo)
  1.2115 +		return KErrArgument;
  1.2116 +
  1.2117 +	TRM_DebugRegisterInformation info;
  1.2118 +	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TRM_DebugRegisterInformation));
  1.2119 +	if (err != KErrNone)
  1.2120 +		return err;
  1.2121 +
  1.2122 +	if ((!info.iRegisterIds) || (!info.iRegisterValues) ||(!info.iRegisterFlags))
  1.2123 +		return KErrArgument;
  1.2124 +
  1.2125 +	//read ids from client thread
  1.2126 +	TPtr8 ids(NULL, 0);
  1.2127 +	err = AllocAndReadDes(iClientThread, *info.iRegisterIds, ids);
  1.2128 +	if(err != KErrNone)
  1.2129 +		{
  1.2130 +		if(err == KErrNoMemory)
  1.2131 +			{
  1.2132 +			NKern::ThreadEnterCS();
  1.2133 +			Kern::Free((TAny*)ids.Ptr());
  1.2134 +			NKern::ThreadLeaveCS();
  1.2135 +			}
  1.2136 +		return err;
  1.2137 +		}
  1.2138 +
  1.2139 +	//read values from client thread
  1.2140 +	TPtr8 values(NULL, 0);
  1.2141 +	err = AllocAndReadDes(iClientThread, *info.iRegisterValues, values);
  1.2142 +	if(err != KErrNone)
  1.2143 +		{
  1.2144 +		if(err == KErrNoMemory)
  1.2145 +			{
  1.2146 +			NKern::ThreadEnterCS();
  1.2147 +			Kern::Free((TAny*)values.Ptr());
  1.2148 +			NKern::ThreadLeaveCS();
  1.2149 +			}
  1.2150 +		NKern::ThreadEnterCS();
  1.2151 +		Kern::Free((TAny*)ids.Ptr());
  1.2152 +		NKern::ThreadLeaveCS();
  1.2153 +		return err;
  1.2154 +		}
  1.2155 +
  1.2156 +	//read flags from client thread
  1.2157 +	TPtr8 flags(NULL, 0);
  1.2158 +	err = AllocAndReadDes(iClientThread, *info.iRegisterFlags, flags, EFalse);
  1.2159 +	if(err != KErrNone)
  1.2160 +		{
  1.2161 +		if(err == KErrNoMemory)
  1.2162 +			{
  1.2163 +			NKern::ThreadEnterCS();
  1.2164 +			Kern::Free((TAny*)flags.Ptr());
  1.2165 +			NKern::ThreadLeaveCS();
  1.2166 +			}
  1.2167 +		NKern::ThreadEnterCS();
  1.2168 +		Kern::Free((TAny*)ids.Ptr());
  1.2169 +		Kern::Free((TAny*)values.Ptr());
  1.2170 +		NKern::ThreadLeaveCS();
  1.2171 +		return err;
  1.2172 +		}
  1.2173 +
  1.2174 +	err = DoWriteRegisters(aThread, ids, values, flags);
  1.2175 +	if(err == KErrNone)
  1.2176 +		{
  1.2177 +		err = Kern::ThreadDesWrite(iClientThread, info.iRegisterFlags, flags, 0, KChunkShiftBy0, iClientThread);
  1.2178 +		}
  1.2179 +
  1.2180 +	NKern::ThreadEnterCS();
  1.2181 +	Kern::Free((TAny*)ids.Ptr());
  1.2182 +	Kern::Free((TAny*)values.Ptr());
  1.2183 +	Kern::Free((TAny*)flags.Ptr());
  1.2184 +	NKern::ThreadLeaveCS();
  1.2185 +
  1.2186 +	return err;
  1.2187 +}
  1.2188 +
  1.2189 +/**
  1.2190 +Suspends execution of the specified thread.
  1.2191 +
  1.2192 +@param aThread thread to resume
  1.2193 +
  1.2194 +@return KErrNone if there were no problems or KErrArgument if aThread is NULL
  1.2195 +*/
  1.2196 +TInt DRM_DebugChannel::DoSuspendThread(DThread *aThread)
  1.2197 +	{
  1.2198 +	LOG_MSG("DRM_DebugChannel::DoSuspendThread()");
  1.2199 +
  1.2200 +	if (!aThread)
  1.2201 +		{
  1.2202 +		LOG_MSG("Invalid dthread object");
  1.2203 +		return KErrArgument;
  1.2204 +		}
  1.2205 +
  1.2206 +	return TheDProcessTracker.SuspendThread(aThread);
  1.2207 +	}
  1.2208 +
  1.2209 +/**
  1.2210 +Resumes execution of the specified thread.
  1.2211 +
  1.2212 +@param aThread thread to resume
  1.2213 +
  1.2214 +@return KErrNone if there were no problems, KErrArgument if aThread is NULL
  1.2215 +        or an error value returned from DoStepRange()
  1.2216 +*/
  1.2217 +TInt DRM_DebugChannel::DoResumeThread(DThread *aThread)
  1.2218 +	{
  1.2219 +	LOG_MSG("DRM_DebugChannel::DoResumeThread()");
  1.2220 +
  1.2221 +	if (!aThread)
  1.2222 +		return KErrArgument;
  1.2223 +
  1.2224 +	// get the current PC
  1.2225 +	TUint32 currentPC;
  1.2226 +	TInt err = ReadKernelRegisterValue(aThread, PC_REGISTER, currentPC);
  1.2227 +	if(err != KErrNone)
  1.2228 +		{
  1.2229 +		LOG_MSG2("DRM_DebugChannel::DoResumeThread - Non-zero error code discarded: %d", err);
  1.2230 +		}
  1.2231 +
  1.2232 +	// if there is a breakpoint at the current PC, we need to single step past it
  1.2233 +	TBreakEntry* breakEntry = NULL;
  1.2234 +	do
  1.2235 +		{
  1.2236 +		breakEntry = iBreakManager->GetNextBreak(breakEntry);
  1.2237 +		if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  1.2238 +			{
  1.2239 +			if (breakEntry->iAddress == currentPC)
  1.2240 +				{
  1.2241 +				return DoStepRange(aThread, currentPC, currentPC+1, ETrue, 1, ETrue);
  1.2242 +				}
  1.2243 +			}
  1.2244 +		} while(breakEntry);
  1.2245 +	return TheDProcessTracker.ResumeThread(aThread);
  1.2246 +	}
  1.2247 +
  1.2248 +//
  1.2249 +// DRM_DebugChannel::DoStepRange
  1.2250 +//
  1.2251 +TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
  1.2252 +{
  1.2253 +	LOG_MSG("DRM_DebugChannel::DoStepRange()");
  1.2254 +
  1.2255 +	if (!aThread)
  1.2256 +		return KErrArgument;
  1.2257 +
  1.2258 +	//check that the thread is suspended
  1.2259 +	if(!TheDProcessTracker.CheckSuspended(aThread))
  1.2260 +		{
  1.2261 +		LOG_MSG2("DRM_DebugChannel::DoStepRange() Thread with id 0x%08x not suspended.", aThread->iId);
  1.2262 +		return KErrInUse;
  1.2263 +		}
  1.2264 +
  1.2265 +	TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
  1.2266 +	TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;;
  1.2267 +
  1.2268 +	// don't allow the user to step in the excluded ROM region.  this could be called
  1.2269 +	// internally however.  for example, the the special breakpoints we set to handle
  1.2270 +	// panics, exceptions, and library loaded events are in the user library, and we
  1.2271 +	// will need to step past the breakpoint before continuing the thread.
  1.2272 +	//if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
  1.2273 +	//{
  1.2274 +	//	return KErrNotSupported;
  1.2275 +	//}
  1.2276 +
  1.2277 +	// set the temp breakpoint, and disable the breakpoint at the current PC if necessary
  1.2278 +	// if its not a user request, and we are just trying to resume from a breakpoint,
  1.2279 +	// then we don't need to check for stubs. The last parameter aUserRequest tells
  1.2280 +	// ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs
  1.2281 +	// is true even if its not a user request.For example, this is true in cases where
  1.2282 +	// we are doing a step range and the instruction in the range modified PC.
  1.2283 +	// in this case, DoStepRange will be called from the exception handler where
  1.2284 +	// we need to check for the stubs for the valid behavior. So truly, we don't need to check
  1.2285 +	// for stubs only when resuming from  a breakpoint.
  1.2286 +	ReturnIfError(iStepper->ModifyBreaksForStep(aThread, startAddress, stopAddress, aResumeOnceOutOfRange, aUserRequest, aNumSteps));
  1.2287 +
  1.2288 +	LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
  1.2289 +
  1.2290 +	return TheDProcessTracker.ResumeThread(aThread);
  1.2291 +}
  1.2292 +
  1.2293 +/**
  1.2294 +Read memory from the specified addres into the aData descriptor. If there is a
  1.2295 +breakpoint set in the region of memory returned then the correct data value is
  1.2296 +inserted into the descriptor
  1.2297 +
  1.2298 +@param aThread pointer to thread whose address space memory is to be read from
  1.2299 +@param aAddress address to start reading memory from
  1.2300 +@param aLength length of memory block to read
  1.2301 +@param aData descriptor to read memory into
  1.2302 +
  1.2303 +@return KErrNone if memory read successfully,
  1.2304 +        KErrNotSupported if reading from the rom section is not supported,
  1.2305 +        KErrBadHandle if aThread is invalid,
  1.2306 +        or one of the other system wide error codes
  1.2307 +*/
  1.2308 +TInt DRM_DebugChannel::DoReadMemory(const DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData) const
  1.2309 +	{
  1.2310 +	LOG_MSG("DRM_DebugChannel::DoReadMemory()");
  1.2311 +
  1.2312 +	// make sure the parameters are valid
  1.2313 +	if (aLength > aData.MaxSize())
  1.2314 +		return KErrArgument;
  1.2315 +
  1.2316 +	TInt err = KErrNone;
  1.2317 +
  1.2318 +	// trap exceptions in case the address is invalid
  1.2319 +	XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
  1.2320 +
  1.2321 +	err = (KErrNone == r) ? err : r;
  1.2322 +
  1.2323 +	if (KErrNone == err)
  1.2324 +		{
  1.2325 +		aData.SetLength(aLength);
  1.2326 +
  1.2327 +		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
  1.2328 +
  1.2329 +		// if we have any breakpoints in this range, put the actual instruction in the buffer
  1.2330 +		TBreakEntry* breakEntry = NULL;
  1.2331 +		do
  1.2332 +			{
  1.2333 +			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  1.2334 +			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  1.2335 +				{
  1.2336 +				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
  1.2337 +					{
  1.2338 +					TInt instSize;
  1.2339 +
  1.2340 +					switch(breakEntry->iMode)
  1.2341 +						{
  1.2342 +						case EArmMode:
  1.2343 +							instSize = 4;
  1.2344 +							break;
  1.2345 +
  1.2346 +						case EThumbMode:
  1.2347 +							instSize = 2;
  1.2348 +							break;
  1.2349 +
  1.2350 +						case EThumb2EEMode:
  1.2351 +						default:
  1.2352 +							LOG_MSG("DRM_DebugChannel::DoReadMemory() cannot fixup breakpoints with unsupported architecture");
  1.2353 +							return KErrNotSupported;
  1.2354 +						}
  1.2355 +					memcpy((TAny*)&data[breakEntry->iAddress - aAddress], (TAny *)breakEntry->iInstruction.Ptr(), instSize);
  1.2356 +					}
  1.2357 +				}
  1.2358 +			} while(breakEntry);
  1.2359 +		}
  1.2360 +
  1.2361 +	return err;
  1.2362 +	}
  1.2363 +
  1.2364 +/**
  1.2365 +Attempt to write memory to aThread's address space
  1.2366 +
  1.2367 +@param aThread thread to whose address space memory is to be written
  1.2368 +@param aAddress memory location to write memory to
  1.2369 +@param aLength number of bytes of data to write
  1.2370 +@param aData descriptor containing memory to write
  1.2371 +
  1.2372 +@return KErrNone if memory written successfully,
  1.2373 +        KErrArgument if aLength is greater than than the length of the aData
  1.2374 +        KErrBadHandle if aThread is invalid,
  1.2375 +	or another of the system wide error codes
  1.2376 +*/
  1.2377 +TInt DRM_DebugChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TUint32 aLength, TDes8 &aData)
  1.2378 +	{
  1.2379 +	LOG_MSG("DRM_DebugChannel::DoWriteMemory()");
  1.2380 +
  1.2381 +	// make sure the parameters are valid
  1.2382 +	if (aLength > aData.Length())
  1.2383 +		return KErrArgument;
  1.2384 +
  1.2385 +	TInt err = KErrNone;
  1.2386 +
  1.2387 +	// trap exceptions in case the address is invalid
  1.2388 +	XTRAPD(r, XT_DEFAULT,  err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
  1.2389 +
  1.2390 +	err = (KErrNone == r) ? err : r;
  1.2391 +
  1.2392 +	// reset any breakpoints we may have just overwritten
  1.2393 +	if (KErrNone == err)
  1.2394 +		{
  1.2395 +		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
  1.2396 +
  1.2397 +		TBreakEntry* breakEntry = NULL;
  1.2398 +		do
  1.2399 +			{
  1.2400 +			breakEntry = iBreakManager->GetNextBreak(breakEntry);
  1.2401 +			if(breakEntry && !iBreakManager->IsTemporaryBreak(*breakEntry))
  1.2402 +				{
  1.2403 +				if ((breakEntry->iAddress >= aAddress) && (breakEntry->iAddress < (aAddress + aLength)))
  1.2404 +					{
  1.2405 +					// default to arm mode
  1.2406 +					TUint32 inst;
  1.2407 +					TInt instSize;
  1.2408 +
  1.2409 +					switch (breakEntry->iMode)
  1.2410 +						{
  1.2411 +						case EArmMode:
  1.2412 +							inst = KArmBreakPoint;
  1.2413 +							instSize = 4;
  1.2414 +							break;
  1.2415 +
  1.2416 +						case EThumbMode:
  1.2417 +							inst = KThumbBreakPoint;
  1.2418 +							instSize = 2;
  1.2419 +							break;
  1.2420 +
  1.2421 +						case EThumb2EEMode:
  1.2422 +						default:
  1.2423 +							LOG_MSG("DRM_DebugChannel::DoWriteMemory() cannot fixup breakpoints of unsupported architecture type");
  1.2424 +
  1.2425 +							return KErrNotSupported;
  1.2426 +						}
  1.2427 +
  1.2428 +					breakEntry->iInstruction.Copy(&data[breakEntry->iAddress - aAddress], instSize);
  1.2429 +					memcpy((TAny*)breakEntry->iAddress, (TAny *)&inst, instSize);
  1.2430 +					}
  1.2431 +				}
  1.2432 +
  1.2433 +			} while(breakEntry);
  1.2434 +		}
  1.2435 +	return err;
  1.2436 +	}
  1.2437 +
  1.2438 +//
  1.2439 +// DRM_DebugChannel::DoReadRegisters
  1.2440 +//
  1.2441 +TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
  1.2442 +{
  1.2443 +	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
  1.2444 +
  1.2445 +	// make sure the parameters are valid
  1.2446 +	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  1.2447 +		return KErrArgument;
  1.2448 +
  1.2449 +	// make sure the descriptor is big enough to hold the requested data
  1.2450 +	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
  1.2451 +		return KErrArgument;
  1.2452 +
  1.2453 +	TArmRegSet regSet;
  1.2454 +    TUint32 unused;
  1.2455 +
  1.2456 +	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  1.2457 +
  1.2458 +	LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
  1.2459 +
  1.2460 +    TArmReg *reg = &regSet.iR0;
  1.2461 +
  1.2462 +	if (!reg)
  1.2463 +		return KErrGeneral;
  1.2464 +
  1.2465 +    for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
  1.2466 +    	aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
  1.2467 +
  1.2468 +	return KErrNone;
  1.2469 +}
  1.2470 +
  1.2471 +/**
  1.2472 +  @prototype
  1.2473 +
  1.2474 +  Experimental function for determining whether a thread is suspended.
  1.2475 +
  1.2476 +  @param aThread thread to check if suspended
  1.2477 +
  1.2478 +  @return ETrue if the thread is suspended, EFalse if it isn't or does not exist
  1.2479 +  */
  1.2480 +TBool DRM_DebugChannel::CheckSuspended(const DThread *aThread) const
  1.2481 +	{
  1.2482 +	if(!aThread)
  1.2483 +		{
  1.2484 +		return EFalse;
  1.2485 +		}
  1.2486 +
  1.2487 +	if( (aThread->iNThread.iCsCount>0) && (aThread->iNThread.iCsFunction>0) )
  1.2488 +		{
  1.2489 +		return ETrue;
  1.2490 +		}
  1.2491 +
  1.2492 +	if(aThread->iNThread.iSuspendCount > 0)
  1.2493 +		{
  1.2494 +		return ETrue;
  1.2495 +		}
  1.2496 +	return EFalse;
  1.2497 +	}
  1.2498 +
  1.2499 +/**
  1.2500 +Read registers and store register values in aRegisterValues and the flags
  1.2501 +indicating which registers could be read in aRegisterFlags
  1.2502 +
  1.2503 +@param aThread thread to read registers from
  1.2504 +@param aRegisterIds array containing register IDs to read
  1.2505 +@param aRegisterValues array to store register values in
  1.2506 +@param aRegisterFlags array to store flags in
  1.2507 +
  1.2508 +@return KErrNone if registers were read successfully. Note that this does not
  1.2509 +        mean that all the registers could be read, the aRegisterFlags array
  1.2510 +        should be checked as to whether each individual register could be read,
  1.2511 +        KErrArgument if aThread is NULL, if an unknown register is specified in
  1.2512 +        aRegisterValues or if aRegisterValues is too small
  1.2513 +        KErrGeneral if there was a problem initialising the register set
  1.2514 +*/
  1.2515 +TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
  1.2516 +{
  1.2517 +	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
  1.2518 +
  1.2519 +	// make sure the parameters are valid
  1.2520 +	if (!aThread)
  1.2521 +		return KErrArgument;
  1.2522 +
  1.2523 +	//Need to revisit this to determine whether there is a way to validate this
  1.2524 +#if 0
  1.2525 +	if ( !CheckSuspended(aThread) )
  1.2526 +		{
  1.2527 +		LOG_MSG2("DRM_DebugChannel::DoReadRegisters() thread with id 0x%08x is not suspended", aThread->iId);
  1.2528 +		return KErrInUse;
  1.2529 +		}
  1.2530 +#endif
  1.2531 +
  1.2532 +	//set lengths of output descriptors to 0 prior to filling
  1.2533 +	aRegisterValues.SetLength(0);
  1.2534 +	aRegisterFlags.SetLength(0);
  1.2535 +
  1.2536 +	TArmRegSet regSet;
  1.2537 +	TUint32 flags;
  1.2538 +
  1.2539 +	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
  1.2540 +
  1.2541 +	LOG_MSG2( "DRM_DebugChannel::DoReadRegisters() : flags = 0x%X\n", flags );
  1.2542 +
  1.2543 +	TArmReg *regPtr = &regSet.iR0;
  1.2544 +
  1.2545 +	if (!regPtr)
  1.2546 +		return KErrGeneral;
  1.2547 +
  1.2548 +	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
  1.2549 +
  1.2550 +	//iterate through registers setting the relevant aFlags value
  1.2551 +	for(TUint i=0; i<numberOfRegisters; i++)
  1.2552 +		{
  1.2553 +		//get current register id
  1.2554 +		TRegisterInfo reg;
  1.2555 +		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
  1.2556 +		//exit with the error value if there was an error
  1.2557 +		if(err != KErrNone)
  1.2558 +			return err;
  1.2559 +
  1.2560 +		//if unknown register then exit as can't know how many bytes this entry will
  1.2561 +		//represent in aRegisterValues
  1.2562 +		TTag registerTag;
  1.2563 +		TDebugFunctionality::GetRegister(reg, registerTag);
  1.2564 +		if(registerTag.iValue == EAccessUnknown)
  1.2565 +			{
  1.2566 +			return KErrArgument;
  1.2567 +			}
  1.2568 +
  1.2569 +		//get the current register id as a kernel register
  1.2570 +		TArmReg armReg;
  1.2571 +		err = GetKernelRegisterId(reg, armReg);
  1.2572 +		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessWriteOnly))
  1.2573 +			{
  1.2574 +			//reading this register is not supported
  1.2575 +			aRegisterFlags.Append(ENotSupported);
  1.2576 +			//just skip over this entry in the values buffer
  1.2577 +			if(aRegisterValues.Length() + registerTag.iSize > aRegisterValues.MaxLength())
  1.2578 +				{
  1.2579 +				//writing this value would cause overflow so exit
  1.2580 +				return KErrArgument;
  1.2581 +				}
  1.2582 +			aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
  1.2583 +			}
  1.2584 +		else
  1.2585 +			{
  1.2586 +			if(registerTag.iSize == sizeof(TArmReg))
  1.2587 +				{
  1.2588 +				if(GetFlagAtOffset(flags, armReg))
  1.2589 +					{
  1.2590 +					//set flag as valid
  1.2591 +					aRegisterFlags.Append(EValid);
  1.2592 +					}
  1.2593 +				else
  1.2594 +					{
  1.2595 +					// Even though the flag is invalid, we can return the value of the register
  1.2596 +					// and let the user decide what to do
  1.2597 +					aRegisterFlags.Append(EInValid);
  1.2598 +					}
  1.2599 +
  1.2600 +				if(aRegisterValues.Length() + sizeof(TArmReg) > aRegisterValues.MaxLength())
  1.2601 +					{
  1.2602 +					//writing this value would cause overflow so exit
  1.2603 +					return KErrArgument;
  1.2604 +					}
  1.2605 +				//write value into register into regSet
  1.2606 +				aRegisterValues.Append((TUint8 *)&regPtr[armReg], registerTag.iSize);
  1.2607 +				}
  1.2608 +			else
  1.2609 +				{
  1.2610 +				//currently all kernel supported registers are 4 bytes so
  1.2611 +				//return EBadSize. Would need updating if/when other register
  1.2612 +				//value sizes are supported
  1.2613 +				aRegisterFlags.Append(EBadSize);
  1.2614 +				aRegisterValues.SetLength(aRegisterValues.Length() + registerTag.iSize);
  1.2615 +				}
  1.2616 +			}
  1.2617 +		}
  1.2618 +	return KErrNone;
  1.2619 +}
  1.2620 +
  1.2621 +//
  1.2622 +// DRM_DebugChannel::DoWriteRegisters
  1.2623 +//
  1.2624 +TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
  1.2625 +{
  1.2626 +	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
  1.2627 +
  1.2628 +	// make sure the parameters are valid
  1.2629 +	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  1.2630 +		return KErrArgument;
  1.2631 +
  1.2632 +	// make sure the descriptor is big enough to hold the data to write
  1.2633 +	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
  1.2634 +		return KErrArgument;
  1.2635 +
  1.2636 +	TArmRegSet regSet;
  1.2637 +	TUint32 unused;
  1.2638 +
  1.2639 +	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  1.2640 +
  1.2641 +	TArmReg *reg = &regSet.iR0;
  1.2642 +
  1.2643 +	for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
  1.2644 +		reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
  1.2645 +
  1.2646 +	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
  1.2647 +
  1.2648 +	return KErrNone;
  1.2649 +}
  1.2650 +
  1.2651 +/**
  1.2652 +Write registers and store flags indicating which registers could be read in
  1.2653 +aRegisterFlags
  1.2654 +
  1.2655 +@param aThread thread to write registers to
  1.2656 +@param aRegisterIds array containing register IDs to write
  1.2657 +@param aRegisterValues array containing register values to write
  1.2658 +@param aRegisterFlags array to store flags in
  1.2659 +
  1.2660 +@return KErrNone if registers were written successfully. Note that this does not
  1.2661 +        mean that all the registers could be written, the aRegisterFlags array
  1.2662 +        should be checked as to whether each individual register could be read,
  1.2663 +        KErrArgument if aThread is NULL, if the buffer passed in as
  1.2664 +        aRegisterValue is too small, or if an unknown register is requested,
  1.2665 +        KErrGeneral if there was a problem initialising the register set
  1.2666 +*/
  1.2667 +TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
  1.2668 +{
  1.2669 +	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
  1.2670 +
  1.2671 +	// make sure the parameters are valid
  1.2672 +	if (!aThread)
  1.2673 +		return KErrArgument;
  1.2674 +
  1.2675 +	//check that the thread is suspended before reading the registers
  1.2676 +	if(!TheDProcessTracker.CheckSuspended(aThread))
  1.2677 +		{
  1.2678 +		LOG_MSG2("DRM_DebugChannel::DoWriteRegisters() thread with id 0x%08x is not suspended", aThread->iId);
  1.2679 +		return KErrInUse;
  1.2680 +		}
  1.2681 +
  1.2682 +	//get register values from kernel
  1.2683 +	TArmRegSet regSet;
  1.2684 +	TUint32 flags;
  1.2685 +	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, flags);
  1.2686 +
  1.2687 +	//set lengths of output descriptors to 0 prior to filling
  1.2688 +	aRegisterFlags.SetLength(0);
  1.2689 +
  1.2690 +	//pointer to first kernel register
  1.2691 +	TArmReg *regPtr = &regSet.iR0;
  1.2692 +
  1.2693 +	if (!regPtr)
  1.2694 +		return KErrGeneral;
  1.2695 +
  1.2696 +	//calculate number of registers
  1.2697 +	TUint numberOfRegisters = aRegisterIds.Length() / sizeof(TRegisterInfo);
  1.2698 +
  1.2699 +	//iterate through registers setting the relevant aRegisterFlags value and
  1.2700 +	//setting the necessary value in regSet ready to write to kernel
  1.2701 +	for(TUint i=0, offset = 0; i<numberOfRegisters; i++)
  1.2702 +		{
  1.2703 +		//get current register id
  1.2704 +		TRegisterInfo reg;
  1.2705 +		TInt err = GetTRegisterInfo(aRegisterIds, i, reg);
  1.2706 +		//exit with the error value if there was an error
  1.2707 +		if(err != KErrNone)
  1.2708 +			{
  1.2709 +			return err;
  1.2710 +			}
  1.2711 +
  1.2712 +		//if unknown register then exit as can't know how many bytes this entry will
  1.2713 +		//represent in aRegisterValues
  1.2714 +		TTag registerTag;
  1.2715 +		TDebugFunctionality::GetRegister(reg, registerTag);
  1.2716 +		if(registerTag.iValue == EAccessUnknown)
  1.2717 +			{
  1.2718 +			return KErrArgument;
  1.2719 +			}
  1.2720 +
  1.2721 +		//get the current register id as a kernel register
  1.2722 +		TArmReg armReg;
  1.2723 +		err = GetKernelRegisterId(reg, armReg);
  1.2724 +		if((err == KErrNotSupported) || (registerTag.iValue == EAccessNone) || (registerTag.iValue == EAccessReadOnly))
  1.2725 +			{
  1.2726 +			//writing to this register is not supported
  1.2727 +			aRegisterFlags.Append(ENotSupported);
  1.2728 +			}
  1.2729 +		else if(GetFlagAtOffset(flags, armReg))
  1.2730 +			{
  1.2731 +			if(registerTag.iSize == sizeof(TArmReg))
  1.2732 +				{
  1.2733 +				//set flag as valid
  1.2734 +				aRegisterFlags.Append(EValid);
  1.2735 +				if(offset + sizeof(TArmReg) > aRegisterValues.Length())
  1.2736 +					{
  1.2737 +					//getting this value would cause overflow so exit
  1.2738 +					return KErrArgument;
  1.2739 +					}
  1.2740 +				//write value into register into regSet
  1.2741 +				regPtr[armReg] = *(TUint32 *)&aRegisterValues[offset];
  1.2742 +				}
  1.2743 +			else
  1.2744 +				{
  1.2745 +				//currently all kernel supported registers are 4 bytes so
  1.2746 +				//return EBadSize. Would need updating if/when other register
  1.2747 +				//value sizes are supported
  1.2748 +				aRegisterFlags.Append(EBadSize);
  1.2749 +				}
  1.2750 +
  1.2751 +			}
  1.2752 +		else
  1.2753 +			{
  1.2754 +			//set flag as invalid as register value couldn't be read
  1.2755 +			aRegisterFlags.Append(EInValid);
  1.2756 +			}
  1.2757 +		offset+=registerTag.iSize;
  1.2758 +		}
  1.2759 +
  1.2760 +	//write the input data into the registers
  1.2761 +	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
  1.2762 +
  1.2763 +	//return normally
  1.2764 +	return KErrNone;
  1.2765 +	}
  1.2766 +
  1.2767 +//
  1.2768 +// DRM_DebugChannel::DoSecurityCheck
  1.2769 +//
  1.2770 +TBool DRM_DebugChannel::DoSecurityCheck()
  1.2771 +{
  1.2772 +	LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
  1.2773 +	DProcess* clientProcess = iClientThread->iOwningProcess;
  1.2774 +	if (clientProcess)
  1.2775 +	{
  1.2776 +		SSecurityInfo secureInfo = clientProcess->iS;
  1.2777 +
  1.2778 +		LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
  1.2779 +
  1.2780 +		// Ensure we really are communicating with the Debug Security Server
  1.2781 +		if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
  1.2782 +		{
  1.2783 +			return ETrue;
  1.2784 +		}
  1.2785 +	}
  1.2786 +	return EFalse;
  1.2787 +}
  1.2788 +
  1.2789 +/**
  1.2790 +Attempt to read memory from aThread's address space
  1.2791 +
  1.2792 +@param aThread thread from whose address space memory is to be read
  1.2793 +@param aSrc pointer to memory location to read memory from
  1.2794 +@param aDest pointer to memory location to write memory to
  1.2795 +@param aLength number of bytes of data to read
  1.2796 +
  1.2797 +@return KErrNone if memory read successfully,
  1.2798 +	or another of the system wide error codes
  1.2799 +*/
  1.2800 +TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
  1.2801 +{
  1.2802 +	LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
  1.2803 +
  1.2804 +	// make sure the parameters are valid
  1.2805 +	if (!aThread)
  1.2806 +		return KErrArgument;
  1.2807 +
  1.2808 +	//Need to revisit this to determine whether there is a way to validate this
  1.2809 +#if 0
  1.2810 +	//check that the thread is suspended before reading the memory
  1.2811 +	if ( !CheckSuspended(aThread) )
  1.2812 +		{
  1.2813 +		LOG_MSG2("DRM_DebugChannel::TryToReadMemory() thread with id 0x%08x is not suspended", aThread->iId);
  1.2814 +		return KErrInUse;
  1.2815 +		}
  1.2816 +#endif
  1.2817 +
  1.2818 +	LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
  1.2819 +	return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
  1.2820 +}
  1.2821 +
  1.2822 +/**
  1.2823 +Attempt to write memory to aThread's address space
  1.2824 +
  1.2825 +@param aThread thread to whose address space memory is to be written
  1.2826 +@param aDest pointer to memory location to write memory to
  1.2827 +@param aSrc pointer to memory location to read memory from
  1.2828 +@param aLength number of bytes of data to write
  1.2829 +
  1.2830 +@return KErrNone if memory written successfully, or another of the system wide
  1.2831 +        error codes
  1.2832 +*/
  1.2833 +TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
  1.2834 +{
  1.2835 +	LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
  1.2836 +
  1.2837 +	//check that the thread is suspended before writing the memory
  1.2838 +	if(!TheDProcessTracker.CheckSuspended((DThread*)aThread))
  1.2839 +		{
  1.2840 +		LOG_MSG2("DRM_DebugChannel::TryToWriteMemory() thread with id 0x%08x is not suspended", aThread->iId);
  1.2841 +		return KErrInUse;
  1.2842 +		}
  1.2843 +
  1.2844 +	LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
  1.2845 +	return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
  1.2846 +}
  1.2847 +
  1.2848 +/**
  1.2849 +@deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
  1.2850 +*/
  1.2851 +TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
  1.2852 +{
  1.2853 +	LOG_MSG("DRM_DebugChannel::ReadRegister()");
  1.2854 +
  1.2855 +	if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
  1.2856 +	{
  1.2857 +		LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
  1.2858 +		return 0;
  1.2859 +	}
  1.2860 +
  1.2861 +	TArmRegSet regSet;
  1.2862 +    TUint32 unused;
  1.2863 +
  1.2864 +	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
  1.2865 +
  1.2866 +    TArmReg *reg = &regSet.iR0;
  1.2867 +
  1.2868 +	return ((TUint32 *)reg)[aNum];
  1.2869 +}
  1.2870 +
  1.2871 +/**
  1.2872 +Given a TArmReg register ID, read the value of the register. The register value
  1.2873 +will be stored in aValue if the register could be read.
  1.2874 +
  1.2875 +@param aThread thread to read register from
  1.2876 +@param aKernelRegisterId ID of register to read from
  1.2877 +@param aValue value read from register
  1.2878 +
  1.2879 +@return KErrNone if value was successfully stored in aValue,
  1.2880 +        KErrNotSupported if aKernelRegister is not supported by the debug
  1.2881 +	security server,
  1.2882 +        or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
  1.2883 +*/
  1.2884 +TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
  1.2885 +{
  1.2886 +	//get register ID as a TRegisterInfo ID
  1.2887 +	TRegisterInfo regId;
  1.2888 +	TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
  1.2889 +	if(err != KErrNone)
  1.2890 +		return err;
  1.2891 +
  1.2892 +	//get the value for the register
  1.2893 +	err = ReadDebugRegisterValue(aThread, regId, aValue);
  1.2894 +	return err;
  1.2895 +	}
  1.2896 +
  1.2897 +/**
  1.2898 +Given a TRegisterInfo register ID, read the value of this register. The
  1.2899 +register value will be stored in aValue if the register could be read.
  1.2900 +
  1.2901 +@param aThread thread to read register from
  1.2902 +@param aDebugRegisterId ID of register to read from
  1.2903 +@param aValue value read from register
  1.2904 +
  1.2905 +@return KErrNone if value was successfully stored in aValue,
  1.2906 +        TRegisterFlag::EInValid if value could not be read from the register,
  1.2907 +        TRegisterFlag::ENotSupported if the register is not supported,
  1.2908 +        KErrNoMemory if temporary memory could not be allocated,
  1.2909 +        or a return value from DRM_DebugChannel::DoReadRegisters
  1.2910 +*/
  1.2911 +TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
  1.2912 +{
  1.2913 +	//allocate temporary buffers to store data
  1.2914 +	NKern::ThreadEnterCS();
  1.2915 +	TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
  1.2916 +	NKern::ThreadLeaveCS();
  1.2917 +	if(id == NULL)
  1.2918 +	{
  1.2919 +		return KErrNoMemory;
  1.2920 +	}
  1.2921 +	TPtr8 idPtr(id, sizeof(TRegisterInfo));
  1.2922 +
  1.2923 +	NKern::ThreadEnterCS();
  1.2924 +	TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
  1.2925 +	NKern::ThreadLeaveCS();
  1.2926 +	if(value == NULL)
  1.2927 +	{
  1.2928 +		return KErrNoMemory;
  1.2929 +	}
  1.2930 +	TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
  1.2931 +
  1.2932 +	NKern::ThreadEnterCS();
  1.2933 +	TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
  1.2934 +	NKern::ThreadLeaveCS();
  1.2935 +	if(flag == NULL)
  1.2936 +	{
  1.2937 +		return KErrNoMemory;
  1.2938 +	}
  1.2939 +	TPtr8 flagPtr(flag, sizeof(TUint8));
  1.2940 +
  1.2941 +	//store register id in buffer
  1.2942 +	idPtr.Append((TUint8*)&aDebugRegisterId, sizeof(TRegisterInfo));
  1.2943 +
  1.2944 +	//read registers
  1.2945 +	TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
  1.2946 +	if(err == KErrNone)
  1.2947 +	{
  1.2948 +		if(*flag == EValid)
  1.2949 +		{
  1.2950 +			//register could be read so store value
  1.2951 +			aValue = *(T4ByteRegisterValue*)value;
  1.2952 +		}
  1.2953 +		else
  1.2954 +		{
  1.2955 +			//register couldn't be read for some reason
  1.2956 +			err = *flag;
  1.2957 +		}
  1.2958 +	}
  1.2959 +
  1.2960 +	//free memory
  1.2961 +	NKern::ThreadEnterCS();
  1.2962 +	Kern::Free(id);
  1.2963 +	Kern::Free(value);
  1.2964 +	Kern::Free(flag);
  1.2965 +	NKern::ThreadLeaveCS();
  1.2966 +
  1.2967 +	return err;
  1.2968 +}
  1.2969 +
  1.2970 +//
  1.2971 +// DRM_DebugChannel::NotifyEvent
  1.2972 +//
  1.2973 +void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
  1.2974 +{
  1.2975 +	LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
  1.2976 +
  1.2977 +	// Look for the relevant DTargetProcess
  1.2978 +	// We can find out the relevant process id from aEventInfo
  1.2979 +	TUint32 pid = aEventInfo.iProcessId;
  1.2980 +
  1.2981 +	//opening handle to process
  1.2982 +	DProcess* targetProcess = DebugUtils::OpenProcessHandle(pid);
  1.2983 +
  1.2984 +	if(!targetProcess)
  1.2985 +		{
  1.2986 +		LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - process does not exist!");
  1.2987 +		return;
  1.2988 +		}
  1.2989 +
  1.2990 +	// Are we debugging this process - decide based on iFileName
  1.2991 +	DCodeSeg* p = targetProcess->iCodeSeg;
  1.2992 +	DTargetProcess* foundProcess;
  1.2993 +	if (p)
  1.2994 +		{
  1.2995 +		 foundProcess = TheDProcessTracker.FindProcess(*(p->iFileName));
  1.2996 +		}
  1.2997 +	else
  1.2998 +		{
  1.2999 +		// special case: may not have a code seg in some cases. in which case we tell everyone!
  1.3000 +		if (targetProcess->iName)
  1.3001 +			{
  1.3002 +			// copy the name of the process
  1.3003 +			foundProcess = TheDProcessTracker.FindProcess(*(targetProcess->iName));
  1.3004 +			}
  1.3005 +		else
  1.3006 +			{
  1.3007 +			foundProcess = NULL;
  1.3008 +			}
  1.3009 +		}
  1.3010 +
  1.3011 +	//close the handle
  1.3012 +	targetProcess->Close(NULL);
  1.3013 +
  1.3014 +	if (!foundProcess)
  1.3015 +		{
  1.3016 +		// No: just ignore this exception
  1.3017 +		LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent - we are not debugging this process!");
  1.3018 +		return;
  1.3019 +		}
  1.3020 +
  1.3021 +	foundProcess->NotifyEvent(aEventInfo);
  1.3022 +}
  1.3023 +
  1.3024 +#ifndef __LAUNCH_AS_EXTENSION__
  1.3025 +DECLARE_STANDARD_LDD()
  1.3026 +	{
  1.3027 +	return new DRM_DebugDriverFactory;
  1.3028 +	}
  1.3029 +#else
  1.3030 +
  1.3031 +DStopModeExtension* TheStopModeExtension = NULL;
  1.3032 +
  1.3033 +DECLARE_EXTENSION_LDD()
  1.3034 +	{
  1.3035 +	return new DRM_DebugDriverFactory;
  1.3036 +	}
  1.3037 +
  1.3038 +/**
  1.3039 +  This value is used as an initialiser for the size of the Stop-Mode Debug API's
  1.3040 +  default request buffer.
  1.3041 +  */
  1.3042 +const TInt KRequestBufferSize = 0x200;
  1.3043 +/**
  1.3044 +  This value is used as an initialiser for the size of the Stop-Mode Debug API's
  1.3045 +  default response buffer.
  1.3046 +  */
  1.3047 +const TInt KResponseBufferSize = 0x1000;
  1.3048 +
  1.3049 +DECLARE_STANDARD_EXTENSION()
  1.3050 +	{
  1.3051 +	__KTRACE_OPT(KBOOT,Kern::Printf("Starting RM_DEBUG extension"));
  1.3052 +
  1.3053 +	// get a reference to the DDebuggerInfo and to the DStopModeExtension
  1.3054 +	TSuperPage& superPage = Kern::SuperPage();
  1.3055 +
  1.3056 +	if(!superPage.iDebuggerInfo)
  1.3057 +		{
  1.3058 +		//kdebug has not been installed so create DDebuggerInfo using our stub constructor
  1.3059 +		superPage.iDebuggerInfo = new DDebuggerInfo();
  1.3060 +		}
  1.3061 +
  1.3062 +	if(!TheStopModeExtension)
  1.3063 +		{
  1.3064 +		TheStopModeExtension = new DStopModeExtension();
  1.3065 +		}
  1.3066 +
  1.3067 +	// create the request buffer and store a reference to it
  1.3068 +	TTag tag;
  1.3069 +	tag.iTagId = EBuffersRequest;
  1.3070 +	tag.iType = ETagTypePointer;
  1.3071 +	tag.iSize = KRequestBufferSize;
  1.3072 +	TInt err = TheDBufferManager.CreateBuffer(tag);
  1.3073 +	if(KErrNone != err)
  1.3074 +		{
  1.3075 +		return KErrNone;
  1.3076 +		}
  1.3077 +
  1.3078 +	// create the response buffer and store a reference to it
  1.3079 +	tag.iTagId = EBuffersResponse;
  1.3080 +	tag.iSize = KResponseBufferSize;
  1.3081 +	err = TheDBufferManager.CreateBuffer(tag);
  1.3082 +	if(KErrNone != err)
  1.3083 +		{
  1.3084 +		return KErrNone;
  1.3085 +		}
  1.3086 +	// create the debug functionality buffer and store a reference to it
  1.3087 +	TDebugFunctionality df;
  1.3088 +	TUint dfSize = df.GetStopModeFunctionalityBufSize();
  1.3089 +	tag.iTagId = EBuffersFunctionality;
  1.3090 +	tag.iSize = dfSize;
  1.3091 +	err = TheDBufferManager.CreateBuffer(tag);
  1.3092 +	if(KErrNone != err)
  1.3093 +		{
  1.3094 +		return KErrNone;
  1.3095 +		}
  1.3096 +
  1.3097 +	// fill the functionality buffer with the functionality data and store it in
  1.3098 +	// the super page
  1.3099 +	TPtr8 dfBlockPtr((TUint8*)tag.iValue, dfSize);
  1.3100 +	if(!df.GetStopModeFunctionality(dfBlockPtr))
  1.3101 +		{
  1.3102 +		return KErrNone;
  1.3103 +		}
  1.3104 +	TheStopModeExtension->iFunctionalityBlock = (DFunctionalityBlock*)tag.iValue;
  1.3105 +
  1.3106 +	DStopModeExtension::Install(TheStopModeExtension);
  1.3107 +
  1.3108 +	return KErrNone;
  1.3109 +	}
  1.3110 +
  1.3111 +/**
  1.3112 + * This stub constructor is intended to be used in the case where the old deprecated
  1.3113 + * stop mode api, kdebug, is not in place. It will initialise all values to NULL except
  1.3114 + * the pointer to the new stop mode api extension. This allows the new stop mode solution
  1.3115 + * to both co-exist and exist independantly of the existing one *
  1.3116 + */
  1.3117 +DDebuggerInfo::DDebuggerInfo():
  1.3118 +    iObjectOffsetTable(NULL),
  1.3119 +    iObjectOffsetTableCount(NULL),
  1.3120 +    iThreadContextTable(NULL),
  1.3121 +    iStopModeExtension(new DStopModeExtension()),
  1.3122 +    iContainers(NULL),
  1.3123 +    iCodeSegLock(NULL),
  1.3124 +    iCodeSegGlobalList(NULL),
  1.3125 +    iScheduler(NULL),
  1.3126 +    iShadowPages(NULL),
  1.3127 +    iShadowPageCount(0),
  1.3128 +    iCurrentThread(NULL),
  1.3129 +    iEventMask(),
  1.3130 +    iEventHandlerBreakpoint(0),
  1.3131 +    iMemModelObjectOffsetTable(NULL),
  1.3132 +    iMemModelObjectOffsetTableCount(0)
  1.3133 +    {
  1.3134 +    }
  1.3135 +
  1.3136 +/**
  1.3137 + * Installs the stop-mode debugger extension
  1.3138 + * Make the stop-mode API visible to a JTAG debugger, by publishing its
  1.3139 + * existence in the superpage
  1.3140 +*/
  1.3141 +void DStopModeExtension::Install(DStopModeExtension* aExt)
  1.3142 +    {
  1.3143 +    Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
  1.3144 +    }
  1.3145 +
  1.3146 +#endif
  1.3147 +
  1.3148 +/**
  1.3149 +Helper function
  1.3150 +
  1.3151 +Allocates memory in current thread with a max length the same as aSrcDes. If
  1.3152 +aReadFromClient is true (as it is by default) then the data from aSrdDes is
  1.3153 +copied into the allocated aDestDes buffer.
  1.3154 +
  1.3155 +Use of this function should be followed at a later time by a call such as
  1.3156 +Kern::Free(aDestDes.Ptr())
  1.3157 +
  1.3158 +@param aThread pointer to thread to read data from
  1.3159 +@param aSrcDes descriptor in aThread to read data from
  1.3160 +@param aDestDes location to read data to. Memory is allocated at this location,
  1.3161 +       if memory is already allocated at this location then the function will
  1.3162 +       return KErrArgument
  1.3163 +@param aReadFromClient if false then data is not actually read from the
  1.3164 +       client, the memory is simply allocated
  1.3165 +@param aOffest offset into aSrcDes to start reading from. Default is 0.
  1.3166 +
  1.3167 +@return KErrNone if there were no problems,
  1.3168 +        KErrArgument if aDestDes.Ptr() != NULL or aSrcDes has max length 0,
  1.3169 +        KErrNoMemory if could not allocate memory,
  1.3170 +        or one of the other system wide error codes
  1.3171 +*/
  1.3172 +TInt DRM_DebugChannel::AllocAndReadDes(DThread *aThread, const TDesC8& aSrcDes, TPtr8& aDestDes, const TBool aReadFromClient, const TUint aOffset) const
  1.3173 +	{
  1.3174 +
  1.3175 +	//check thread is not null
  1.3176 +	if(!aThread)
  1.3177 +		{
  1.3178 +		return KErrArgument;
  1.3179 +		}
  1.3180 +
  1.3181 +	//check aDestDes is empty
  1.3182 +	if(aDestDes.Ptr() != NULL)
  1.3183 +		{
  1.3184 +		return KErrArgument;
  1.3185 +		}
  1.3186 +
  1.3187 +	//get the source descriptor's max length and exit if 0
  1.3188 +	TUint srcMaxLength = Kern::ThreadGetDesMaxLength(aThread, &aSrcDes);
  1.3189 +	if(srcMaxLength == 0)
  1.3190 +		{
  1.3191 +		return KErrNone;
  1.3192 +		}
  1.3193 +
  1.3194 +	//allocate memory and return if none available
  1.3195 +	NKern::ThreadEnterCS();
  1.3196 +	TUint8 *destPtr = (TUint8*)Kern::Alloc(srcMaxLength);
  1.3197 +	NKern::ThreadLeaveCS();
  1.3198 +	if (!destPtr)
  1.3199 +		{
  1.3200 +		return KErrNoMemory;
  1.3201 +		}
  1.3202 +
  1.3203 +	//point the TPtr8 at the target memory
  1.3204 +	aDestDes.Set(destPtr, srcMaxLength, srcMaxLength);
  1.3205 +
  1.3206 +	if(aReadFromClient)
  1.3207 +		{
  1.3208 +		//read data from the client thread and return status code
  1.3209 +		return Kern::ThreadDesRead(aThread, &aSrcDes, aDestDes, aOffset);
  1.3210 +		}
  1.3211 +	else
  1.3212 +		{
  1.3213 +		return KErrNone;
  1.3214 +		}
  1.3215 +	}
  1.3216 +
  1.3217 +/**
  1.3218 +Helper function to extract a TRegisterInfo value from a descriptor containing
  1.3219 +binary data.
  1.3220 +
  1.3221 +@param aRegisterIds descriptor containing register IDs
  1.3222 +@param aOffset offset in bytes into the descriptor to start reading data from.
  1.3223 +       If this value is not a multiple of sizeof(TRegisterInfo) then a
  1.3224 +       KErrArgument error is returned.
  1.3225 +@param aValue will contain the returned value
  1.3226 +
  1.3227 +@return KErrNone if aValue was set correctly, KErrArgument if bad arguments
  1.3228 +        were passed in
  1.3229 +*/
  1.3230 +TInt DRM_DebugChannel::GetTRegisterInfo(const TDesC8 &aRegisterIds, const TUint aIndex, TRegisterInfo &aValue) const
  1.3231 +	{
  1.3232 +	TUint length = aRegisterIds.Length();
  1.3233 +
  1.3234 +	TUint size = sizeof(TRegisterInfo);
  1.3235 +
  1.3236 +	//check that not trying to read past end of descriptor
  1.3237 +	if((aIndex + 1) * size > length)
  1.3238 +		return KErrArgument;
  1.3239 +
  1.3240 +	//get pointer to descriptor's data
  1.3241 +	const TUint8 *dataPtr = aRegisterIds.Ptr();
  1.3242 +	const TRegisterInfo *registerId = reinterpret_cast<const TRegisterInfo*>(dataPtr + (aIndex * size));
  1.3243 +
  1.3244 +	aValue = *registerId;
  1.3245 +
  1.3246 +	return KErrNone;
  1.3247 +	}
  1.3248 +
  1.3249 +/**
  1.3250 +Helper function to get the kernel register ID of the TRegisterInfo defined register.
  1.3251 +
  1.3252 +@param aDebugRegister the debug register ID to return the kernel ID for
  1.3253 +@param aKernelRegister corresponding value of register aDebugRegister
  1.3254 +
  1.3255 +@return KErrNone if translation occurred without problems
  1.3256 +        KErrNotSupported if aDebugRegister is not supported by the kernel
  1.3257 +*/
  1.3258 +TInt DRM_DebugChannel::GetKernelRegisterId(const TRegisterInfo aDebugRegister, TArmReg& aKernelRegister) const
  1.3259 +	{
  1.3260 +	if(Register::IsCoreReg(aDebugRegister))
  1.3261 +		{
  1.3262 +		TUint id = Register::GetCoreRegId(aDebugRegister);
  1.3263 +		//first 17 registers match the first 17 kernel registers
  1.3264 +		if(id < 17)
  1.3265 +			{
  1.3266 +			aKernelRegister = id;
  1.3267 +			}
  1.3268 +		else
  1.3269 +			{
  1.3270 +			return KErrNotSupported;
  1.3271 +			}
  1.3272 +		}
  1.3273 +	else if(Register::IsCoproReg(aDebugRegister))
  1.3274 +		{
  1.3275 +		TUint32 crn = Register::GetCRn(aDebugRegister);
  1.3276 +		TUint32 crm = Register::GetCRm(aDebugRegister);
  1.3277 +		TUint32 opcode1 = Register::GetOpcode1(aDebugRegister);
  1.3278 +		TUint32 opcode2 = Register::GetOpcode2(aDebugRegister);
  1.3279 +		TUint32 coproNum = Register::GetCoproNum(aDebugRegister);
  1.3280 +
  1.3281 +		//each coprocessor register has potentially different characteristics
  1.3282 +		//so need to identify each individually
  1.3283 +
  1.3284 +		//this is the DACR, the ARM ARM specifies that the CRn and the
  1.3285 +		//Opcodes are not relevant, section B3-24, point 3.7.3
  1.3286 +		if((coproNum == 15) && (crm == 3))
  1.3287 +			{
  1.3288 +			aKernelRegister = EArmDacr;
  1.3289 +			}
  1.3290 +		else
  1.3291 +			{
  1.3292 +			return KErrNotSupported;
  1.3293 +			}
  1.3294 +		}
  1.3295 +	else // might be supported at a later date
  1.3296 +		{
  1.3297 +		return KErrNotSupported;
  1.3298 +		}
  1.3299 +
  1.3300 +	return KErrNone;
  1.3301 +	}
  1.3302 +
  1.3303 +/**
  1.3304 +Helper function to get the debug register ID of the kernel defined register.
  1.3305 +
  1.3306 +@param aKernelRegister the kernel register ID to return the debug ID for
  1.3307 +@param aDebugRegister corresponding value of register aKernelRegister
  1.3308 +
  1.3309 +@return KErrNone if translation occured without problems
  1.3310 +        KErrNotSupported if aKernelRegister is not supported by the debug
  1.3311 +	security server
  1.3312 +*/
  1.3313 +TInt DRM_DebugChannel::GetDebugRegisterId(const TArmReg aKernelRegister, TRegisterInfo &aDebugRegister) const
  1.3314 +	{
  1.3315 +
  1.3316 +	// registers 0 - 15 and the CPSR share the same values as with the debug enums
  1.3317 +	if(aKernelRegister < 17)
  1.3318 +		{
  1.3319 +		TUint32 id = aKernelRegister;
  1.3320 +		aDebugRegister = id << 8;
  1.3321 +		}
  1.3322 +	//the DACR value is special and corresponds to EDF_Register_DACR
  1.3323 +	else if(aKernelRegister == EArmDacr)
  1.3324 +		{
  1.3325 +		aDebugRegister = 0x00300f01;
  1.3326 +		}
  1.3327 +	// must be an unsupported register, return an error as such
  1.3328 +	else
  1.3329 +		{
  1.3330 +		return KErrNotSupported;
  1.3331 +		}
  1.3332 +
  1.3333 +	//found a supported register so return KErrNone
  1.3334 +	return KErrNone;
  1.3335 +	}
  1.3336 +
  1.3337 +/**
  1.3338 +Helper function to find out whether the aIndex flag is set. This is equivalent
  1.3339 +to the aIndex bit of aFlags being non-zero.
  1.3340 +
  1.3341 +@param aFlags set of flags
  1.3342 +@param aIndex offset into aFlags to get flag from
  1.3343 +
  1.3344 +@return ETrue if bit is set, EFalse if not
  1.3345 +*/
  1.3346 +TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
  1.3347 +	{
  1.3348 +	return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
  1.3349 +	}
  1.3350 +
  1.3351 +/* Register the attachment of a debug agent to a process to be debugged
  1.3352 + *
  1.3353 + * @param a1 - TDes8 target process name
  1.3354 + * @param a2 - &TUint64 - Debug Agent Id
  1.3355 + *
  1.3356 + * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
  1.3357 + * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
  1.3358 + * if appropriate.
  1.3359 + */
  1.3360 +TInt DRM_DebugChannel::AttachProcess(TAny* a1, TAny* a2)
  1.3361 +	{
  1.3362 +	LOG_MSG("DRM_DebugChannel::AttachProcess()");
  1.3363 +
  1.3364 +	// Validate the supplied TDes8 target process name in a1
  1.3365 +	TInt length, maxLength;
  1.3366 +	TUint8* aPtr;
  1.3367 +
  1.3368 +	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  1.3369 +		a1,\
  1.3370 +		length,\
  1.3371 +		maxLength,\
  1.3372 +		aPtr,\
  1.3373 +		EFalse);
  1.3374 +	if (err != KErrNone)
  1.3375 +		{
  1.3376 +		// Could not read the descriptor information
  1.3377 +		return err;
  1.3378 +		}
  1.3379 +
  1.3380 +	// Check the processname is a valid size for a filepath
  1.3381 +	if (length < 1 || length >= KMaxPath)
  1.3382 +		{
  1.3383 +		return KErrArgument;
  1.3384 +		}
  1.3385 +
  1.3386 +	if (maxLength < 1 || maxLength >= KMaxPath)
  1.3387 +		{
  1.3388 +		return KErrArgument;
  1.3389 +		}
  1.3390 +
  1.3391 +	// Allocate space to store the target process name in a kernel-side TPtr8
  1.3392 +	NKern::ThreadEnterCS();
  1.3393 +	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  1.3394 +	NKern::ThreadLeaveCS();
  1.3395 +	if (buffer==NULL)
  1.3396 +		{
  1.3397 +		// Out of memory
  1.3398 +		return KErrNoMemory;
  1.3399 +		}
  1.3400 +
  1.3401 +	// A temporary descriptor to store the target process name
  1.3402 +	TPtr8 targetProcessName(buffer,length,length);
  1.3403 +
  1.3404 +	// Read the user-side data into targetProcessName
  1.3405 +	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  1.3406 +	if (err != KErrNone)
  1.3407 +		{
  1.3408 +		// Could not read the user-side descriptor containing the target process name
  1.3409 +		NKern::ThreadEnterCS();
  1.3410 +		Kern::Free(buffer);
  1.3411 +		NKern::ThreadLeaveCS();
  1.3412 +
  1.3413 +		return err;
  1.3414 +		}
  1.3415 +
  1.3416 +	// Obtain the Debug Agent Id
  1.3417 +	TUint64 debugAgentId = 0;
  1.3418 +
  1.3419 +	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
  1.3420 +	if (err != KErrNone)
  1.3421 +		{
  1.3422 +		// Something bad happened so free the memory and return
  1.3423 +		NKern::ThreadEnterCS();
  1.3424 +		Kern::Free(buffer);
  1.3425 +		NKern::ThreadLeaveCS();
  1.3426 +		return err;
  1.3427 +		}
  1.3428 +
  1.3429 +	// Add the target process to our list of tracked processes
  1.3430 +	err = TheDProcessTracker.AttachProcess(targetProcessName, debugAgentId);
  1.3431 +
  1.3432 +	// Free the kernel-side memory containing targetProcessName data
  1.3433 +	NKern::ThreadEnterCS();
  1.3434 +	Kern::Free(buffer);
  1.3435 +	NKern::ThreadLeaveCS();
  1.3436 +
  1.3437 +	return err;
  1.3438 +	}
  1.3439 +
  1.3440 +/* Register the detachment of a debug agent to a process to be debugged.
  1.3441 + *
  1.3442 + * @param - a1 TDes8 target process name in a1
  1.3443 + * @param a2 - &TUint64 - Debug Agent Id
  1.3444 + *
  1.3445 + * @return - KErrNone if successful. KErrArgument if the filepath is not a valid size.
  1.3446 + * KErrOutOfMemory if there is insufficient memory. Or one of the other system wide error codes
  1.3447 + * if appropriate.
  1.3448 + */
  1.3449 +TInt DRM_DebugChannel::DetachProcess(TAny* a1, TAny* a2)
  1.3450 +	{
  1.3451 +	// Validate the supplied TDes8 target process name in a1
  1.3452 +	TInt length, maxLength;
  1.3453 +	TUint8* aPtr;
  1.3454 +
  1.3455 +	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  1.3456 +		a1,\
  1.3457 +		length,\
  1.3458 +		maxLength,\
  1.3459 +		aPtr,\
  1.3460 +		EFalse);
  1.3461 +	if (err != KErrNone)
  1.3462 +		{
  1.3463 +		return err;
  1.3464 +		}
  1.3465 +
  1.3466 +	if (length < 1 || length >= KMaxPath)
  1.3467 +		{
  1.3468 +		return KErrArgument;
  1.3469 +		}
  1.3470 +
  1.3471 +	if (maxLength < 1 || maxLength >= KMaxPath)
  1.3472 +		{
  1.3473 +		return KErrArgument;
  1.3474 +		}
  1.3475 +
  1.3476 +	// Allocate space to store the target process name in a kernel-side TPtr8
  1.3477 +	NKern::ThreadEnterCS();
  1.3478 +	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  1.3479 +	NKern::ThreadLeaveCS();
  1.3480 +	if (buffer==NULL)
  1.3481 +	{
  1.3482 +		// Out of memory
  1.3483 +		return KErrNoMemory;
  1.3484 +	}
  1.3485 +
  1.3486 +	TPtr8 targetProcessName(buffer,length,length);
  1.3487 +
  1.3488 +	// Read the user-side data into targetProcessName
  1.3489 +	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  1.3490 +	if (err != KErrNone)
  1.3491 +	{
  1.3492 +		// Something bad happened so free the memory and return
  1.3493 +		NKern::ThreadEnterCS();
  1.3494 +		Kern::Free(buffer);
  1.3495 +		NKern::ThreadLeaveCS();
  1.3496 +
  1.3497 +		return err;
  1.3498 +	}
  1.3499 +
  1.3500 +	// Obtain the AgentId
  1.3501 +	TUint64 debugAgentId = 0;
  1.3502 +
  1.3503 +	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
  1.3504 +	if (err != KErrNone)
  1.3505 +	{
  1.3506 +		// Something bad happened so free the memory and return
  1.3507 +		NKern::ThreadEnterCS();
  1.3508 +		Kern::Free(buffer);
  1.3509 +		NKern::ThreadLeaveCS();
  1.3510 +
  1.3511 +		return err;
  1.3512 +	}
  1.3513 +
  1.3514 +	// Remove the process from our list of tracked processes
  1.3515 +	err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
  1.3516 +
  1.3517 +	// Free the kernel-side memory containing targetProcessName data
  1.3518 +	NKern::ThreadEnterCS();
  1.3519 +	Kern::Free(buffer);
  1.3520 +	NKern::ThreadLeaveCS();
  1.3521 +
  1.3522 +	return err;
  1.3523 +	}
  1.3524 +
  1.3525 +/* Register the detachment of a debug agent from all processes being debugged.
  1.3526 + *
  1.3527 + * @param - a1 - &TUint64 Debug Agent Id.
  1.3528 + * @return - KErrNone if successful. One of the system-wide error codes otherwise.
  1.3529 + */
  1.3530 +TInt DRM_DebugChannel::DetachAgent(TAny* a1, TAny* a2)
  1.3531 +	{
  1.3532 +	// Obtain the AgentId
  1.3533 +	TUint64 debugAgentId = 0;
  1.3534 +
  1.3535 +	TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
  1.3536 +	if (err != KErrNone)
  1.3537 +	{
  1.3538 +		return err;
  1.3539 +	}
  1.3540 +
  1.3541 +	// Remove the process from our list of tracked processes
  1.3542 +	return TheDProcessTracker.DetachAgent(debugAgentId);
  1.3543 +	}
  1.3544 +
  1.3545 +/* Set the action associated with a particular kernel event for a given agent and target process
  1.3546 + *
  1.3547 + * @param - a1 TDes8 target process name in a1
  1.3548 + * @param - a2 &TRM_DebugEventActionInfo
  1.3549 + * @return - KErrNone if successful. KErrArgument if the filepath is an invalid size. Or one of
  1.3550 + * the other system wide error codes if appropriate.
  1.3551 + */
  1.3552 +TInt DRM_DebugChannel::SetEventAction(TAny* a1, TAny* a2)
  1.3553 +	{
  1.3554 +	// Validate the supplied TDes8 target process name in a1
  1.3555 +	TInt length, maxLength;
  1.3556 +	TUint8* aPtr;
  1.3557 +
  1.3558 +	TInt err = Kern::ThreadGetDesInfo(iClientThread,\
  1.3559 +		a1,\
  1.3560 +		length,\
  1.3561 +		maxLength,\
  1.3562 +		aPtr,\
  1.3563 +		EFalse);
  1.3564 +	if (err != KErrNone)
  1.3565 +		{
  1.3566 +		return err;
  1.3567 +		}
  1.3568 +
  1.3569 +	if (length < 1 || length >= KMaxPath)
  1.3570 +		{
  1.3571 +		return KErrArgument;
  1.3572 +		}
  1.3573 +
  1.3574 +	if (maxLength < 1 || maxLength >= KMaxPath)
  1.3575 +		{
  1.3576 +		return KErrArgument;
  1.3577 +		}
  1.3578 +
  1.3579 +	// Allocate space to store the target process name in a kernelspace TPtr8
  1.3580 +	NKern::ThreadEnterCS();
  1.3581 +	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
  1.3582 +	NKern::ThreadLeaveCS();
  1.3583 +	if (buffer==NULL)
  1.3584 +	{
  1.3585 +		// Out of memory
  1.3586 +		return KErrNoMemory;
  1.3587 +	}
  1.3588 +	TPtr8 targetProcessName(buffer,length,length);
  1.3589 +
  1.3590 +	// Read the user-side data into targetProcessName
  1.3591 +	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
  1.3592 +	if (err != KErrNone)
  1.3593 +	{
  1.3594 +		// Something bad happened so free the memory and return
  1.3595 +		NKern::ThreadEnterCS();
  1.3596 +		Kern::Free(buffer);
  1.3597 +		NKern::ThreadLeaveCS();
  1.3598 +
  1.3599 +		return err;
  1.3600 +	}
  1.3601 +
  1.3602 +	// Read the Event and Action from the user-side
  1.3603 +	TRM_DebugEventActionInfo info(0,0,0);
  1.3604 +
  1.3605 +	err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
  1.3606 +	if (err != KErrNone)
  1.3607 +	{
  1.3608 +		// Could not read event action data from the user-side
  1.3609 +
  1.3610 +		// Free memory used for targetProcessName
  1.3611 +		NKern::ThreadEnterCS();
  1.3612 +		Kern::Free(buffer);
  1.3613 +		NKern::ThreadLeaveCS();
  1.3614 +
  1.3615 +		return err;
  1.3616 +	}
  1.3617 +
  1.3618 +	// Find the target process
  1.3619 +	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
  1.3620 +	if (pProcess == NULL)
  1.3621 +	{
  1.3622 +		// Could not find this process
  1.3623 +
  1.3624 +		// Free memory used for targetProcessName
  1.3625 +		NKern::ThreadEnterCS();
  1.3626 +		Kern::Free(buffer);
  1.3627 +		NKern::ThreadLeaveCS();
  1.3628 +
  1.3629 +		return KErrArgument;
  1.3630 +	}
  1.3631 +
  1.3632 +	TUint64 debugAgentId = info.iAgentId;
  1.3633 +
  1.3634 +	// Find the agent
  1.3635 +	DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
  1.3636 +	if (debugAgent == NULL)
  1.3637 +	{
  1.3638 +		// Bad agent means there is no tracking agent
  1.3639 +		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
  1.3640 +
  1.3641 +		// Free memory used for targetProcessName
  1.3642 +		NKern::ThreadEnterCS();
  1.3643 +		Kern::Free(buffer);
  1.3644 +		NKern::ThreadLeaveCS();
  1.3645 +
  1.3646 +		return KErrGeneral;
  1.3647 +	}
  1.3648 +
  1.3649 +	// Set the event action
  1.3650 +	debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
  1.3651 +
  1.3652 +	// Free memory used for targetProcessName
  1.3653 +	NKern::ThreadEnterCS();
  1.3654 +	Kern::Free(buffer);
  1.3655 +	NKern::ThreadLeaveCS();
  1.3656 +
  1.3657 +	return KErrNone;
  1.3658 +	}
  1.3659 +
  1.3660 +TInt DRM_DebugChannel::Step(const TUint32 aThreadId, const TUint32 aNumSteps)
  1.3661 +	{
  1.3662 +	LOG_MSG3("DRM_DebugChannel::Step(aThreadId = 0x%08x, aNumSteps = 0x%08x)\n",aThreadId,aNumSteps);
  1.3663 +
  1.3664 +	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
  1.3665 +
  1.3666 +	if (thread == NULL)
  1.3667 +		{
  1.3668 +		// The thread terminated before we could open it.
  1.3669 +		LOG_MSG2("DRM_DebugChannel::Step - Could not open thread %u", aThreadId);
  1.3670 +
  1.3671 +		return KErrArgument;
  1.3672 +		}
  1.3673 +
  1.3674 +	// We simply repeat this for desired number of steps
  1.3675 +	TInt err = KErrNone;
  1.3676 +
  1.3677 +	// Need to step from the current location for 'n' steps
  1.3678 +	TUint32 startAddress;
  1.3679 +
  1.3680 +	// We always step from the current PC.
  1.3681 +	err = ReadKernelRegisterValue(thread, PC_REGISTER, startAddress);
  1.3682 +	if(err != KErrNone)
  1.3683 +		{
  1.3684 +		LOG_MSG2("DRM_DebugChannel::Step - Could not read the PC: %d", err);
  1.3685 +
  1.3686 +		// Close the handle
  1.3687 +		thread->Close(NULL);
  1.3688 +
  1.3689 +		return err;
  1.3690 +		}
  1.3691 +
  1.3692 +	err = DoStepRange(thread, startAddress, startAddress, ETrue, EFalse, aNumSteps, ETrue);
  1.3693 +
  1.3694 +	if (err != KErrNone)
  1.3695 +		{
  1.3696 +		// There was a problem, return straightaway
  1.3697 +		LOG_MSG("DRM_DebugChannel::Step - failed to step");
  1.3698 +		}
  1.3699 +
  1.3700 +	// Close the handle
  1.3701 +	thread->Close(NULL);
  1.3702 +
  1.3703 +	return err;
  1.3704 +	}
  1.3705 +
  1.3706 +TInt DRM_DebugChannel::KillProcess(const TUint32 aProcessId, const TInt aReason)
  1.3707 +	{
  1.3708 +	LOG_MSG3("DRM_DebugChannel::KillProcess(aProcessId = 0x%08x, aReason = 0x%08x)\n",aProcessId,aReason);
  1.3709 +
  1.3710 +	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
  1.3711 +
  1.3712 +	if (process == NULL)
  1.3713 +		{
  1.3714 +		// The process terminated before we could open it to kill it ourselves.
  1.3715 +		LOG_MSG2("DRM_DebugChannel::KillProcess - Could not open process %u", aProcessId);
  1.3716 +
  1.3717 +		return KErrArgument;
  1.3718 +		}
  1.3719 +
  1.3720 +	TInt err = KErrNone;
  1.3721 +
  1.3722 +	DebugSupport::TerminateProcess(process,aReason);
  1.3723 +
  1.3724 +	// Close the handle
  1.3725 +	process->Close(NULL);
  1.3726 +
  1.3727 +	return err;
  1.3728 +	}
  1.3729 +
  1.3730 +/* Security critical - this checks whether the specified process is debuggable or not
  1.3731 + *
  1.3732 + * @param aProcessId - The process id of the process to check
  1.3733 + * @return KErrNone if debuggable, KErrPermissionDenied if not debuggable.
  1.3734 + */
  1.3735 +TInt DRM_DebugChannel::IsDebuggable(const TUint32 aProcessId)
  1.3736 +	{
  1.3737 +	/* In order to ensure that only processes which are debuggable
  1.3738 +	 * can be debugged, this function enables the security server
  1.3739 +	 * to read the DProcess.iDebugAttributes field and ensure
  1.3740 +	 * the process was created from a debuggable executable.
  1.3741 +	 */
  1.3742 +	LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x)\n",aProcessId);
  1.3743 +
  1.3744 +	TInt err = KErrPermissionDenied;
  1.3745 +
  1.3746 +	DProcess* process = DebugUtils::OpenProcessHandle(aProcessId);
  1.3747 +	if (process)
  1.3748 +		{
  1.3749 +		if (process->iDebugAttributes & TProcessCreateInfo::EDebugAllowed)
  1.3750 +			{
  1.3751 +			// Yes this process exists and is debuggable
  1.3752 +			err = KErrNone;
  1.3753 +			}
  1.3754 +		process->Close(NULL);
  1.3755 +		}
  1.3756 +
  1.3757 +	if (err == KErrNone)
  1.3758 +	{
  1.3759 +		LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
  1.3760 +	}
  1.3761 +
  1.3762 +	return err;
  1.3763 +	}