kernel/eka/drivers/debug/rmdebug/d_rmd_breakpoints.cpp
branchRCL_3
changeset 257 3e88ff8f41d5
child 258 880ff05ad710
equal deleted inserted replaced
256:c1f20ce4abcf 257:3e88ff8f41d5
       
     1 // Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    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 				return err;
       
  1570 				}
       
  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