dbgagents/trkagent/eka2driver/TrkKernelDriver.cpp
changeset 0 c6b0df440bee
equal deleted inserted replaced
-1:000000000000 0:c6b0df440bee
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #ifdef __WINS__
       
    20 #error - this driver cannot be built for emulation
       
    21 #endif
       
    22 
       
    23 #include <e32def.h>
       
    24 #include <e32cmn.h>
       
    25 #include <u32std.h>
       
    26 #include <kernel.h>
       
    27 #include <kern_priv.h>
       
    28 #include <nk_trace.h>
       
    29 //#include <mmboot.h>
       
    30 #include <arm.h>
       
    31 #include <cache.h>
       
    32 #include <platform.h>
       
    33 #include <nkern.h>
       
    34 #include <u32hal.h>
       
    35 
       
    36 #include "TrkKernelDriver.h"
       
    37 #include "TrkDriver.h"
       
    38 #include "TrkEventHandler.h"
       
    39 
       
    40 #define KTrkAppSecurUid 0x200170BB
       
    41 #define KTrkExeSecurUid 0x200159E2
       
    42 #define KTrkSrvSecurUid 0x200170B7
       
    43 
       
    44 // Uncomment the line below for reading kernel thread registers.
       
    45 // There is a problem using NKern::Lock before calling UserContextType on old releases like S60 3.0
       
    46 // So for now, disabling the supporting reading kern thread registers as we are not really supporting
       
    47 // device driver debugging anyway.
       
    48 //#define SUPPORT_KERNCONTEXT
       
    49 
       
    50 //
       
    51 // Static function definitions
       
    52 //
       
    53 
       
    54 static TInt Bitcount(TUint32 val)
       
    55 {
       
    56 	TInt nbits;
       
    57 
       
    58 	for (nbits = 0; val != 0; nbits++)
       
    59 	{
       
    60 		val &= val - 1;		// delete rightmost 1-bit in val
       
    61 	}
       
    62 	
       
    63 	return nbits;
       
    64 }
       
    65 
       
    66 static TUint8 tolower(TUint8 c)
       
    67 {
       
    68 	if (c >= 'A' && c <= 'Z')
       
    69 		c = c + ('a' - 'A');
       
    70 	
       
    71 	return c;
       
    72 }
       
    73 
       
    74 
       
    75 static TInt _strnicmp(const TUint8 *s1, const TUint8 *s2, int n)
       
    76 {	
       
    77     int i;
       
    78     TUint8 c1, c2;
       
    79     for (i=0; i<n; i++)
       
    80     {
       
    81         c1 = tolower(*s1++);
       
    82         c2 = tolower(*s2++);
       
    83         if (c1 < c2) return -1;
       
    84         if (c1 > c2) return 1;
       
    85         if (!c1) return 0;
       
    86     }
       
    87     return 0;
       
    88 }
       
    89 
       
    90 //
       
    91 //
       
    92 // DMetroTrkDriverFactory implementation
       
    93 //
       
    94 //
       
    95 
       
    96 //
       
    97 // DMetroTrkDriverFactory constructor
       
    98 //
       
    99 DMetroTrkDriverFactory::DMetroTrkDriverFactory()
       
   100 {
       
   101     iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);    
       
   102 }
       
   103 
       
   104 //
       
   105 // DMetroTrkDriverFactory::Create
       
   106 //
       
   107 TInt DMetroTrkDriverFactory::Create(DLogicalChannelBase*& aChannel)
       
   108 {
       
   109 	if (iOpenChannels != 0)
       
   110 		return KErrInUse; // a channel is already open
       
   111 	
       
   112 	aChannel = new DMetroTrkChannel(this);
       
   113 	
       
   114 	return aChannel ? KErrNone : KErrNoMemory;
       
   115 }
       
   116 
       
   117 //
       
   118 // DMetroTrkDriverFactory::Install
       
   119 //
       
   120 TInt DMetroTrkDriverFactory::Install()
       
   121 {
       
   122     return(SetName(&KMetroTrkDriverName));
       
   123 }
       
   124 
       
   125 //
       
   126 // DMetroTrkDriverFactory::Install
       
   127 //
       
   128 void DMetroTrkDriverFactory::GetCaps(TDes8& aDes) const
       
   129 {
       
   130     TCapsMetroTrkDriver b;
       
   131     b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
       
   132     
       
   133     Kern::InfoCopy(aDes,(TUint8*)&b, sizeof(b));
       
   134 }
       
   135 
       
   136 
       
   137 //
       
   138 //
       
   139 // DMetroTrkChannel implementation
       
   140 //
       
   141 //
       
   142 
       
   143 //
       
   144 // DMetroTrkChannel constructor
       
   145 //
       
   146 DMetroTrkChannel::DMetroTrkChannel(DLogicalDevice* aLogicalDevice)
       
   147 	: iExcludedROMAddressStart(ROM_LINEAR_BASE),
       
   148       iExcludedROMAddressEnd(0),
       
   149    	  iBreakPointList(NUMBER_OF_TEMP_BREAKPOINTS, 0),
       
   150   	  iNextBreakId(NUMBER_OF_TEMP_BREAKPOINTS),
       
   151       iEventInfo(NULL),
       
   152   	  iEventQueue(NUMBER_OF_EVENTS_TO_QUEUE, 0),
       
   153   	  iTraceEventQueue(NUMBER_OF_EVENTS_TO_QUEUE, 0),
       
   154       iRequestGetEventStatus(NULL),
       
   155    	  iPageSize(0x1000),
       
   156    	  iNotifyLibLoadedEvent(ETrue),
       
   157    	  iMultipleMemModel(EFalse),
       
   158    	  iExcInfoValid(EFalse),
       
   159    	  iDebugging(ETrue)
       
   160 {
       
   161 	LOG_MSG("DMetroTrkChannel::DMetroTrkChannel()");
       
   162 
       
   163 	iDevice = aLogicalDevice;
       
   164 	
       
   165 	iClientThread = &Kern::CurrentThread();
       
   166 	TInt err = iClientThread->Open();
       
   167 	
       
   168 	iBreakPointList.Reset();	
       
   169 	TBreakEntry emptyTempBreak;
       
   170 	
       
   171 	for (TInt i = 0; i < NUMBER_OF_TEMP_BREAKPOINTS; i++)
       
   172 	{
       
   173 		emptyTempBreak.iId = i;
       
   174 		
       
   175 		if (KErrNone != iBreakPointList.Append(emptyTempBreak))
       
   176 		{
       
   177 			LOG_MSG("Error appending blank temp break entry");
       
   178 		}
       
   179 	}
       
   180 	
       
   181 	SEventInfo emptyEvent;
       
   182 
       
   183 	for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
   184 	{
       
   185 		if (KErrNone != iEventQueue.Append(emptyEvent))
       
   186 		{
       
   187 			LOG_MSG("Error appending blank event entry");
       
   188 		}
       
   189 	}
       
   190 	
       
   191 	for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
   192 	{
       
   193 		if (KErrNone != iTraceEventQueue.Append(emptyEvent))
       
   194 		{
       
   195 			LOG_MSG("Error appending blank trace event entry");
       
   196 		}
       
   197 	}
       
   198 		
       
   199 	TTrkLibName emptyLib;
       
   200 	for (TInt i=0; i<NUMBER_OF_LIBS_TO_REGISTER; i++)
       
   201     {
       
   202         if (KErrNone != iLibraryNotifyList.Append(emptyLib))
       
   203         {
       
   204             LOG_MSG("Error appending blank empty lib entry");
       
   205         }
       
   206     }
       
   207 		
       
   208 	iPageSize = Kern::RoundToPageSize(1);
       
   209 }
       
   210 
       
   211 //
       
   212 // DMetroTrkChannel destructor
       
   213 //
       
   214 DMetroTrkChannel::~DMetroTrkChannel()
       
   215 {
       
   216 	LOG_MSG("DMetroTrkChannel::~DMetroTrkChannel()");
       
   217 	
       
   218 	iDebugging = EFalse;
       
   219 	
       
   220 	Kern::SafeClose((DObject*&)iClientThread, NULL);
       
   221 	
       
   222 	ClearAllBreakPoints();
       
   223 	
       
   224 	// close the breakpoint list and free the memory associated with it
       
   225 	iBreakPointList.Close();
       
   226 
       
   227 	// close the event queue and free the memory associated with it
       
   228 	iEventQueue.Close();
       
   229 	
       
   230 	// close the trace event queue and free the memory associated with it
       
   231 	iTraceEventQueue.Close();
       
   232 	
       
   233 	//close the debug process list
       
   234 	iDebugProcessList.Close();
       
   235 	
       
   236 	//close the process notify list
       
   237 	iProcessNotifyList.Close();
       
   238 	
       
   239 	//close the code modifier
       
   240 	DebugSupport::CloseCodeModifier();
       
   241 
       
   242 	// PANIC_BACKPORT
       
   243 	// Resume all the frozen threads with semaphores.
       
   244 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
   245 	{
       
   246 		NKern::FSSignal(iFrozenThreadSemaphores[i]);
       
   247 		NKern::ThreadEnterCS();
       
   248 		delete iFrozenThreadSemaphores[i];
       
   249 		NKern::ThreadLeaveCS();
       
   250 		iFrozenThreadSemaphores.Remove(i);		
       
   251 	}
       
   252 	//Reset the array and delete the objects that its members point to
       
   253 	iFrozenThreadSemaphores.ResetAndDestroy();
       
   254 	// END PANIC_BACKPORT
       
   255 }
       
   256 
       
   257 //
       
   258 // DMetroTrkChannel::DoCreate
       
   259 //
       
   260 TInt DMetroTrkChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
       
   261 {
       
   262 	LOG_MSG("DMetroTrkChannel::DoCreate()");
       
   263 
       
   264   	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
       
   265 		return KErrNotSupported; 
       
   266   	
       
   267   	// Do the security check here so that any arbitrary application doesn't make 
       
   268   	// use of Trk kernel driver.
       
   269   	if (!DoSecurityCheck())
       
   270   	{
       
   271   		return KErrPermissionDenied;
       
   272   	}
       
   273   	
       
   274   	if (anInfo)
       
   275   	{
       
   276   		// this is the end address of the user library. 
       
   277   		// this doesn't seem to be valid for EKA2.
       
   278   		// right now we dont need this for EKA2 since we are not worried
       
   279   		// about kernel being stopped as kernel is multithreaded.
       
   280   		// just retaining this for future use.		
       
   281 		TBuf8<32> buf;
       
   282 		TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
       
   283 		if(err != KErrNone)
       
   284 			return err;
       
   285 		
       
   286 		//iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
       
   287 	}
       
   288   	
       
   289   	//check whether the memory model is multiple or not.
       
   290   	TUint32 memModelAttrib = (TUint32)Kern::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);	
       
   291 	if ((memModelAttrib & EMemModelTypeMask) == EMemModelTypeMultiple) 
       
   292     { 
       
   293         //Multiple memory model
       
   294         iMultipleMemModel = ETrue;        
       
   295     } 
       
   296 
       
   297 	TUint caps; //ignored for now
       
   298 	TInt err = DebugSupport::InitialiseCodeModifier(caps, NUMBER_OF_MAX_BREAKPOINTS);
       
   299 	//if code modifier initializer failed, 
       
   300 	//return here, since we can't set an breakpoints
       
   301 	if(err != KErrNone) 
       
   302 		return err;
       
   303 		       
       
   304 	//Setup the driver for receiving client messages
       
   305 	iDFCQue = NULL;
       
   306 	TBuf8<KMaxInfoName> trkDFC = _L8("TRK DFC");
       
   307 	
       
   308 	err = Kern::DfcQCreate(iDFCQue, 27, &trkDFC);
       
   309 	if (err == KErrNone)
       
   310 	{
       
   311 		SetDfcQ(iDFCQue);
       
   312 	}
       
   313 	else
       
   314 	{
       
   315 		SetDfcQ(Kern::DfcQue0());
       
   316 	}
       
   317 	iMsgQ.Receive();  	
       
   318 	
       
   319 	iEventHandler = new DMetroTrkEventHandler;
       
   320 	if (!iEventHandler)
       
   321 		return KErrNoMemory;
       
   322 	err = iEventHandler->Create(iDevice, this, iClientThread);
       
   323 	if (err != KErrNone)
       
   324 		return err;
       
   325 		
       
   326 	return iEventHandler->Start();
       
   327 }
       
   328 
       
   329 //
       
   330 // DMetroTrkChannel::DoCancel
       
   331 //
       
   332 void DMetroTrkChannel::DoCancel(TInt aReqNo)
       
   333 {
       
   334 	LOG_MSG("DMetroTrkChannel::DoCancel()");
       
   335 	
       
   336 	switch(aReqNo)
       
   337 	{
       
   338 		case RMetroTrkDriver::ERequestGetEventCancel:
       
   339 		{
       
   340 			Kern::RequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
       
   341 			iEventInfo = NULL;
       
   342 			iRequestGetEventStatus = 0;
       
   343 		}
       
   344 		break;
       
   345 	}
       
   346 
       
   347 }
       
   348 
       
   349 //
       
   350 // DMetroTrkChannel::DoRequest
       
   351 //
       
   352 void DMetroTrkChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   353 {
       
   354 	LOG_MSG("DMetroTrkChannel::DoRequest()");
       
   355 	
       
   356 	switch(aReqNo)
       
   357 	{
       
   358 		case RMetroTrkDriver::ERequestGetEvent:
       
   359 		{
       
   360 			// check to see if we have any queued up events
       
   361 			for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
   362 			{
       
   363 				if (SEventInfo::EUnknown != iEventQueue[i].iEventType)
       
   364 				{
       
   365 					LOG_MSG("DoRequest - slot NOT empty");
       
   366 					// iClientThread is the user side debugger thread, so use it to write the info to it memory
       
   367 					TInt err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8 *)&iEventQueue[i], sizeof(SEventInfo), iClientThread);
       
   368 					if (KErrNone != err)
       
   369 						LOG_MSG2("Error writing event info: %d", err);
       
   370 
       
   371 					// signal the debugger thread
       
   372 					Kern::RequestComplete(iClientThread, aStatus, KErrNone);
       
   373 				
       
   374 					iEventQueue[i].Reset();
       
   375 					return;
       
   376 				}
       
   377 				
       
   378 				LOG_MSG("DoRequest - slot empty");
       
   379 			}
       
   380 
       
   381 			// check to see if we have any queued up trace events
       
   382 			for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
   383 			{
       
   384 				if (SEventInfo::EUnknown != iTraceEventQueue[i].iEventType)
       
   385 				{
       
   386 					LOG_MSG("DoRequest - slot NOT empty");
       
   387 					// iClientThread is the user side debugger thread, so use it to write the info to it memory
       
   388 					TInt err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8 *)&iTraceEventQueue[i], sizeof(SEventInfo), iClientThread);
       
   389 					if (KErrNone != err)
       
   390 						LOG_MSG2("Error writing trace event info: %d", err);
       
   391 
       
   392 					// signal the debugger thread
       
   393 					Kern::RequestComplete(iClientThread, aStatus, KErrNone);
       
   394 				
       
   395 					iTraceEventQueue[i].Reset();
       
   396 					return;
       
   397 				}
       
   398 				
       
   399 				LOG_MSG("DoRequest - trace slot empty");
       
   400 			}
       
   401 			
       
   402 			// store the pointer so we can modify it later
       
   403 			iEventInfo = (SEventInfo *)a1;
       
   404 			iRequestGetEventStatus = aStatus;
       
   405 			break;
       
   406 		}		
       
   407 		default:
       
   408 			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
       
   409 	}
       
   410 
       
   411 }
       
   412 
       
   413 //
       
   414 // DMetroTrkChannel::DoControl
       
   415 //
       
   416 TInt DMetroTrkChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
       
   417 {
       
   418 	LOG_MSG("DMetroTrkChannel::DoControl()");
       
   419 
       
   420 	LOG_MSG2("DoControl Function %d", aFunction);
       
   421 	
       
   422 	TInt err = KErrNone;
       
   423 	
       
   424 	switch(aFunction)
       
   425 	{
       
   426 		case RMetroTrkDriver::EControlSetBreak:
       
   427 		{
       
   428 			err = SetBreak((TUint32)a1, (TMetroTrkBreakInfo*)a2);
       
   429 			break;
       
   430 		}
       
   431 		case RMetroTrkDriver::EControlClearBreak:
       
   432 		{
       
   433 			err = DoClearBreak((TInt32)a1);
       
   434 			break;
       
   435 		}
       
   436 		case RMetroTrkDriver::EControlChangeBreakThread:
       
   437 		{
       
   438 			err = DoChangeBreakThread((TUint32)a1, (TInt32)a2);
       
   439 			break;
       
   440 		}
       
   441 		case RMetroTrkDriver::EControlSuspendThread:
       
   442 		{
       
   443 			err = DoSuspendThread(ThreadFromId((TUint32)a1));
       
   444 			break;
       
   445 		}
       
   446 		case RMetroTrkDriver::EControlResumeThread:
       
   447 		{			
       
   448 			err = DoResumeThread(ThreadFromId((TUint32)a1));
       
   449 			break;
       
   450 		}
       
   451 		case RMetroTrkDriver::EControlStepRange:
       
   452 		{
       
   453 			err = StepRange(ThreadFromId((TUint32)a1), (TMetroTrkStepInfo*)a2);
       
   454 			break;
       
   455 		}
       
   456 		case RMetroTrkDriver::EControlReadMemory:
       
   457 		{
       
   458 			err = ReadMemory(ThreadFromId((TUint32)a1), (TMetroTrkMemoryInfo*)a2);
       
   459 			break;
       
   460 		}
       
   461 		case RMetroTrkDriver::EControlWriteMemory:
       
   462 		{
       
   463 			err = WriteMemory(ThreadFromId((TUint32)a1), (TMetroTrkMemoryInfo*)a2);
       
   464 			break;
       
   465 		}
       
   466 		case RMetroTrkDriver::EControlReadRegisters:
       
   467 		{
       
   468 			err = ReadRegisters(ThreadFromId((TUint32)a1), (TMetroTrkRegisterInfo*)a2);
       
   469 			break;
       
   470 		}
       
   471 		case RMetroTrkDriver::EControlWriteRegisters:
       
   472 		{
       
   473 			err = WriteRegisters(ThreadFromId((TUint32)a1), (TMetroTrkRegisterInfo*)a2);
       
   474 			break;
       
   475 		}
       
   476 		case RMetroTrkDriver::EControlGetProcessInfo:
       
   477 		{
       
   478 			err = GetProcessInfo((TInt)a1, (TMetroTrkTaskInfo*)a2);
       
   479 			break;
       
   480 		}
       
   481 		case RMetroTrkDriver::EControlGetThreadInfo:
       
   482 		{
       
   483 			err = GetThreadInfo((TInt)a1, (TMetroTrkTaskInfo*)a2);
       
   484 			break;
       
   485 		}
       
   486 		case RMetroTrkDriver::EControlGetProcessAddresses:
       
   487 		{
       
   488 			err = GetProcessAddresses(ThreadFromId((TUint32)a1), (TMetroTrkProcessInfo*)a2);
       
   489 			break;
       
   490 		}
       
   491 		case RMetroTrkDriver::EControlGetStaticLibraryInfo:
       
   492 		{
       
   493 			err = GetStaticLibraryInfo((TInt)a1, (SEventInfo*)a2);
       
   494 			break;
       
   495 		}
       
   496 		case RMetroTrkDriver::EControlEnableLibLoadedEvent:
       
   497 		{
       
   498 			iNotifyLibLoadedEvent = ETrue;
       
   499 			break;
       
   500 		}
       
   501 		case RMetroTrkDriver::EControlDisableLibLoadedEvent:
       
   502 		{
       
   503 			iNotifyLibLoadedEvent = EFalse;
       
   504 			break;
       
   505 		}
       
   506 		case RMetroTrkDriver::EControlGetLibraryInfo:
       
   507 		{
       
   508 			err = GetLibraryInfo((TMetroTrkLibInfo*)a1);
       
   509 			break;
       
   510 		}
       
   511 		case RMetroTrkDriver::EControlGetExeInfo:
       
   512 		{
       
   513 			err = GetExeInfo((TMetroTrkExeInfo*)a1);
       
   514 			break;
       
   515 		}
       
   516 		case RMetroTrkDriver::EControlGetProcUidInfo:
       
   517 		{	
       
   518 			err = GetProcUidInfo((TMetroTrkProcUidInfo*)a1);
       
   519 			break;
       
   520 		}
       
   521 		case RMetroTrkDriver::EControlDetachProcess:
       
   522 		{
       
   523 		    err = DetachProcess(ProcessFromId((TInt32)a1));
       
   524 			break;
       
   525 		}
       
   526 		default:
       
   527 		{
       
   528 			return KErrGeneral;
       
   529 		}
       
   530 	}
       
   531 	
       
   532 	if (KErrNone != err)
       
   533 	{
       
   534 		LOG_MSG2("Error %d from control function", err);
       
   535 	}
       
   536 	
       
   537 	return err;
       
   538 }
       
   539 
       
   540 void DMetroTrkChannel::HandleMsg(TMessageBase* aMsg)
       
   541 {
       
   542 	LOG_MSG("DMetroTrkChannel::HandleMsg()");
       
   543 	
       
   544 	TThreadMessage& m = *(TThreadMessage*)aMsg;
       
   545 	TInt id = m.iValue;
       
   546 
       
   547 
       
   548 	if (id == (TInt)ECloseMsg)
       
   549 	{
       
   550 		if (iEventHandler)
       
   551 		{
       
   552 			iDebugging = EFalse;
       
   553 			iEventHandler->Stop();
       
   554 			iEventHandler->Close();
       
   555 			iEventHandler = NULL;
       
   556 		}
       
   557 		m.Complete(KErrNone, EFalse);
       
   558 		return;
       
   559 	}
       
   560 
       
   561 	if (id == KMaxTInt)
       
   562 	{
       
   563 		// DoCancel
       
   564 		DoCancel(m.Int0());
       
   565 		m.Complete(KErrNone, ETrue); 
       
   566 		return;
       
   567 	}
       
   568 
       
   569 	if (id < 0)
       
   570 	{
       
   571 		// DoRequest
       
   572 		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
       
   573 		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
       
   574 		m.Complete(KErrNone, ETrue);
       
   575 	}
       
   576 	else
       
   577 	{
       
   578 		// DoControl
       
   579 		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
       
   580 		m.Complete(err, ETrue);
       
   581 	}
       
   582 }
       
   583 
       
   584 //
       
   585 // DMetroTrkChannel::AddProcess
       
   586 //
       
   587 void DMetroTrkChannel::AddProcess(DProcess *aProcess, DThread *aThread)
       
   588 {
       
   589 	LOG_MSG("DMetroTrkChannel::AddProcess()");
       
   590 	// check to see if we are still debugging, otherwise just return
       
   591 	if (!iDebugging) 
       
   592 		return;
       
   593 
       
   594 	if (aProcess)
       
   595 	{		
       
   596 		if (!aThread)
       
   597 			LOG_MSG("Creator thread not available");
       
   598 	
       
   599 		// check to see if this process is being started by debug agent.
       
   600 		// If this is the case, we don't need to notify the agent since the debug agent already knows about it.
       
   601 		if (aThread && aThread->iOwningProcess->iId == iClientThread->iOwningProcess->iId)
       
   602 			return;		
       
   603 		
       
   604 		SEventInfo processEventInfo;
       
   605 		processEventInfo.iEventType = processEventInfo.EProcessAdded; 
       
   606 		processEventInfo.iProcessId = aProcess->iId;
       
   607 		processEventInfo.iFileName.Copy(*aProcess->iName);
       
   608 		processEventInfo.iUid = aProcess->iUids.iUid[2].iUid; 		
       
   609 
       
   610 		// Kernel hasn't created teh code segment yet for this process,
       
   611 		// so queue this event separately and wait for start thread event to notify.
       
   612 		iProcessNotifyList.Append(processEventInfo);	
       
   613 	}	
       
   614 }
       
   615 
       
   616 //
       
   617 // DMetroTrkChannel::StartThread
       
   618 //
       
   619 void DMetroTrkChannel::StartThread(DThread *aThread)
       
   620 {
       
   621 	LOG_MSG("DMetroTrkChannel::StartThread()");
       
   622 	// check to see if we are still debugging, otherwise just return
       
   623 	if (!iDebugging) 
       
   624 		return;
       
   625 	
       
   626 	// Using the lib loaded event flag for notifying processes as well.
       
   627 	// Check if lib loaded event is disabled. Lib loaded event
       
   628 	// is disabled temporarily in some situations, when the engine
       
   629 	// is performing some complex operations  like installing sis 
       
   630 	// files, in which case, suspending the thread for lib loaded 
       
   631 	// events would end up in a dead lock. This is due  to the fact 
       
   632 	// that the active object that handles the event notification 
       
   633 	// wouldn't get a chance to run since the code in TRK engine  
       
   634 	// which handles the commands from the host debugger is also 
       
   635 	// done in an active object which runs in the same thread. 
       
   636 	if (!iNotifyLibLoadedEvent)
       
   637 		return;
       
   638 	
       
   639 	if (aThread && aThread->iOwningProcess)
       
   640 	{				
       
   641 		DCodeSeg* codeSeg = aThread->iOwningProcess->iCodeSeg;		
       
   642 		if (codeSeg)
       
   643 		{
       
   644 			TModuleMemoryInfo processMemoryInfo;
       
   645 			TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aThread->iOwningProcess);
       
   646 			if (err == KErrNone)
       
   647 			{						
       
   648 				for (TInt i = 0; i < iProcessNotifyList.Count(); i++)
       
   649 				{
       
   650 					if (iProcessNotifyList[i].iProcessId == aThread->iOwningProcess->iId)
       
   651 					{
       
   652 						// Suspend the thread so that the host debugger can set breakpoints.
       
   653 						Kern::ThreadSuspend(*aThread, 1); 
       
   654 						iProcessNotifyList[i].iThreadId = aThread->iId;
       
   655 						iProcessNotifyList[i].iCodeAddress = processMemoryInfo.iCodeBase;
       
   656 						iProcessNotifyList[i].iDataAddress = processMemoryInfo.iInitialisedDataBase;
       
   657 						// Notify the process added event now that we have the code segment for the process
       
   658 						NotifyEvent(iProcessNotifyList[i]);
       
   659 						// Now remove from the list
       
   660 						iProcessNotifyList.Remove(i);
       
   661 						break;
       
   662 					}
       
   663 				}
       
   664 			}
       
   665 			else
       
   666 			{
       
   667 				LOG_MSG2("Error in getting memory info: %d", err);
       
   668 			}			
       
   669 		}
       
   670 		else
       
   671 		{
       
   672 			LOG_MSG2("Invalid code segment found for the started thread: %d", aThread->iId);
       
   673 		}
       
   674 	}	
       
   675 }
       
   676 
       
   677 //
       
   678 // DMetroTrkChannel::RemoveProcess
       
   679 //
       
   680 void DMetroTrkChannel::RemoveProcess(DProcess *aProcess)
       
   681 {
       
   682 	LOG_MSG("DMetroTrkChannel::RemoveProcess()");
       
   683 	// check to see if we are still debugging, otherwise just return
       
   684 	if (!iDebugging) 
       
   685 		return;
       
   686 
       
   687 	// this is called when a process dies.  we want to mark any breakpoints in this
       
   688 	// process space as obsolete.  the main reason for this is so we don't return
       
   689 	// an error when the host debugger tries to clear breakpoints for the process
       
   690 	
       
   691 	TUint32 codeAddress = 0;
       
   692 	TUint32 codeSize = 0;
       
   693 	
       
   694 	LOG_MSG2("Process being removed, Name %S", aProcess->iName);
       
   695 	
       
   696 	DCodeSeg* codeSeg = aProcess->iCodeSeg;
       
   697 	
       
   698 	if (codeSeg)
       
   699 	{
       
   700 		TModuleMemoryInfo processMemoryInfo;
       
   701 		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, aProcess);
       
   702 		if (err != KErrNone)
       
   703 		{
       
   704 		
       
   705 			codeAddress = processMemoryInfo.iCodeBase;
       
   706 			codeSize = processMemoryInfo.iCodeSize;
       
   707 		}
       
   708 		else
       
   709 		{
       
   710 			LOG_MSG2("Error in getting memory info: %d", err);
       
   711 		}
       
   712 		
       
   713 	}
       
   714 	
       
   715 	if (!codeAddress || !codeSize)
       
   716 	{
       
   717 		LOG_MSG2("Code segment not available for process %d", aProcess->iId);
       
   718 		// make sure there is not already a breakpoint at this address
       
   719 		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
   720 		{
       
   721 			if (iDebugProcessList[i].iId == aProcess->iId)
       
   722 			{
       
   723 				codeAddress = iDebugProcessList[i].iCodeAddress;
       
   724 				codeSize = iDebugProcessList[i].iCodeSize;
       
   725 				
       
   726 				//now remove from the list
       
   727 				iDebugProcessList.Remove(i);
       
   728 				break;
       
   729 			}
       
   730 		}
       
   731 	}
       
   732 	
       
   733 	if (!codeAddress || !codeSize)
       
   734 		return;
       
   735 		
       
   736 	// first invalidate all breakpoints that were set in the library code
       
   737 	for (TInt i=0; i<iBreakPointList.Count(); i++)
       
   738 	{
       
   739 		if ((iBreakPointList[i].iAddress >= codeAddress) && (iBreakPointList[i].iAddress < (codeAddress + codeSize)))
       
   740 		{
       
   741 			LOG_MSG2("Disabling process breakpoint at address %x", iBreakPointList[i].iAddress);
       
   742 			iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
       
   743 		}
       
   744 	}
       
   745 }
       
   746 
       
   747 
       
   748 //
       
   749 // DMetroTrkChannel::AddLibrary
       
   750 //
       
   751 void DMetroTrkChannel::AddLibrary(DLibrary *aLibrary, DThread *aThread)
       
   752 {
       
   753 	LOG_MSG("DMetroTrkChannel::AddLibrary()");
       
   754 	
       
   755 	LOG_MSG2(("Lib loaded: %S"), aLibrary->iName);
       
   756 	
       
   757 	// check to see if we are still debugging, otherwise just return
       
   758 	if (!iDebugging) 
       
   759 		return;
       
   760 	
       
   761 	// Check if lib loaded event is disabled. Lib loaded event
       
   762 	// is disabled temporarily in some situations, when the engine
       
   763 	// is performing some complex operations  like installing sis 
       
   764 	// files, in which case, suspending the thread for lib loaded 
       
   765 	// events would end up in a dead lock. This is due  to the fact 
       
   766 	// that the active object that handles the event notification 
       
   767 	// wouldn't get a chance to run since the code in TRK engine  
       
   768 	// which handles the commands from the host debugger is also 
       
   769 	// done in an active object which runs in the same thread. 
       
   770 	if (!iNotifyLibLoadedEvent)
       
   771 		return;
       
   772 
       
   773 	TBool isDebugging = EFalse;	
       
   774 	for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
   775 	{
       
   776 		if (iDebugProcessList[i].iId == aThread->iOwningProcess->iId)
       
   777 		{
       
   778 			isDebugging = ETrue;
       
   779 			break;
       
   780 		}
       
   781 	}
       
   782 	if (isDebugging == EFalse)
       
   783 		return;
       
   784 
       
   785 	if (aThread)
       
   786 	{
       
   787 		// make sure this is not the debugger thread
       
   788 		if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
       
   789 		{
       
   790 			SEventInfo info;
       
   791 
       
   792 			Kern::ThreadSuspend(*aThread, 1); 
       
   793 			
       
   794 			info.iEventType = SEventInfo::ELibraryLoaded;
       
   795 			info.iProcessId = aThread->iOwningProcess->iId;
       
   796 			info.iThreadId = aThread->iId;
       
   797 			
       
   798 			//get the code address
       
   799 			DCodeSeg* codeSeg = aLibrary->iCodeSeg;
       
   800 			if (!codeSeg)
       
   801 			{
       
   802 				LOG_MSG2("Code segment not available for library %S", aLibrary->iName);
       
   803 				return;
       
   804 			}
       
   805 			
       
   806 			TModuleMemoryInfo memoryInfo;
       
   807 			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
       
   808 			if (err != KErrNone)
       
   809 			{
       
   810 				LOG_MSG2("Error in getting memory info: %d", err);
       
   811 				return;
       
   812 			}
       
   813 				
       
   814 			info.iCodeAddress = memoryInfo.iCodeBase;
       
   815 			info.iDataAddress = memoryInfo.iInitialisedDataBase;
       
   816 			
       
   817 			info.iFileName.Copy(*(aLibrary->iName)); //just the name, without uid info.
       
   818 						
       
   819 			// now remove this library if its in our notify list
       
   820 			for (TInt i =0; i<iLibraryNotifyList.Count(); i++)
       
   821 			{
       
   822 				if (!iLibraryNotifyList[i].iEmptySlot &&
       
   823 				    !_strnicmp(iLibraryNotifyList[i].iName.Ptr(), info.iFileName.Ptr(), info.iFileName.Length()))
       
   824 				{										
       
   825 					iLibraryNotifyList[i].iEmptySlot = ETrue;
       
   826 					break;
       
   827 				}
       
   828 			}
       
   829 			// now check to see if any libs are loaded because of this library load event.
       
   830 			CheckLibraryNotifyList(info.iProcessId);
       
   831 			//queue up or complete the event
       
   832 			NotifyEvent(info);
       
   833 		}
       
   834 	
       
   835 	}
       
   836 		
       
   837 }
       
   838 
       
   839 //
       
   840 // DMetroTrkChannel::RemoveLibrary
       
   841 //
       
   842 void DMetroTrkChannel::RemoveLibrary(DLibrary *aLibrary)
       
   843 {
       
   844 	LOG_MSG("DMetroTrkChannel::RemoveLibrary()");
       
   845 	LOG_MSG2(("Lib unloaded: %S"), aLibrary->iName);
       
   846 	
       
   847 	// check to see if we are still debugging, otherwise just return
       
   848 	if (!iDebugging) 
       
   849 		return;
       
   850 	
       
   851 	// this is called when all handles to this library have been closed.  this can happen when a process dies, or when a dll is
       
   852 	// unloaded while the process lives on.  in former case, we don't need to notify the host debugger because that process is
       
   853 	// dying anyway.  for the latter case, we do need to notify the host so it can unload the symbolics, etc.
       
   854 	
       
   855 	DThread* aThread = &Kern::CurrentThread();
       
   856    
       
   857 	if ((aThread) &&
       
   858        (aThread != iClientThread) && 
       
   859        (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
       
   860 	{
       
   861 		//the library gets unloaded only when the mapcount is 0.
       
   862 		if (aLibrary->iMapCount != 0)
       
   863 			return;
       
   864 		
       
   865 		DCodeSeg* codeSeg = aLibrary->iCodeSeg;
       
   866 		if (!codeSeg)
       
   867 		{
       
   868 			LOG_MSG2("Code segment not available for library %S", aLibrary->iName);
       
   869 			return;
       
   870 		}
       
   871 		
       
   872 		TModuleMemoryInfo processMemoryInfo;
       
   873 		TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, NULL); //passing NULL for the DProcess argument should be ok;
       
   874 		if (err != KErrNone)
       
   875 		{
       
   876 			LOG_MSG2("Error in getting memory info: %d", err);
       
   877 			return;
       
   878 		}
       
   879 		
       
   880 		TUint32 codeAddress = processMemoryInfo.iCodeBase;
       
   881 		TUint32 codeSize = processMemoryInfo.iCodeSize;
       
   882 		
       
   883 		// first invalidate all breakpoints that were set in the library code
       
   884 		for (TInt i=0; i<iBreakPointList.Count(); i++)
       
   885 		{
       
   886 			if ((iBreakPointList[i].iAddress >= codeAddress) && (iBreakPointList[i].iAddress < (codeAddress + codeSize)))
       
   887 			{
       
   888 				LOG_MSG2("Disabling library breakpoint at address %x", iBreakPointList[i].iAddress);
       
   889 				iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
       
   890 			}
       
   891 		}
       
   892 
       
   893 	   	DProcess *process = &Kern::CurrentProcess();
       
   894 	   	if (process)
       
   895 	   	{
       
   896 			RArray<SCodeSegEntry>* dynamicCode = &(process->iDynamicCode);			
       
   897 			if (dynamicCode)
       
   898 			{
       
   899 				for (TInt j=0; j<dynamicCode->Count(); j++)
       
   900 				{
       
   901 					if ((*dynamicCode)[j].iLib == aLibrary)
       
   902 					{
       
   903 						SEventInfo info;
       
   904 						
       
   905 						info.iEventType = SEventInfo::ELibraryUnloaded;
       
   906 						info.iFileName.Copy(*(aLibrary->iName)); //lib name without uid info
       
   907 						//info.iFileName.ZeroTerminate();
       
   908 						info.iProcessId = process->iId;
       
   909 						info.iThreadId = 0xFFFFFFFF; // don't care!
       
   910 						
       
   911 						//queue up or complete the event
       
   912 						NotifyEvent(info);
       
   913 					}
       
   914 				}
       
   915 			}
       
   916 		}
       
   917 	}
       
   918 }
       
   919 
       
   920 
       
   921 //
       
   922 // DMetroTrkChannel::AddCodeSegment
       
   923 //
       
   924 void DMetroTrkChannel::AddCodeSegment(DCodeSeg *aCodeSeg, DProcess *aProcess)
       
   925 {
       
   926 	LOG_MSG("DMetroTrkChannel::AddCodeSegment()");
       
   927 	
       
   928 	// Check if lib loaded event is disabled. Lib loaded event
       
   929 	// is disabled temporarily in some situations, when the engine
       
   930 	// is performing some complex operations  like installing sis 
       
   931 	// files, in which case, suspending the thread for lib loaded 
       
   932 	// events would end up in a dead lock. This is due  to the fact 
       
   933 	// that the active object that handles the event notification 
       
   934 	// wouldn't get a chance to run since the code in TRK engine  
       
   935 	// which handles the commands from the host debugger is also 
       
   936 	// done in an active object which runs in the same thread. 
       
   937 	if (!iNotifyLibLoadedEvent)
       
   938 		return;	
       
   939 
       
   940 	TBool isDebugging = EFalse;	
       
   941 	for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
   942 	{
       
   943 		if (iDebugProcessList[i].iId == aProcess->iId)
       
   944 		{
       
   945 			isDebugging = ETrue;
       
   946 			break;
       
   947 		}
       
   948 	}
       
   949 	if (isDebugging == EFalse)
       
   950 		return;
       
   951 		
       
   952 	if (aCodeSeg)
       
   953 	{
       
   954 		const TUint8* ptr = aCodeSeg->iFileName->Ptr();
       
   955 		if (aCodeSeg->IsDll())
       
   956 		{
       
   957 			LOG_MSG2("DLL code segment is loaded: %s", ptr);
       
   958 			
       
   959 			DThread* mainThread = aProcess->FirstThread();
       
   960 			if (mainThread)
       
   961 			{
       
   962 				// make sure this is not the debugger thread
       
   963 				if ((mainThread->iId != iClientThread->iId) && (aProcess->iId != iClientThread->iOwningProcess->iId))
       
   964 				{
       
   965 					SEventInfo info;
       
   966 
       
   967 					//DoSuspendThread(mainThread); 
       
   968 					Kern::ThreadSuspend(*mainThread, 1);
       
   969 					
       
   970 					info.iEventType = SEventInfo::ELibraryLoaded;
       
   971 					info.iProcessId = aProcess->iId;
       
   972 					info.iThreadId = mainThread->iId;				
       
   973 					
       
   974 					TModuleMemoryInfo memoryInfo;
       
   975 					TInt err = aCodeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
       
   976 					if (err != KErrNone)
       
   977 					{
       
   978 						LOG_MSG2("Error in getting memory info: %d", err);
       
   979 						return;
       
   980 					}
       
   981 						
       
   982 					info.iCodeAddress = memoryInfo.iCodeBase;
       
   983 					info.iDataAddress = memoryInfo.iInitialisedDataBase;
       
   984 					
       
   985 					info.iFileName.Copy(aCodeSeg->iRootName); //just the name, without uid info.
       
   986 								
       
   987 					//queue up or complete the event
       
   988 					NotifyEvent(info);
       
   989 				}
       
   990 		
       
   991 			}
       
   992 			else
       
   993 			{
       
   994 				LOG_MSG2("Invalid main thread for this process: %d", aProcess->iId);
       
   995 			}
       
   996 
       
   997 		}
       
   998 		else 
       
   999 		{
       
  1000 			if (aCodeSeg->IsExe())
       
  1001 				LOG_MSG2("EXE code segment is loaded: %s", ptr);		
       
  1002 		}
       
  1003 		
       
  1004 	}	
       
  1005 
       
  1006 }
       
  1007 
       
  1008 //
       
  1009 // DMetroTrkChannel::RemoveCodeSegment
       
  1010 //
       
  1011 void DMetroTrkChannel::RemoveCodeSegment(DCodeSeg *aCodeSeg, DProcess *aProcess)
       
  1012 {
       
  1013 	LOG_MSG("DMetroTrkChannel::RemoveCodeSegment()");
       
  1014 	
       
  1015 	// We don't do anything right now as we are not using the code segment events.		
       
  1016 
       
  1017 }
       
  1018 
       
  1019 //
       
  1020 // DMetroTrkChannel::HandleEventKillThread
       
  1021 //
       
  1022 TBool DMetroTrkChannel::HandleEventKillThread(DThread* aThread)
       
  1023 {
       
  1024 	LOG_MSG("DMetroTrkChannel::HandleEventKillThread");
       
  1025 	// check to see if we are still debugging, otherwise just return
       
  1026 	if (!iDebugging) 
       
  1027 		return EFalse;
       
  1028 
       
  1029 	if (!aThread)
       
  1030 	{
       
  1031 		LOG_MSG("Invalid thread handle");
       
  1032 		return EFalse;
       
  1033 	}
       
  1034 
       
  1035 
       
  1036 	DThread* currentThread = &Kern::CurrentThread();
       
  1037 	if (!currentThread)
       
  1038 	{
       
  1039 		LOG_MSG("Error getting current thread");
       
  1040 		return EFalse;
       
  1041 	}
       
  1042 
       
  1043 	//Kern::ThreadSuspend(*currentThread, 1); 
       
  1044 	
       
  1045 	if (aThread->iExitType != EExitPanic)
       
  1046 	{
       
  1047 		return EFalse;
       
  1048 	}
       
  1049 		
       
  1050 	SEventInfo info;
       
  1051 	
       
  1052 	info.iProcessId = aThread->iOwningProcess->iId;
       
  1053 	info.iThreadId = aThread->iId;
       
  1054 	info.iCurrentPC = ReadRegister(aThread, 14);//PC_REGISTER); 
       
  1055 	info.iPanicCategory.Copy(aThread->iExitCategory);
       
  1056 	
       
  1057 	info.iExceptionNumber = 100;//aThread->iExitReason;
       
  1058 	info.iPanicReason = aThread->iExitReason;
       
  1059 	info.iEventType = SEventInfo::EThreadPanic;
       
  1060 
       
  1061 	// if its not an invalide opcode exception, check to see if we are debugging 
       
  1062 	// the process.
       
  1063 	TBool isDebugging = EFalse;	
       
  1064 	for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  1065 	{
       
  1066 		if (iDebugProcessList[i].iId == info.iProcessId)
       
  1067 		{
       
  1068 			isDebugging = ETrue;
       
  1069 			break;
       
  1070 		}
       
  1071 	}
       
  1072 	if (!isDebugging)
       
  1073 		return EFalse;
       
  1074 	
       
  1075 #define DOFREEZE 1
       
  1076 	// PANIC_BACKPORT
       
  1077 #if DOFREEZE
       
  1078 	NKern::ThreadEnterCS();
       
  1079 	NFastSemaphore* sem = new NFastSemaphore();
       
  1080 	NKern::ThreadLeaveCS();
       
  1081 //	sem->iOwningThread = &(Kern::CurrentThread().iNThread);
       
  1082 	sem->iOwningThread = &aThread->iNThread;
       
  1083 	iFrozenThreadSemaphores.Append(sem);
       
  1084 	// First do the notify, then FSWait
       
  1085 	NotifyEvent(info);
       
  1086 	NKern::FSWait(sem);	
       
  1087 	return ETrue;
       
  1088 #else
       
  1089 	NotifyEvent(info);
       
  1090 	LOG_MSG("DMetroTrkChannel::HandleEventKillThread - Panic Do Nothing");
       
  1091 	return EFalse;
       
  1092 #endif
       
  1093 	// END PANIC_BACKPORT	
       
  1094 }
       
  1095 
       
  1096 //
       
  1097 // DMetroTrkChannel::HandleSwException
       
  1098 //
       
  1099 TBool DMetroTrkChannel::HandleSwException(TExcType aExcType)
       
  1100 {
       
  1101 	LOG_MSG("DMetroTrkChannel::HandleSwException");
       
  1102 
       
  1103 	SEventInfo info;
       
  1104 	
       
  1105 	DThread* currentThread = &Kern::CurrentThread();
       
  1106 	if (!currentThread)
       
  1107 	{
       
  1108 		LOG_MSG("Error getting current thread");
       
  1109 		return EFalse;
       
  1110 	}
       
  1111 
       
  1112 	info.iProcessId = currentThread->iOwningProcess->iId;
       
  1113 	info.iThreadId = currentThread->iId;
       
  1114 	info.iCurrentPC = ReadRegister(currentThread, PC_REGISTER);
       
  1115 	info.iExceptionNumber = aExcType;
       
  1116 	info.iEventType = SEventInfo::EThreadException;
       
  1117 
       
  1118 	if (info.iExceptionNumber != EExcInvalidOpCode) 
       
  1119 	{
       
  1120 		// if its not an invalide opcode exception, check to see if we are debugging 
       
  1121 		// the process.
       
  1122 		TBool isDebugging = EFalse;	
       
  1123 		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  1124 		{
       
  1125 			if (iDebugProcessList[i].iId == info.iProcessId)
       
  1126 			{
       
  1127 				isDebugging = ETrue;
       
  1128 				break;
       
  1129 			}
       
  1130 		}
       
  1131 		if (!isDebugging)
       
  1132 			return EFalse;
       
  1133 	}	
       
  1134 
       
  1135 	NThread nThread = currentThread->iNThread;
       
  1136 	
       
  1137 	if (nThread.iSuspendCount == 0)
       
  1138 		Kern::ThreadSuspend(*currentThread, 1);
       
  1139 	
       
  1140 	HandleException(info, currentThread);
       
  1141 	
       
  1142 	return ETrue;
       
  1143 }
       
  1144 
       
  1145 //
       
  1146 // DMetroTrkChannel::HandleHwException
       
  1147 //
       
  1148 TBool DMetroTrkChannel::HandleHwException(TArmExcInfo* aExcInfo)
       
  1149 {
       
  1150 	LOG_MSG("DMetroTrkChannel::HandleHwException()");
       
  1151 
       
  1152 	SEventInfo info;
       
  1153 	
       
  1154 	DThread* currentThread = &Kern::CurrentThread();
       
  1155 	
       
  1156 	if (!currentThread)
       
  1157 	{
       
  1158 		LOG_MSG("Error getting current thread");
       
  1159 		return EFalse;
       
  1160 	}
       
  1161 
       
  1162 	//store the exception info as its needed to read the context for system threads
       
  1163 	iExcInfoValid = ETrue;
       
  1164 	iCurrentExcInfo = *aExcInfo;
       
  1165 
       
  1166 	info.iProcessId = currentThread->iOwningProcess->iId;
       
  1167 	info.iThreadId = currentThread->iId;
       
  1168 	info.iCurrentPC = aExcInfo->iR15;
       
  1169 
       
  1170 	switch (aExcInfo->iExcCode)
       
  1171 	{
       
  1172 		case 0:
       
  1173 			info.iExceptionNumber = EExcCodeAbort;
       
  1174 			break;
       
  1175 		case 1:
       
  1176 			info.iExceptionNumber = EExcDataAbort;
       
  1177 			break;
       
  1178 		case 2:
       
  1179 			info.iExceptionNumber = EExcInvalidOpCode;
       
  1180 			break;
       
  1181 		default:
       
  1182 			return EFalse;
       
  1183 		
       
  1184 	}	
       
  1185 	info.iEventType = SEventInfo::EThreadException;
       
  1186 	
       
  1187 	if (info.iExceptionNumber != EExcInvalidOpCode) 
       
  1188 	{
       
  1189 		// if its not an invalide opcode exception, check to see if we are debugging 
       
  1190 		// the process.
       
  1191 		TBool isDebugging = EFalse;	
       
  1192 		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  1193 		{
       
  1194 			if (iDebugProcessList[i].iId == info.iProcessId)
       
  1195 			{
       
  1196 				isDebugging = ETrue;
       
  1197 				break;
       
  1198 			}
       
  1199 		}
       
  1200 		if (!isDebugging)
       
  1201 			return EFalse;
       
  1202 	}	
       
  1203 	
       
  1204 	NThread nThread = currentThread->iNThread;	
       
  1205 
       
  1206 	if (nThread.iSuspendCount == 0) //don't suspend the thread if its already suspended.
       
  1207 		Kern::ThreadSuspend(*currentThread, 1);
       
  1208 	
       
  1209 	HandleException(info, currentThread);
       
  1210 	
       
  1211 	return ETrue;
       
  1212 }
       
  1213 
       
  1214 //
       
  1215 // DMetroTrkChannel::HandleException
       
  1216 //
       
  1217 void DMetroTrkChannel::HandleException(SEventInfo& aEventInfo, DThread* aCurrentThread)
       
  1218 {
       
  1219 	TInt err = KErrNone;
       
  1220 	// see if it was a breakpoint that stopped the thread
       
  1221 	if (((TInt)2 == aEventInfo.iExceptionNumber) || ((TInt)EExcInvalidOpCode == aEventInfo.iExceptionNumber))
       
  1222 	{
       
  1223 		TUint32 inst = KArmBreakPoint;
       
  1224 		TInt instSize = 4;
       
  1225 
       
  1226 		// change these for thumb mode
       
  1227 		if (ReadRegister(aCurrentThread, STATUS_REGISTER) & ECpuThumb)
       
  1228 		{
       
  1229 			inst = KThumbBreakPoint;
       
  1230 			instSize = 2;
       
  1231 		}
       
  1232 		
       
  1233 		TUint32 instruction = 0;
       
  1234 		err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iCurrentPC, (TUint8 *)&instruction, instSize);
       
  1235 
       
  1236 		if (KErrNone != err)
       
  1237 			LOG_MSG2("Error reading instruction at currentpc: %d", err);
       
  1238 		
       
  1239 		if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
       
  1240 		{
       
  1241 			// the exception was a breakpoint instruction.  see if we have a breakpoint at that address
       
  1242 			for (TInt i=0; i<iBreakPointList.Count(); i++)
       
  1243 			{
       
  1244 				TBreakEntry breakEntry = iBreakPointList[i];
       
  1245 				
       
  1246 				if (breakEntry.iAddress == aEventInfo.iCurrentPC)
       
  1247 				{
       
  1248 					LOG_MSG2("Breakpoint with Id %d has been hit", breakEntry.iId);
       
  1249 
       
  1250 					//change the event type to breakpoint type
       
  1251 					aEventInfo.iEventType = SEventInfo::EThreadBreakPoint;
       
  1252 					
       
  1253 				
       
  1254 					// enable any breakpoints we had to disable for this thread
       
  1255 					err = DoEnableDisabledBreak(aEventInfo.iThreadId);
       
  1256 					if (KErrNone != err)
       
  1257 						LOG_MSG2("Error %d enabling disabled breakpoints", err);
       
  1258 						
       
  1259 					// see if this is a temp breakpoint
       
  1260 					if (i < NUMBER_OF_TEMP_BREAKPOINTS)
       
  1261 					{
       
  1262 						// this was a temp breakpoint, so we need to clear it now
       
  1263 						err = DoClearBreak(i);
       
  1264 						if (KErrNone != err)
       
  1265 							LOG_MSG2("Error %d clearing temp breakpoint", err);
       
  1266 						
       
  1267 						// if we're not out of range yet, go ahead and single step again
       
  1268 						// if we are out of range, either continue or report the event depending
       
  1269 						// on the iResumeOnceOutOfRange flag
       
  1270 						if ((aEventInfo.iCurrentPC > breakEntry.iRangeStart) && (aEventInfo.iCurrentPC < breakEntry.iRangeEnd))
       
  1271 						{
       
  1272 							LOG_MSG("PC is still in range, stepping will continue");
       
  1273 							err = DoStepRange(aCurrentThread, breakEntry.iRangeStart, breakEntry.iRangeEnd, breakEntry.iSteppingInto, breakEntry.iResumeOnceOutOfRange, breakEntry.iSteppingInto);
       
  1274 							if (KErrNone != err)
       
  1275 							{
       
  1276 								LOG_MSG2("Error in DoStepRange: %d.  Resuming thread.", err);
       
  1277 								err = DoResumeThread(aCurrentThread);
       
  1278 								if (KErrNone != err)
       
  1279 									LOG_MSG2("Error in DoResumeThread: %d", err);
       
  1280 							}
       
  1281 							return;												
       
  1282 						}
       
  1283 						else
       
  1284 						{
       
  1285 							if (breakEntry.iResumeOnceOutOfRange)
       
  1286 							{
       
  1287 								LOG_MSG("PC is out of range, continuing thread");
       
  1288 								DoResumeThread(aCurrentThread);
       
  1289 								
       
  1290 								return;
       
  1291 							}
       
  1292 						}
       
  1293 					}
       
  1294 					
       
  1295 					// if the breakpoint is thread specific, make sure it's the right thread
       
  1296 					// if not, just continue the thread.  take special care if it's the debugger
       
  1297 					// thread.  if it hits a regular breakpoint, we NEVER want to stop at it.  if
       
  1298 					// it hits a temp breakpoint, we're probably just stepping past a real breakpoint
       
  1299 					// and we do need to handle it.
       
  1300 					if (((breakEntry.iThreadId != aEventInfo.iThreadId) && breakEntry.iThreadSpecific)/*(breakEntry.iThreadId != 0xFFFFFFFF))*/ ||
       
  1301 						((aEventInfo.iProcessId == iClientThread->iOwningProcess->iId) && (breakEntry.iThreadId != aEventInfo.iThreadId)))
       
  1302 					{
       
  1303 						LOG_MSG("breakpoint does not match threadId, calling DoResumeThread");
       
  1304 						err = DoResumeThread(aCurrentThread);
       
  1305 						if (KErrNone != err)
       
  1306 							LOG_MSG2("Error in DoResumeThread: %d", err);
       
  1307 
       
  1308 						return;					
       
  1309 					}
       
  1310 					
       
  1311 					//normal user break point, just notify the event
       
  1312 					break;
       
  1313 				}
       
  1314 			}
       
  1315 
       
  1316 		}
       
  1317 	}
       
  1318 	
       
  1319 	NotifyEvent(aEventInfo);
       
  1320 }
       
  1321 
       
  1322 //
       
  1323 // DMetroTrkChannel::HandleUserTrace
       
  1324 //
       
  1325 TBool DMetroTrkChannel::HandleUserTrace(TText* aStr, TInt aLen)
       
  1326 {
       
  1327 	LOG_MSG("DMetroTrkChannel::HandleUserTrace()");
       
  1328 
       
  1329 // handle user trace events only for app trk.
       
  1330 #ifndef __OEM_TRK__ 
       
  1331 	// check to see if we are still debugging, otherwise just return
       
  1332 	if (!iDebugging) 
       
  1333 		return EFalse;
       
  1334 	
       
  1335 	DThread* currentThread = &Kern::CurrentThread();
       
  1336 	
       
  1337 	if (!currentThread)
       
  1338 	{
       
  1339 		LOG_MSG("Error getting current thread");
       
  1340 		return EFalse;
       
  1341 	}
       
  1342 
       
  1343 	if (currentThread->iOwningProcess->iId == iClientThread->iOwningProcess->iId)
       
  1344 		return EFalse;
       
  1345 
       
  1346 	// only send traces for processes you are debugging	
       
  1347 	TBool isDebugging = EFalse;	
       
  1348 	for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  1349 	{
       
  1350 		if (iDebugProcessList[i].iId == currentThread->iOwningProcess->iId)
       
  1351 		{
       
  1352 			isDebugging = ETrue;
       
  1353 			break;
       
  1354 		}
       
  1355 	}
       
  1356 	if (!isDebugging)
       
  1357 		return EFalse;
       
  1358 	
       
  1359 	if (aLen > 0)
       
  1360 	{
       
  1361 		SEventInfo info;
       
  1362 
       
  1363 		// This is a temporary solution for grabbing the rdebug printfs.
       
  1364 		// With the current TRK implementation, we don't have a mechanism for 
       
  1365 		// using dynamically allocated buffers between the engine and the driver. 
       
  1366 		// So for now we are limiting the printf strings to 256 bytes.		
       
  1367 		TUint8 traceStr[260];
       
  1368 		info.iTraceDataLen = aLen;
       
  1369 		
       
  1370 		if (info.iTraceDataLen > 256)
       
  1371 			info.iTraceDataLen  = 256;
       
  1372 			
       
  1373 		XTRAPD(r, XT_DEFAULT, kumemget(traceStr, aStr, info.iTraceDataLen));
       
  1374 		
       
  1375 		if (r == KErrNone)
       
  1376 		{
       
  1377 			info.iEventType = SEventInfo::EUserTrace;			
       
  1378 			traceStr[info.iTraceDataLen] = '\r';
       
  1379 			traceStr[info.iTraceDataLen+1] = '\n';
       
  1380 			info.iTraceDataLen += 2; // account for \r and \n.
       
  1381 
       
  1382 			info.iTraceData.Copy((TUint8*)traceStr, info.iTraceDataLen);
       
  1383 			NotifyEvent(info, ETrue);										
       
  1384 		}
       
  1385 		else
       
  1386 		{
       
  1387 			return EFalse;
       
  1388 		}
       
  1389 	}
       
  1390 #endif	
       
  1391 
       
  1392 	return ETrue;
       
  1393 }
       
  1394 
       
  1395 
       
  1396 //
       
  1397 // DMetroTrkChannel::SetBreak
       
  1398 //
       
  1399 TInt DMetroTrkChannel::SetBreak(TUint32 aThreadId, TMetroTrkBreakInfo* aBreakInfo)
       
  1400 {
       
  1401 	LOG_MSG("DMetroTrkChannel::SetBreak()");
       
  1402 
       
  1403 	TInt err = KErrNone;
       
  1404 	
       
  1405 	if (!aBreakInfo)
       
  1406 		return KErrArgument;
       
  1407 	
       
  1408 	//User side memory is not accessible directly
       
  1409 	TMetroTrkBreakInfo info(0, 0, 0, 0);
       
  1410 	err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TMetroTrkBreakInfo));
       
  1411 	if (err != KErrNone)
       
  1412 		return err;
       
  1413 				
       
  1414 	if (!info.iId) //first check if the iId address is valid
       
  1415 		return KErrArgument;
       
  1416 				
       
  1417 	if (err == KErrNone) 
       
  1418 	{
       
  1419 		TInt32 iId;
       
  1420 		
       
  1421 		err = DoSetBreak(info.iProcessId, aThreadId, info.iAddress, info.iThumbMode, iId);
       
  1422 		
       
  1423 		if (err == KErrNone)
       
  1424 		{
       
  1425 			err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iId, &iId, sizeof(TInt32), iClientThread);
       
  1426 		}
       
  1427 	}
       
  1428 	return err;
       
  1429 }
       
  1430 
       
  1431 //
       
  1432 // DMetroTrkChannel::StepRange
       
  1433 //
       
  1434 TInt DMetroTrkChannel::StepRange(DThread* aThread, TMetroTrkStepInfo* aStepInfo)
       
  1435 {
       
  1436 	LOG_MSG("DMetroTrkChannel::StepRange()");
       
  1437 
       
  1438 	TInt err = KErrNone;
       
  1439 	
       
  1440 	if (!aStepInfo)
       
  1441 		return KErrArgument;
       
  1442 	
       
  1443 	TMetroTrkStepInfo info(0, 0, 0);
       
  1444 	err = Kern::ThreadRawRead(iClientThread, aStepInfo, (TUint8*)&info, sizeof(TMetroTrkStepInfo));
       
  1445 	
       
  1446 	if (err != KErrNone)
       
  1447 		return err;
       
  1448 	
       
  1449 	err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
       
  1450 	
       
  1451 	return err;
       
  1452 }
       
  1453 
       
  1454 //
       
  1455 // DMetroTrkChannel::ReadMemory
       
  1456 //
       
  1457 TInt DMetroTrkChannel::ReadMemory(DThread* aThread, TMetroTrkMemoryInfo* aMemoryInfo)
       
  1458 {
       
  1459 	LOG_MSG("DMetroTrkChannel::ReadMemory()");
       
  1460 
       
  1461 	TInt err = KErrNone;
       
  1462 	
       
  1463 	if (!aMemoryInfo)
       
  1464 		return KErrArgument;
       
  1465 		
       
  1466 #ifndef __OEM_TRK__
       
  1467 	if (!IsBeingDebugged(aThread))
       
  1468 		return KErrPermissionDenied;
       
  1469 #endif
       
  1470 		
       
  1471 	TMetroTrkMemoryInfo info(0, 0, 0);
       
  1472 	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TMetroTrkMemoryInfo));
       
  1473 	if (err != KErrNone)
       
  1474 		return err;
       
  1475 	
       
  1476 	if (!info.iData)
       
  1477 		return KErrArgument;
       
  1478 
       
  1479 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
       
  1480 	if (!data)
       
  1481 		return KErrNoMemory;
       
  1482 	
       
  1483 	TPtr8 dataDes(data, info.iLength);
       
  1484 		
       
  1485 	err = DoReadMemory(aThread, info.iAddress, info.iLength, dataDes);
       
  1486 	if (err != KErrNone)
       
  1487 		return err;
       
  1488 	
       
  1489 	err = Kern::ThreadDesWrite(iClientThread, info.iData, dataDes, 0, KChunkShiftBy0, iClientThread);
       
  1490 	
       
  1491 	Kern::Free(data);
       
  1492 	
       
  1493 	return err;
       
  1494 }
       
  1495 
       
  1496 //
       
  1497 // DMetroTrkChannel::WriteMemory
       
  1498 //
       
  1499 TInt DMetroTrkChannel::WriteMemory(DThread* aThread, TMetroTrkMemoryInfo* aMemoryInfo)
       
  1500 {
       
  1501 	LOG_MSG("DMetroTrkChannel::WriteMemory()");
       
  1502 
       
  1503 	TInt err = KErrNone;
       
  1504 	
       
  1505 	if (!aMemoryInfo)
       
  1506 		return KErrArgument;
       
  1507 	
       
  1508 #ifndef __OEM_TRK__
       
  1509 	if (!IsBeingDebugged(aThread))
       
  1510 		return KErrPermissionDenied;
       
  1511 #endif	
       
  1512 	
       
  1513 	TMetroTrkMemoryInfo info(0, 0, 0);
       
  1514 	err = Kern::ThreadRawRead(iClientThread, aMemoryInfo, (TUint8*)&info, sizeof(TMetroTrkMemoryInfo));
       
  1515 	if (err != KErrNone)
       
  1516 		return err;
       
  1517 	
       
  1518 	if (!info.iData)
       
  1519 		return KErrArgument;
       
  1520 	
       
  1521 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
       
  1522 	if (!data)
       
  1523 		return KErrNoMemory;
       
  1524 	
       
  1525 	TPtr8 dataDes(data, info.iLength);
       
  1526 	
       
  1527 	err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
       
  1528 	if (err != KErrNone)
       
  1529 		return err;
       
  1530 							
       
  1531 	err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
       
  1532 	
       
  1533 	Kern::Free(data);
       
  1534 	
       
  1535 	return err;
       
  1536 }
       
  1537 
       
  1538 //
       
  1539 // DMetroTrkChannel::ReadRegisters
       
  1540 //
       
  1541 TInt DMetroTrkChannel::ReadRegisters(DThread* aThread, TMetroTrkRegisterInfo* aRegisterInfo)
       
  1542 {
       
  1543 	LOG_MSG("DMetroTrkChannel::ReadRegisters()");
       
  1544 
       
  1545 	TInt err = KErrNone;
       
  1546 	
       
  1547 	if (!aRegisterInfo)
       
  1548 		return KErrArgument;
       
  1549 	
       
  1550 #ifndef __OEM_TRK__	
       
  1551 	if (!IsBeingDebugged(aThread))
       
  1552 		return KErrPermissionDenied;
       
  1553 #endif
       
  1554 	
       
  1555 	TMetroTrkRegisterInfo info(0, 0, 0);
       
  1556 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TMetroTrkRegisterInfo));
       
  1557 	if (err != KErrNone)
       
  1558 		return err;
       
  1559 
       
  1560 	if (!info.iValues)
       
  1561 		return KErrArgument;
       
  1562 	
       
  1563 	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
       
  1564 	TUint8 *values = (TUint8*)Kern::Alloc(length);
       
  1565 	if (!values)
       
  1566 		return KErrNoMemory;
       
  1567 
       
  1568 	TPtr8 valuesDes(values, length);
       
  1569 	
       
  1570 	err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
       
  1571 	if (err != KErrNone)
       
  1572 		return err;
       
  1573 	
       
  1574 	err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
       
  1575 
       
  1576 	Kern::Free(values);
       
  1577 	
       
  1578 	return err;
       
  1579 }
       
  1580 
       
  1581 //
       
  1582 // DMetroTrkChannel::WriteRegisters
       
  1583 //
       
  1584 TInt DMetroTrkChannel::WriteRegisters(DThread* aThread, TMetroTrkRegisterInfo* aRegisterInfo)
       
  1585 {
       
  1586 	LOG_MSG("DMetroTrkChannel::WriteRegisters()");
       
  1587 
       
  1588 	TInt err = KErrNone;
       
  1589 	
       
  1590 	if (!aRegisterInfo)
       
  1591 		return KErrArgument;
       
  1592 
       
  1593 #ifndef __OEM_TRK__
       
  1594 	if (!IsBeingDebugged(aThread))
       
  1595 		return KErrPermissionDenied;
       
  1596 #endif
       
  1597 
       
  1598 	TMetroTrkRegisterInfo info(0, 0, 0);
       
  1599 	err = Kern::ThreadRawRead(iClientThread, aRegisterInfo, (TUint8*)&info, sizeof(TMetroTrkRegisterInfo));
       
  1600 	if (err != KErrNone)
       
  1601 		return err;
       
  1602 		
       
  1603 	if (!info.iValues)
       
  1604 		return KErrArgument;
       
  1605 	
       
  1606 	TUint length = (info.iLastRegister - info.iFirstRegister + 1) * 4;
       
  1607 	
       
  1608 	TUint8 *values = (TUint8*)Kern::Alloc(length);
       
  1609 	if (!values)
       
  1610 		return KErrNoMemory;
       
  1611 	
       
  1612 	TPtr8 valuesDes(values, length);
       
  1613 	
       
  1614 	err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
       
  1615 	if (err != KErrNone)
       
  1616 		return err;
       
  1617 
       
  1618 	err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
       
  1619 	
       
  1620 	Kern::Free(values);
       
  1621 	
       
  1622 	return err;
       
  1623 }
       
  1624 
       
  1625 //
       
  1626 // DMetroTrkChannel::GetProcessInfo
       
  1627 //
       
  1628 TInt DMetroTrkChannel::GetProcessInfo(TInt aIndex, TMetroTrkTaskInfo* aTaskInfo)
       
  1629 {
       
  1630 	LOG_MSG("DMetroTrkChannel::GetProcessInfo()");
       
  1631 
       
  1632 	TInt err = KErrNone;
       
  1633 	
       
  1634 	if (!aTaskInfo)
       
  1635 		return KErrArgument;
       
  1636 
       
  1637 	TMetroTrkTaskInfo info(0);
       
  1638 	
       
  1639 	err = DoGetProcessInfo(aIndex, &info);
       
  1640 	
       
  1641 	if (err != KErrNone)
       
  1642 		return err;
       
  1643 	
       
  1644 	err = Kern::ThreadRawWrite(iClientThread, aTaskInfo, &info, sizeof(TMetroTrkTaskInfo), iClientThread);
       
  1645 	
       
  1646 	return err;
       
  1647 }
       
  1648 
       
  1649 //
       
  1650 // DMetroTrkChannel::GetThreadInfo
       
  1651 //
       
  1652 TInt DMetroTrkChannel::GetThreadInfo(TInt aIndex, TMetroTrkTaskInfo* aTaskInfo)
       
  1653 {
       
  1654 	LOG_MSG("DMetroTrkChannel::GetThreadInfo()");
       
  1655 
       
  1656 	TInt err = KErrNone;
       
  1657 	
       
  1658 	if (!aTaskInfo)
       
  1659 		return KErrArgument;
       
  1660 	
       
  1661 	TMetroTrkTaskInfo info(0);
       
  1662 	err = Kern::ThreadRawRead(iClientThread, aTaskInfo, (TUint8*)&info, sizeof(TMetroTrkTaskInfo));
       
  1663 	if (err != KErrNone)
       
  1664 		return err;
       
  1665 	
       
  1666 	err = DoGetThreadInfo(aIndex, &info);
       
  1667 	
       
  1668 	if (err != KErrNone)
       
  1669 		return err;
       
  1670 	
       
  1671 	err = Kern::ThreadRawWrite(iClientThread, aTaskInfo, &info, sizeof(TMetroTrkTaskInfo), iClientThread);
       
  1672 	
       
  1673 	return err;
       
  1674 }
       
  1675 
       
  1676 //
       
  1677 // DMetroTrkChannel::GetProcessAddresses
       
  1678 //
       
  1679 TInt DMetroTrkChannel::GetProcessAddresses(DThread* aThread, TMetroTrkProcessInfo* aProcessInfo)
       
  1680 {
       
  1681 	LOG_MSG("DMetroTrkChannel::GetProcessAddresses()");
       
  1682 
       
  1683 	TInt err = KErrNone;
       
  1684 
       
  1685 	if  (!aProcessInfo)
       
  1686 		return KErrArgument;
       
  1687 	
       
  1688 	TMetroTrkProcessInfo info(0, 0);
       
  1689 	err = Kern::ThreadRawRead(iClientThread, aProcessInfo, (TUint8*)&info, sizeof(TMetroTrkProcessInfo));
       
  1690 	
       
  1691 	if (err != KErrNone)
       
  1692 		return err;
       
  1693 		
       
  1694 	if (!info.iCodeAddress || !info.iDataAddress)
       
  1695 		return KErrArgument;
       
  1696 	
       
  1697 	TUint32 codeAddress;
       
  1698 	TUint32 dataAddress;
       
  1699 	
       
  1700 	err = DoGetProcessAddresses(aThread, codeAddress, dataAddress);
       
  1701 	
       
  1702 	if (err != KErrNone)
       
  1703 		return err;
       
  1704 		
       
  1705 	err = Kern::ThreadRawWrite(iClientThread, info.iCodeAddress, (TUint8*)&codeAddress, sizeof(TUint32), iClientThread);
       
  1706 	err = Kern::ThreadRawWrite(iClientThread, info.iDataAddress, (TUint8*)&dataAddress, sizeof(TUint32), iClientThread);
       
  1707 
       
  1708 	return err;
       
  1709 }
       
  1710 
       
  1711 //
       
  1712 // DMetroTrkChannel::GetStaticLibraryInfo
       
  1713 //
       
  1714 TInt DMetroTrkChannel::GetStaticLibraryInfo(TInt aIndex, SEventInfo* aEventInfo)
       
  1715 {
       
  1716 	LOG_MSG("DMetroTrkChannel::GetStaticLibraryInfo()");
       
  1717 
       
  1718 	TInt err = KErrNone;
       
  1719 
       
  1720 	if (!aEventInfo)
       
  1721 		return KErrArgument;
       
  1722 
       
  1723 	SEventInfo info;
       
  1724 
       
  1725 	err = Kern::ThreadRawRead(iClientThread, aEventInfo, (TUint8*)&info, sizeof(SEventInfo));
       
  1726 	
       
  1727 	if (err != KErrNone)
       
  1728 		return err;
       
  1729 
       
  1730 	err = DoGetStaticLibraryInfo(aIndex, &info);
       
  1731 	
       
  1732 	if (err != KErrNone)
       
  1733 		return err;
       
  1734 	
       
  1735 	err = Kern::ThreadRawWrite(iClientThread, aEventInfo, &info, sizeof(SEventInfo), iClientThread);
       
  1736 
       
  1737 	return err;
       
  1738 }
       
  1739 
       
  1740 //
       
  1741 // DMetroTrkChannel::GetLibInfo
       
  1742 //
       
  1743 TInt DMetroTrkChannel::GetLibraryInfo(TMetroTrkLibInfo* aLibInfo)
       
  1744 {
       
  1745 	LOG_MSG("DMetroTrkChannel::GetLibraryInfo()");
       
  1746 
       
  1747 	TInt err = KErrNone;
       
  1748 	
       
  1749 	if (!aLibInfo)
       
  1750 		return KErrArgument;
       
  1751 
       
  1752 	TMetroTrkLibInfo info(0, 0);
       
  1753 
       
  1754 	err = Kern::ThreadRawRead(iClientThread, aLibInfo, (TUint8*)&info, sizeof(TMetroTrkLibInfo));
       
  1755 
       
  1756 	if (err != KErrNone)
       
  1757 		return err;
       
  1758 
       
  1759 	if (!info.iFileName)
       
  1760 		return KErrArgument;
       
  1761 	
       
  1762 	TUint8 *dllName = (TUint8*)Kern::Alloc(info.iFileNameLength);
       
  1763 	if (!dllName)
       
  1764 		return KErrNoMemory;
       
  1765 	
       
  1766 	TPtr8 dllNameDes(dllName, info.iFileNameLength);
       
  1767 	
       
  1768 	err = Kern::ThreadDesRead(iClientThread, info.iFileName, dllNameDes, 0);
       
  1769 	if (!err)
       
  1770 	{
       
  1771 		err = DoGetLibraryInfo(dllNameDes, &info);
       
  1772 	
       
  1773 		if (!err)		
       
  1774 			err = Kern::ThreadRawWrite(iClientThread, aLibInfo, &info, sizeof(TMetroTrkLibInfo), iClientThread);
       
  1775 		
       
  1776 		// we couldn't find the library info, so add to our list to look for 
       
  1777 		// when a library is loaded or a process is loaded.	
       
  1778 		if (err != KErrNone)
       
  1779 		{
       
  1780             for (TInt i=0; i<NUMBER_OF_LIBS_TO_REGISTER; i++)
       
  1781             {                
       
  1782                 if (!iLibraryNotifyList[i].iName.Length() && iLibraryNotifyList[i].iEmptySlot)
       
  1783 		        {
       
  1784                     iLibraryNotifyList[i].iName.Copy(dllNameDes);
       
  1785                     iLibraryNotifyList[i].iEmptySlot = EFalse;
       
  1786                     break;
       
  1787 		        }
       
  1788 		        else if (!iLibraryNotifyList[i].iEmptySlot && !_strnicmp(iLibraryNotifyList[i].iName.Ptr(), dllNameDes.Ptr(), dllNameDes.Length()))
       
  1789 		        {
       
  1790 		        	break;
       
  1791 		        }
       
  1792             }
       
  1793 		}		
       
  1794 	}
       
  1795 	
       
  1796 	// now free the allocated memory
       
  1797 	Kern::Free(dllName);	
       
  1798 
       
  1799 	return err;
       
  1800 }
       
  1801 
       
  1802 //
       
  1803 // DMetroTrkChannel::GetExeInfo
       
  1804 //
       
  1805 TInt DMetroTrkChannel::GetExeInfo(TMetroTrkExeInfo* aExeInfo)
       
  1806 {
       
  1807 	LOG_MSG("DMetroTrkChannel::GetExeInfo()");
       
  1808 
       
  1809 	TInt err = KErrNone;
       
  1810 	
       
  1811 	if (!aExeInfo)
       
  1812 		return KErrArgument;
       
  1813 
       
  1814 	TMetroTrkExeInfo info(0, 0, 0);
       
  1815 
       
  1816 	err = Kern::ThreadRawRead(iClientThread, aExeInfo, (TUint8*)&info, sizeof(TMetroTrkExeInfo));
       
  1817 
       
  1818 	if (err != KErrNone)
       
  1819 		return err;
       
  1820 
       
  1821 	if (!info.iFileName)
       
  1822 		return KErrArgument;
       
  1823 	
       
  1824 	TUint8 *exeName = (TUint8*)Kern::Alloc(info.iFileNameLength);
       
  1825 	if (!exeName)
       
  1826 		return KErrNoMemory;
       
  1827 	
       
  1828 	TPtr8 exeNameDes(exeName, info.iFileNameLength);
       
  1829 	
       
  1830 	err = Kern::ThreadDesRead(iClientThread, info.iFileName, exeNameDes, 0);
       
  1831 	if (KErrNone == err)
       
  1832 	{
       
  1833 			err = DoGetExeInfo(exeNameDes, &info);
       
  1834 		if (KErrNone == err)
       
  1835 		{		
       
  1836 			err = Kern::ThreadRawWrite(iClientThread, aExeInfo, &info, sizeof(TMetroTrkExeInfo), iClientThread);
       
  1837 		}
       
  1838 	}
       
  1839 	
       
  1840 	Kern::Free(exeName);
       
  1841 
       
  1842 	return err;
       
  1843 }
       
  1844 
       
  1845 //
       
  1846 // DMetroTrkChannel::GetProcUidInfo
       
  1847 //
       
  1848 TInt DMetroTrkChannel::GetProcUidInfo(TMetroTrkProcUidInfo* aProcUidInfo)
       
  1849 {
       
  1850 	LOG_MSG("DMetroTrkChannel::GetProcUidInfo()");
       
  1851 
       
  1852 	TInt err = KErrNone;
       
  1853 	
       
  1854 	if (!aProcUidInfo)
       
  1855 		return KErrArgument;
       
  1856 
       
  1857 	TMetroTrkProcUidInfo info(0);
       
  1858 
       
  1859 	err = Kern::ThreadRawRead(iClientThread, aProcUidInfo, (TUint8*)&info, sizeof(TMetroTrkProcUidInfo));
       
  1860 
       
  1861 	if (err != KErrNone)
       
  1862 		return err;
       
  1863 	
       
  1864 	err = DoGetProcUidInfo(&info);
       
  1865 	
       
  1866 	if (err != KErrNone)
       
  1867 		return err;
       
  1868 	
       
  1869 	err = Kern::ThreadRawWrite(iClientThread, aProcUidInfo, &info, sizeof(TMetroTrkProcUidInfo), iClientThread);
       
  1870 
       
  1871 	return err;
       
  1872 }
       
  1873 
       
  1874 //
       
  1875 //DMetroTrkChannel::DetachProcess
       
  1876 //
       
  1877 TInt DMetroTrkChannel::DetachProcess(DProcess *aProcess)
       
  1878 {
       
  1879     LOG_MSG("DMetroTrkChannel::DetachProcess()");
       
  1880     // check to see if we are still debugging, otherwise just return
       
  1881     if (!iDebugging || !aProcess) 
       
  1882         return KErrArgument;
       
  1883 
       
  1884     // This is called when a process has been detached.  
       
  1885     // We want to mark any breakpoints in this process space as clear.      
       
  1886     TUint32 codeAddress = 0;
       
  1887     TUint32 codeSize = 0;
       
  1888     
       
  1889     LOG_MSG2("Process being Detached, Name %S", aProcess->iName);    
       
  1890 
       
  1891     // make sure there is not already a breakpoint at this address
       
  1892     for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  1893     {
       
  1894         if (iDebugProcessList[i].iId == aProcess->iId)
       
  1895         {
       
  1896             codeAddress = iDebugProcessList[i].iCodeAddress;
       
  1897             codeSize = iDebugProcessList[i].iCodeSize;
       
  1898             //now remove from the list
       
  1899             iDebugProcessList.Remove(i);
       
  1900             break;
       
  1901         }
       
  1902 	}
       
  1903 
       
  1904     if (!codeAddress || !codeSize)
       
  1905         return KErrArgument;
       
  1906         
       
  1907     // first invalidate all breakpoints that were set in the library code
       
  1908     for (TInt i=0; i<iBreakPointList.Count(); i++)
       
  1909     {
       
  1910         if ((iBreakPointList[i].iAddress >= codeAddress) && (iBreakPointList[i].iAddress < (codeAddress + codeSize)))
       
  1911         {
       
  1912             LOG_MSG2("Clearing process breakpoint at address %x", iBreakPointList[i].iAddress);
       
  1913             // clear the break here
       
  1914             TInt32 err = KErrNone;
       
  1915             err = DoClearBreak(iBreakPointList[i].iId);
       
  1916             
       
  1917             //If not able to clear the break point host debugger  make obselete.
       
  1918             if (KErrNone != err)
       
  1919             {
       
  1920                 LOG_MSG2("Clearing process breakpoint at address %x failed", iBreakPointList[i].iAddress);                
       
  1921             }
       
  1922         }
       
  1923 	}
       
  1924 
       
  1925     return KErrNone;
       
  1926 }
       
  1927 
       
  1928 
       
  1929 //
       
  1930 // DMetroTrkChannel::DoSetBreak
       
  1931 //
       
  1932 TInt DMetroTrkChannel::DoSetBreak(const TUint32 aProcessId, const TUint32 aThreadId, const TUint32 aAddress, const TBool aThumbMode, TInt32 &aId)
       
  1933 {
       
  1934 	LOG_MSG("DMetroTrkChannel::DoSetBreak()");
       
  1935 
       
  1936 	// do not allow breakpoints in the excluded ROM region
       
  1937 	//if ((aAddress >= iExcludedROMAddressStart) && (aAddress < iExcludedROMAddressEnd))
       
  1938 	//{
       
  1939 	//	return KErrNotSupported;
       
  1940 	//}
       
  1941 	
       
  1942 	// make sure there is not already a breakpoint at this address
       
  1943 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
       
  1944 	{
       
  1945 		if (iBreakPointList[i].iAddress == aAddress)
       
  1946 		{
       
  1947 			return KErrAlreadyExists;
       
  1948 		}
       
  1949 	}
       
  1950 	
       
  1951 	// increment the break id
       
  1952 	aId = iNextBreakId++;	
       
  1953 
       
  1954 	// create the new breakpoint entry
       
  1955 	TBreakEntry breakEntry(aId, aThreadId, aAddress, aThumbMode);
       
  1956 
       
  1957 	// IDE currently sends non-thread specific breakpoints (threadId == 0xffffffff)
       
  1958 	// if this changes, we will get a real thread ID
       
  1959 	// This check must be done before calling DoEnableBreak as it will replace the 
       
  1960 	// the breakentry threadId with a real one
       
  1961 	if (aThreadId == 0xFFFFFFFF)
       
  1962 	{
       
  1963 	    breakEntry.iThreadSpecific = EFalse;
       
  1964 	    breakEntry.iThreadId = aProcessId+1; //process wide break, just use the main thread id for this process		
       
  1965 	}
       
  1966 	else
       
  1967 	{
       
  1968 		breakEntry.iThreadSpecific = ETrue;
       
  1969 	}
       
  1970         
       
  1971 	TInt err = DoEnableBreak(breakEntry, ETrue);
       
  1972 	
       
  1973 	if (KErrNone == err)
       
  1974 	{
       
  1975 		ReturnIfError(iBreakPointList.Append(breakEntry));
       
  1976 	}
       
  1977 	
       
  1978 	return err;
       
  1979 }
       
  1980 
       
  1981 
       
  1982 //
       
  1983 // DMetroTrkChannel::DoEnableBreak
       
  1984 //
       
  1985 TInt DMetroTrkChannel::DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
       
  1986 {
       
  1987 	LOG_MSG("DMetroTrkChannel::DoEnableBreak()");
       
  1988 
       
  1989 	// default to arm mode
       
  1990 	TUint32 inst = KArmBreakPoint;
       
  1991 	TInt instSize = 4;
       
  1992 	
       
  1993 	if (aEntry.iThumbMode)
       
  1994 	{
       
  1995 		LOG_MSG("Thumb Breakpoint");
       
  1996 		inst = KThumbBreakPoint;
       
  1997 		instSize = 2;
       
  1998 	}
       
  1999 
       
  2000 	TInt err = KErrNone;
       
  2001   			
       
  2002 	// Get thread id from the process that we are debugging
       
  2003 	TProcessInfo * proc = NULL;
       
  2004 	TUint32 threadId = NULL;
       
  2005 	
       
  2006 	threadId = aEntry.iThreadId;
       
  2007 	
       
  2008 	if (!threadId || threadId==0xFFFFFFFF) //threadId=0xFFFFFFFF is special case with CW debugger.
       
  2009 	{
       
  2010 		for (TInt i=0; i<iDebugProcessList.Count(); i++)
       
  2011 		{
       
  2012 			proc = &iDebugProcessList[i];
       
  2013 			if ( proc && (proc->iCodeAddress <= aEntry.iAddress) && (aEntry.iAddress <= (proc->iCodeAddress + proc->iCodeSize)))
       
  2014 			{
       
  2015 				threadId = proc->iId+1;
       
  2016 				break;
       
  2017 			}
       
  2018 		}
       
  2019 	}
       
  2020 	
       
  2021 	DThread* threadObj = ThreadFromId(threadId);
       
  2022 	//if we don't have the right thread id for the address, 
       
  2023 	//then try with the thread id of the process that we are debugging 	
       
  2024 	if (!threadObj && iDebugProcessList.Count())
       
  2025 	{
       
  2026 		proc = &iDebugProcessList[0];
       
  2027 		if (proc)
       
  2028 		{
       
  2029 			threadId = proc->iId+1;	
       
  2030 		}
       
  2031 		threadObj = ThreadFromId(threadId);
       
  2032 	}
       
  2033 	
       
  2034 	if (threadObj)
       
  2035 	{		
       
  2036 		if (aSaveOldInstruction)
       
  2037 		{
       
  2038 			TUint32 instruction;
       
  2039 
       
  2040 			// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
       
  2041 			// trap exceptions in case the address is invalid
       
  2042 			XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(threadObj, (TAny *)aEntry.iAddress, (TAny *)&instruction, instSize));
       
  2043 
       
  2044 			ReturnIfError((KErrNone == r) ? err : r);
       
  2045 
       
  2046 			aEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
       
  2047 		}
       
  2048 
       
  2049 		aEntry.iThreadId = threadId; //set the thread ID here 
       
  2050 		XTRAPD(r, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, aEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
       
  2051 		err = (DebugSupport::EBreakpointGlobal == r) ? KErrNone : r;
       
  2052 	}
       
  2053 	else
       
  2054 	{
       
  2055 		err = KErrBadHandle;	
       
  2056 	}
       
  2057 
       
  2058 
       
  2059 	return err;
       
  2060 }
       
  2061 
       
  2062 //
       
  2063 // DMetroTrkChannel::DoClearBreak
       
  2064 //
       
  2065 TInt DMetroTrkChannel::DoClearBreak(const TInt32 aId)
       
  2066 {
       
  2067 	LOG_MSG("DMetroTrkChannel::DoClearBreak()");
       
  2068 
       
  2069 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
       
  2070 	TBreakEntry entry;
       
  2071 	entry.iId = aId;
       
  2072 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
       
  2073 
       
  2074 	TInt err = KErrNone;
       
  2075 	if (index >= 0)
       
  2076 	{
       
  2077 		// if this breakpoint was set in a library and that library has already been unloaded, don't try to clear it
       
  2078 		if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
       
  2079 		{
       
  2080 			LOG_MSG2("Clearing breakpoint at address %x", iBreakPointList[index].iAddress);
       
  2081 
       
  2082 			DThread* threadObj = ThreadFromId(iBreakPointList[index].iThreadId);
       
  2083 			// In case of multiple memory model, if the thread doesn't exist any more, don't try to clear it.
       
  2084 			// For example it might be in a static library which was unloaded when the thread exited,
       
  2085 			// but we didn't get told so we didn't mark it as iObsoleteLibraryBreakpoint.
       
  2086 			if (threadObj != NULL)
       
  2087 			{
       
  2088 				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
       
  2089 				err = (KErrNone == r) ? err : r;
       
  2090 
       
  2091 			}
       
  2092 			else
       
  2093 			{
       
  2094 				err = KErrBadHandle;
       
  2095 			}
       
  2096 		}
       
  2097 		
       
  2098 		if (KErrNone == err)
       
  2099 		{
       
  2100 			// if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
       
  2101 			if (index < NUMBER_OF_TEMP_BREAKPOINTS)
       
  2102 			{
       
  2103 				iBreakPointList[index].Reset();
       
  2104 			}
       
  2105 			else
       
  2106 			{
       
  2107 				iBreakPointList.Remove(index);
       
  2108 			}
       
  2109 		}
       
  2110 		else
       
  2111 		{
       
  2112 			LOG_MSG2("Error clearing breakpoint %d", err);
       
  2113 		}
       
  2114 				
       
  2115 		return err;
       
  2116 	}
       
  2117 
       
  2118 	LOG_MSG2("Break Id %d not found", aId);
       
  2119 
       
  2120 	return KErrNotFound;
       
  2121 }
       
  2122 
       
  2123 
       
  2124 //
       
  2125 // DMetroTrkChannel::DoChangeBreakThread
       
  2126 //
       
  2127 TInt DMetroTrkChannel::DoChangeBreakThread(TUint32 aThreadId, TInt32 aId)
       
  2128 {
       
  2129 	LOG_MSG("DMetroTrkChannel::DoChangeBreakThread()");
       
  2130 
       
  2131 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
       
  2132 	TBreakEntry entry;
       
  2133 	entry.iId = aId;
       
  2134 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
       
  2135 	
       
  2136 	if (index >=0)
       
  2137 	{
       
  2138 		// change the thread id for this breakpoint
       
  2139 		iBreakPointList[index].iThreadId = aThreadId;
       
  2140 		return KErrNone;
       
  2141 	}
       
  2142 
       
  2143 	return KErrNotFound;
       
  2144 }
       
  2145 
       
  2146 //
       
  2147 // DMetroTrkChannel::DoSuspendThread
       
  2148 //
       
  2149 TInt DMetroTrkChannel::DoSuspendThread(DThread *aThread)
       
  2150 {
       
  2151 	LOG_MSG("DMetroTrkChannel::DoSuspendThread()");
       
  2152 
       
  2153 	if (!aThread)
       
  2154 	{
       
  2155 		LOG_MSG("Invalid dthread object");
       
  2156 		return KErrArgument;
       
  2157 	}
       
  2158 	
       
  2159 	NThread nThread = aThread->iNThread;
       
  2160 	
       
  2161 	if (nThread.iSuspendCount == 0)
       
  2162 		Kern::ThreadSuspend(*aThread, 1); 
       
  2163 
       
  2164 	return KErrNone;
       
  2165 }
       
  2166 
       
  2167 //
       
  2168 // DMetroTrkChannel::DoResumeThread
       
  2169 //
       
  2170 TInt DMetroTrkChannel::DoResumeThread(DThread *aThread)
       
  2171 {
       
  2172 	LOG_MSG("DMetroTrkChannel::DoResumeThread()");
       
  2173 
       
  2174 	if (!aThread)
       
  2175 		return KErrArgument;
       
  2176 
       
  2177 	// get the current PC
       
  2178 	TUint32 currentPC = ReadRegister(aThread, PC_REGISTER);
       
  2179 
       
  2180 	// if there is a breakpoint at the current PC, we need to single step past it
       
  2181 	for (TInt i=NUMBER_OF_TEMP_BREAKPOINTS; i<iBreakPointList.Count(); i++)
       
  2182 	{
       
  2183 		if (iBreakPointList[i].iAddress == currentPC)
       
  2184 		{
       
  2185 			return DoStepRange(aThread, currentPC, currentPC+1, ETrue, ETrue);
       
  2186 		}
       
  2187 	}
       
  2188 
       
  2189 	// PANIC_BACKPORT
       
  2190 	// if frozen use semaphore
       
  2191 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
  2192 	{
       
  2193 		if(iFrozenThreadSemaphores[i]->iOwningThread == &aThread->iNThread)
       
  2194 		{
       
  2195 			NKern::FSSignal(iFrozenThreadSemaphores[i]);
       
  2196 			NKern::ThreadEnterCS();
       
  2197 			delete iFrozenThreadSemaphores[i];
       
  2198 			NKern::ThreadLeaveCS();
       
  2199 			iFrozenThreadSemaphores.Remove(i);
       
  2200 			return KErrNone;
       
  2201 		}
       
  2202 	}
       
  2203 	// END PANIC_BACKPORT
       
  2204 
       
  2205 	// else use ThreadResume
       
  2206 	Kern::ThreadResume(*aThread);
       
  2207 	
       
  2208 	return KErrNone;
       
  2209 }
       
  2210 
       
  2211 //
       
  2212 // DMetroTrkChannel::DoStepRange
       
  2213 //
       
  2214 TInt DMetroTrkChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, TBool aUserRequest)
       
  2215 {
       
  2216 	LOG_MSG("DMetroTrkChannel::DoStepRange()");
       
  2217 
       
  2218 	if (!aThread)
       
  2219 		return KErrArgument;
       
  2220 
       
  2221 	TUint32 startAddress = (aStartAddress & 0x1) ? aStartAddress + 1 : aStartAddress;
       
  2222 	TUint32 stopAddress = (aStopAddress & 0x1) ? aStopAddress + 1 : aStopAddress;
       
  2223 
       
  2224 	// don't allow the user to step in the excluded ROM region.  this could be called
       
  2225 	// internally however.  for example, the the special breakpoints we set to handle
       
  2226 	// panics, exceptions, and library loaded events are in the user library, and we
       
  2227 	// will need to step past the breakpoint before continuing the thread.
       
  2228 	//if (aUserRequest && (startAddress >= iExcludedROMAddressStart) && (startAddress < iExcludedROMAddressEnd))
       
  2229 	//{
       
  2230 	//	return KErrNotSupported;
       
  2231 	//}
       
  2232 
       
  2233 	// set the temp breakpoint, and disable the breakpoint at the current PC if necessary
       
  2234 	// if its not a user request, and we are just trying to resume from a breakpoint, 
       
  2235 	// then we don't need to check for stubs. The last parameter aUserRequest tells 
       
  2236 	// ModifyBreaksForStep to check for stubs or not. In some cases, the check for stubs 
       
  2237 	// is true even if its not a user request.For example, this is true in cases where 
       
  2238 	// we are doing a step range and the instruction in the range modified PC.
       
  2239 	// in this case, DoStepRange will be called from the exception handler where 
       
  2240 	// we need to check for the stubs for the valid behavior. So truly, we don't need to check 
       
  2241 	// for stubs only when resuming from  a breakpoint.
       
  2242 	ReturnIfError(ModifyBreaksForStep(aThread, startAddress, stopAddress, aStepInto, aResumeOnceOutOfRange, aUserRequest));
       
  2243 	
       
  2244 	// PANIC_BACKPORT
       
  2245 	// if frozen use semaphore
       
  2246 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
       
  2247 		{
       
  2248 		if(iFrozenThreadSemaphores[i]->iOwningThread == &aThread->iNThread)
       
  2249 			{
       
  2250 			NKern::FSSignal(iFrozenThreadSemaphores[i]);
       
  2251 			NKern::ThreadEnterCS();
       
  2252 			delete iFrozenThreadSemaphores[i];
       
  2253 			NKern::ThreadLeaveCS();
       
  2254 			iFrozenThreadSemaphores.Remove(i);
       
  2255 			return KErrNone;
       
  2256 			}
       
  2257 		}
       
  2258 
       
  2259 	// END PANIC_BACKPORT
       
  2260 	// else use ThreadResume
       
  2261 	Kern::ThreadResume(*aThread);
       
  2262 	
       
  2263 	return KErrNone;
       
  2264 }
       
  2265 
       
  2266 //
       
  2267 // DMetroTrkChannel::DoReadMemory
       
  2268 //
       
  2269 TInt DMetroTrkChannel::DoReadMemory(DThread *aThread, const TUint32 aAddress, const TInt16 aLength, TDes8 &aData)
       
  2270 {
       
  2271 	LOG_MSG("DMetroTrkChannel::DoReadMemory()");
       
  2272 
       
  2273 	// make sure the parameters are valid
       
  2274 	if (aLength > aData.MaxSize())
       
  2275 		return KErrArgument;
       
  2276 
       
  2277 	TInt err = KErrNone;
       
  2278 	
       
  2279 	// trap exceptions in case the address is invalid
       
  2280 	XTRAPD(r, XT_DEFAULT, err = TryToReadMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
       
  2281 	
       
  2282 	err = (KErrNone == r) ? err : r;
       
  2283 	
       
  2284 	if (KErrNone == err)
       
  2285 	{
       
  2286 		aData.SetLength(aLength);
       
  2287 		
       
  2288 		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
       
  2289 		
       
  2290 		// if we have any breakpoints in this range, put the actual instruction in the buffer
       
  2291 		for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
       
  2292 		{
       
  2293 			if ((iBreakPointList[i].iAddress >= aAddress) && (iBreakPointList[i].iAddress < (aAddress + aLength)))
       
  2294 			{	
       
  2295 				TInt instSize = (TInt)(iBreakPointList[i].iThumbMode ? 2 : 4);								
       
  2296 				memcpy((TAny*)&data[iBreakPointList[i].iAddress - aAddress], (TAny *)iBreakPointList[i].iInstruction.Ptr(), instSize);
       
  2297 			}
       
  2298 		}
       
  2299 	}
       
  2300 
       
  2301 	return err;
       
  2302 }
       
  2303 
       
  2304 //
       
  2305 // DMetroTrkChannel::DoWriteMemory
       
  2306 //
       
  2307 TInt DMetroTrkChannel::DoWriteMemory(DThread *aThread, const TUint32 aAddress, const TInt16 aLength, TDes8 &aData)
       
  2308 {
       
  2309 	LOG_MSG("DMetroTrkChannel::DoWriteMemory()");
       
  2310 
       
  2311 	// make sure the parameters are valid
       
  2312 	if (aLength > aData.Length())
       
  2313 		return KErrArgument;
       
  2314 
       
  2315 	TInt err = KErrNone;
       
  2316 	
       
  2317 	// trap exceptions in case the address is invalid
       
  2318 	XTRAPD(r, XT_DEFAULT,  err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
       
  2319 	
       
  2320 	err = (KErrNone == r) ? err : r;
       
  2321 
       
  2322 	// reset any breakpoints we may have just overwritten
       
  2323 	if (KErrNone == err)
       
  2324 	{
       
  2325 		TPtr8 data((TUint8 *)aData.Ptr(), aLength, aLength);
       
  2326 		
       
  2327 		for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
       
  2328 		{
       
  2329 			if ((iBreakPointList[i].iAddress >= aAddress) && (iBreakPointList[i].iAddress < (aAddress + aLength)))
       
  2330 			{
       
  2331 				// default to arm mode
       
  2332 				TUint32 inst = KArmBreakPoint;
       
  2333 				TInt instSize = 4;
       
  2334 				
       
  2335 				if (iBreakPointList[i].iThumbMode)
       
  2336 				{
       
  2337 					inst = KThumbBreakPoint;
       
  2338 					instSize = 2;
       
  2339 				}
       
  2340 				
       
  2341 				iBreakPointList[i].iInstruction.Copy(&data[iBreakPointList[i].iAddress - aAddress], instSize);
       
  2342 				//memcpy((TAny*)iBreakPointList[i].iAddress, (TAny *)&inst, instSize);			
       
  2343 				TryToWriteMemory(aThread, (TAny*)iBreakPointList[i].iAddress, (TAny *)&inst, instSize);			
       
  2344 			}
       
  2345 		}
       
  2346 		
       
  2347 	}
       
  2348 	
       
  2349 	return err;
       
  2350 }
       
  2351 
       
  2352 //
       
  2353 // DMetroTrkChannel::DoReadRegisters
       
  2354 //
       
  2355 TInt DMetroTrkChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
       
  2356 {
       
  2357 	LOG_MSG("DMetroTrkChannel::DoReadRegisters()");
       
  2358 
       
  2359 	// make sure the parameters are valid
       
  2360 	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
       
  2361 		return KErrArgument;
       
  2362 
       
  2363 	// make sure the descriptor is big enough to hold the requested data
       
  2364 	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.MaxSize()))
       
  2365 		return KErrArgument;
       
  2366 	
       
  2367 	TArmRegSet regSet;
       
  2368     TUint32 unused;
       
  2369 
       
  2370 #ifdef SUPPORT_KERNCONTEXT
       
  2371 	NKern::Lock(); // lock the kernel before callin UserContextType as its required by this function
       
  2372 	NThread nThread = aThread->iNThread;
       
  2373 	NThread::TUserContextType userContextType = nThread.UserContextType();
       
  2374 	NKern::Unlock(); //unlock the kernel now
       
  2375 	
       
  2376 	if (userContextType == NThread::EContextNone || userContextType == NThread::EContextKernel)
       
  2377 	{
       
  2378 		//NKern::ThreadGetSystemContext(&aThread->iNThread, &regSet, unused);
       
  2379 		if (!GetSystemThreadRegisters(&regSet))
       
  2380 			return KErrGeneral;
       
  2381 	}
       
  2382 	else
       
  2383 #endif
       
  2384 	{
       
  2385 		NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
       
  2386 	}
       
  2387     
       
  2388     TArmReg *reg = &regSet.iR0;
       
  2389 
       
  2390 	if (!reg)
       
  2391 		return KErrGeneral;
       
  2392 			    
       
  2393     for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
       
  2394     	aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
       
  2395 
       
  2396 	return KErrNone;
       
  2397 }
       
  2398 
       
  2399 //
       
  2400 // DMetroTrkChannel::DoWriteRegisters
       
  2401 //
       
  2402 TInt DMetroTrkChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
       
  2403 {
       
  2404 	LOG_MSG("DMetroTrkChannel::DoWriteRegisters()");
       
  2405 
       
  2406 	// make sure the parameters are valid
       
  2407 	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
       
  2408 		return KErrArgument;
       
  2409 
       
  2410 	// make sure the descriptor is big enough to hold the data to write
       
  2411 	if ((TInt)((aLastRegister - aFirstRegister + 1) * sizeof(TArmReg)) > (aValues.Length()))
       
  2412 		return KErrArgument;
       
  2413 
       
  2414     TArmRegSet regSet;
       
  2415     TUint32 unused;
       
  2416 
       
  2417 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
       
  2418 	
       
  2419     TArmReg *reg = &regSet.iR0;
       
  2420 
       
  2421     for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
       
  2422     {
       
  2423     	#ifndef __OEM_TRK__	
       
  2424 		if (IsRegisterSecure(i))
       
  2425 			return KErrNotSupported;
       
  2426 		#endif
       
  2427     	reg[i] = *(TUint32 *)&aValues[(i-aFirstRegister)*sizeof(TArmReg)];
       
  2428     }
       
  2429     	
       
  2430     	
       
  2431     NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
       
  2432 
       
  2433 	return KErrNone;
       
  2434 }
       
  2435 
       
  2436 //
       
  2437 // DMetroTrkChannel::DoGetProcessInfo
       
  2438 //
       
  2439 TInt DMetroTrkChannel::DoGetProcessInfo(const TInt aIndex, TMetroTrkTaskInfo *aInfo)
       
  2440 {
       
  2441 	LOG_MSG("DMetroTrkChannel::DoGetProcessInfo()");
       
  2442 	
       
  2443 	DObjectCon *processes = Kern::Containers()[EProcess];
       
  2444 	if (!processes)
       
  2445 		return KErrGeneral;
       
  2446 	
       
  2447 	TInt err = KErrNone;
       
  2448 	
       
  2449 	NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
  2450 	processes->Wait(); // Obtain the container mutex so the list does get changed under us
       
  2451 		
       
  2452 	// make sure the index is valid
       
  2453 	if ((aIndex >= 0) && (aIndex < processes->Count())) // >= because the index is zero based
       
  2454 	{
       
  2455 		DProcess *process = (DProcess *)((*processes)[aIndex]);
       
  2456 		
       
  2457 		if (process)
       
  2458 		{
       
  2459 			process->Name(aInfo->iName);
       
  2460 			aInfo->iId = process->iId;
       
  2461 			aInfo->iPriority = (TUint32)process->iPriority;
       
  2462 		}
       
  2463 		else
       
  2464 		{
       
  2465 			LOG_MSG2("Process %d not found", aIndex);
       
  2466 			err = KErrArgument;
       
  2467 		}
       
  2468 	}
       
  2469 	else
       
  2470 	{
       
  2471 		err = KErrArgument;
       
  2472 	}
       
  2473 	
       
  2474 	processes->Signal();
       
  2475 	NKern::ThreadLeaveCS();
       
  2476 	
       
  2477 	return err;
       
  2478 }
       
  2479 
       
  2480 //
       
  2481 // DMetroTrkChannel::DoGetThreadInfo
       
  2482 //
       
  2483 TInt DMetroTrkChannel::DoGetThreadInfo(const TInt aIndex, TMetroTrkTaskInfo *aInfo)
       
  2484 {
       
  2485 	LOG_MSG("DMetroTrkChannel::DoGetThreadInfo()");
       
  2486 		
       
  2487 	DObjectCon *threads = Kern::Containers()[EThread];
       
  2488 	if (!threads)
       
  2489 		return KErrGeneral;	
       
  2490 	
       
  2491 	NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
  2492 	threads->Wait(); // Obtain the container mutex so the list does get changed under us
       
  2493 	
       
  2494 	TInt err = KErrNone;
       
  2495 	if ((aIndex >= 0) && (aIndex < threads->Count()))
       
  2496 	{
       
  2497 		DThread *thread = NULL;
       
  2498 		
       
  2499 		TInt threadsForProcessCount = 0;
       
  2500 		TBool found = EFalse;
       
  2501 		
       
  2502 		for (TInt i=0; i<threads->Count(); i++)
       
  2503 		{
       
  2504 			thread = (DThread *)((*threads)[i]);
       
  2505 			
       
  2506 			if (thread && (aInfo->iOtherId == thread->iOwningProcess->iId))
       
  2507 			{
       
  2508 				if (threadsForProcessCount == aIndex)
       
  2509 				{
       
  2510 					thread->Name(aInfo->iName);
       
  2511 					aInfo->iId = thread->iId;
       
  2512 					aInfo->iPriority = (TUint32)thread->iThreadPriority;
       
  2513 					found = ETrue;				
       
  2514 					break;
       
  2515 				}
       
  2516 				threadsForProcessCount++;
       
  2517 			}
       
  2518 		}
       
  2519 		
       
  2520 		if (!found)
       
  2521 		{
       
  2522 			LOG_MSG("Thread for process matching index not found");
       
  2523 			err = KErrArgument;
       
  2524 		}
       
  2525 	
       
  2526 	}
       
  2527 	else
       
  2528 	{		
       
  2529 		err = KErrArgument;
       
  2530 	}
       
  2531 	
       
  2532 	threads->Signal();
       
  2533 	NKern::ThreadLeaveCS();
       
  2534 
       
  2535 	return err;
       
  2536 }
       
  2537 
       
  2538 //
       
  2539 // DMetroTrkChannel::DoGetProcessAddresses
       
  2540 //
       
  2541 TInt DMetroTrkChannel::DoGetProcessAddresses(DThread *aThread, TUint32 &aCodeAddress, TUint32 &aDataAddress)
       
  2542 {
       
  2543 	LOG_MSG("DMetroTrkChannel::DoGetProcessAddresses()");
       
  2544 
       
  2545 	if (!aThread)
       
  2546 		return KErrArgument;
       
  2547 	
       
  2548 #ifndef __OEM_TRK__			
       
  2549 	if (HasManufacturerCaps(aThread))
       
  2550 		return KErrPermissionDenied;
       
  2551 #endif
       
  2552 	
       
  2553 	DProcess *process = (DProcess *)aThread->iOwningProcess;
       
  2554 	
       
  2555 	if (!process)
       
  2556 		return KErrArgument;
       
  2557 	
       
  2558 	DCodeSeg* codeSeg = process->iCodeSeg;
       
  2559 	if (!codeSeg)
       
  2560 		return KErrArgument;
       
  2561 		
       
  2562 	TModuleMemoryInfo processMemoryInfo;
       
  2563 	TInt err = codeSeg->GetMemoryInfo(processMemoryInfo, process);
       
  2564 	if (err != KErrNone)
       
  2565 		return err;
       
  2566 	
       
  2567 	aCodeAddress = processMemoryInfo.iCodeBase;
       
  2568 	aDataAddress = processMemoryInfo.iInitialisedDataBase;
       
  2569 	
       
  2570 	//add this process to the list of processes that we are debugging
       
  2571 	TProcessInfo processInfo(process->iId, aCodeAddress, processMemoryInfo.iCodeSize, aDataAddress);
       
  2572 	iDebugProcessList.Append(processInfo);
       
  2573 		
       
  2574 	return KErrNone;
       
  2575 }
       
  2576 
       
  2577 //
       
  2578 // DMetroTrkChannel::DoGetStaticLibraryInfo
       
  2579 //
       
  2580 
       
  2581 TInt DMetroTrkChannel::DoGetStaticLibraryInfo(const TInt aIndex, SEventInfo *aInfo)
       
  2582 {
       
  2583 	LOG_MSG("DMetroTrkChannel::DoGetStaticLibraryInfo()");
       
  2584 	
       
  2585 	if (!aInfo)
       
  2586 		return KErrArgument;
       
  2587 		
       
  2588 	DThread *thread = ThreadFromId(aInfo->iThreadId);
       
  2589 
       
  2590 	if (!thread)
       
  2591 		return KErrArgument;
       
  2592 	
       
  2593 	DProcess *process = (DProcess *)thread->iOwningProcess;
       
  2594 	
       
  2595 
       
  2596 	if (!process)
       
  2597 		return KErrArgument;
       
  2598 	
       
  2599 	
       
  2600 	DCodeSeg *processCodeSeg = process->iCodeSeg;
       
  2601 	
       
  2602 	if (!processCodeSeg)
       
  2603 		return KErrArgument;
       
  2604 	
       
  2605 	int count = processCodeSeg->iDepCount;
       
  2606 	LOG_MSG2("code segment count %d", count);
       
  2607 
       
  2608 	
       
  2609 	if (aIndex < 0 || aIndex >= count)
       
  2610 		return KErrArgument;
       
  2611 	
       
  2612 	DCodeSeg **codeSegList = processCodeSeg->iDeps;
       
  2613 	if (!codeSegList)
       
  2614 		return KErrArgument;
       
  2615 	
       
  2616 	DCodeSeg* codeSeg = codeSegList[aIndex];
       
  2617 	if (!codeSeg)
       
  2618 	{
       
  2619 		return KErrArgument;
       
  2620 	}
       
  2621 	if (!codeSeg->IsDll())
       
  2622 	{
       
  2623 		LOG_MSG(" -- code segment is not for a dll");
       
  2624 		return KErrArgument;		
       
  2625 	}
       
  2626 	TModuleMemoryInfo memoryInfo;
       
  2627 	TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
       
  2628 	if (err != KErrNone)
       
  2629 	{
       
  2630 		LOG_MSG2("Error in getting TModuleMemoryInfo info: %d", err);
       
  2631 		return KErrArgument;
       
  2632 	}
       
  2633 
       
  2634 	aInfo->iEventType = SEventInfo::ELibraryLoaded;	
       
  2635 	aInfo->iFileName.Copy(*(codeSeg->iFileName)); //just the name, without uid info.		
       
  2636 	aInfo->iCodeAddress = memoryInfo.iCodeBase;
       
  2637 	aInfo->iDataAddress = memoryInfo.iInitialisedDataBase;
       
  2638 	//this way, host debugger will not resume the thread, instead engine will resume
       
  2639 	//after going through the list of all static libraries..
       
  2640 	aInfo->iThreadId = 0xFFFFFFFF; 
       
  2641 	
       
  2642 	LOG_MSG2("library name: %S", codeSeg->iFileName);		
       
  2643 	LOG_MSG2("code address: %x", aInfo->iCodeAddress);
       
  2644 	LOG_MSG2("data address: %x", aInfo->iDataAddress);
       
  2645 
       
  2646 	return KErrNone;
       
  2647 }
       
  2648 
       
  2649 
       
  2650 //
       
  2651 // DMetroTrkChannel::DoGetLibraryInfo
       
  2652 //
       
  2653 TInt DMetroTrkChannel::DoGetLibraryInfo(TDesC8 &aDllName, TMetroTrkLibInfo *aInfo)
       
  2654 {
       
  2655 	LOG_MSG("DMetroTrkChannel::DoGetLibraryInfo()");
       
  2656 		
       
  2657 	TInt err = KErrArgument;
       
  2658 	
       
  2659 	if (!aInfo)
       
  2660 		return err;
       
  2661 		
       
  2662 	err = DoGetLibInfoFromCodeSegList(aDllName, aInfo);
       
  2663 					
       
  2664 	return err;
       
  2665 }
       
  2666 
       
  2667 //
       
  2668 // DMetroTrkChannel::DoGetExeInfo
       
  2669 //
       
  2670 TInt DMetroTrkChannel::DoGetExeInfo(TDesC8 &aExeName, TMetroTrkExeInfo* aExeInfo)
       
  2671 {
       
  2672 	LOG_MSG("DMetroTrkChannel::DoGetExeInfo()");
       
  2673 	
       
  2674 	DObjectCon *processes = Kern::Containers()[EProcess];
       
  2675 	if (!processes)
       
  2676 		return KErrGeneral;
       
  2677 		
       
  2678 	NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
  2679 	processes->Wait(); // Obtain the container mutex so the list does get changed under us
       
  2680 			
       
  2681 	TInt err = KErrNotFound; //set err to KErrNotFound
       
  2682 	for (TInt i=0;  i < processes->Count(); i++) // >= because the index is zero based
       
  2683 	{
       
  2684 		DProcess *process = (DProcess *)((*processes)[i]);		
       
  2685 		if (process && (0x0 != aExeInfo->iUid) && (aExeInfo->iUid == process->iUids.iUid[2].iUid))
       
  2686 		{
       
  2687 			DCodeSeg* codeSeg = process->iCodeSeg;
       
  2688 			DThread* mainThread = process->FirstThread();
       
  2689 			if (codeSeg && mainThread)
       
  2690 			{
       
  2691 				aExeInfo->iProcessID = process->iId;
       
  2692 				aExeInfo->iThreadID = mainThread->iId;
       
  2693 
       
  2694 				TModuleMemoryInfo memoryInfo;
       
  2695 				err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
       
  2696 				if (KErrNone == err)
       
  2697 				{
       
  2698 					aExeInfo->iCodeAddress = memoryInfo.iCodeBase;
       
  2699 					aExeInfo->iDataAddress = memoryInfo.iInitialisedDataBase;					
       
  2700 					break;
       
  2701 				}								
       
  2702 			}
       
  2703 		}
       
  2704 	}
       
  2705 		
       
  2706 	processes->Signal();
       
  2707 	NKern::ThreadLeaveCS();
       
  2708 					
       
  2709 	return err;
       
  2710 }
       
  2711 
       
  2712 
       
  2713 //
       
  2714 // DMetroTrkChannel::DoGetProcUidInfo
       
  2715 //
       
  2716 TInt DMetroTrkChannel::DoGetProcUidInfo(TMetroTrkProcUidInfo* aProcUidInfo)
       
  2717 {
       
  2718 	LOG_MSG("DMetroTrkChannel::DoGetProcUidInfo()");	
       
  2719 	
       
  2720 	TInt err = KErrNotFound;
       
  2721 	DProcess* process = ProcessFromId(aProcUidInfo->iProcessID);	
       
  2722 	if (process)
       
  2723 	{
       
  2724 		aProcUidInfo->iUid1 = process->iUids.iUid[0].iUid;
       
  2725 		aProcUidInfo->iUid2 = process->iUids.iUid[1].iUid;
       
  2726 		aProcUidInfo->iUid3 = process->iUids.iUid[2].iUid;
       
  2727 		aProcUidInfo->iSecurID = process->iS.iSecureId;
       
  2728 		aProcUidInfo->iVendorID = process->iS.iVendorId;
       
  2729 		
       
  2730 		err = KErrNone;
       
  2731 	}								
       
  2732 	return err;
       
  2733 }
       
  2734 
       
  2735 //
       
  2736 // DMetroTrkChannel::DoGetLibInfoFromCodeSegList
       
  2737 //
       
  2738 TInt DMetroTrkChannel::DoGetLibInfoFromCodeSegList(TDesC8 &aDllName, TMetroTrkLibInfo *aInfo)
       
  2739 {
       
  2740 	LOG_MSG("DMetroTrkChannel::DoGetLibInfoFromCodeSegList()");
       
  2741 		
       
  2742 	TInt err = KErrArgument;
       
  2743 
       
  2744 	//get global code seg list
       
  2745 	SDblQue* codeSegList = Kern::CodeSegList();
       
  2746 	if (!codeSegList)
       
  2747 		return KErrBadHandle;		
       
  2748 
       
  2749 	//iterate through the list
       
  2750 	for (SDblQueLink* codeSegPtr = codeSegList->First(); codeSegPtr!=(SDblQueLink*) (codeSegList); codeSegPtr=codeSegPtr->iNext)
       
  2751 	{
       
  2752 		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iLink);	
       
  2753 		if (codeSeg && codeSeg->IsDll())
       
  2754 		{
       
  2755 			if (codeSeg->iFileName) //If this is valid, the rootname will also be valid.
       
  2756 			{
       
  2757 				// some dll names from the code segment list have some characters towards the end.
       
  2758 				// Not sure why.
       
  2759 				// To account for this, we need to compare those strings that are 
       
  2760 				// atleast as big as the dll we are looking for.
       
  2761 				// Also the dll names in the code segment list don't have null terminator and so -1.
       
  2762 				if (codeSeg->iRootName.Length() < aDllName.Length()-1)
       
  2763 					continue;
       
  2764 								
       
  2765 				if (!_strnicmp(codeSeg->iRootName.Ptr(), aDllName.Ptr(), aDllName.Length()-1))
       
  2766 				{
       
  2767 					TModuleMemoryInfo memoryInfo;
       
  2768 
       
  2769 					TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
       
  2770 					if (err != KErrNone)
       
  2771 					{
       
  2772 						//there's been an error so return it
       
  2773 						return err;
       
  2774 					}							
       
  2775 					
       
  2776 					aInfo->iCodeAddress = memoryInfo.iCodeBase;
       
  2777 					aInfo->iDataAddress = memoryInfo.iInitialisedDataBase;
       
  2778 					if (codeSeg->iAttachProcess) //not valid if dll is used by multiple processes, so not reliable.
       
  2779 					{
       
  2780 						aInfo->iAttachProcessId = codeSeg->iAttachProcess->iId;
       
  2781 						if (codeSeg->iAttachProcess->FirstThread())
       
  2782 							aInfo->iAttachThreadId = codeSeg->iAttachProcess->FirstThread()->iId;
       
  2783 					}
       
  2784 					
       
  2785 					LOG_MSG2("Code segment found for lib: %s", aDllName.Ptr());
       
  2786 					LOG_MSG2("code address: %x", aInfo->iCodeAddress);
       
  2787 					LOG_MSG2("data address: %x", aInfo->iDataAddress);
       
  2788 
       
  2789 					return KErrNone;
       
  2790 				}
       
  2791 			}
       
  2792 		}
       
  2793 	}
       
  2794 	
       
  2795 	LOG_MSG2("Code segment not found for lib: %s", aDllName.Ptr());
       
  2796 	return err;
       
  2797 }
       
  2798 
       
  2799 //
       
  2800 // DMetroTrkChannel::DoGetLibInfoFromKernLibContainer
       
  2801 //
       
  2802 TInt DMetroTrkChannel::DoGetLibInfoFromKernLibContainer(TDesC8 &aDllName, TMetroTrkLibInfo *aInfo)
       
  2803 {
       
  2804 	LOG_MSG("DMetroTrkChannel::DoGetLibInfoFromKernLibContainer()");
       
  2805 		
       
  2806 	TInt err = KErrNone;	
       
  2807 		
       
  2808 	DObjectCon *libraries = Kern::Containers()[ELibrary];
       
  2809 	
       
  2810 	if (!libraries)
       
  2811 		return KErrGeneral;	
       
  2812 
       
  2813 	NKern::ThreadEnterCS(); // Prevent us from dying or suspending whilst holding a DMutex
       
  2814 	libraries->Wait(); // Obtain the container mutex so the list does get changed under us
       
  2815 		
       
  2816 	for (TInt i=0; i<libraries->Count(); i++)
       
  2817 	{
       
  2818 		DLibrary *library = (DLibrary *)((*libraries)[i]);
       
  2819 		
       
  2820 		if (library)
       
  2821 		{
       
  2822 			TBuf<KMaxPath> libName;
       
  2823 			libName.Copy(*(library->iName)); //just copy the name without the UID info.
       
  2824 						
       
  2825 			if (libName.Length() < aDllName.Length()-1)
       
  2826 				continue;
       
  2827 								
       
  2828 			if (!_strnicmp(libName.Ptr(), aDllName.Ptr(), aDllName.Length()-1))
       
  2829 			{			
       
  2830 				//get the code address
       
  2831 				DCodeSeg* codeSeg = library->iCodeSeg;
       
  2832 				if (codeSeg)
       
  2833 				{
       
  2834 					TModuleMemoryInfo memoryInfo;
       
  2835 
       
  2836 					TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
       
  2837 					if (err == KErrNone)
       
  2838 					{
       
  2839 						// there's been an error so return it					
       
  2840 						aInfo->iCodeAddress = memoryInfo.iCodeBase;
       
  2841 						aInfo->iDataAddress = memoryInfo.iInitialisedDataBase;						
       
  2842 						// process id and thread id are in DLibrary object.
       
  2843 					}					
       
  2844 				}
       
  2845 				else
       
  2846 				{
       
  2847 					LOG_MSG2("Code segment not available for library %S", library->iName);
       
  2848 					err = KErrNotFound;
       
  2849 				}				
       
  2850 				break;
       
  2851 			}		
       
  2852 		}										
       
  2853 	}
       
  2854 
       
  2855 	libraries->Signal();
       
  2856 	NKern::ThreadLeaveCS();
       
  2857 	
       
  2858 	return err;		
       
  2859 }
       
  2860 
       
  2861 //
       
  2862 // DMetroTrkChannel::DoSecurityCheck
       
  2863 //
       
  2864 TBool DMetroTrkChannel::DoSecurityCheck()
       
  2865 {
       
  2866 	DProcess* clientProcess = iClientThread->iOwningProcess;
       
  2867 	if (clientProcess)
       
  2868 	{
       
  2869 		// now we also check to make sure that TRK app has ALLFILES capability as well.
       
  2870 		if (!iClientThread->HasCapability(ECapabilityAllFiles))
       
  2871 			return EFalse;
       
  2872 		
       
  2873 		SSecurityInfo secureInfo = clientProcess->iS;
       
  2874 		if ((secureInfo.iSecureId == KTrkSrvSecurUid) || (secureInfo.iSecureId == KTrkAppSecurUid) || (secureInfo.iSecureId == KTrkExeSecurUid))
       
  2875 		{
       
  2876 			return ETrue;
       
  2877 		}
       
  2878 	}
       
  2879 	return EFalse;
       
  2880 }
       
  2881 
       
  2882 //
       
  2883 // DMetroTrkChannel::TryToReadMemory
       
  2884 //
       
  2885 TInt DMetroTrkChannel::TryToReadMemory(DThread *aThread, TAny *aSrc, TAny *aDest, TInt16 aLength)
       
  2886 {
       
  2887 	LOG_MSG("DMetroTrkChannel::TryToReadMemory()");
       
  2888 	
       
  2889 	TInt err = KErrNone;
       
  2890 	// on some targets reading from 0xFFFFFFFF address causes a kernel fault.
       
  2891 	// avoid reading the last 4 bytes in the 32 bit address space.
       
  2892 	TUint32 srcAddr = (TUint32)(aSrc);
       
  2893 	if ((srcAddr >= 0xFFFFFFFC) || (aLength > (0xFFFFFFFC-srcAddr)))
       
  2894 		return KErrAccessDenied;
       
  2895 
       
  2896 #ifndef __OEM_TRK__
       
  2897 	if (IsAddressInRom((TUint32)(aSrc)) || IsAddressSecure((TUint32)(aSrc)))
       
  2898 		return KErrNotSupported;
       
  2899 #endif
       
  2900 
       
  2901 	//check if we have a valid thread object
       
  2902 	if (!aThread)
       
  2903 		return KErrBadHandle;
       
  2904 
       
  2905 	LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
       
  2906 	err = Kern::ThreadRawRead(aThread, aSrc, aDest, aLength);	
       
  2907 
       
  2908 	return err;
       
  2909 }
       
  2910 
       
  2911 
       
  2912 //
       
  2913 // DMetroTrkChannel::TryToWriteMemory
       
  2914 //
       
  2915 TInt DMetroTrkChannel::TryToWriteMemory(DThread *aThread, TAny *aDest, TAny *aSrc, TInt16 aLength)
       
  2916 {
       
  2917 	LOG_MSG("DMetroTrkChannel::TryToWriteMemory()");
       
  2918 
       
  2919 	TInt err = KErrNone;
       
  2920 	// on some targets writing to 0xFFFFFFFF address causes a kernel fault.
       
  2921 	// avoid writing the last 4 bytes in the 32 bit address space.
       
  2922 	TUint32 destAddr = (TUint32)(aDest);
       
  2923 	if ((destAddr>=0xFFFFFFFC) || (aLength > (0xFFFFFFFC-destAddr)))
       
  2924 		return KErrAccessDenied;
       
  2925 
       
  2926 #ifndef __OEM_TRK__
       
  2927 	if (IsAddressInRom((TUint32)(aDest)) || IsAddressSecure((TUint32)(aDest)))
       
  2928 		return KErrNotSupported;
       
  2929 #endif
       
  2930 
       
  2931 	//check if we have a valid thread object
       
  2932 	if (!aThread)
       
  2933 		return KErrBadHandle;
       
  2934 		
       
  2935 	LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
       
  2936 	err = Kern::ThreadRawWrite(aThread, aDest, aSrc, aLength, iClientThread);		
       
  2937 
       
  2938 	return err;
       
  2939 }
       
  2940 
       
  2941 //
       
  2942 // DMetroTrkChannel::ReadRegister
       
  2943 //
       
  2944 TInt32 DMetroTrkChannel::ReadRegister(DThread *aThread, TInt aNum)
       
  2945 {
       
  2946 	LOG_MSG("DMetroTrkChannel::ReadRegister()");
       
  2947 
       
  2948 	if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
       
  2949 	{
       
  2950 		LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
       
  2951 		return 0;
       
  2952 	}
       
  2953 	
       
  2954 	TArmRegSet regSet;
       
  2955     TUint32 unused;
       
  2956 
       
  2957 #ifdef SUPPORT_KERNCONTEXT	
       
  2958   	NKern::Lock(); // lock the kernel before callin UserContextType as its required by this function
       
  2959 	NThread nThread = aThread->iNThread;
       
  2960 	NThread::TUserContextType userContextType = nThread.UserContextType();
       
  2961 	NKern::Unlock(); // unlock the kernel now
       
  2962 	
       
  2963 	if (userContextType == NThread::EContextNone || userContextType == NThread::EContextKernel)
       
  2964 	{
       
  2965 		//NKern::ThreadGetSystemContext(&aThread->iNThread, &regSet, unused);
       
  2966 		if (!GetSystemThreadRegisters(&regSet))
       
  2967 			return KErrGeneral;
       
  2968 	}
       
  2969 	else
       
  2970 #endif	
       
  2971 	{
       
  2972 		NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
       
  2973 	}
       
  2974     
       
  2975     TArmReg *reg = &regSet.iR0;
       
  2976 	
       
  2977 	return ((TUint32 *)reg)[aNum];
       
  2978 }
       
  2979 
       
  2980 //
       
  2981 // DMetroTrkChannel::ShiftedRegValue
       
  2982 //
       
  2983 TUint32 DMetroTrkChannel::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister)
       
  2984 {
       
  2985 	LOG_MSG("DMetroTrkChannel::ShiftedRegValue()");
       
  2986 
       
  2987 	TUint32 shift = 0;
       
  2988 	if (aInstruction & 0x10)	// bit 4
       
  2989 	{
       
  2990 		shift = (ARM_RS(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF;
       
  2991 	}
       
  2992 	else
       
  2993 	{
       
  2994 		shift = ARM_DATA_C(aInstruction);
       
  2995 	}
       
  2996 	
       
  2997 	TInt rm = ARM_RM(aInstruction);
       
  2998 	TUint32 res = (rm == PC_REGISTER ? (aCurrentPC + ((aInstruction & 0x10) ? 12 : 8)) : ReadRegister(aThread, rm));
       
  2999 
       
  3000 	switch(ARM_DATA_SHIFT(aInstruction))
       
  3001 	{
       
  3002 		case 0:			// LSL
       
  3003 		{
       
  3004 			res = shift >= 32 ? 0 : res << shift;
       
  3005 			break;
       
  3006 		}
       
  3007 		case 1:			// LSR
       
  3008 		{
       
  3009 			res = shift >= 32 ? 0 : res >> shift;
       
  3010 			break;
       
  3011 		}
       
  3012 		case 2:			// ASR
       
  3013 		{
       
  3014 			if (shift >= 32)
       
  3015 			shift = 31;
       
  3016 			res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift);
       
  3017 			break;
       
  3018 		}
       
  3019 		case 3:			// ROR/RRX
       
  3020 		{
       
  3021 			shift &= 31;
       
  3022 			if (shift == 0)
       
  3023 			{
       
  3024 				res = (res >> 1) | ((aStatusRegister & ARM_CARRY_BIT) ? 0x80000000L : 0);
       
  3025 			}
       
  3026 			else
       
  3027 			{
       
  3028 				res = (res >> shift) | (res << (32 - shift));
       
  3029 			}
       
  3030 			break;
       
  3031     	}
       
  3032     }
       
  3033 
       
  3034   	return res & 0xFFFFFFFF;
       
  3035 }
       
  3036 
       
  3037 
       
  3038 //
       
  3039 // DMetroTrkChannel::ModifyBreaksForStep
       
  3040 //
       
  3041 // Set a temporary breakpoint at the next instruction to be executed after the one at the current PC
       
  3042 // Disable the breakpoint at the current PC if one exists
       
  3043 //
       
  3044 TInt DMetroTrkChannel::ModifyBreaksForStep(DThread *aThread, TUint32 aRangeStart, TUint32 aRangeEnd, TBool aStepInto, TBool aResumeOnceOutOfRange, TBool aCheckForStubs)
       
  3045 {
       
  3046 	LOG_MSG("DMetroTrkChannel::ModifyBreaksForStep()");
       
  3047 	
       
  3048 	if (!aThread)
       
  3049 		return KErrArgument;
       
  3050 
       
  3051 	LOG_MSG2("Range Start: %x", aRangeStart);
       
  3052 	LOG_MSG2("Range End: %x", aRangeEnd);
       
  3053 
       
  3054 	// get the current PC
       
  3055 	TUint32 currentPC = ReadRegister(aThread, PC_REGISTER);
       
  3056 	LOG_MSG2("Current PC: %x", currentPC);
       
  3057 
       
  3058 	// disable breakpoint at the current PC if necessary
       
  3059 	ReturnIfError(DisableBreakAtAddress(currentPC));
       
  3060 
       
  3061 	// get the status register
       
  3062 	TUint32 statusRegister = ReadRegister(aThread, STATUS_REGISTER);
       
  3063 	LOG_MSG2("Current SR: %x", statusRegister);
       
  3064 
       
  3065 	TBool thumbMode = (statusRegister & ECpuThumb);
       
  3066 	if (thumbMode)
       
  3067 		LOG_MSG("Thumb Mode");
       
  3068 
       
  3069 	TInt instSize = thumbMode ? 2 : 4;
       
  3070 
       
  3071 	TBool changingModes = EFalse;
       
  3072 	
       
  3073 	TUint32 breakAddress = 0;
       
  3074 
       
  3075 	TInt rangeSize = aRangeEnd - currentPC;
       
  3076 	
       
  3077 	const TInt KMaxInstructionBuffer = 80;
       
  3078 	
       
  3079 	// scan the memory and see if any instruction might modify the PC.  if one does,
       
  3080 	// stop scanning and just set a breakpoint at that instruction (with the range set accordingly).
       
  3081 	// if none is found just set the breakpoint after the range.
       
  3082 	// if there is only one instruction there is no need to parse the memory, just execute it
       
  3083 	if ((rangeSize <= KMaxInstructionBuffer) && (rangeSize > instSize))
       
  3084 	{
       
  3085 		LOG_MSG("Scanning range for instructions that might modify the PC");
       
  3086 		
       
  3087 		// set it to the end of the range by default
       
  3088 		breakAddress = aRangeEnd;
       
  3089 
       
  3090 		// get the instructions in range
       
  3091 		// we really should be dynamically allocating this memory, but this could be
       
  3092 		// called from another thread, so we can't
       
  3093 		TBuf8<KMaxInstructionBuffer> instructions;
       
  3094 			
       
  3095 		ReturnIfError(DoReadMemory(aThread, currentPC, rangeSize, instructions));
       
  3096 		
       
  3097 		for (TInt i = 0; i < (TInt)rangeSize/instSize; i++)
       
  3098 		{
       
  3099 			if (InstructionModifiesPC(aThread, &instructions[i*instSize], thumbMode, aStepInto))
       
  3100 			{
       
  3101 				breakAddress = currentPC + i*instSize;
       
  3102 				LOG_MSG2("Setting breakpoint at %x inside range", breakAddress);
       
  3103 				break;
       
  3104 			}
       
  3105 		}
       
  3106 	}
       
  3107 	
       
  3108 
       
  3109 	TUint32 newRangeEnd = aRangeEnd;
       
  3110 
       
  3111 	if ((breakAddress == 0) || (breakAddress == currentPC))
       
  3112 	{
       
  3113 		// either the range consists of a single instruction, or the instruction at the currentPC may modify the PC
       
  3114 		// decode the instruction and see where we need to set the breakpoint
       
  3115 		breakAddress = PCAfterInstructionExecutes(aThread, currentPC, statusRegister, instSize, aStepInto, newRangeEnd, changingModes);
       
  3116 				
       
  3117 		// check to see if this is one of the stubs (found in stubs.s)
       
  3118 		if (aStepInto && aCheckForStubs)
       
  3119 		{
       
  3120 			TBuf8<16> destination;
       
  3121 			TInt err = DoReadMemory(aThread, breakAddress, 16, destination);
       
  3122 
       
  3123 			if (KErrNone == err)
       
  3124 			{
       
  3125 				TInt offset = 0;
       
  3126 				
       
  3127 				if (0 == destination.Find(KArm4Stub, sizeof(KArm4Stub)))
       
  3128 				{
       
  3129 					LOG_MSG("Arm4 stub found");
       
  3130 					offset = 8;
       
  3131 				}
       
  3132 				else if ((0 == destination.Find(KArmIStub, sizeof(KArmIStub))) ||
       
  3133 						 (0 == destination.Find(KFastArmIStub, sizeof(KFastArmIStub))))
       
  3134 				{
       
  3135 					LOG_MSG("ArmI stub found");
       
  3136 					offset = 12;
       
  3137 				}
       
  3138 				else if ((0 == destination.Find(KThumbStub, sizeof(KThumbStub))) ||
       
  3139 						 (0 == destination.Find(KFastThumbStub, sizeof(KFastThumbStub))))
       
  3140 				{
       
  3141 					LOG_MSG("Thumb stub found");
       
  3142 					offset = 12;
       
  3143 				}
       
  3144 				else if ((0 == destination.Find(KThumbStub2, sizeof(KThumbStub2))) ||
       
  3145 						 (0 == destination.Find(KFastThumbStub2, sizeof(KFastThumbStub2))))
       
  3146 				{
       
  3147 					LOG_MSG("Thumb stub found");
       
  3148 					offset = 8;
       
  3149 				}
       
  3150 				//check to see if this is the stub generated with RVCT tools. 
       
  3151 				//Look into genstubs.cpp for more details on this stub
       
  3152 				else if(0 == destination.Find(KRvctArm4Stub, sizeof(KRvctArm4Stub)))
       
  3153 				{
       
  3154 					LOG_MSG("RVCT Arm4 stub found");
       
  3155 					offset = 4;
       
  3156 				}
       
  3157 
       
  3158 				
       
  3159 				if (offset != 0)
       
  3160 				{
       
  3161 					if (offset == 4)
       
  3162 					{
       
  3163 						breakAddress = *(TUint32 *)&destination[offset];
       
  3164 					}
       
  3165 					else
       
  3166 					{
       
  3167 						err = DoReadMemory(aThread, *(TUint32 *)&destination[offset], 4, destination);
       
  3168 						if (KErrNone == err)
       
  3169 							breakAddress = *(TUint32 *)destination.Ptr();
       
  3170 					}
       
  3171 					
       
  3172 					if (KErrNone == err)
       
  3173 					{						
       
  3174 						if (thumbMode)
       
  3175 						{
       
  3176 							if ((breakAddress & 0x00000001) == 1)
       
  3177 								changingModes = EFalse;
       
  3178 							else
       
  3179 								changingModes = ETrue;
       
  3180 						}
       
  3181 						else
       
  3182 						{
       
  3183 							if ((breakAddress & 0x00000001) == 1)
       
  3184 								changingModes = ETrue;
       
  3185 							else
       
  3186 								changingModes = EFalse;	
       
  3187 						}
       
  3188 						
       
  3189 						breakAddress &= 0xFFFFFFFE;
       
  3190 					}
       
  3191 					else
       
  3192 					{
       
  3193 						LOG_MSG("Error reading destination of stub");
       
  3194 					}
       
  3195 				}
       
  3196 			}
       
  3197 			else
       
  3198 			{
       
  3199 				LOG_MSG("Error reading memory while decoding branch instruction");
       
  3200 			}					
       
  3201 		}
       
  3202 		
       
  3203 		// don't allow the user to step in a function in the excluded ROM region.
       
  3204 		//if ((breakAddress >= iExcludedROMAddressStart) && (breakAddress < iExcludedROMAddressEnd))
       
  3205 		//{
       
  3206 		//	breakAddress = currentPC + instSize;
       
  3207 		//	changingModes = EFalse;
       
  3208 		//}
       
  3209 	}
       
  3210 	
       
  3211 	// see if there is already a breakpoint at this address.  if there is, we do not need to set the temp breakpoint
       
  3212 	for (TInt i=NUMBER_OF_TEMP_BREAKPOINTS; i<iBreakPointList.Count(); i++)
       
  3213 	{
       
  3214 		if (iBreakPointList[i].iAddress == breakAddress)
       
  3215 		{
       
  3216 			return KErrNone;
       
  3217 		}
       
  3218 	}
       
  3219 	
       
  3220 	for (TInt i=0; i<NUMBER_OF_TEMP_BREAKPOINTS; i++)
       
  3221 	{
       
  3222 		if (iBreakPointList[i].iAddress == 0)
       
  3223 		{
       
  3224 			iBreakPointList[i].iThreadId = aThread->iId;
       
  3225 			iBreakPointList[i].iAddress = breakAddress;
       
  3226 			iBreakPointList[i].iThumbMode = (thumbMode && !changingModes) || (!thumbMode && changingModes);
       
  3227 			iBreakPointList[i].iResumeOnceOutOfRange = aResumeOnceOutOfRange;
       
  3228 			iBreakPointList[i].iSteppingInto = aStepInto;
       
  3229 			iBreakPointList[i].iRangeStart = aRangeStart;
       
  3230 			iBreakPointList[i].iRangeEnd = newRangeEnd;
       
  3231 			
       
  3232 			// Temporary breakpoints are always thread specific
       
  3233 			iBreakPointList[i].iThreadSpecific = ETrue;
       
  3234 
       
  3235 			LOG_MSG2("Adding temp breakpoint with id: %d", i);
       
  3236 			LOG_MSG2("Adding temp breakpoint with thread id: %d", aThread->iId);
       
  3237 
       
  3238 			return DoEnableBreak(iBreakPointList[i], ETrue);			
       
  3239 		}
       
  3240 	}
       
  3241 	
       
  3242 	return KErrNoMemory;
       
  3243 }
       
  3244 
       
  3245 //
       
  3246 // DMetroTrkChannel::ClearAllBreakPoints
       
  3247 //
       
  3248 void DMetroTrkChannel::ClearAllBreakPoints()
       
  3249 {
       
  3250 	LOG_MSG("DMetroTrkChannel::ClearAllBreakPoints()");
       
  3251 
       
  3252 	TInt err = KErrNone;
       
  3253 
       
  3254 	for (TInt i=0; i<iBreakPointList.Count(); i++)
       
  3255 	{		
       
  3256 		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
       
  3257 		{
       
  3258 			LOG_MSG2("Clearing breakpoint at address %x", iBreakPointList[i].iAddress);
       
  3259 			
       
  3260 			DThread* threadObj = ThreadFromId(iBreakPointList[i].iThreadId);
       
  3261 		
       
  3262 			if (threadObj != NULL)
       
  3263 			{
       
  3264 				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[i].iAddress));
       
  3265 		
       
  3266 				err = (KErrNone == r) ? err : r;
       
  3267 			}
       
  3268 			else
       
  3269 			{
       
  3270 				err = KErrBadHandle;
       
  3271 			}
       
  3272 				
       
  3273 			if (KErrNone != err)
       
  3274 			{
       
  3275 				LOG_MSG2("Error %d while clearing breakpoint", err);
       
  3276 			}		
       
  3277 		}
       
  3278 	}
       
  3279 	
       
  3280 	iBreakPointList.Reset();	
       
  3281 }
       
  3282 
       
  3283 
       
  3284 //
       
  3285 // DMetroTrkChannel::DisableBreakAtAddress
       
  3286 //
       
  3287 TInt DMetroTrkChannel::DisableBreakAtAddress(TUint32 aAddress)
       
  3288 {
       
  3289 	LOG_MSG("DMetroTrkChannel::DisableBreakAtAddress()");
       
  3290 
       
  3291 	TInt err = KErrNone;
       
  3292 	
       
  3293 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
       
  3294 	{
       
  3295 		if (iBreakPointList[i].iAddress == aAddress)
       
  3296 		{
       
  3297 			iBreakPointList[i].iDisabledForStep = ETrue;
       
  3298 			LOG_MSG2("Disabling breakpoint at address %x", iBreakPointList[i].iAddress);
       
  3299 		
       
  3300 			DThread* threadObj = ThreadFromId(iBreakPointList[i].iThreadId);
       
  3301 
       
  3302 			//clear the breakpoint with code modifier
       
  3303 			//code modifier will restore the org instruction and also frees the shadow page if necessary
       
  3304 			if (threadObj != NULL)
       
  3305 			{
       
  3306 				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, aAddress));
       
  3307 		
       
  3308 				err = (KErrNone == r) ? err : r;
       
  3309 			}
       
  3310 			else
       
  3311 			{
       
  3312 				err = KErrBadHandle;
       
  3313 			}
       
  3314 			break;
       
  3315 		}
       
  3316 	}
       
  3317 	
       
  3318 	return err;
       
  3319 }
       
  3320 
       
  3321 //
       
  3322 // DMetroTrkChannel::InstructionModifiesPC
       
  3323 //
       
  3324 TBool DMetroTrkChannel::InstructionModifiesPC(DThread *aThread, TUint8 *aInstruction, TBool aThumbMode, TBool aStepInto)
       
  3325 {
       
  3326 	LOG_MSG("DMetroTrkChannel::InstructionModifiesPC()");
       
  3327 
       
  3328 	if (aThumbMode)
       
  3329 	{
       
  3330 		TUint16 inst = *(TUint16 *)aInstruction;
       
  3331 		
       
  3332 		switch(THUMB_OPCODE(inst))
       
  3333 		{
       
  3334 			case 0x08:
       
  3335 			{
       
  3336 				if (aStepInto && (THUMB_INST_7_15(inst) == 0x08F))
       
  3337 				{
       
  3338 					// BLX(2)
       
  3339 					return ETrue;				
       
  3340 				}
       
  3341 				else if (THUMB_INST_7_15(inst) == 0x08E)
       
  3342 				{
       
  3343 					// BX
       
  3344 					return ETrue;				
       
  3345 				}
       
  3346 				else if (((THUMB_INST_8_15(inst) == 0x46) || (THUMB_INST_8_15(inst) == 0x44)) && ((inst & 0x87) == 0x87))
       
  3347 				{
       
  3348 					// ADD or MOV with PC as the destination
       
  3349 					return ETrue;				
       
  3350 				}
       
  3351 				break;
       
  3352 			}
       
  3353 			case 0x13:
       
  3354 			{
       
  3355 				if (THUMB_INST_8_15(inst) == 0x9F)
       
  3356 				{
       
  3357 					// LDR(4) with the PC as the destination
       
  3358 					return ETrue;				
       
  3359 				}
       
  3360 				break;
       
  3361 			}
       
  3362 			case 0x17:
       
  3363 			{	
       
  3364 				if (THUMB_INST_8_15(inst) == 0xBD)
       
  3365 				{
       
  3366 					// POP with the PC in the list
       
  3367 					return ETrue;				
       
  3368 				}
       
  3369 				break;
       
  3370 			}
       
  3371 			case 0x1A:
       
  3372 			case 0x1B:
       
  3373 			{	
       
  3374 				if (THUMB_INST_8_15(inst) < 0xDE)
       
  3375 				{
       
  3376 					// B(1) conditional branch
       
  3377 					return ETrue;				
       
  3378 				}
       
  3379 				break;
       
  3380 			}
       
  3381 			case 0x1C:
       
  3382 			{	
       
  3383 				// B(2) unconditional branch
       
  3384 				return ETrue;				
       
  3385 			}
       
  3386 			case 0x1D:
       
  3387 			{
       
  3388 				// NOTE: Only return true for the suffix since it's the second instruction that actually does the branch
       
  3389 				if (aStepInto && !(inst & 0x00000001))
       
  3390 				{
       
  3391 					// BLX(1)
       
  3392 					return ETrue;				
       
  3393 				}
       
  3394 				break;
       
  3395 			}
       
  3396 			case 0x1F:
       
  3397 			{
       
  3398 				// NOTE: Only return true for the suffix since it's the second instruction that actually does the branch
       
  3399 				if (aStepInto)
       
  3400 				{
       
  3401 					// BL
       
  3402 					return ETrue;				
       
  3403 				}
       
  3404 				break;
       
  3405 			}
       
  3406 		}
       
  3407 	}
       
  3408 	else
       
  3409 	{
       
  3410 		// Arm mode
       
  3411 		TUint32 inst = *(TUint32 *)aInstruction;
       
  3412 
       
  3413 		switch(ARM_OPCODE(inst)) // bits 27-25
       
  3414 		{
       
  3415 			case 0:
       
  3416 			{
       
  3417 				switch((inst & 0x00000010) >> 4) // bit 4
       
  3418 				{
       
  3419 					case 0:
       
  3420 					{
       
  3421 						switch((inst & 0x01800000) >> 23) // bits 24-23
       
  3422 						{
       
  3423 							case 2:
       
  3424 							{
       
  3425 								// move to/from status register.  pc updates not allowed
       
  3426 								// or TST, TEQ, CMP, CMN which don't modify the PC
       
  3427 								break;
       
  3428 							}
       
  3429 							default:
       
  3430 							{
       
  3431 								// Data processing immediate shift
       
  3432 								if (ARM_RD(inst) == PC_REGISTER)
       
  3433 								{
       
  3434 									// destination register is the PC
       
  3435 									if (IsPreviousInstructionMovePCToLR(aThread))
       
  3436 									{
       
  3437 										return aStepInto;
       
  3438 									}
       
  3439 									else
       
  3440 									{
       
  3441 										return ETrue;
       
  3442 									}										
       
  3443 								}
       
  3444 								break;
       
  3445 							}
       
  3446 						}
       
  3447 						break;
       
  3448 					}					
       
  3449 					case 1:
       
  3450 					{
       
  3451 						switch((inst & 0x00000080) >> 7) // bit 7
       
  3452 						{
       
  3453 							case 0:
       
  3454 							{
       
  3455 								switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
       
  3456 								{
       
  3457 									case 0x10:
       
  3458 									{
       
  3459 										// from figure 3-3
       
  3460 										switch((inst & 0x000000F0) >> 4) // bits 7-4
       
  3461 										{
       
  3462 											case 1:
       
  3463 											{
       
  3464 												if (((inst & 0x00400000) >> 22) == 0) // bit 22
       
  3465 												{
       
  3466 													// BX
       
  3467 													if (IsPreviousInstructionMovePCToLR(aThread))
       
  3468 													{
       
  3469 														return aStepInto;
       
  3470 													}
       
  3471 													else
       
  3472 													{
       
  3473 														return ETrue;
       
  3474 													}										
       
  3475 												}
       
  3476 												break;
       
  3477 											}
       
  3478 											case 3:
       
  3479 											{
       
  3480 												// BLX
       
  3481 												if (aStepInto)
       
  3482 												{
       
  3483 													return ETrue;
       
  3484 												}
       
  3485 												break;
       
  3486 											}
       
  3487 											default:
       
  3488 											{
       
  3489 												// either doesn't modify the PC or it is illegal to
       
  3490 												break;
       
  3491 											}
       
  3492 										}
       
  3493 										break;
       
  3494 									}
       
  3495 									default:
       
  3496 									{
       
  3497 										// Data processing register shift
       
  3498 										if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
       
  3499 										{
       
  3500 											// TST, TEQ, CMP, CMN don't modify the PC
       
  3501 											return EFalse;
       
  3502 										}
       
  3503 										else if (ARM_RD(inst) == PC_REGISTER)
       
  3504 										{
       
  3505 											// destination register is the PC
       
  3506 											if (IsPreviousInstructionMovePCToLR(aThread))
       
  3507 											{
       
  3508 												return aStepInto;
       
  3509 											}
       
  3510 											else
       
  3511 											{
       
  3512 												return ETrue;
       
  3513 											}										
       
  3514 										}
       
  3515 										break;
       
  3516 									}
       
  3517 								}
       
  3518 								break;
       
  3519 							}
       
  3520 							default:
       
  3521 							{
       
  3522 								// from figure 3-2, updates to the PC illegal
       
  3523 								break;
       
  3524 							}
       
  3525 						}
       
  3526 						break;
       
  3527 					}
       
  3528 				}
       
  3529 				break;
       
  3530 			}
       
  3531 			case 1:
       
  3532 			{
       
  3533 				if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
       
  3534 				{
       
  3535 					// cannot modify the PC
       
  3536 					break;
       
  3537 				}
       
  3538 				else if (ARM_RD(inst) == PC_REGISTER)
       
  3539 				{
       
  3540 					// destination register is the PC
       
  3541 					if (IsPreviousInstructionMovePCToLR(aThread))
       
  3542 					{
       
  3543 						return aStepInto;
       
  3544 					}
       
  3545 					else
       
  3546 					{
       
  3547 						return ETrue;
       
  3548 					}										
       
  3549 				}
       
  3550 				break;
       
  3551 			}
       
  3552 			case 2:
       
  3553 			{
       
  3554 				// load/store immediate offset
       
  3555 				if (ARM_LOAD(inst)) // bit 20
       
  3556 				{
       
  3557 					// loading a register from memory
       
  3558 					if (ARM_RD(inst) == PC_REGISTER)
       
  3559 					{
       
  3560 						// loading the PC register
       
  3561 						if (IsPreviousInstructionMovePCToLR(aThread))
       
  3562 						{
       
  3563 							return aStepInto;
       
  3564 						}
       
  3565 						else
       
  3566 						{
       
  3567 							return ETrue;
       
  3568 						}										
       
  3569 					}
       
  3570 				}	
       
  3571 				break;
       
  3572 			}
       
  3573 			case 3:
       
  3574 			{
       
  3575 				if (((inst & 0xF0000000) != 0xF) && ((inst & 0x00000010) == 0))
       
  3576 				{
       
  3577 					// load/store register offset
       
  3578 					if (ARM_LOAD(inst)) // bit 20
       
  3579 					{
       
  3580 						// loading a register from memory
       
  3581 						if (ARM_RD(inst) == PC_REGISTER)
       
  3582 						{
       
  3583 							// loading the PC register
       
  3584 							if (IsPreviousInstructionMovePCToLR(aThread))
       
  3585 							{
       
  3586 								return aStepInto;
       
  3587 							}
       
  3588 							else
       
  3589 							{
       
  3590 								return ETrue;
       
  3591 							}										
       
  3592 						}
       
  3593 					}	
       
  3594 				}
       
  3595 				break;
       
  3596 			}
       
  3597 			case 4:
       
  3598 			{
       
  3599 				if ((inst & 0xF0000000) != 0xF)
       
  3600 				{
       
  3601 					// load/store multiple
       
  3602 					if (ARM_LOAD(inst)) // bit 20
       
  3603 					{
       
  3604 						// loading a register from memory
       
  3605 						if (((inst & 0x00008000) >> 15))
       
  3606 						{
       
  3607 							// loading the PC register
       
  3608 							return ETrue;
       
  3609 						}
       
  3610 					}					
       
  3611 				}
       
  3612 				break;
       
  3613 			}
       
  3614 			case 5:
       
  3615 			{
       
  3616 				if ((inst & 0xF0000000) == 0xF)
       
  3617 				{
       
  3618 					// BLX
       
  3619 					if (aStepInto)
       
  3620 					{
       
  3621 						return ETrue;
       
  3622 					}
       
  3623 				}
       
  3624 				else
       
  3625 				{
       
  3626 					if ((inst & 0x01000000)) // bit 24
       
  3627 					{
       
  3628 						// BL
       
  3629 						if (aStepInto)
       
  3630 						{
       
  3631 							return ETrue;
       
  3632 						}
       
  3633 					}
       
  3634 					else
       
  3635 					{
       
  3636 						// B
       
  3637 						return ETrue;
       
  3638 					}
       
  3639 				}
       
  3640 				break;
       
  3641 			}
       
  3642 		}	
       
  3643 	}
       
  3644 	
       
  3645 	return EFalse;
       
  3646 }
       
  3647 
       
  3648 //
       
  3649 // DMetroTrkChannel::PCAfterInstructionExecutes
       
  3650 //
       
  3651 TUint32 DMetroTrkChannel::PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 aStatusRegister, TInt aInstSize, TBool aStepInto, TUint32 &aNewRangeEnd, TBool &aChangingModes)
       
  3652 {
       
  3653 	LOG_MSG("DMetroTrkChannel::PCAfterInstructionExecutes()");
       
  3654 
       
  3655 	// by default we will set the breakpoint at the next instruction
       
  3656 	TUint32 breakAddress = aCurrentPC + aInstSize;
       
  3657 	
       
  3658 	// get the instruction at the current PC
       
  3659 	TBuf8<4> instruction;
       
  3660 	TInt err = DoReadMemory(aThread, aCurrentPC, aInstSize, instruction); 
       
  3661 
       
  3662 	if (KErrNone != err)
       
  3663 	{
       
  3664 		return breakAddress;
       
  3665 	}
       
  3666 	
       
  3667 	if (4 == aInstSize)
       
  3668 	{
       
  3669 		TUint32 inst = *(TUint32 *)instruction.Ptr();
       
  3670 		LOG_MSG2("Current instruction: %x", inst);
       
  3671 
       
  3672 		// check the conditions to see if this will actually get executed
       
  3673 		if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) 
       
  3674 		{
       
  3675 			switch(ARM_OPCODE(inst)) // bits 27-25
       
  3676 			{
       
  3677 				case 0:
       
  3678 				{
       
  3679 					switch((inst & 0x00000010) >> 4) // bit 4
       
  3680 					{
       
  3681 						case 0:
       
  3682 						{
       
  3683 							switch((inst & 0x01800000) >> 23) // bits 24-23
       
  3684 							{
       
  3685 								case 2:
       
  3686 								{
       
  3687 									// move to/from status register.  pc updates not allowed
       
  3688 									// or TST, TEQ, CMP, CMN which don't modify the PC
       
  3689 									break;
       
  3690 								}
       
  3691 								default:
       
  3692 								{
       
  3693 									// Data processing immediate shift
       
  3694 									if (ARM_RD(inst) == PC_REGISTER)
       
  3695 									{
       
  3696 										// destination register is the PC
       
  3697 										if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3698 										{
       
  3699 											return breakAddress;
       
  3700 										}
       
  3701 
       
  3702 										TUint32 rn = aCurrentPC + 8;
       
  3703 										if (ARM_RN(inst) != PC_REGISTER) // bits 19-16
       
  3704 										{
       
  3705 											rn = ReadRegister(aThread, ARM_RN(inst));
       
  3706 										}
       
  3707 										
       
  3708 										TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
       
  3709 										
       
  3710 										DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
       
  3711 									}
       
  3712 									break;
       
  3713 								}
       
  3714 							}
       
  3715 							break;
       
  3716 						}					
       
  3717 						case 1:
       
  3718 						{
       
  3719 							switch((inst & 0x00000080) >> 7) // bit 7
       
  3720 							{
       
  3721 								case 0:
       
  3722 								{
       
  3723 									switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
       
  3724 									{
       
  3725 										case 0x10:
       
  3726 										{
       
  3727 											// from figure 3-3
       
  3728 											switch((inst & 0x000000F0) >> 4) // bits 7-4
       
  3729 											{
       
  3730 												case 1:
       
  3731 												{
       
  3732 													if (((inst & 0x00400000) >> 22) == 0) // bit 22
       
  3733 													{
       
  3734 														// BX
       
  3735 														// this is a strange case.  normally this is used in the epilogue to branch the the link
       
  3736 														// register.  sometimes it is used to call a function, and the LR is stored in the previous
       
  3737 														// instruction.  since what we want to do is different for the two cases when stepping over,
       
  3738 														// we need to read the previous instruction to see what we should do
       
  3739 														if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3740 														{
       
  3741 															return breakAddress;
       
  3742 														}
       
  3743 														
       
  3744 														breakAddress = ReadRegister(aThread, (inst & 0x0000000F));
       
  3745 														
       
  3746 														if ((breakAddress & 0x00000001) == 1)
       
  3747 														{
       
  3748 															aChangingModes = ETrue;
       
  3749 														}
       
  3750 														
       
  3751 														breakAddress &= 0xFFFFFFFE;
       
  3752 													}
       
  3753 													break;
       
  3754 												}
       
  3755 												case 3:
       
  3756 												{
       
  3757 													// BLX
       
  3758 													if (aStepInto)
       
  3759 													{
       
  3760 														breakAddress = ReadRegister(aThread, (inst & 0x0000000F));
       
  3761 
       
  3762 														if ((breakAddress & 0x00000001) == 1)
       
  3763 														{
       
  3764 															aChangingModes = ETrue;
       
  3765 														}
       
  3766 														
       
  3767 														breakAddress &= 0xFFFFFFFE;
       
  3768 													}
       
  3769 													break;
       
  3770 												}
       
  3771 												default:
       
  3772 												{
       
  3773 													// either doesn't modify the PC or it is illegal to
       
  3774 													break;
       
  3775 												}
       
  3776 											}
       
  3777 											break;
       
  3778 										}
       
  3779 										default:
       
  3780 										{
       
  3781 											// Data processing register shift
       
  3782 											if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
       
  3783 											{
       
  3784 												// TST, TEQ, CMP, CMN don't modify the PC
       
  3785 											}
       
  3786 											else if (ARM_RD(inst) == PC_REGISTER)
       
  3787 											{
       
  3788 												// destination register is the PC
       
  3789 												if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3790 												{
       
  3791 													return breakAddress;
       
  3792 												}
       
  3793 
       
  3794 												TUint32 rn = aCurrentPC + 8;
       
  3795 												if (ARM_RN(inst) != PC_REGISTER) // bits 19-16
       
  3796 												{
       
  3797 													rn = ReadRegister(aThread, ARM_RN(inst));
       
  3798 												}
       
  3799 												
       
  3800 												TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
       
  3801 												
       
  3802 												DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
       
  3803 											}
       
  3804 											break;
       
  3805 										}
       
  3806 									}
       
  3807 									break;
       
  3808 								}
       
  3809 								default:
       
  3810 								{
       
  3811 									// from figure 3-2, updates to the PC illegal
       
  3812 									break;
       
  3813 								}
       
  3814 							}
       
  3815 							break;
       
  3816 						}
       
  3817 					}
       
  3818 					break;
       
  3819 				}
       
  3820 				case 1:
       
  3821 				{
       
  3822 					if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
       
  3823 					{
       
  3824 						// cannot modify the PC
       
  3825 						break;
       
  3826 					}
       
  3827 					else if (ARM_RD(inst) == PC_REGISTER)
       
  3828 					{
       
  3829 						// destination register is the PC
       
  3830 						if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3831 						{
       
  3832 							return breakAddress;
       
  3833 						}
       
  3834 
       
  3835 						TUint32 rn = ReadRegister(aThread, ARM_RN(inst)); // bits 19-16
       
  3836 						TUint32 shifter = ((ARM_DATA_IMM(inst) >> ARM_DATA_ROT(inst)) | (ARM_DATA_IMM(inst) << (32 - ARM_DATA_ROT(inst)))) & 0xffffffff;
       
  3837 
       
  3838 						DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
       
  3839 					}
       
  3840 					break;
       
  3841 				}
       
  3842 				case 2:
       
  3843 				{
       
  3844 					// load/store immediate offset
       
  3845 					if (ARM_LOAD(inst)) // bit 20
       
  3846 					{
       
  3847 						// loading a register from memory
       
  3848 						if (ARM_RD(inst) == PC_REGISTER)
       
  3849 						{
       
  3850 							// loading the PC register
       
  3851 							if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3852 							{
       
  3853 								return breakAddress;
       
  3854 							}
       
  3855 
       
  3856 					    	TUint32 base = ReadRegister(aThread, ARM_RN(inst));
       
  3857 					    	TUint32 offset = 0;
       
  3858 					    	
       
  3859 					    	if (ARM_SINGLE_PRE(inst))
       
  3860 					    	{
       
  3861 					    		// Pre-indexing
       
  3862 					    		offset = ARM_SINGLE_IMM(inst);
       
  3863 							    
       
  3864 							    if (ARM_SINGLE_U(inst))
       
  3865 							    {
       
  3866 							    	base += offset;
       
  3867 							    }
       
  3868 							    else
       
  3869 							    {
       
  3870 							    	base -= offset;
       
  3871 								}
       
  3872 							}
       
  3873 
       
  3874 							TBuf8<4> destination;
       
  3875 							TInt err = DoReadMemory(aThread, base, 4, destination);
       
  3876 							
       
  3877 							if (KErrNone == err)
       
  3878 							{
       
  3879 								breakAddress = *(TUint32 *)destination.Ptr();
       
  3880 							
       
  3881 								if ((breakAddress & 0x00000001) == 1)
       
  3882 								{
       
  3883 									aChangingModes = ETrue;
       
  3884 								}								
       
  3885 								breakAddress &= 0xFFFFFFFE;
       
  3886 							}
       
  3887 							else
       
  3888 							{
       
  3889 								LOG_MSG("Error reading memory in decoding step instruction");
       
  3890 							}
       
  3891 						}
       
  3892 					}	
       
  3893 					break;
       
  3894 				}
       
  3895 				case 3:
       
  3896 				{
       
  3897 					if (((inst & 0xF0000000) != 0xF) && ((inst & 0x00000010) == 0))
       
  3898 					{
       
  3899 						// load/store register offset
       
  3900 						if (ARM_LOAD(inst)) // bit 20
       
  3901 						{
       
  3902 							// loading a register from memory
       
  3903 							if (ARM_RD(inst) == PC_REGISTER)
       
  3904 							{
       
  3905 								// loading the PC register
       
  3906 								if (IsPreviousInstructionMovePCToLR(aThread) && !aStepInto)
       
  3907 								{
       
  3908 									return breakAddress;
       
  3909 								}
       
  3910 
       
  3911 						    	TUint32 base = (ARM_RN(inst) == PC_REGISTER) ? aCurrentPC + 8 : ReadRegister(aThread, ARM_RN(inst));
       
  3912 						    	TUint32 offset = 0;
       
  3913 						    	
       
  3914 						    	if (ARM_SINGLE_PRE(inst))
       
  3915 						    	{
       
  3916 							      	offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
       
  3917 
       
  3918 								    if (ARM_SINGLE_U(inst))
       
  3919 								    {
       
  3920 								    	base += offset;
       
  3921 								    }
       
  3922 								    else
       
  3923 								    {
       
  3924 								    	base -= offset;
       
  3925 									}
       
  3926 								}
       
  3927 
       
  3928 								TBuf8<4> destination;
       
  3929 								TInt err = DoReadMemory(aThread, base, 4, destination);
       
  3930 								
       
  3931 								if (KErrNone == err)
       
  3932 								{
       
  3933 									breakAddress = *(TUint32 *)destination.Ptr();
       
  3934 									
       
  3935 									if ((breakAddress & 0x00000001) == 1)
       
  3936 									{
       
  3937 										aChangingModes = ETrue;
       
  3938 									}								
       
  3939 									breakAddress &= 0xFFFFFFFE;
       
  3940 								}
       
  3941 								else
       
  3942 								{
       
  3943 									LOG_MSG("Error reading memory in decoding step instruction");
       
  3944 								}
       
  3945 							}
       
  3946 						}	
       
  3947 					}
       
  3948 					break;
       
  3949 				}
       
  3950 				case 4:
       
  3951 				{
       
  3952 					if ((inst & 0xF0000000) != 0xF)
       
  3953 					{
       
  3954 						// load/store multiple
       
  3955 						if (ARM_LOAD(inst)) // bit 20
       
  3956 						{
       
  3957 							// loading a register from memory
       
  3958 							if (((inst & 0x00008000) >> 15))
       
  3959 							{
       
  3960 								// loading the PC register
       
  3961 								TInt offset = 0;	
       
  3962 								if (ARM_BLOCK_U(inst))
       
  3963 								{
       
  3964 									TUint32 reglist = ARM_BLOCK_REGLIST(inst);
       
  3965 									offset = Bitcount(reglist) * 4 - 4;
       
  3966 									if (ARM_BLOCK_PRE(inst))
       
  3967 										offset += 4;
       
  3968 								}
       
  3969 								else if (ARM_BLOCK_PRE(inst))
       
  3970 								{
       
  3971 									offset = -4;
       
  3972 								}
       
  3973 									
       
  3974 						    	TUint32 temp = ReadRegister(aThread, ARM_RN(inst));
       
  3975 								
       
  3976 								temp += offset;
       
  3977 
       
  3978 								TBuf8<4> destination;
       
  3979 								TInt err = DoReadMemory(aThread, temp, 4, destination);
       
  3980 								
       
  3981 								if (KErrNone == err)
       
  3982 								{
       
  3983 									breakAddress = *(TUint32 *)destination.Ptr();
       
  3984 									if ((breakAddress & 0x00000001) == 1)
       
  3985 									{
       
  3986 										aChangingModes = ETrue;
       
  3987 									}
       
  3988 									breakAddress &= 0xFFFFFFFE;
       
  3989 								}
       
  3990 								else
       
  3991 								{
       
  3992 									LOG_MSG("Error reading memory in decoding step instruction");
       
  3993 								}
       
  3994 							}
       
  3995 						}					
       
  3996 					}
       
  3997 					break;
       
  3998 				}
       
  3999 				case 5:
       
  4000 				{
       
  4001 					if ((inst & 0xF0000000) == 0xF)
       
  4002 					{
       
  4003 						// BLX
       
  4004 						if (aStepInto)
       
  4005 						{
       
  4006 							breakAddress = (TUint32)ARM_INSTR_B_DEST(inst, aCurrentPC);
       
  4007 
       
  4008 							if ((breakAddress & 0x00000001) == 1)
       
  4009 							{
       
  4010 								aChangingModes = ETrue;
       
  4011 							}
       
  4012 							
       
  4013 							breakAddress &= 0xFFFFFFFE;
       
  4014 						}
       
  4015 					}
       
  4016 					else
       
  4017 					{
       
  4018 						if ((inst & 0x01000000)) // bit 24
       
  4019 						{
       
  4020 							// BL
       
  4021 							if (aStepInto)
       
  4022 							{
       
  4023 								breakAddress = (TUint32)ARM_INSTR_B_DEST(inst, aCurrentPC);
       
  4024 							}
       
  4025 						}
       
  4026 						else
       
  4027 						{
       
  4028 							// B
       
  4029 							breakAddress = (TUint32)ARM_INSTR_B_DEST(inst, aCurrentPC);
       
  4030 						}
       
  4031 					}
       
  4032 					break;
       
  4033 				}
       
  4034 			}	
       
  4035 		}
       
  4036 	}
       
  4037 	else
       
  4038 	{
       
  4039 		// Thumb Mode
       
  4040 		TUint16 inst = *(TUint16 *)instruction.Ptr();
       
  4041 		LOG_MSG2("Current instruction: %x", inst);
       
  4042 
       
  4043 		switch(THUMB_OPCODE(inst))
       
  4044 		{
       
  4045 			case 0x08:
       
  4046 			{
       
  4047 				if (aStepInto && (THUMB_INST_7_15(inst) == 0x08F))
       
  4048 				{
       
  4049 					// BLX(2)
       
  4050 					breakAddress = ReadRegister(aThread, ((inst & 0x0078) >> 3));
       
  4051 
       
  4052 					if ((breakAddress & 0x00000001) == 0)
       
  4053 					{
       
  4054 						aChangingModes = ETrue;
       
  4055 					}
       
  4056 					
       
  4057 					breakAddress &= 0xFFFFFFFE;
       
  4058 				}
       
  4059 				else if (THUMB_INST_7_15(inst) == 0x08E)
       
  4060 				{
       
  4061 					// BX
       
  4062 					breakAddress = ReadRegister(aThread, ((inst & 0x0078) >> 3));
       
  4063 
       
  4064 					if ((breakAddress & 0x00000001) == 0)
       
  4065 					{
       
  4066 						aChangingModes = ETrue;
       
  4067 					}
       
  4068 					
       
  4069 					breakAddress &= 0xFFFFFFFE;
       
  4070 				}
       
  4071 				else if ((THUMB_INST_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87))
       
  4072 				{
       
  4073 					// MOV with PC as the destination
       
  4074 					breakAddress = ReadRegister(aThread, ((inst & 0x0078) >> 3));
       
  4075 				}
       
  4076 				else if ((THUMB_INST_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87))
       
  4077 				{
       
  4078 					// ADD with PC as the destination
       
  4079 					breakAddress = aCurrentPC + ReadRegister(aThread, ((inst & 0x0078) >> 3));
       
  4080 				}
       
  4081 				break;
       
  4082 			}
       
  4083 			case 0x13:
       
  4084 			{
       
  4085 				//This instruction doesn't modify the PC.
       
  4086 
       
  4087 				//if (THUMB_INST_8_15(inst) == 0x9F)
       
  4088 				//{
       
  4089 					// LDR(4) with the PC as the destination
       
  4090 				//	breakAddress = ReadRegister(aThread, SP_REGISTER) + (4 * (inst & 0x00FF));
       
  4091 				//}
       
  4092 				break;
       
  4093 			}
       
  4094 			case 0x17:
       
  4095 			{	
       
  4096 				if (THUMB_INST_8_15(inst) == 0xBD)
       
  4097 				{
       
  4098 					// POP with the PC in the list
       
  4099 					TUint32 regList = (inst & 0x00FF);
       
  4100 					TInt offset = ReadRegister(aThread, SP_REGISTER) + (Bitcount(regList) * 4);
       
  4101 
       
  4102 					TBuf8<4> destination;
       
  4103 					TInt err = DoReadMemory(aThread, offset, 4, destination);
       
  4104 					
       
  4105 					if (KErrNone == err)
       
  4106 					{
       
  4107 						breakAddress = *(TUint32 *)destination.Ptr();
       
  4108 
       
  4109 						if ((breakAddress & 0x00000001) == 0)
       
  4110 						{
       
  4111 							aChangingModes = ETrue;
       
  4112 						}
       
  4113 
       
  4114 						breakAddress &= 0xFFFFFFFE;
       
  4115 					}
       
  4116 					else
       
  4117 					{
       
  4118 						LOG_MSG("Error reading memory in decoding step instruction");
       
  4119 					}
       
  4120 				}
       
  4121 				break;
       
  4122 			}
       
  4123 			case 0x1A:
       
  4124 			case 0x1B:
       
  4125 			{	
       
  4126 				if (THUMB_INST_8_15(inst) < 0xDE)
       
  4127 				{
       
  4128 					// B(1) conditional branch
       
  4129 					if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister))
       
  4130 					{
       
  4131 						TUint32 offset = ((inst & 0x000000FF) << 1);
       
  4132 						if (offset & 0x00000100)
       
  4133 						{
       
  4134 							offset |= 0xFFFFFF00;
       
  4135 						}
       
  4136 						
       
  4137 						breakAddress = aCurrentPC + 4 + offset;
       
  4138 					}
       
  4139 				}
       
  4140 				break;
       
  4141 			}
       
  4142 			case 0x1C:
       
  4143 			{	
       
  4144 				// B(2) unconditional branch
       
  4145 				TUint32 offset = (inst & 0x000007FF) << 1;
       
  4146 				if (offset & 0x00000800)
       
  4147 				{
       
  4148 					offset |= 0xFFFFF800;
       
  4149 				}
       
  4150 				
       
  4151 				breakAddress = aCurrentPC + 4 + offset;
       
  4152 				break;
       
  4153 			}
       
  4154 			case 0x1D:
       
  4155 			{
       
  4156 				if (aStepInto && !(inst & 0x0001))
       
  4157 				{
       
  4158 					// BLX(1)
       
  4159 					breakAddress = (ReadRegister(aThread, LINK_REGISTER) + ((inst & 0x07FF) << 1));
       
  4160 					if ((breakAddress & 0x00000001) == 0)
       
  4161 					{
       
  4162 						aChangingModes = ETrue;
       
  4163 					}
       
  4164 					
       
  4165 					breakAddress &= 0xFFFFFFFC;
       
  4166 				}
       
  4167 				break;
       
  4168 			}
       
  4169 			case 0x1E:
       
  4170 			{
       
  4171 				// BL/BLX prefix - destination is encoded in this and the next instruction
       
  4172 				aNewRangeEnd += 2;
       
  4173                 // BL Stepping Changes
       
  4174                 if (aStepInto)
       
  4175                 {
       
  4176                     TBuf8<2> nextInstruction;
       
  4177                     TInt err = DoReadMemory(aThread, aCurrentPC+2, aInstSize, nextInstruction);
       
  4178                     if (KErrNone == err)
       
  4179                     {
       
  4180                         TUint16 nextInst = *(TUint16*)nextInstruction.Ptr();
       
  4181                         LOG_MSG2("Next instruction: %x", nextInst);
       
  4182                         
       
  4183                         // base new LR from first instruction
       
  4184                         TUint32 newLR = inst & 0x07FF;
       
  4185                         newLR <<= 12;
       
  4186                         if (newLR & (TUint32)(0x0400 << 12))
       
  4187                         {
       
  4188                             // sign-extend it
       
  4189                             newLR |= 0xFF800000;
       
  4190                         }
       
  4191                         newLR += aCurrentPC + 4;        // pc is pointing to first instruction + 4
       
  4192                         TUint32 newPC = newLR + ((nextInst & 0x07FF) << 1);
       
  4193                         if (THUMB_OPCODE(nextInst) == 0x1D)         // H = 01 changing to ARM (BLX)
       
  4194                         {
       
  4195                             newPC &= 0xFFFFFFFC;
       
  4196                             aChangingModes = ETrue;
       
  4197                         }
       
  4198                         
       
  4199                         breakAddress = newPC;
       
  4200                     }
       
  4201                 }
       
  4202                 else    // step over
       
  4203                 {
       
  4204                     breakAddress += 2;
       
  4205                 }
       
  4206                 // End of BL Stepping Changes
       
  4207 				break;
       
  4208 			}
       
  4209 			case 0x1F:
       
  4210 			{
       
  4211 				if (aStepInto)
       
  4212 				{
       
  4213 					// BL
       
  4214 					breakAddress = ReadRegister(aThread, LINK_REGISTER) + ((inst & 0x07FF) << 1);
       
  4215 				}
       
  4216 				break;
       
  4217 			}
       
  4218 		}
       
  4219 	}
       
  4220 	
       
  4221 	return breakAddress;
       
  4222 }
       
  4223 
       
  4224 
       
  4225 //
       
  4226 // DMetroTrkChannel::DecodeDataProcessingInstruction
       
  4227 //
       
  4228 void DMetroTrkChannel::DecodeDataProcessingInstruction(TUint8 aOpcode, TUint32 aOp1, TUint32 aOp2, TUint32 aStatusRegister, TUint32 &aBreakAddress)
       
  4229 {
       
  4230 	LOG_MSG("DMetroTrkChannel::DecodeDataProcessingInstruction()");
       
  4231 
       
  4232 	switch(aOpcode)
       
  4233 	{
       
  4234 		case 0:
       
  4235 		{
       
  4236 			// AND
       
  4237 			aBreakAddress = aOp1 & aOp2;
       
  4238 			break;
       
  4239 		}
       
  4240 		case 1:
       
  4241 		{
       
  4242 			// EOR
       
  4243 			aBreakAddress = aOp1 ^ aOp2;
       
  4244 			break;
       
  4245 		}
       
  4246 		case 2:
       
  4247 		{
       
  4248 			// SUB
       
  4249 			aBreakAddress = aOp1 - aOp2;
       
  4250 			break;
       
  4251 		}
       
  4252 		case 3:
       
  4253 		{
       
  4254 			// RSB
       
  4255 			aBreakAddress = aOp2 - aOp1;
       
  4256 			break;
       
  4257 		}
       
  4258 		case 4:
       
  4259 		{
       
  4260 			// ADD
       
  4261 			aBreakAddress = aOp1 + aOp2;
       
  4262 			break;
       
  4263 		}
       
  4264 		case 5:
       
  4265 		{
       
  4266 			// ADC
       
  4267 			aBreakAddress = aOp1 + aOp2 + (aStatusRegister & ARM_CARRY_BIT) ? 1 : 0;
       
  4268 			break;
       
  4269 		}
       
  4270 		case 6:
       
  4271 		{
       
  4272 			// SBC
       
  4273 			aBreakAddress = aOp1 - aOp2 - (aStatusRegister & ARM_CARRY_BIT) ? 0 : 1;
       
  4274 			break;
       
  4275 		}
       
  4276 		case 7:
       
  4277 		{
       
  4278 			// RSC
       
  4279 			aBreakAddress = aOp2 - aOp1 - (aStatusRegister & ARM_CARRY_BIT) ? 0 : 1;
       
  4280 			break;
       
  4281 		}
       
  4282 		case 12:
       
  4283 		{
       
  4284 			// ORR
       
  4285 			aBreakAddress = aOp1 | aOp2;
       
  4286 			break;
       
  4287 		}
       
  4288 		case 13:
       
  4289 		{
       
  4290 			// MOV
       
  4291 			aBreakAddress = aOp2;
       
  4292 			break;
       
  4293 		}
       
  4294 		case 14:
       
  4295 		{
       
  4296 			// BIC
       
  4297 			aBreakAddress = aOp1 & ~aOp2;
       
  4298 			break;
       
  4299 		}
       
  4300 		case 15:
       
  4301 		{
       
  4302 			// MVN
       
  4303 			aBreakAddress = ~aOp2;
       
  4304 			break;
       
  4305 		}
       
  4306 	}
       
  4307 }
       
  4308 
       
  4309 //
       
  4310 // DMetroTrkChannel::IsPreviousInstructionMovePCToLR
       
  4311 //
       
  4312 TBool DMetroTrkChannel::IsPreviousInstructionMovePCToLR(DThread *aThread)
       
  4313 {
       
  4314 	LOG_MSG("DMetroTrkChannel::IsPreviousInstructionMovePCToLR()");
       
  4315 
       
  4316 	// there are several types of instructions that modify the PC that aren't
       
  4317 	// designated as linked or non linked branches.  the way gcc generates the
       
  4318 	// code can tell us whether or not these instructions are to be treated as
       
  4319 	// linked branches.  the main cases are bx and any type of mov or load or
       
  4320 	// arithmatic operation that changes the PC.  if these are really just
       
  4321 	// function calls that will return, gcc will generate a mov	lr, pc
       
  4322 	// instruction as the previous instruction.  note that this is just for arm
       
  4323 	// and armi
       
  4324 	
       
  4325 	// get the address of the previous instruction
       
  4326 	TUint32 address = ReadRegister(aThread, PC_REGISTER) - 4;
       
  4327 
       
  4328 	TBuf8<4> previousInstruction;
       
  4329 	TInt err = DoReadMemory(aThread, address, 4, previousInstruction);
       
  4330 	if (KErrNone != err)
       
  4331 	{
       
  4332 		LOG_MSG2("Error %d reading memory at address %x", address);
       
  4333 		return EFalse;
       
  4334 	}
       
  4335 
       
  4336 	const TUint32 movePCToLRIgnoringCondition = 0x01A0E00F;
       
  4337 
       
  4338 	TUint32 inst = *(TUint32 *)previousInstruction.Ptr();
       
  4339 	
       
  4340 	if ((inst & 0x0FFFFFFF) == movePCToLRIgnoringCondition)
       
  4341 	{
       
  4342 		return ETrue;
       
  4343 	}
       
  4344 		
       
  4345 	return EFalse;
       
  4346 }
       
  4347 
       
  4348 //
       
  4349 // DMetroTrkChannel::DoEnableDisabledBreak
       
  4350 //
       
  4351 // Restore the breakpoint that was disabled for stepping past it if necessary
       
  4352 //
       
  4353 TInt DMetroTrkChannel::DoEnableDisabledBreak(TUint32 aThreadId)
       
  4354 {
       
  4355 	LOG_MSG("DMetroTrkChannel::DoEnableDisabledBreak()");
       
  4356 		
       
  4357 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
       
  4358 	{
       
  4359 //	    if (iBreakPointList[i].iDisabledForStep && ((iBreakPointList[i].iThreadId == aThreadId) || (iBreakPointList[i].iThreadId == 0xFFFFFFFF)))
       
  4360 	    //  Always re-enable non-Thread Specific breakpoints
       
  4361 		if (iBreakPointList[i].iDisabledForStep && ((iBreakPointList[i].iThreadId == aThreadId) || (iBreakPointList[i].iThreadSpecific == EFalse)))
       
  4362 		{
       
  4363 			LOG_MSG2("Re-enabling breakpoint at address %x", iBreakPointList[i].iAddress);
       
  4364 			iBreakPointList[i].iDisabledForStep = EFalse;
       
  4365 			return DoEnableBreak(iBreakPointList[i], EFalse);
       
  4366 		}		
       
  4367 	}
       
  4368 	
       
  4369 	return KErrNone;
       
  4370 }
       
  4371 
       
  4372 //
       
  4373 // DMetroTrkChannel::IsExecuted
       
  4374 //
       
  4375 // Determines whether or not an instruction will be executed
       
  4376 //
       
  4377 TBool DMetroTrkChannel::IsExecuted(TUint8 aCondition ,TUint32 aStatusRegister)
       
  4378 {
       
  4379 	LOG_MSG("DMetroTrkChannel::IsExecuted()");
       
  4380 
       
  4381 	TBool N = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000008;
       
  4382 	TBool Z = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000004;
       
  4383 	TBool C = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000002;
       
  4384 	TBool V = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000001;
       
  4385 
       
  4386 	switch(aCondition)
       
  4387 	{
       
  4388 		case 0:
       
  4389 			return Z;
       
  4390 		case 1:
       
  4391 			return !Z;
       
  4392 		case 2:
       
  4393 			return C;
       
  4394 		case 3:
       
  4395 			return !C;
       
  4396 		case 4:
       
  4397 			return N;
       
  4398 		case 5:
       
  4399 			return !N;
       
  4400 		case 6:
       
  4401 			return V;
       
  4402 		case 7:
       
  4403 			return !V;
       
  4404 		case 8:
       
  4405 			return (C && !Z);
       
  4406 		case 9:
       
  4407 			return (!C || Z);
       
  4408 		case 10:
       
  4409 			return (N == V);
       
  4410 		case 11:
       
  4411 			return (N != V);
       
  4412 		case 12:
       
  4413 			return ((N == V) && !Z);
       
  4414 		case 13:
       
  4415 			return (Z || (N != V));
       
  4416 		case 14:
       
  4417 		case 15:
       
  4418 			return ETrue;
       
  4419 	}
       
  4420 	
       
  4421 	return EFalse;
       
  4422 }
       
  4423 
       
  4424 
       
  4425 TBool DMetroTrkChannel::IsAddressInRom(TUint32 aAddress)
       
  4426 {
       
  4427 	LOG_MSG("DMetroTrkChannel::IsAddressInRom()");
       
  4428 	
       
  4429 	TRomHeader romHeader = Epoc::RomHeader();
       
  4430 	
       
  4431 	if ((aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iRomSize)))
       
  4432 		return ETrue;
       
  4433 	
       
  4434 	return EFalse;
       
  4435 }
       
  4436 
       
  4437 TBool DMetroTrkChannel::IsAddressSecure(TUint32 aAddress)
       
  4438 {
       
  4439 	LOG_MSG("DMetroTrkChannel::IsAddressInRom()");
       
  4440 	
       
  4441 	// SHORT TERM FIX...
       
  4442 	// For now, don't allow access to Kernel memory...
       
  4443 	TLinAddr kernDataStartAddr =  iMultipleMemModel ? KSuperPageMultipleLinAddr: KSuperPageMovingLinAddr;
       
  4444 	TLinAddr kernDataEndAddr = iMultipleMemModel ? KKernDataEndMultipleLinAddr: KKernDataEndMovingLinAddr;
       
  4445 	
       
  4446 	if ((aAddress >= kernDataStartAddr) && (aAddress <= kernDataEndAddr))
       
  4447 		return ETrue;
       
  4448 		
       
  4449 	return EFalse;
       
  4450 }
       
  4451 
       
  4452 TBool DMetroTrkChannel::IsRegisterSecure(TInt registerIndex)
       
  4453 {	
       
  4454 	LOG_MSG("DMetroTrkChannel::IsRegisterSecure()");
       
  4455 		
       
  4456 	if (registerIndex == SP_REGISTER || registerIndex == LINK_REGISTER || registerIndex == STATUS_REGISTER)
       
  4457 		return ETrue;
       
  4458 		
       
  4459 	return EFalse;
       
  4460 }
       
  4461 
       
  4462 //
       
  4463 // DMetroTrkChannel::AllocateShadowPageIfNecessary
       
  4464 //
       
  4465 // Allocate a shadow page if the address is in ROM and no page has been allocated for that range yet
       
  4466 //
       
  4467 TInt DMetroTrkChannel::AllocateShadowPageIfNecessary(TUint32 aAddress, TUint32 &aPageAddress)
       
  4468 {
       
  4469 	LOG_MSG("DMetroTrkChannel::AllocateShadowPageIfNecessary()");
       
  4470 
       
  4471 	// if this is in ROM, we need to shadow memory
       
  4472 	TBool inRom = EFalse;
       
  4473 	
       
  4474 	//find out if M::IsRomAddress is available from ekern or any other library
       
  4475 	//ReturnIfError(inRom = M::IsRomAddress((TAny *)aAddress));
       
  4476 	TRomHeader romHeader = Epoc::RomHeader();
       
  4477 	
       
  4478 	if ((aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iRomSize)))
       
  4479 		inRom = ETrue;
       
  4480 
       
  4481 	TInt err = KErrNone;
       
  4482 	
       
  4483 	if (inRom) // && (TSuperPage().iRomConfig[0].iType != KBdbBankTypeRamAsRom))
       
  4484 	{
       
  4485 		// if a shadow page has not already been allocated for this address range, do so now
       
  4486 		TUint32 pageAddress = (aAddress & ~(iPageSize-1));
       
  4487 		
       
  4488 		TBool found = EFalse;
       
  4489 		for (TInt i=0; i<iBreakPointList.Count(); i++)
       
  4490 		{
       
  4491 			if (pageAddress == iBreakPointList[i].iPageAddress)
       
  4492 			{
       
  4493 				LOG_MSG2("Shadow page already allocated at address %x", pageAddress);
       
  4494 				found = ETrue;
       
  4495 			}
       
  4496 		}
       
  4497 
       
  4498 		if (!found)
       
  4499 		{
       
  4500 			LOG_MSG2("Allocating shadow page starting at address %x", pageAddress);
       
  4501 			err = Epoc::AllocShadowPage(pageAddress);
       
  4502 			if (KErrNone != err)
       
  4503 			{
       
  4504 				LOG_MSG2("Error %d allocating shadow page", err);
       
  4505 				return KErrGeneral;
       
  4506 			}
       
  4507 
       
  4508 			//check to see if this is still necessary
       
  4509 			//if ((ASSPID() & ASSP_ID_MASK) == XSCALE_ASSP_ID)
       
  4510 				//FlushDataCache(); // workaround for cache flush problem on Lubbock/PXA255 base port
       
  4511 		}
       
  4512 		
       
  4513 		// return the page address
       
  4514 		aPageAddress = pageAddress;
       
  4515 	}
       
  4516 
       
  4517 	return err;
       
  4518 }
       
  4519 
       
  4520 //
       
  4521 // DMetroTrkChannel::FreeShadowPageIfNecessary
       
  4522 //
       
  4523 // Free a shadow page if the address is in ROM and no no other breakpoints are set in that page range
       
  4524 //
       
  4525 TInt DMetroTrkChannel::FreeShadowPageIfNecessary(TUint32 aAddress, TUint32 aPageAddress)
       
  4526 {
       
  4527 	LOG_MSG("DMetroTrkChannel::FreeShadowPageIfNecessary()");
       
  4528 
       
  4529 	TInt err = KErrNone;
       
  4530 	
       
  4531 	TBool found = EFalse;
       
  4532 
       
  4533 	TBool inRom = EFalse;
       
  4534 	
       
  4535 	//find out if M::IsRomAddress is available from ekern or any other library
       
  4536 	//ReturnIfError(inRom = M::IsRomAddress((TAny *)aAddress));
       
  4537 	TRomHeader romHeader = Epoc::RomHeader();
       
  4538 	
       
  4539 	if ((aAddress >= romHeader.iRomBase ) && (aAddress < (romHeader.iRomBase + romHeader.iRomSize)))
       
  4540 		inRom = ETrue;
       
  4541 	
       
  4542 	if (inRom)// && (TSuperPage().iRomConfig[0].iType != KBdbBankTypeRamAsRom))
       
  4543 	{
       
  4544 		// if there are no other breakpoints in this shadow page, we can free it now
       
  4545 		for (TInt i = 0; i < iBreakPointList.Count(); i++)
       
  4546 		{
       
  4547 			if (aAddress != iBreakPointList[i].iAddress) // ignore the current entry
       
  4548 			{
       
  4549 				if ((iBreakPointList[i].iAddress >= aPageAddress) &&
       
  4550 					(iBreakPointList[i].iAddress < (aPageAddress + iPageSize)))
       
  4551 				{
       
  4552 					LOG_MSG("Still a breakpoint in this shadow page range");
       
  4553 					found = ETrue;
       
  4554 					break;
       
  4555 				}
       
  4556 			}
       
  4557 		}
       
  4558 
       
  4559 		if (!found)
       
  4560 		{
       
  4561 			LOG_MSG2("Freeing shadow page starting at address %x", aPageAddress);
       
  4562 			err = Epoc::FreeShadowPage(aPageAddress);
       
  4563 			if (KErrNone != err)
       
  4564 			{
       
  4565 				LOG_MSG2("Error %d freeing shadow page", err);
       
  4566 				return KErrGeneral;
       
  4567 			}
       
  4568 		}
       
  4569 	}
       
  4570 
       
  4571 	return err;
       
  4572 }
       
  4573 
       
  4574 
       
  4575 
       
  4576 //
       
  4577 // DMetroTrkChannel::NotifyEvent
       
  4578 //
       
  4579 void DMetroTrkChannel::NotifyEvent(SEventInfo aEventInfo, TBool isTraceEvent)
       
  4580 {
       
  4581 	LOG_MSG("DMetroTrkChannel::NotifyEvent()");
       
  4582 	
       
  4583 	if (iEventInfo)
       
  4584 	{
       
  4585 		LOG_MSG2("Completing event, type: %d", aEventInfo.iEventType);
       
  4586 		
       
  4587 		// iThread is the user side debugger thread, so use it to write the info to it memory
       
  4588 		TInt err = Kern::ThreadRawWrite(iClientThread, iEventInfo, (TUint8 *)&aEventInfo, sizeof(SEventInfo), iClientThread);
       
  4589 
       
  4590 		if (KErrNone != err)
       
  4591 			LOG_MSG2("Error writing event info: %d", err);
       
  4592 
       
  4593 		// clear this since we've completed the request
       
  4594 		iEventInfo = NULL;
       
  4595 		
       
  4596 		// signal the debugger thread
       
  4597 		Kern::RequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
       
  4598 	}
       
  4599 	else
       
  4600 	{
       
  4601 		if (isTraceEvent)
       
  4602 		{
       
  4603 			LOG_MSG("Queuing trace event\r\n");
       
  4604 
       
  4605 			for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
  4606 			{
       
  4607 				if (SEventInfo::EUnknown == iTraceEventQueue[i].iEventType)
       
  4608 				{
       
  4609 					iTraceEventQueue[i] = aEventInfo;
       
  4610 					break;
       
  4611 				}
       
  4612 			}			
       
  4613 		}
       
  4614 		else
       
  4615 		{
       
  4616 			LOG_MSG2("Queuing event, type: %d", aEventInfo.iEventType);
       
  4617 			
       
  4618 			for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
       
  4619 			{
       
  4620 				if (SEventInfo::EUnknown == iEventQueue[i].iEventType)
       
  4621 				{
       
  4622 					iEventQueue[i] = aEventInfo;
       
  4623 					break;
       
  4624 				}
       
  4625 			}			
       
  4626 		}		
       
  4627 	}
       
  4628 }
       
  4629 
       
  4630 
       
  4631 //
       
  4632 // DMetroTrkChannel::ThreadFromId
       
  4633 //
       
  4634 DThread* DMetroTrkChannel::ThreadFromId(TUint32 aId)
       
  4635 {
       
  4636 	LOG_MSG("DMetroTrkChannel::ThreadFromId()");
       
  4637 	
       
  4638 	NKern::ThreadEnterCS();  // Prevent us from dying or suspending whilst holding a DMutex
       
  4639 	DObjectCon& threads = *Kern::Containers()[EThread];  // Get containing holding threads
       
  4640 	threads.Wait();  // Obtain the container mutex so the list does get changed under us
       
  4641 	
       
  4642 	DThread* thread = Kern::ThreadFromId(aId);
       
  4643 	
       
  4644 	threads.Signal();  // Release the container mutex
       
  4645 	NKern::ThreadLeaveCS();  // End of critical section
       
  4646 	
       
  4647 	return thread;
       
  4648 }
       
  4649 
       
  4650 //
       
  4651 // DMetroTrkChannel::ProcessFromId
       
  4652 //
       
  4653 DProcess* DMetroTrkChannel::ProcessFromId(TUint32 aId)
       
  4654 {
       
  4655 	LOG_MSG("DMetroTrkChannel::ProcessFromId()");
       
  4656 	
       
  4657 	NKern::ThreadEnterCS();  // Prevent us from dying or suspending whilst holding a DMutex
       
  4658 	DObjectCon& processes = *Kern::Containers()[EProcess];  // Get containing holding threads
       
  4659 	processes.Wait();  // Obtain the container mutex so the list does get changed under us
       
  4660 	
       
  4661 	DProcess* process = Kern::ProcessFromId(aId);
       
  4662 	
       
  4663 	processes.Signal();  // Release the container mutex
       
  4664 	NKern::ThreadLeaveCS();  // End of critical section
       
  4665 	
       
  4666 	return process;
       
  4667 }
       
  4668 
       
  4669 //
       
  4670 // DMetroTrkChannel::GetSystemThreadRegisters
       
  4671 //
       
  4672 TBool DMetroTrkChannel::GetSystemThreadRegisters(TArmRegSet* aArmRegSet)
       
  4673 {
       
  4674 	if (iExcInfoValid)
       
  4675 	{
       
  4676 		aArmRegSet->iR0 = iCurrentExcInfo.iR0;
       
  4677 		aArmRegSet->iR1 = iCurrentExcInfo.iR1;
       
  4678 		aArmRegSet->iR2 = iCurrentExcInfo.iR2;
       
  4679 		aArmRegSet->iR3 = iCurrentExcInfo.iR3;
       
  4680 		aArmRegSet->iR4 = iCurrentExcInfo.iR4;
       
  4681 		aArmRegSet->iR5 = iCurrentExcInfo.iR5;
       
  4682 		aArmRegSet->iR6 = iCurrentExcInfo.iR6;		
       
  4683 		aArmRegSet->iR7 = iCurrentExcInfo.iR7;		
       
  4684 		aArmRegSet->iR8 = iCurrentExcInfo.iR8;		
       
  4685 		aArmRegSet->iR9 = iCurrentExcInfo.iR9;	
       
  4686 		aArmRegSet->iR10 = iCurrentExcInfo.iR10;
       
  4687 		aArmRegSet->iR11 = iCurrentExcInfo.iR11;
       
  4688 		aArmRegSet->iR12 = iCurrentExcInfo.iR12;
       
  4689 		aArmRegSet->iR13 = iCurrentExcInfo.iR13;		
       
  4690 		aArmRegSet->iR14 = iCurrentExcInfo.iR14;		
       
  4691 		aArmRegSet->iR15 = iCurrentExcInfo.iR15;		
       
  4692 		aArmRegSet->iFlags = iCurrentExcInfo.iCpsr;
       
  4693 		
       
  4694 		return ETrue;				
       
  4695 	}
       
  4696 	
       
  4697 	return EFalse;
       
  4698 
       
  4699 }
       
  4700 
       
  4701 TBool DMetroTrkChannel::HasManufacturerCaps(DThread* aThread)
       
  4702 {
       
  4703 	if (aThread && (aThread->HasCapability(ECapabilityTCB) || 
       
  4704 		    		aThread->HasCapability(ECapabilityDRM) || 
       
  4705 					aThread->HasCapability(ECapabilityAllFiles)))
       
  4706 	{				
       
  4707 		return ETrue;
       
  4708 	}
       
  4709 	return EFalse;
       
  4710 }
       
  4711 
       
  4712 TBool DMetroTrkChannel::IsBeingDebugged(const DThread* aThread)
       
  4713 {	
       
  4714 	TBool isDebugging = EFalse;	
       
  4715 	if (aThread)
       
  4716 	{
       
  4717 		for (TInt i = 0; i < iDebugProcessList.Count(); i++)
       
  4718 		{
       
  4719 			if (iDebugProcessList[i].iId == aThread->iOwningProcess->iId)
       
  4720 			{
       
  4721 				isDebugging = ETrue;
       
  4722 				break;
       
  4723 			}
       
  4724 		}
       
  4725 	}
       
  4726 	return isDebugging;
       
  4727 }
       
  4728 
       
  4729 void DMetroTrkChannel::CheckLibraryNotifyList(TUint32 aProcessId)
       
  4730 {   
       
  4731 	SDblQue* codeSegList = Kern::CodeSegList();
       
  4732 
       
  4733 	for (TInt i=0; i<iLibraryNotifyList.Count(); i++)
       
  4734 	{	
       
  4735 		if (!iLibraryNotifyList[i].iEmptySlot)
       
  4736 		{
       
  4737 			//iterate through the list
       
  4738 			for (SDblQueLink* codeSegPtr = codeSegList->First(); codeSegPtr != (SDblQueLink*)(codeSegList); codeSegPtr = codeSegPtr->iNext)
       
  4739 			{
       
  4740 				DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr, DCodeSeg, iLink);   
       
  4741 				if (codeSeg && codeSeg->IsDll())
       
  4742 				{
       
  4743 					SEventInfo info;						
       
  4744 					if (!_strnicmp(iLibraryNotifyList[i].iName.Ptr(), codeSeg->iRootName.Ptr(), codeSeg->iRootName.Length()))
       
  4745 					{
       
  4746 						info.iFileName.Copy((codeSeg->iRootName.Ptr())); 
       
  4747 						LOG_MSG2("library name match: %S", &info.iFileName);
       
  4748 						TModuleMemoryInfo memoryInfo;
       
  4749 						TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
       
  4750 						if (err != KErrNone)
       
  4751 				  		{
       
  4752 				       		break;
       
  4753 				   		}
       
  4754 				   		// 
       
  4755 				   		// check the process id from the DCodeSeg instead of using aProcessId
       
  4756 				   		// if the iAttachProcess from DCodeSeg is null, then we should use aProcessId
       
  4757 						info.iProcessId = aProcessId;
       
  4758 						info.iEventType = SEventInfo::ELibraryLoaded; 
       
  4759 						info.iCodeAddress = memoryInfo.iCodeBase;
       
  4760 						info.iDataAddress = memoryInfo.iInitialisedDataBase;
       
  4761 						info.iThreadId = 0xFFFFFFFF; 
       
  4762 						LOG_MSG2("info.iCodeAddress: %x", info.iCodeAddress);
       
  4763 						LOG_MSG2("info.iDataAddress: %x", info.iDataAddress);
       
  4764 						LOG_MSG2("info.iProcessId: %d", info.iProcessId);
       
  4765 						NotifyEvent(info);
       
  4766 						
       
  4767 						// now reset this entry					
       
  4768 						iLibraryNotifyList[i].iEmptySlot = ETrue;
       
  4769 						break;
       
  4770 					}
       
  4771 				}
       
  4772 			}
       
  4773 		}
       
  4774 	}
       
  4775 }
       
  4776 
       
  4777 DECLARE_STANDARD_LDD()
       
  4778 {
       
  4779     return new DMetroTrkDriverFactory;
       
  4780 }