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