os/kernelhwsrv/kernel/eka/drivers/debug/rmdebug/d_rmd_breakpoints.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 
    17 #include <e32def.h>
    18 #include <e32def_private.h>
    19 #include <e32cmn.h>
    20 #include <e32cmn_private.h>
    21 #include <u32std.h>
    22 #include <kernel/kernel.h>
    23 #include <kernel/kern_priv.h>
    24 #include <nk_trace.h>
    25 #include <arm.h>
    26 #include <kernel/cache.h>
    27 #include <platform.h>
    28 #include <nkern.h>
    29 #include <u32hal.h>
    30 
    31 #include <rm_debug_api.h>
    32 #include <sm_debug_api.h>
    33 #include "d_rmd_breakpoints.h"
    34 #include "d_process_tracker.h"
    35 #include "d_rmd_stepping.h"
    36 #include "rm_debug_kerneldriver.h"	// needed to access DRM_DebugChannel
    37 #include "rm_debug_driver.h"
    38 #include "debug_utils.h"
    39 #include "debug_logging.h"
    40 
    41 using namespace Debug;
    42 
    43 /* @internalTechnology
    44  *
    45  * Checks whether aAddress is correctly aligned for placing a breakpoint of
    46  * cpu architecture aMode.
    47  *
    48  * @param aAddress - Virtual memory address to check
    49  * @param aMode - The CPU architecture mode of the breakpoint to be placed at aAddress
    50  * @return ETrue if aAddress is suitably aligned, EFalse otherwise.
    51  */
    52 TBool D_RMD_Breakpoints::Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode)
    53 	{
    54 	switch(aMode)
    55 		{
    56 		case Debug::EArmMode:
    57 			// ARM breakpoints must be 32-bit aligned (lower two bits must be zero)
    58 			if (aAddress & 0x3)
    59 			{
    60 				// Not 32-bit aligned.
    61 				return EFalse;
    62 			}
    63 			break;
    64 		case Debug::EThumbMode:
    65 			// Thumb breakpoints must be 16-bit aligned (low bit must be zero)
    66 			if (aAddress & 0x1)
    67 			{
    68 				// Not 16-bit aligned
    69 				return EFalse;
    70 			}
    71 			break;
    72 		case Debug::EThumb2EEMode:
    73 			// Thumb-EE instructions are half-word aligned. See ARM ARM DDI0406A, section A3.2 Alignment Support
    74 			// Note that some instructions need to be word-aligned, but this function does not know which ones.
    75 			// It may also depend on the System Control register U bit.
    76 			if (aAddress & 0x1)
    77 			{
    78 				// Not 16-bit aligned
    79 				return EFalse;
    80 			}
    81 			break;
    82 		default:
    83 			{
    84 			// No idea
    85 			return EFalse;
    86 			}
    87 		}
    88 
    89 	// Must be OK
    90 	return ETrue;
    91 	};
    92 
    93 /* @internalTechnology
    94  *
    95  * Returns the size of a breakpoint of architecture aMode in bytes
    96  * 
    97  * @param aMode - The architure of the breakpoint
    98  * @return The size of the breakpoints in bytes. 0 if un-recognised architecture.
    99  */
   100 TInt D_RMD_Breakpoints::BreakSize(Debug::TArchitectureMode aMode)
   101 	{
   102 	switch(aMode)
   103 		{
   104 		case Debug::EArmMode:
   105 			{
   106 				return 4;
   107 			}
   108 		case Debug::EThumbMode:
   109 			{
   110 				return 2;
   111 			}
   112 		case Debug::EThumb2EEMode:
   113 			{
   114 			// Only needs to be two bytes in size.
   115 			return 2;
   116 			}
   117 		default:
   118 			{
   119 				// No idea
   120 				return 0;
   121 			}
   122 		}
   123 	};
   124 
   125 /* @internalTechnology
   126  *
   127  * Checks whether two TBreakEntrys overlap
   128  *
   129  * @param aFirst - A TBreakEntry with valid iAddress and iMode fields.
   130  * @param aSecond  - A TBreakEntry with valid iAddress and iMode fields.
   131  * @return ETrue if the aFirst and aSecond overlap or the overlap cannot be determined
   132  *         , EFalse otherwise
   133  */
   134 TBool D_RMD_Breakpoints::BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond)
   135 	{
   136 	TInt firstSize = BreakSize(aFirst.iMode);
   137 	TInt secondSize = BreakSize(aSecond.iMode);
   138 
   139 	// Do we know the size of each breakpoint?
   140 	if ((firstSize <= 0) || (secondSize <= 0))
   141 		{
   142 		// We don't know the size of the breakpoint, so assume they overlap
   143 		return ETrue;
   144 		}
   145 
   146 	TInt firstStartAddress = aFirst.iAddress;
   147 	TInt secondStartAddress = aSecond.iAddress;
   148 	TInt firstEndAddress = firstStartAddress + firstSize - 1;
   149 	TInt secondEndAddress = secondStartAddress + secondSize - 1;
   150 
   151 	// If second breakpoint is past the end of the first then we're ok
   152 	if(firstEndAddress < secondStartAddress)
   153 		{
   154 		return EFalse;
   155 		}
   156 
   157 	// If first breakpoint is past the end of the second then we're ok
   158 	if(secondEndAddress < firstStartAddress)
   159 		{
   160 		return EFalse;
   161 		}
   162 
   163 	// The breakpoints overlap
   164 	return ETrue;
   165 	}
   166 
   167 /* @internalTechnology
   168  * 
   169  * Returns the breakpoint bitpattern to use for each architecture type
   170  *
   171  * @param aMode - the cpu architecture type
   172  * @return The bit-pattern to use for the specified architecture, or 0 if unsupported.
   173  */
   174 TUint32 D_RMD_Breakpoints::BreakInst(Debug::TArchitectureMode aMode)
   175 	{
   176 	switch(aMode)
   177 		{
   178 		case Debug::EArmMode:
   179 			{
   180 				return KArmBreakPoint;
   181 			}
   182 		case Debug::EThumbMode:
   183 			{
   184 				return KThumbBreakPoint;
   185 			}
   186 		case Debug::EThumb2EEMode:
   187 			{
   188 			return KT2EEBreakPoint;
   189 			}
   190 		default:
   191 			{
   192 				// No idea what the breakpoint should be
   193 				return 0;
   194 			}
   195 		}
   196 	};
   197 
   198 /**
   199 Constructor. Initialises its internal list of empty breakpoints.
   200 */
   201 D_RMD_Breakpoints::D_RMD_Breakpoints(DRM_DebugChannel* aChannel)
   202 : iBreakPointList(NUMBER_OF_TEMP_BREAKPOINTS, 0),
   203   iNextBreakId(NUMBER_OF_TEMP_BREAKPOINTS),
   204   iChannel(aChannel),
   205   iInitialised(EFalse)
   206 	{
   207 	iBreakPointList.Reset();	
   208 	TBreakEntry emptyTempBreak;
   209 	
   210 	for (TInt i = 0; i < NUMBER_OF_TEMP_BREAKPOINTS; i++)
   211 		{
   212 		emptyTempBreak.iBreakId = i;
   213 		
   214 		if (KErrNone != iBreakPointList.Append(emptyTempBreak))
   215 			{
   216 			LOG_MSG("D_RMD_Breakpoints::D_RMD_Breakpoints() - Error appending blank temp break entry");
   217 			}
   218 		}
   219 	}
   220 
   221 /**
   222 Destructor. Clears all the breakpoints in the system, deletes its internal list of breakpoints,
   223 and closes the exclusivity semaphore.
   224 */
   225 D_RMD_Breakpoints::~D_RMD_Breakpoints()
   226 	{
   227 	ClearAllBreakPoints();
   228 	
   229 	// close the breakpoint list and free the memory associated with it
   230 	iBreakPointList.Close();
   231 
   232 	if (iLock)
   233 		iLock->Close(NULL);
   234 	}
   235 
   236 /**
   237 Initialises the breakpoint list exclusion semaphore. This should be called once immediately after
   238 the constructor.
   239 
   240 @return KErrNone if successful, one of the other system wide error codes otherwise.
   241 */
   242 TInt D_RMD_Breakpoints::Init()
   243 	{
   244 	TInt err = KErrNone;
   245 
   246 	// Only create a semaphore if we are not initialised
   247 	if(!iInitialised)
   248 		{
   249 		// Initialise the semaphore ensuring exclusive access to the breakpoint list
   250 		err = Kern::SemaphoreCreate(iLock, _L("RM_DebugBreakpointLock"), 1 /* Initial count */);
   251 		if (err == KErrNone)
   252 			{
   253 			iInitialised = ETrue;
   254 			}
   255 		}
   256 	else
   257 		{
   258 		err = KErrNone;
   259 		}
   260 
   261 	return err;
   262 	}
   263 
   264 /** 
   265 Public member function which sets a thread-specific breakpoint in the specified thread
   266 and returns an opaque handle to the caller.
   267 
   268 Note 1:
   269 This function ensures exclusive access to the breakpoint data structures
   270 by using a semaphore to serialise access.
   271 
   272 @see priv_DoSetBreak
   273 
   274 Note 2:
   275 As implied by Note 1, the caller must have previously called Init() or this
   276 function will return KErrNotReady;
   277  
   278 @param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
   279 @param aThreadId - The thread Id in which to place the breakpoint
   280 @param aAddress - Address to place the breakpoint
   281 @param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
   282 @return KErrNone if successful, otherwise one of the other system wide error codes.
   283 */
   284 TInt D_RMD_Breakpoints::DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
   285 	{
   286 	// Ensure we have a valid semaphore
   287 	if (!iInitialised || !iLock)
   288 		{
   289 		return KErrNotReady;
   290 		}
   291 
   292 	// Acquire the lock
   293 	NKern::ThreadEnterCS();
   294 	Kern::SemaphoreWait(*iLock);
   295 
   296 	// Really do the work
   297 	TInt err = priv_DoSetBreak(aBreakId, aId, aThreadSpecific, aAddress,aMode);
   298 	
   299 	// Release the lock
   300 	Kern::SemaphoreSignal(*iLock);
   301 	NKern::ThreadLeaveCS();
   302 	
   303 	return err;
   304 	}
   305 /**
   306 Private member function which sets a thread-specific breakpoint in the specified thread
   307 and returns an opaque handle to the caller.
   308 
   309 @see DoSetBreak
   310 
   311 @param aBreakId - Reference to a TUint32 into which the function will return a unique breakpoint Id.
   312 @param aThreadId - The thread Id in which to place the breakpoint
   313 @param aAddress - Address to place the breakpoint
   314 @param aMode - The cpu instruction set architecture type breakpoint (e.g. EArmMode or EThumbMode)
   315 @return KErrNone if successful, otherwise one of the other system wide error codes.
   316 */
   317 TInt D_RMD_Breakpoints::priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
   318 	{
   319 	LOG_MSG4("D_RMD_Breakpoints::priv_DoSetBreak(aThreadId = 0x%016lx, aAddress = 0x%08x, aMode = %d)",aId,aAddress,aMode);
   320 
   321 	// EThumb2EEMode breakpoints are not supported
   322 	if (EThumb2EEMode == aMode)
   323 		{
   324 		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - EThumb2EEMode breakpoints are not supported");
   325 		return KErrNotSupported;
   326 		}
   327 
   328 	// Check how many breakpoints we have in existence
   329 	if ((iBreakPointList.Count()+1) >= NUMBER_OF_MAX_BREAKPOINTS)
   330 		{
   331 		// Too many breakpoints are set!
   332 		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Too many breakpoints set");
   333 		return KErrOverflow;
   334 		}
   335 
   336 	// check the alignment of the breakpoint
   337 	if (!Aligned(aAddress,aMode))
   338 		{
   339 		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unaligned address");
   340 		return KErrArgument;
   341 		}
   342 
   343 	// make sure there is not already a breakpoint at this address
   344 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
   345 		{
   346 		/* We need to check if the breakpoint overlaps the address at all,
   347 		 * and this depends upon the size of the two breakpoints as well as 
   348 		 * their address.
   349 		 */
   350 
   351 		// newInstSize = size in bytes of new breakpoint
   352 		TInt newInstSize = BreakSize(aMode);
   353 		if (newInstSize == 0)
   354 			{
   355 			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unknown architecture type for new breakpoint");
   356 			return KErrNotSupported;
   357 			}
   358 
   359 		// oldInstSize = size in bytes of the existing breakpoint
   360 		TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
   361 		if (oldInstSize == 0)
   362 			{
   363 			LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - : Unknown architecture type of existing breakpoint");
   364 			return KErrNotSupported;
   365 			}
   366 
   367 		// Overlap checking - temp is used as the new breakpoint description for checking purposes only
   368 		TBreakEntry temp;
   369 
   370 		temp.iAddress = aAddress;
   371 		temp.iMode = aMode;
   372 
   373 		// do they overlap?
   374 		if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
   375 			{
   376 			// Yes
   377 			if(iBreakPointList[i].iThreadSpecific && aThreadSpecific)
   378 				{
   379 				if(aId == iBreakPointList[i].iId)
   380 					{
   381 					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing thread specific breakpoint");
   382 					return KErrAlreadyExists;
   383 					}
   384 				}
   385 			else if(!iBreakPointList[i].iThreadSpecific && aThreadSpecific)
   386 				{
   387 				DThread* thread = DebugUtils::OpenThreadHandle(aId);
   388 				if(!thread)
   389 					{
   390 					return KErrNotFound;
   391 					}
   392 				if(thread->iOwningProcess->iId == iBreakPointList[i].iId)
   393 					{
   394 					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing breakpoint");
   395 					thread->Close(NULL);
   396 					return KErrAlreadyExists;
   397 					}
   398 				thread->Close(NULL);
   399 				}
   400 			else if(iBreakPointList[i].iThreadSpecific && !aThreadSpecific)
   401 				{
   402 				DThread* thread = DebugUtils::OpenThreadHandle(iBreakPointList[i].iId);
   403 				if(!thread)
   404 					{
   405 					return KErrNotFound;
   406 					}
   407 				if(thread->iOwningProcess->iId == aId)
   408 					{
   409 					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing thread specific breakpoint");
   410 					thread->Close(NULL);
   411 					return KErrAlreadyExists;
   412 					}
   413 				thread->Close(NULL);
   414 				}
   415 			else // !iBreakPointList[i].iThreadSpecific && !aThreadSpecific
   416 				{
   417 				if(iBreakPointList[i].iId == aId)
   418 					{
   419 					LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing breakpoint");
   420 					return KErrAlreadyExists;
   421 					}
   422 				}
   423 			}
   424 		}
   425 
   426 	// increment the break id
   427 	aBreakId = iNextBreakId++;	
   428 
   429 	// create the new breakpoint entry
   430 	TBreakEntry breakEntry(aBreakId, aId, aThreadSpecific, aAddress, aMode);
   431 
   432 	TInt err = priv_DoEnableBreak(breakEntry, ETrue);
   433 	if (KErrNone != err)
   434 		{
   435 		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Could not enable the breakpoint");
   436 		
   437 		return err;
   438 		}
   439 
   440 	err = iBreakPointList.Append(breakEntry);
   441 	if (err != KErrNone)
   442 		{
   443 		LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Failed to append breakpoint");
   444 		}
   445 
   446 	LOG_MSG2("D_RMD_Breakpoints::priv_DoSetBreak(breakId = 0x%08x) done",aBreakId);
   447 
   448 	return err;
   449 	}
   450 
   451 /**
   452 Public member function which enables a previously set breakpoint.
   453 
   454 Note 1:
   455 This function ensures exclusive access to the breakpoint data structures
   456 by using a semaphore to serialise access.
   457 
   458 @see priv_DoEnableBreak
   459 
   460 Note 2:
   461 As implied by Note 1, the caller must have previously called Init() or this
   462 function will return KErrNotReady;
   463 
   464 Note 3
   465 Historically, this function accepted a reference to a TBreakEntry in the class' own
   466 iBreakPointList. It now checks whether the reference is to an element of its own list,
   467 or one invented by the caller.
   468 
   469 @param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
   470 @param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
   471 @return KErrNone if successful, otherwise one of the other system wide error codes.
   472 */
   473 TInt D_RMD_Breakpoints::DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
   474 	{
   475 	// Ensure we have a valid semaphore
   476 	if (!iInitialised || !iLock)
   477 		{
   478 		return KErrNotReady;
   479 		}
   480 
   481 	// Acquire the lock
   482 	NKern::ThreadEnterCS();
   483 	Kern::SemaphoreWait(*iLock);
   484 
   485 	// Really do the work
   486 	TInt err = priv_DoEnableBreak(aEntry,aSaveOldInstruction);
   487 	
   488 	// Release the lock
   489 	Kern::SemaphoreSignal(*iLock);
   490 	NKern::ThreadLeaveCS();
   491 
   492 	return err;
   493 	}
   494 
   495 /**
   496 Private member function which enables a previously set breakpoint, as per DoEnableBreak, but
   497 does not serialise access.
   498 
   499 @see DoEnableBreak
   500 
   501 @param aEntry reference to a TBreakEntry datastructure describing the breakpoint to be re-enabled.
   502 @param aSaveOldInstruction ETrue preserves the instruction at the breakpoint address, EFalse otherwise.
   503 @return KErrNone if successful, otherwise one of the other system wide error codes.
   504 */
   505 TInt D_RMD_Breakpoints::priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
   506 	{
   507 	LOG_MSG("D_RMD_Breakpoints::DoEnableBreak()");
   508 
   509 	TUint32 inst = BreakInst(aEntry.iMode);	
   510 	TInt instSize = BreakSize(aEntry.iMode);
   511 	if (instSize == 0 || inst == 0)
   512 		{
   513 		// not supported
   514 		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - unsupported breakpoint architecture");
   515 		return KErrNotSupported;
   516 		}
   517 
   518 	TInt err = KErrNone;
   519 
   520 	// Get thread id
   521 	TUint64 threadId = aEntry.iId + (aEntry.iThreadSpecific ? 0 : 1);
   522 
   523 	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
   524 	if (!threadObj)
   525 		{
   526 		LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - bad handle. Could not identify a threadObj");
   527 		return KErrBadHandle;
   528 		}
   529 
   530 	if (aSaveOldInstruction)
   531 		{
   532 		TUint32 instruction;
   533 
   534 		// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
   535 		// trap exceptions in case the address is invalid
   536 		XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)aEntry.iAddress, (TAny *)&instruction, instSize));
   537 
   538 		//consider the leave as more important than the error code so store the leave if it's not KErrNone
   539 		if(KErrNone != r)
   540 			{
   541 			err = r;
   542 			}
   543 
   544 		if(KErrNone != err)
   545 			{
   546 			threadObj->Close(NULL);
   547 			LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak() - failed to read memory");
   548 			return err;
   549 			}
   550 
   551 		aEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
   552 		}
   553 
   554 	TBool breakpointAlredySet = EFalse;
   555 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
   556 		{
   557 		if(iBreakPointList[i].iAddress == aEntry.iAddress && !iBreakPointList[i].iDisabledForStep )
   558 			{
   559 			breakpointAlredySet = ETrue;
   560 			break;
   561 			}
   562 		}
   563 	if(!breakpointAlredySet)
   564 		{
   565 		XTRAPD(r, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, aEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
   566 		if(r != DebugSupport::EBreakpointGlobal)
   567 			{
   568 			err = r;
   569 			}
   570 		}
   571 
   572 	// Close the thread handle which has been opened by OpenThreadHandle
   573 	threadObj->Close(NULL);
   574 
   575 	return err;
   576 	}
   577 
   578 /**
   579 Public member function which clears a previously set breakpoint.
   580 
   581 Note 1:
   582 This function ensures exclusive access to the breakpoint data structures
   583 by using a semaphore to serialise access.
   584 
   585 @see priv_DoClearBreak
   586 
   587 Note 2:
   588 As implied by Note 1, the caller must have previously called Init() or this
   589 function will return KErrNotReady;
   590 
   591 @param aBreakId A breakpoint Id as previously returned by DoSetBreak.
   592 @return KErrNone if successful, otherwise one of the other system wide error codes.
   593 */
   594 TInt D_RMD_Breakpoints::DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
   595 	{
   596 	// Ensure we have a valid semaphore
   597 	if (!iInitialised || !iLock)
   598 		{
   599 		return KErrNotReady;
   600 		}
   601 
   602 	// Acquire the lock
   603 	NKern::ThreadEnterCS();
   604 	Kern::SemaphoreWait(*iLock);
   605 
   606 	// Really do the work
   607 	TInt err = priv_DoClearBreak(aBreakId, aIgnoreTerminatedThreads);
   608 	
   609 	// Release the lock
   610 	Kern::SemaphoreSignal(*iLock);
   611 	NKern::ThreadLeaveCS();
   612 
   613 	return err;
   614 	}
   615 
   616 /**
   617 Private member function which clears a previously set breakpoint, as per DoClearBreak, but
   618 does not serialise access.
   619 
   620 @see DoClearBreak
   621 
   622 @param aBreakId A breakpoint Id as previously returned by DoSetBreak.
   623 @return KErrNone if successful, otherwise one of the other system wide error codes.
   624 */
   625 TInt D_RMD_Breakpoints::priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
   626 	{
   627 	LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak(0x%08x)",aBreakId);
   628 
   629 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
   630 	TBreakEntry entry;
   631 	entry.iBreakId = aBreakId;
   632 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
   633 
   634 	TInt err = KErrNone;
   635 	if (index >= 0)
   636 		{
   637 		//only let the agent clear the break if they have previously suspended the thread
   638 		//iThreadSpecific value decides whether the the iBreakPointList.Id has a thread id(TID) or the process id(PID) 
   639 		//the assumption here that TID = PID + 1
   640 		if(!TheDProcessTracker.CheckSuspended((iBreakPointList[index].iId + (iBreakPointList[index].iThreadSpecific ? 0 : 1))))
   641 			{
   642 			LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Thread with id 0x%08x not suspended", iBreakPointList[index].iId);
   643 			// should be "return KErrInUse;" but not always possible, e.g. cleaning up threads which die after debugger disconnects
   644 			}
   645  		// if this breakpoint was set in a library and that library has already been unloaded, don't try to clear it
   646 		if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
   647 			{
   648 			DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId + (iBreakPointList[index].iThreadSpecific ? 0 : 1));
   649 			if (threadObj)
   650 				{
   651 				TBool needToCallCodeModifier = ETrue;
   652 				for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
   653 					{
   654 					if (i != index)
   655 						{
   656 						if ( BreakpointsOverlap(iBreakPointList[index],iBreakPointList[i]) )
   657 							{
   658 							needToCallCodeModifier = EFalse;
   659 							break;
   660 							}
   661 						}
   662 					}
   663 				if(needToCallCodeModifier)
   664 					{
   665 					XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
   666 					if (r != KErrNone)
   667 						{
   668 						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code trap harness returned error %d",r);
   669 						}
   670 
   671 				if (err != KErrNone)
   672 						{
   673 						LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code returned error %d",err);
   674 						}
   675 					err = (KErrNone == r) ? err : r;
   676 					}
   677 
   678 				// Close the thread handle opened by OpenThreadHandle
   679 				threadObj->Close(NULL);
   680 				}
   681 			else
   682 				{
   683 				err = KErrBadHandle;
   684 				}
   685 			}
   686 		
   687 		LOG_MSG4("D_RMD_Breakpoints::priv_DoClearBreak() - Clearing breakpoint at address: %x, err: %d, ignore terminated: %d", iBreakPointList[index].iAddress, err, aIgnoreTerminatedThreads?1:0);
   688 		if ((aIgnoreTerminatedThreads && KErrBadHandle == err) || KErrNone == err)
   689 			{
   690 			// if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
   691 			err = KErrNone;
   692 			if (index < NUMBER_OF_TEMP_BREAKPOINTS)
   693 				{
   694 				iBreakPointList[index].Reset();
   695 				}
   696 			else
   697 				{
   698 				LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak() - Removing breakpoint 0x%08x as breakid 0x%08x\n",index, entry.iBreakId);
   699 				iBreakPointList.Remove(index);
   700 				}			
   701 			}
   702 				
   703 		return err;
   704 		}
   705 
   706 	LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Break Id %d not found", aBreakId);
   707 
   708 	return KErrNotFound;
   709 	}
   710 
   711 /**
   712 Public member function which modifies a previously set breakpoint.
   713 
   714 Note 1:
   715 This function ensures exclusive access to the breakpoint data structures
   716 by using a semaphore to serialise access.
   717 
   718 @see priv_DoModifyBreak
   719 
   720 Note 2:
   721 As implied by Note 1, the caller must have previously called Init() or this
   722 function will return KErrNotReady;
   723 
   724 @param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
   725 @return KErrNone if successful, otherwise one of the other system wide error codes.
   726 */
   727 TInt D_RMD_Breakpoints::DoModifyBreak(TModifyBreakInfo* aBreakInfo)
   728 	{
   729 	// Ensure we have a valid semaphore
   730 	if (!iInitialised || !iLock)
   731 		{
   732 		return KErrNotReady;
   733 		}
   734 
   735 	// Acquire the lock
   736 	NKern::ThreadEnterCS();
   737 	Kern::SemaphoreWait(*iLock); 
   738 
   739 	// Really do the work
   740 	TInt err = priv_DoModifyBreak(aBreakInfo);
   741 	
   742 	// Release the lock
   743 	Kern::SemaphoreSignal(*iLock);
   744 	NKern::ThreadLeaveCS();
   745 
   746 	return err;
   747 	}
   748 
   749 /**
   750 Private member function which modifies a previously set breakpoint, as per DoModifyBreak, but
   751 does not serialise access.
   752 
   753 @see DoModifyBreak
   754 
   755 @param aBreakInfo A TModifyBreakInfo describing the breakpoint properties that are wanted.
   756 @return KErrNone if successful, otherwise one of the other system wide error codes.
   757 */
   758 TInt D_RMD_Breakpoints::priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo)
   759 	{
   760 	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak()");
   761 
   762 	// Check arguments
   763 	if (!aBreakInfo)
   764 		{
   765 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a NULL argument");
   766 		return KErrArgument;
   767 		}
   768 
   769 	//User side memory is not accessible directly
   770 	TSetBreakInfo info;
   771 	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
   772 	if (err != KErrNone)
   773 		{
   774 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a bad argument");
   775 		return err;
   776 		}
   777 
   778 	// EThumb2EEMode breakpoints are not supported
   779 	if (EThumb2EEMode == info.iMode)
   780 		{
   781 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - EThumb2EEMode breakpoints are not supported");
   782 		return KErrNotSupported;
   783 		}
   784 
   785 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
   786 	TBreakEntry entry;
   787 	entry.iBreakId = (TUint32)info.iBreakId;
   788 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
   789 	if (index < 0)
   790 		{
   791 		// Could not find the breakpoint
   792 		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
   793 		return KErrNotFound;
   794 		}
   795 
   796 	//assert that the thread we're moving the break from is suspended
   797 	if(!TheDProcessTracker.CheckSuspended(iBreakPointList[index].iId))
   798 		{
   799 		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Thread with id 0x%08x not suspended", iBreakPointList[index].iId);
   800 		return KErrInUse;
   801 		}
   802 
   803 	//assert that the thread we're moving the break to is suspended
   804 	if(!TheDProcessTracker.CheckSuspended(info.iId))
   805 		{
   806 		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Thread with id 0x%08x not suspended", info.iId);
   807 		return KErrInUse;
   808 		}
   809 
   810 	// first check its not obsolete
   811 	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
   812 		{
   813 		// its still a valid breakpoint
   814 
   815 		// remove the old breakpoint
   816 		DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId);
   817 		if (threadObj)
   818 			{
   819 			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
   820 
   821 			XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
   822 			if (r != 0)
   823 				{
   824 				LOG_MSG("Failed to construct trap handler for DebugSupport::RestoreCode");
   825 				}
   826 
   827 			// Close the thread handle which has been opened by OpenThreadHandle
   828 			threadObj->Close(NULL);
   829 			}
   830 		else
   831 			{
   832 			// Bad handle
   833 			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Could not identify the breakpoint thread id");
   834 			return KErrBadHandle;
   835 			}
   836 		}
   837 
   838 	// make sure there is not already a breakpoint at the new address
   839 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
   840 		{
   841 		// Ignore data for the breakpoint entry being modified.
   842 		if (i != index)
   843 			{
   844 			/* We need to check if the breakpoint overlaps the address at all,
   845 			 * and this depends upon the size of the two breakpoints as well as 
   846 			 * their address.
   847 			 */
   848 
   849 			// newInstSize = size in bytes of new breakpoint
   850 			TInt newInstSize = BreakSize(info.iMode);
   851 			if (newInstSize == 0)
   852 			{
   853 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type for new breakpoint");
   854 				return KErrNotSupported;
   855 			}
   856 
   857 			// oldInstSize = size in bytes of the existing breakpoint
   858 			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
   859 			if (oldInstSize == 0)
   860 			{
   861 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type of existing breakpoint");
   862 				return KErrNotSupported;
   863 			}
   864 
   865 			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
   866 			TBreakEntry temp;
   867 
   868 			temp.iAddress = info.iAddress;
   869 			temp.iMode = info.iMode;
   870 
   871 			// do they overlap?
   872 			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
   873 				{
   874 				// Yes
   875 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - New breakpoint overlaps an existing breakpoint");
   876 				return KErrAlreadyExists;
   877 				}
   878 			}
   879 		}
   880 
   881 	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
   882 	iBreakPointList[index].iId = info.iId;
   883 	iBreakPointList[index].iAddress = info.iAddress;
   884 	iBreakPointList[index].iMode = info.iMode;
   885 
   886 	TBreakEntry& newBreakEntry = iBreakPointList[index];
   887 
   888 	// Decide the size of the breakpoint instruction
   889 	TUint32 inst = BreakInst(newBreakEntry.iMode);
   890 	TInt instSize = BreakSize(newBreakEntry.iMode);
   891 
   892 	if (inst == 0 || instSize == 0)
   893 		{
   894 		// Unsupported architecture
   895 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - unsupported breakpoint architecture");
   896 		return KErrNotSupported;
   897 		}
   898 
   899 
   900 	//if thread id is 0xFFFFFFFF, then the breakpoint is not thread specific
   901 	if (newBreakEntry.iId != 0xFFFFFFFF)
   902 		{
   903 		newBreakEntry.iThreadSpecific = ETrue;
   904 		}
   905 
   906 	// Get thread id from the process that we are debugging
   907 	TProcessInfo * proc = NULL;
   908 	TUint64 threadId = NULL;
   909 
   910 	threadId = newBreakEntry.iId;
   911 
   912 	DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
   913 	//if we don't have the right thread id for the address, 
   914 	//then try with the thread id of the process that we are debugging 	
   915 	if (!threadObj && iChannel->iDebugProcessList.Count())
   916 		{
   917 		proc = &iChannel->iDebugProcessList[0];
   918 		if (proc)
   919 			{
   920 			threadId = proc->iId+1;	
   921 			}
   922 		threadObj = DebugUtils::OpenThreadHandle(threadId);
   923 		}
   924 
   925 	if(!threadObj)
   926 		{
   927 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - bad handle. Could not identify a threadObj");
   928 		return KErrBadHandle;
   929 		}
   930 
   931 	// save the old instruction
   932 	TUint32 instruction;
   933 
   934 	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
   935 	// trap exceptions in case the address is invalid
   936 	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
   937 
   938 	//consider the leave as more important than the error code so store the leave if it's not KErrNone
   939 	if(KErrNone != r)
   940 		{
   941 		err = r;
   942 		}
   943 	if(KErrNone != err)
   944 		{
   945 		threadObj->Close(NULL);
   946 		return err;
   947 		}
   948 
   949 	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
   950 
   951 	newBreakEntry.iId = threadId; //set the thread ID here 
   952 	LOG_MSG3("ModifyCode2 instSize:%d, inst: 0x%08x", instSize, inst);
   953 	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
   954 	if(s != DebugSupport::EBreakpointGlobal)
   955 		{
   956 		err = s;
   957 		}
   958 
   959 	// Close the thread handle which has been opened by OpenThreadHandle
   960 	threadObj->Close(NULL);
   961 
   962 	return err;
   963 	}	
   964 
   965 //
   966 // D_RMD_Breakpoints::DoModifyProcessBreak
   967 //
   968 TInt D_RMD_Breakpoints::DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
   969 	{
   970 	// Ensure we have a valid semaphore
   971 	if (!iInitialised || !iLock)
   972 		{
   973 		return KErrNotReady;
   974 		}
   975 
   976 	// Acquire the lock
   977 	NKern::ThreadEnterCS();
   978 	Kern::SemaphoreWait(*iLock); 
   979 
   980 	// Really do the work
   981 	TInt err = priv_DoModifyProcessBreak(aBreakInfo);
   982 	
   983 	// Release the lock
   984 	Kern::SemaphoreSignal(*iLock);
   985 	NKern::ThreadLeaveCS();
   986 
   987 	return err;
   988 	}
   989 	
   990 TInt D_RMD_Breakpoints::priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
   991 	{	
   992 	LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak()");
   993 
   994 	// Check arguments
   995 	if (!aBreakInfo)
   996 		{
   997 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a NULL argument");
   998 		return KErrArgument;
   999 		}
  1000 
  1001 	//User side memory is not accessible directly
  1002 	TSetBreakInfo info;
  1003 	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TModifyProcessBreakInfo));
  1004 	if (err != KErrNone)
  1005 		{
  1006 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a bad argument");
  1007 		return err;
  1008 		}
  1009 
  1010 	// EThumb2EEMode breakpoints are not supported
  1011 	if (EThumb2EEMode == info.iMode)
  1012 		{
  1013 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - EThumb2EEMode breakpoints are not supported");
  1014 		return KErrNotSupported;
  1015 		}
  1016 
  1017 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
  1018 	TBreakEntry entry;
  1019 	entry.iBreakId = (TUint32)info.iBreakId;
  1020 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
  1021 	if (index < 0)
  1022 		{
  1023 		// Could not find the breakpoint
  1024 		LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not find the breakpoint id 0x%08x",(TUint32)info.iBreakId);
  1025 		return KErrNotFound;
  1026 		}
  1027 
  1028 	// first check its not obsolete
  1029 	if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
  1030 		{
  1031 		// its still a valid breakpoint
  1032 
  1033 		// remove the old breakpoint
  1034 		DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[index].iId);
  1035 		DThread* threadObj = NULL;
  1036 		if(process)
  1037 			{
  1038 			threadObj = process->FirstThread();
  1039 			if(threadObj)
  1040 				{
  1041 				threadObj = DebugUtils::OpenThreadHandle(threadObj->iId);
  1042 				}
  1043 			process->Close(NULL);
  1044 			}
  1045 
  1046 		if (threadObj)
  1047 			{
  1048 			LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
  1049 
  1050 			XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
  1051 			if (r != 0)
  1052 				{
  1053 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Failed to construct trap handler for DebugSupport::RestoreCode");
  1054 				}
  1055 
  1056 			// Close the thread handle which has been opened by OpenThreadHandle
  1057 			threadObj->Close(NULL);
  1058 			}
  1059 		else
  1060 			{
  1061 			// Bad handle
  1062 			LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not identify the breakpoint process id");
  1063 			return KErrBadHandle;
  1064 			}
  1065 		}
  1066 
  1067 	// make sure there is not already a breakpoint at the new address
  1068 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
  1069 		{
  1070 		// Ignore data for the breakpoint entry being modified.
  1071 		if (i != index)
  1072 			{
  1073 			/* We need to check if the breakpoint overlaps the address at all,
  1074 			 * and this depends upon the size of the two breakpoints as well as 
  1075 			 * their address.
  1076 			 */
  1077 
  1078 			// newInstSize = size in bytes of new breakpoint
  1079 			TInt newInstSize = BreakSize(info.iMode);
  1080 			if (newInstSize == 0)
  1081 				{
  1082 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unknown architecture type for new breakpoint");
  1083 				return KErrNotSupported;
  1084 				}
  1085 
  1086 			// oldInstSize = size in bytes of the existing breakpoint
  1087 			TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
  1088 			if (oldInstSize == 0)
  1089 				{
  1090 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - : Unknown architecture type of existing breakpoint");
  1091 				return KErrNotSupported;
  1092 				}
  1093 
  1094 			// Overlap checking - temp is used as the new breakpoint description for checking purposes only
  1095 			TBreakEntry temp;
  1096 
  1097 			temp.iAddress = info.iAddress;
  1098 			temp.iMode = info.iMode;
  1099 
  1100 			// do they overlap?
  1101 			if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
  1102 				{
  1103 				// Yes
  1104 				LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - New breakpoint overlaps an existing breakpoint");
  1105 				return KErrAlreadyExists;
  1106 				}
  1107 			}
  1108 		}
  1109 
  1110 	// Prepare iBreakPointList[index] with the new information, then set the breakpoint
  1111 	iBreakPointList[index].iId = info.iId;
  1112 	iBreakPointList[index].iAddress = info.iAddress;
  1113 	iBreakPointList[index].iMode = info.iMode;
  1114 
  1115 	TBreakEntry& newBreakEntry = iBreakPointList[index];
  1116 
  1117 	// Decide the size of the breakpoint instruction
  1118 	TUint32 inst = BreakInst(newBreakEntry.iMode);
  1119 	TInt instSize = BreakSize(newBreakEntry.iMode);
  1120 
  1121 	if (inst == 0 || instSize == 0)
  1122 		{
  1123 		// Unsupported architecture
  1124 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - unsupported breakpoint architecture");
  1125 		return KErrNotSupported;
  1126 		}
  1127 
  1128 	newBreakEntry.iThreadSpecific = EFalse;
  1129 
  1130 	DProcess* process = DebugUtils::OpenProcessHandle(newBreakEntry.iId);
  1131 	if(!process)
  1132 		{
  1133 		LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - bad handle. Could not identify a process");
  1134 		return KErrBadHandle;
  1135 		}
  1136 
  1137 	DThread* threadObj = process->FirstThread();
  1138 	if(threadObj)
  1139 		{
  1140 		threadObj = DebugUtils::OpenThreadHandle(threadObj->iId);
  1141 		}
  1142 	process->Close(NULL);
  1143 	if(!threadObj)
  1144 		{
  1145 		return KErrNotFound;
  1146 		}
  1147 	// save the old instruction
  1148 	TUint32 instruction;
  1149 
  1150 	// read the instruction at the address so we can store it in the break entry for when we clear this breakpoint
  1151 	// trap exceptions in case the address is invalid
  1152 	XTRAPD(r, XT_DEFAULT, err = iChannel->TryToReadMemory(threadObj, (TAny *)newBreakEntry.iAddress, (TAny *)&instruction, instSize));
  1153 
  1154 	//consider the leave as more important than the error code so store the leave if it's not KErrNone
  1155 	if(KErrNone != r)
  1156 		{
  1157 		err = r;
  1158 		}
  1159 	if(KErrNone != err)
  1160 		{
  1161 		threadObj->Close(NULL);
  1162 		return err;
  1163 		}
  1164 
  1165 	newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
  1166 
  1167 	XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
  1168 	if(s != DebugSupport::EBreakpointGlobal)
  1169 		{
  1170 		err = s;
  1171 		}
  1172 
  1173 	// Close the thread handle which has been opened by OpenThreadHandle
  1174 	threadObj->Close(NULL);
  1175 
  1176 	return err;
  1177 	}
  1178 
  1179 /**
  1180 Public member function which returns information about a previously set breakpoint.
  1181 
  1182 Note 1:
  1183 This function ensures exclusive access to the breakpoint data structures
  1184 by using a semaphore to serialise access.
  1185 
  1186 @see priv_DoBreakInfo
  1187 
  1188 Note 2:
  1189 As implied by Note 1, the caller must have previously called Init() or this
  1190 function will return KErrNotReady;
  1191 
  1192 @param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
  1193 @return KErrNone if successful, otherwise one of the other system wide error codes.
  1194 */
  1195 TInt D_RMD_Breakpoints::DoBreakInfo(TGetBreakInfo* aBreakInfo)
  1196 	{
  1197 	// Ensure we have a valid semaphore
  1198 	if (!iInitialised || !iLock)
  1199 		{
  1200 		return KErrNotReady;
  1201 		}
  1202 
  1203 	// Acquire the lock
  1204 	NKern::ThreadEnterCS();
  1205 	Kern::SemaphoreWait(*iLock);
  1206 
  1207 	// Really do the work
  1208 	TInt err = priv_DoBreakInfo(aBreakInfo);
  1209 	
  1210 	// Release the lock
  1211 	Kern::SemaphoreSignal(*iLock);
  1212 	NKern::ThreadLeaveCS();
  1213 
  1214 	return err;
  1215 	}
  1216 
  1217 /**
  1218 Private member function function which returns information about a previously set breakpoint..
  1219 
  1220 @see DoBreakInfo
  1221 
  1222 @param aBreakInfo Address of aBreakInfo structure in user-side memory within the DSS client thread. CAN ONLY BE ACCESSED VIA Kern::ThreadRawRead()
  1223 @return KErrNone if successful, otherwise one of the other system wide error codes.
  1224 */
  1225 TInt D_RMD_Breakpoints::priv_DoBreakInfo(TGetBreakInfo* aBreakInfo)
  1226 	{
  1227 	LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo()");
  1228 
  1229 	if (!aBreakInfo)
  1230 		{
  1231 		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a NULL argument");
  1232 
  1233 		return KErrArgument;
  1234 		}
  1235 
  1236 	//User side memory is not accessible directly
  1237 	TGetBreakInfo info;
  1238 	TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TGetBreakInfo));
  1239 	if (err != KErrNone)
  1240 		{
  1241 		LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a bad argument");
  1242 
  1243 		return err;
  1244 		}
  1245 
  1246 	// find the break entry matching this id.  note that the breakpoints are already sorted in ascending order by id
  1247 	TBreakEntry entry;
  1248 	entry.iBreakId = (TUint32)info.iBreakId;
  1249 	TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
  1250 	
  1251 	if (index >=0)
  1252 		{
  1253 		// get the thread id for this breakpoint
  1254 		TUint64 threadId = iBreakPointList[index].iId;
  1255 
  1256 		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iId,&threadId,sizeof(TUint64));
  1257 		if (err != KErrNone)
  1258 			{
  1259 			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iThreadId information");
  1260 			return err;
  1261 			}
  1262 
  1263 		// get the threadSpecific-ness
  1264 		TBool threadSpecific = iBreakPointList[index].iThreadSpecific;
  1265 
  1266 		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iThreadSpecific,&threadSpecific,sizeof(TBool));
  1267 		if (err != KErrNone)
  1268 			{
  1269 			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return thread specific information");
  1270 			return err;
  1271 			}
  1272 
  1273 
  1274 		// get the address
  1275 		TUint32 address = iBreakPointList[index].iAddress;
  1276 
  1277 		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iAddress,&address,sizeof(TUint32));
  1278 		if (err != KErrNone)
  1279 			{
  1280 			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iAddress information");
  1281 			return err;
  1282 			}
  1283 
  1284 
  1285 		// get the architecture
  1286 		TArchitectureMode mode = iBreakPointList[index].iMode;
  1287 
  1288 		err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iMode,&mode,sizeof(TUint32));
  1289 		if (err != KErrNone)
  1290 			{
  1291 			LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iMode information");
  1292 			return err;
  1293 			}
  1294 
  1295 		return err;
  1296 		}
  1297 
  1298 	LOG_MSG2("D_RMD_Breakpoints::priv_DoBreakInfo - Could not find the breakpoint id specified 0x%08x", entry.iBreakId);
  1299 	return KErrNotFound;
  1300 	}
  1301 
  1302 /**
  1303 Public member function which clears all the breakpoints in the system. Generally used for shutting down
  1304 the debug device driver.
  1305 
  1306 Note 1:
  1307 This function ensures exclusive access to the breakpoint data structures
  1308 by using a semaphore to serialise access.
  1309 
  1310 @see priv_ClearAllBreakPoints
  1311 
  1312 Note 2:
  1313 As implied by Note 1, the caller must have previously called Init() or this
  1314 function will return KErrNotReady;
  1315 */
  1316 void D_RMD_Breakpoints::ClearAllBreakPoints()
  1317 	{
  1318 	// Ensure we have a valid semaphore
  1319 	if (!iInitialised || !iLock)
  1320 		{
  1321 		return;
  1322 		}
  1323 
  1324 	// Acquire the lock
  1325 	NKern::ThreadEnterCS();
  1326 	Kern::SemaphoreWait(*iLock);
  1327 
  1328 	// Really do the work
  1329 	priv_ClearAllBreakPoints();
  1330 	
  1331 	// Release the lock
  1332 	Kern::SemaphoreSignal(*iLock);
  1333 	NKern::ThreadLeaveCS();
  1334 	}
  1335 
  1336 /**
  1337 Private member function which clears all the breakpoints in the system. Generally used for shutting down
  1338 the debug device driver. 
  1339 
  1340 @see DoClearAllBreakPoints
  1341 */
  1342 void D_RMD_Breakpoints::priv_ClearAllBreakPoints()
  1343 	{
  1344 	LOG_MSG("D_RMD_Breakpoints::priv_ClearAllBreakPoints()");
  1345 
  1346 	TInt err = KErrNone;
  1347 
  1348 	for (TInt i=0; i<iBreakPointList.Count(); i++)
  1349 		{
  1350 		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
  1351 			{
  1352 			LOG_MSG2("D_RMD_Breakpoints::priv_ClearAllBreakPoints() - Clearing breakpoint at address %x", iBreakPointList[i].iAddress);
  1353 			TUint32 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
  1354 			DThread *threadObj = DebugUtils::OpenThreadHandle(id);
  1355 			if (threadObj)
  1356 				{
  1357 				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[i].iAddress));
  1358 				err = (KErrNone == r) ? err : r;
  1359 				threadObj->Close(NULL);
  1360 				}
  1361 			else
  1362 				{
  1363 				err = KErrBadHandle;
  1364 				}
  1365 
  1366 			if (KErrNone != err)
  1367 				{
  1368 				LOG_MSG2("D_RMD_Breakpoints::priv_ClearAllBreakPoints() - Error 0x%08x while clearing breakpoint", err);
  1369 				}
  1370 			}
  1371 		}
  1372 
  1373 	iBreakPointList.Reset();
  1374 	}
  1375 
  1376 /**
  1377 Public member function which disables the breakpoint at the specified address.
  1378 
  1379 Note 1:
  1380 This function ensures exclusive access to the breakpoint data structures
  1381 by using a semaphore to serialise access.
  1382 
  1383 @see priv_DisableBreakAtAddress
  1384 
  1385 Note 2:
  1386 As implied by Note 1, the caller must have previously called Init() or this
  1387 function will return KErrNotReady;
  1388 
  1389 @param aAddress Address at which to disable breakpoints (all threads)
  1390 @return KErrNone if successful, one of the other system wide error codes otherwise.
  1391 */
  1392 TInt D_RMD_Breakpoints::DisableBreakAtAddress(TUint32 aAddress)
  1393 	{
  1394 	// Ensure we have a valid semaphore
  1395 	if (!iInitialised || !iLock)
  1396 		{
  1397 		return KErrNotReady;
  1398 		}
  1399 
  1400 	// Acquire the lock
  1401 	NKern::ThreadEnterCS();
  1402 	Kern::SemaphoreWait(*iLock);
  1403 
  1404 	// Really do the work
  1405 	TInt err = priv_DisableBreakAtAddress(aAddress);
  1406 	
  1407 	// Release the lock
  1408 	Kern::SemaphoreSignal(*iLock);
  1409 	NKern::ThreadLeaveCS();
  1410 
  1411 	return err;
  1412 	}
  1413 
  1414 /**
  1415 Private member function which clears all the breakpoints in the system. Generally used for shutting down
  1416 the debug device driver. 
  1417 
  1418 @see DisableBreakAtAddress
  1419 
  1420 @param aAddress clears the breakpoint at the specified address
  1421 @return KErrNone if successful, one of the other system wide error codes otherwise.
  1422 */
  1423 TInt D_RMD_Breakpoints::priv_DisableBreakAtAddress(TUint32 aAddress)
  1424 	{
  1425 	LOG_MSG("D_RMD_Breakpoints::priv_DisableBreakAtAddress()");
  1426 
  1427 	TInt err = KErrNone;
  1428 
  1429 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
  1430 		{
  1431 		if (iBreakPointList[i].iAddress == aAddress)
  1432 			{
  1433 			iBreakPointList[i].iDisabledForStep = ETrue;
  1434 			LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress - Disabling breakpoint at address 0x%x", iBreakPointList[i].iAddress);
  1435 
  1436 			//clear the breakpoint with code modifier
  1437 			//code modifier will restore the org instruction and also frees the shadow page if necessary
  1438 			TUint64 id = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
  1439 			DThread* threadObj = NULL;
  1440 			if(iBreakPointList[i].iThreadSpecific)
  1441 				{
  1442 				threadObj = DebugUtils::OpenThreadHandle(id);
  1443 				}
  1444 			else
  1445 				{
  1446 				DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[i].iId);
  1447 				if(process)
  1448 					{
  1449 					threadObj = process->FirstThread();
  1450 					if(threadObj)
  1451 						{
  1452 						if(KErrNone != threadObj->Open())
  1453 							{
  1454 							LOG_MSG("Couldn't open threadObj");
  1455 							threadObj = NULL;
  1456 							}
  1457 						}
  1458 					else
  1459 						{
  1460 						LOG_MSG("threadObj is NULL");
  1461 						}
  1462 					}
  1463 				else
  1464 					{
  1465 					LOG_MSG("Process is NULL");
  1466 					}
  1467 				}
  1468 			if (threadObj)
  1469 				{
  1470 				XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, aAddress));			
  1471 				if(KErrNone != err || KErrNone != r)
  1472 					{
  1473 					LOG_MSG3("Error from DebugSupport::RestoreCode: r: %d, err: %d", r, err);
  1474 					}
  1475 				err = (KErrNone == r) ? err : r;
  1476 				threadObj->Close(NULL);
  1477 				}
  1478 			else
  1479 				{
  1480 				err = KErrBadHandle;
  1481 				break;
  1482 				}
  1483 			}
  1484 		}
  1485 		
  1486 	return err;
  1487 	}
  1488 
  1489 /**
  1490 Public member function which enables previously disabled breakpoints within a given thread.
  1491 
  1492 Note 1:
  1493 This function ensures exclusive access to the breakpoint data structures
  1494 by using a semaphore to serialise access. 
  1495 
  1496 @see priv_DoEnableDisabledBreak
  1497 
  1498 Note 2:
  1499 As implied by Note 1, the caller must have previously called Init() or this
  1500 function will return KErrNotReady;
  1501 
  1502 @param aThreadId Thread in which to enable all previously disabled breakpoints
  1503 @return KErrNone if successful, one of the system wide error codes otherwise.
  1504 */
  1505 TInt D_RMD_Breakpoints::DoEnableDisabledBreak(TUint64 aThreadId)
  1506 	{
  1507 	// Ensure we have a valid semaphore
  1508 	if (!iInitialised || !iLock)
  1509 		{
  1510 		return KErrNotReady;
  1511 		}
  1512 
  1513 	// Acquire the lock
  1514 	NKern::ThreadEnterCS();
  1515 	Kern::SemaphoreWait(*iLock);
  1516 
  1517 	// Really do the work
  1518 	TInt err = priv_DoEnableDisabledBreak(aThreadId);
  1519 	
  1520 	// Release the lock
  1521 	Kern::SemaphoreSignal(*iLock);
  1522 	NKern::ThreadLeaveCS();
  1523 
  1524 	return err;
  1525 	}
  1526 
  1527 /**
  1528 Private member function which enables previously disabled breakpoints within a given thread.
  1529 
  1530 @see DoEnableDisabledBreak
  1531 
  1532 @param aThreadId Thread in which to enable all previously disabled breakpoints
  1533 @return KErrNone if successful, one of the system wide error codes otherwise.
  1534 */
  1535 TInt D_RMD_Breakpoints::priv_DoEnableDisabledBreak(TUint64 aThreadId)
  1536 	{
  1537 	LOG_MSG("D_RMD_Breakpoints::priv_DoEnableDisabledBreak()");
  1538 	DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
  1539 	if(!thread)
  1540 		{
  1541 		LOG_MSG2("Thread: 0x%08x does not exist", aThreadId);
  1542 		return KErrNotFound;
  1543 		}
  1544 	TUint64 processId = thread->iOwningProcess->iId;
  1545 	thread->Close(NULL);
  1546 
  1547 	for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
  1548 		{
  1549 		TBool needsEnabling = EFalse;
  1550 		if(iBreakPointList[i].iDisabledForStep)
  1551 			{
  1552 			if(iBreakPointList[i].iThreadSpecific)
  1553 				{
  1554 				needsEnabling = (aThreadId == iBreakPointList[i].iId);
  1555 				}
  1556 			else
  1557 				{
  1558 				needsEnabling = (processId == iBreakPointList[i].iId);
  1559 				}
  1560 			}
  1561 		if (needsEnabling)
  1562 			{
  1563 			LOG_MSG2("Re-enabling breakpoint at address %x", iBreakPointList[i].iAddress);
  1564 			TInt err = priv_DoEnableBreak(iBreakPointList[i], EFalse);
  1565 			if(KErrNone != err)
  1566 				{
  1567 				LOG_MSG2("Error returned from DoEnableBreak: %d", err);
  1568 				iBreakPointList[i].iDisabledForStep = EFalse;
  1569 				}
  1570 			return err;
  1571 			}		
  1572 		}
  1573 	
  1574 	return KErrNone;
  1575 	}
  1576 
  1577 /**
  1578 Public member function which removes all the breakpoints within a given thread.
  1579 
  1580 Note 1:
  1581 This function ensures exclusive access to the breakpoint data structures
  1582 by using a semaphore to serialise access.
  1583 
  1584 @see priv_DoRemoveThreadBreaks
  1585 
  1586 Note 2:
  1587 As implied by Note 1, the caller must have previously called Init() or this
  1588 function will return KErrNotReady;
  1589 
  1590 @param aThreadId Thread from which to remove all existing breakpoints
  1591 @return KErrNone if successful, one of the system wide error codes otherwise.
  1592 */
  1593 void D_RMD_Breakpoints::DoRemoveThreadBreaks(TUint64 aThreadId)
  1594 	{
  1595 	// Ensure we have a valid semaphore
  1596 	if (!iInitialised || !iLock)
  1597 		{
  1598 		return;
  1599 		}
  1600 
  1601 	// Acquire the lock
  1602 	NKern::ThreadEnterCS();
  1603 	Kern::SemaphoreWait(*iLock);
  1604 
  1605 	// Really do the work
  1606 	priv_DoRemoveThreadBreaks(aThreadId);
  1607 
  1608 	// Release the lock
  1609 	Kern::SemaphoreSignal(*iLock);
  1610 	NKern::ThreadLeaveCS();
  1611 	}
  1612 
  1613 /**
  1614 Private member function which removes all the breakpoints particular to a particular thread
  1615 
  1616 @see DoRemoveThreadBreaks
  1617 
  1618 @param aThreadId Thread from which to remove all existing breakpoints
  1619 @return KErrNone if successful, one of the system wide error codes otherwise.
  1620 */
  1621 void D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(TUint64 aThreadId)
  1622 	{
  1623 	LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(aThreadId = 0x%016lx)\n",aThreadId);
  1624 
  1625 	TInt err = KErrNone;
  1626 	TUint64 threadId;
  1627 
  1628 	for (TInt i=iBreakPointList.Count()-1; i >= 0; i--)
  1629 		{
  1630 		if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
  1631 			{
  1632 			threadId = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
  1633 			if (threadId == aThreadId)
  1634 				{
  1635 				LOG_MSG4("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks() - Clearing breakpoint at address 0x%08x for thread id 0x%016lx with id 0x%08x", iBreakPointList[i].iAddress, iBreakPointList[i].iId, iBreakPointList[i].iBreakId);
  1636 
  1637 				err = priv_DoClearBreak(iBreakPointList[i].iBreakId, EFalse);
  1638 
  1639 				if (err != KErrNone)
  1640 					{
  1641 					LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks()  - failed to remove break id 0x%08x\n",iBreakPointList[i].iBreakId);
  1642 					return;
  1643 					}
  1644 				}
  1645 			}
  1646 		}	
  1647 	}
  1648 
  1649 // Remove the process breakpoints for process with PID aProcessId in the range [aCodeAddress, aCodeAddress + aCodeSize)
  1650 void D_RMD_Breakpoints::RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize)
  1651 	{
  1652 	LOG_MSG("D_RMD_Breakpoints::RemoveBreaksForProcess()");
  1653 	for (TInt i=iBreakPointList.Count() - 1; i>=0; i--)
  1654 		{
  1655 		TBreakEntry& breakEntry = iBreakPointList[i];
  1656 		if(!breakEntry.iThreadSpecific && breakEntry.iId == aProcessId)
  1657 			{
  1658 			if ((breakEntry.iAddress >= aCodeAddress) && (breakEntry.iAddress < (aCodeAddress + aCodeSize)))
  1659 				{
  1660 				LOG_MSG2("Removing process breakpoint at address %x", (TUint32)breakEntry.iAddress);
  1661 				TInt err = DoClearBreak(breakEntry.iBreakId, ETrue);
  1662 				if(KErrNone != err)
  1663 					{
  1664 					LOG_MSG2("Error removing process breakpoint: %d", err);
  1665 					}
  1666 				}
  1667 			}
  1668 		}
  1669 	}
  1670 
  1671 // mark the breakpoints in the range [aCodeAddress, aCodeAddress + aCodeSize)
  1672 void D_RMD_Breakpoints::InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize)
  1673 	{
  1674 	LOG_MSG("D_RMD_Breakpoints::InvalidateLibraryBreakPoints()");
  1675 	for (TInt i=0; i<iBreakPointList.Count(); i++)
  1676 		{
  1677 		if ((iBreakPointList[i].iAddress >= aCodeAddress) && (iBreakPointList[i].iAddress < (aCodeAddress + aCodeSize)))
  1678 			{
  1679 			LOG_EVENT_MSG2("Disabling library breakpoint at address %x", iBreakPointList[i].iAddress);
  1680 			iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
  1681 			}
  1682 		}
  1683 	}
  1684 
  1685 TInt D_RMD_Breakpoints::BreakPointCount() const
  1686 	{
  1687 	return iBreakPointList.Count();
  1688 	}
  1689 
  1690 /**
  1691   Gets next breakpoint in list.
  1692   @param aBreakEntry The break entry to get the successor of. If NULL then returns the first entry.
  1693   @return A pointer to the next break entry, or NULL if the end of the list has been reached
  1694   */
  1695 TBreakEntry* D_RMD_Breakpoints::GetNextBreak(const TBreakEntry* aBreakEntry) const
  1696 	{
  1697 	if(!aBreakEntry)
  1698 		{
  1699 		return (TBreakEntry*)&(iBreakPointList[0]);
  1700 		}
  1701 	TInt index = iBreakPointList.FindInSignedKeyOrder(*aBreakEntry) + 1;
  1702 	return (index < BreakPointCount()) ? (TBreakEntry*)&(iBreakPointList[index]) : NULL;
  1703 	}
  1704 
  1705 TBool D_RMD_Breakpoints::IsTemporaryBreak(const TBreakEntry& aBreakEntry) const
  1706 	{
  1707 	// Ensure we have a valid semaphore
  1708 	if (!iInitialised || !iLock)
  1709 		{
  1710 		return EFalse;
  1711 		}
  1712 
  1713 	// Acquire the lock
  1714 	NKern::ThreadEnterCS();
  1715 	Kern::SemaphoreWait(*iLock);
  1716 
  1717 	// Really do the work
  1718 	TBool tempBreak = priv_IsTemporaryBreak(aBreakEntry);
  1719 	
  1720 	// Release the lock
  1721 	Kern::SemaphoreSignal(*iLock);
  1722 	NKern::ThreadLeaveCS();
  1723 	
  1724 	return tempBreak;
  1725 	}
  1726 
  1727 /**
  1728 Private member function which tells us if a breakpoint is temporary
  1729 
  1730 @see IsTemporaryBreak
  1731 
  1732 @param aBreakEntry
  1733 @return TBool indicating if the break is temporary or not
  1734 */
  1735 TBool D_RMD_Breakpoints::priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const 
  1736 	{
  1737 	return aBreakEntry.iBreakId < NUMBER_OF_TEMP_BREAKPOINTS;
  1738 	}
  1739 
  1740 
  1741 // End of file - d_rmd_breakpoints.cpp