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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #include <e32def_private.h>
20 #include <e32cmn_private.h>
22 #include <kernel/kernel.h>
23 #include <kernel/kern_priv.h>
26 #include <kernel/cache.h>
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"
41 using namespace Debug;
43 /* @internalTechnology
45 * Checks whether aAddress is correctly aligned for placing a breakpoint of
46 * cpu architecture aMode.
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.
52 TBool D_RMD_Breakpoints::Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode)
57 // ARM breakpoints must be 32-bit aligned (lower two bits must be zero)
60 // Not 32-bit aligned.
64 case Debug::EThumbMode:
65 // Thumb breakpoints must be 16-bit aligned (low bit must be zero)
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.
93 /* @internalTechnology
95 * Returns the size of a breakpoint of architecture aMode in bytes
97 * @param aMode - The architure of the breakpoint
98 * @return The size of the breakpoints in bytes. 0 if un-recognised architecture.
100 TInt D_RMD_Breakpoints::BreakSize(Debug::TArchitectureMode aMode)
104 case Debug::EArmMode:
108 case Debug::EThumbMode:
112 case Debug::EThumb2EEMode:
114 // Only needs to be two bytes in size.
125 /* @internalTechnology
127 * Checks whether two TBreakEntrys overlap
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
134 TBool D_RMD_Breakpoints::BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond)
136 TInt firstSize = BreakSize(aFirst.iMode);
137 TInt secondSize = BreakSize(aSecond.iMode);
139 // Do we know the size of each breakpoint?
140 if ((firstSize <= 0) || (secondSize <= 0))
142 // We don't know the size of the breakpoint, so assume they overlap
146 TInt firstStartAddress = aFirst.iAddress;
147 TInt secondStartAddress = aSecond.iAddress;
148 TInt firstEndAddress = firstStartAddress + firstSize - 1;
149 TInt secondEndAddress = secondStartAddress + secondSize - 1;
151 // If second breakpoint is past the end of the first then we're ok
152 if(firstEndAddress < secondStartAddress)
157 // If first breakpoint is past the end of the second then we're ok
158 if(secondEndAddress < firstStartAddress)
163 // The breakpoints overlap
167 /* @internalTechnology
169 * Returns the breakpoint bitpattern to use for each architecture type
171 * @param aMode - the cpu architecture type
172 * @return The bit-pattern to use for the specified architecture, or 0 if unsupported.
174 TUint32 D_RMD_Breakpoints::BreakInst(Debug::TArchitectureMode aMode)
178 case Debug::EArmMode:
180 return KArmBreakPoint;
182 case Debug::EThumbMode:
184 return KThumbBreakPoint;
186 case Debug::EThumb2EEMode:
188 return KT2EEBreakPoint;
192 // No idea what the breakpoint should be
199 Constructor. Initialises its internal list of empty breakpoints.
201 D_RMD_Breakpoints::D_RMD_Breakpoints(DRM_DebugChannel* aChannel)
202 : iBreakPointList(NUMBER_OF_TEMP_BREAKPOINTS, 0),
203 iNextBreakId(NUMBER_OF_TEMP_BREAKPOINTS),
207 iBreakPointList.Reset();
208 TBreakEntry emptyTempBreak;
210 for (TInt i = 0; i < NUMBER_OF_TEMP_BREAKPOINTS; i++)
212 emptyTempBreak.iBreakId = i;
214 if (KErrNone != iBreakPointList.Append(emptyTempBreak))
216 LOG_MSG("D_RMD_Breakpoints::D_RMD_Breakpoints() - Error appending blank temp break entry");
222 Destructor. Clears all the breakpoints in the system, deletes its internal list of breakpoints,
223 and closes the exclusivity semaphore.
225 D_RMD_Breakpoints::~D_RMD_Breakpoints()
227 ClearAllBreakPoints();
229 // close the breakpoint list and free the memory associated with it
230 iBreakPointList.Close();
237 Initialises the breakpoint list exclusion semaphore. This should be called once immediately after
240 @return KErrNone if successful, one of the other system wide error codes otherwise.
242 TInt D_RMD_Breakpoints::Init()
246 // Only create a semaphore if we are not initialised
249 // Initialise the semaphore ensuring exclusive access to the breakpoint list
250 err = Kern::SemaphoreCreate(iLock, _L("RM_DebugBreakpointLock"), 1 /* Initial count */);
253 iInitialised = ETrue;
265 Public member function which sets a thread-specific breakpoint in the specified thread
266 and returns an opaque handle to the caller.
269 This function ensures exclusive access to the breakpoint data structures
270 by using a semaphore to serialise access.
275 As implied by Note 1, the caller must have previously called Init() or this
276 function will return KErrNotReady;
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.
284 TInt D_RMD_Breakpoints::DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
286 // Ensure we have a valid semaphore
287 if (!iInitialised || !iLock)
293 NKern::ThreadEnterCS();
294 Kern::SemaphoreWait(*iLock);
296 // Really do the work
297 TInt err = priv_DoSetBreak(aBreakId, aId, aThreadSpecific, aAddress,aMode);
300 Kern::SemaphoreSignal(*iLock);
301 NKern::ThreadLeaveCS();
306 Private member function which sets a thread-specific breakpoint in the specified thread
307 and returns an opaque handle to the caller.
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.
317 TInt D_RMD_Breakpoints::priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const TArchitectureMode aMode)
319 LOG_MSG4("D_RMD_Breakpoints::priv_DoSetBreak(aThreadId = 0x%016lx, aAddress = 0x%08x, aMode = %d)",aId,aAddress,aMode);
321 // EThumb2EEMode breakpoints are not supported
322 if (EThumb2EEMode == aMode)
324 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - EThumb2EEMode breakpoints are not supported");
325 return KErrNotSupported;
328 // Check how many breakpoints we have in existence
329 if ((iBreakPointList.Count()+1) >= NUMBER_OF_MAX_BREAKPOINTS)
331 // Too many breakpoints are set!
332 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Too many breakpoints set");
336 // check the alignment of the breakpoint
337 if (!Aligned(aAddress,aMode))
339 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unaligned address");
343 // make sure there is not already a breakpoint at this address
344 for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
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
351 // newInstSize = size in bytes of new breakpoint
352 TInt newInstSize = BreakSize(aMode);
353 if (newInstSize == 0)
355 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Unknown architecture type for new breakpoint");
356 return KErrNotSupported;
359 // oldInstSize = size in bytes of the existing breakpoint
360 TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
361 if (oldInstSize == 0)
363 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - : Unknown architecture type of existing breakpoint");
364 return KErrNotSupported;
367 // Overlap checking - temp is used as the new breakpoint description for checking purposes only
370 temp.iAddress = aAddress;
374 if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
377 if(iBreakPointList[i].iThreadSpecific && aThreadSpecific)
379 if(aId == iBreakPointList[i].iId)
381 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing thread specific breakpoint");
382 return KErrAlreadyExists;
385 else if(!iBreakPointList[i].iThreadSpecific && aThreadSpecific)
387 DThread* thread = DebugUtils::OpenThreadHandle(aId);
392 if(thread->iOwningProcess->iId == iBreakPointList[i].iId)
394 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New thread specific breakpoint overlaps an existing breakpoint");
396 return KErrAlreadyExists;
400 else if(iBreakPointList[i].iThreadSpecific && !aThreadSpecific)
402 DThread* thread = DebugUtils::OpenThreadHandle(iBreakPointList[i].iId);
407 if(thread->iOwningProcess->iId == aId)
409 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing thread specific breakpoint");
411 return KErrAlreadyExists;
415 else // !iBreakPointList[i].iThreadSpecific && !aThreadSpecific
417 if(iBreakPointList[i].iId == aId)
419 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - New breakpoint overlaps an existing breakpoint");
420 return KErrAlreadyExists;
426 // increment the break id
427 aBreakId = iNextBreakId++;
429 // create the new breakpoint entry
430 TBreakEntry breakEntry(aBreakId, aId, aThreadSpecific, aAddress, aMode);
432 TInt err = priv_DoEnableBreak(breakEntry, ETrue);
435 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Could not enable the breakpoint");
440 err = iBreakPointList.Append(breakEntry);
443 LOG_MSG("D_RMD_Breakpoints::priv_DoSetBreak() - Failed to append breakpoint");
446 LOG_MSG2("D_RMD_Breakpoints::priv_DoSetBreak(breakId = 0x%08x) done",aBreakId);
452 Public member function which enables a previously set breakpoint.
455 This function ensures exclusive access to the breakpoint data structures
456 by using a semaphore to serialise access.
458 @see priv_DoEnableBreak
461 As implied by Note 1, the caller must have previously called Init() or this
462 function will return KErrNotReady;
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.
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.
473 TInt D_RMD_Breakpoints::DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
475 // Ensure we have a valid semaphore
476 if (!iInitialised || !iLock)
482 NKern::ThreadEnterCS();
483 Kern::SemaphoreWait(*iLock);
485 // Really do the work
486 TInt err = priv_DoEnableBreak(aEntry,aSaveOldInstruction);
489 Kern::SemaphoreSignal(*iLock);
490 NKern::ThreadLeaveCS();
496 Private member function which enables a previously set breakpoint, as per DoEnableBreak, but
497 does not serialise access.
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.
505 TInt D_RMD_Breakpoints::priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction)
507 LOG_MSG("D_RMD_Breakpoints::DoEnableBreak()");
509 TUint32 inst = BreakInst(aEntry.iMode);
510 TInt instSize = BreakSize(aEntry.iMode);
511 if (instSize == 0 || inst == 0)
514 LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - unsupported breakpoint architecture");
515 return KErrNotSupported;
521 TUint64 threadId = aEntry.iId + (aEntry.iThreadSpecific ? 0 : 1);
523 DThread* threadObj = DebugUtils::OpenThreadHandle(threadId);
526 LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak - bad handle. Could not identify a threadObj");
527 return KErrBadHandle;
530 if (aSaveOldInstruction)
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));
538 //consider the leave as more important than the error code so store the leave if it's not KErrNone
546 threadObj->Close(NULL);
547 LOG_MSG("D_RMD_Breakpoints::priv_DoEnableBreak() - failed to read memory");
551 aEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
554 TBool breakpointAlredySet = EFalse;
555 for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
557 if(iBreakPointList[i].iAddress == aEntry.iAddress && !iBreakPointList[i].iDisabledForStep )
559 breakpointAlredySet = ETrue;
563 if(!breakpointAlredySet)
565 XTRAPD(r, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, aEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
566 if(r != DebugSupport::EBreakpointGlobal)
572 // Close the thread handle which has been opened by OpenThreadHandle
573 threadObj->Close(NULL);
579 Public member function which clears a previously set breakpoint.
582 This function ensures exclusive access to the breakpoint data structures
583 by using a semaphore to serialise access.
585 @see priv_DoClearBreak
588 As implied by Note 1, the caller must have previously called Init() or this
589 function will return KErrNotReady;
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.
594 TInt D_RMD_Breakpoints::DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
596 // Ensure we have a valid semaphore
597 if (!iInitialised || !iLock)
603 NKern::ThreadEnterCS();
604 Kern::SemaphoreWait(*iLock);
606 // Really do the work
607 TInt err = priv_DoClearBreak(aBreakId, aIgnoreTerminatedThreads);
610 Kern::SemaphoreSignal(*iLock);
611 NKern::ThreadLeaveCS();
617 Private member function which clears a previously set breakpoint, as per DoClearBreak, but
618 does not serialise access.
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.
625 TInt D_RMD_Breakpoints::priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads)
627 LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak(0x%08x)",aBreakId);
629 // find the break entry matching this id. note that the breakpoints are already sorted in ascending order by id
631 entry.iBreakId = aBreakId;
632 TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
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))))
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
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)
648 DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId + (iBreakPointList[index].iThreadSpecific ? 0 : 1));
651 TBool needToCallCodeModifier = ETrue;
652 for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
656 if ( BreakpointsOverlap(iBreakPointList[index],iBreakPointList[i]) )
658 needToCallCodeModifier = EFalse;
663 if(needToCallCodeModifier)
665 XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
668 LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code trap harness returned error %d",r);
673 LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - restore code returned error %d",err);
675 err = (KErrNone == r) ? err : r;
678 // Close the thread handle opened by OpenThreadHandle
679 threadObj->Close(NULL);
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)
690 // if this is a temp breakpoint, just clear out the values, otherwise remove it from the list
692 if (index < NUMBER_OF_TEMP_BREAKPOINTS)
694 iBreakPointList[index].Reset();
698 LOG_MSG3("D_RMD_Breakpoints::priv_DoClearBreak() - Removing breakpoint 0x%08x as breakid 0x%08x\n",index, entry.iBreakId);
699 iBreakPointList.Remove(index);
706 LOG_MSG2("D_RMD_Breakpoints::priv_DoClearBreak() - Break Id %d not found", aBreakId);
712 Public member function which modifies a previously set breakpoint.
715 This function ensures exclusive access to the breakpoint data structures
716 by using a semaphore to serialise access.
718 @see priv_DoModifyBreak
721 As implied by Note 1, the caller must have previously called Init() or this
722 function will return KErrNotReady;
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.
727 TInt D_RMD_Breakpoints::DoModifyBreak(TModifyBreakInfo* aBreakInfo)
729 // Ensure we have a valid semaphore
730 if (!iInitialised || !iLock)
736 NKern::ThreadEnterCS();
737 Kern::SemaphoreWait(*iLock);
739 // Really do the work
740 TInt err = priv_DoModifyBreak(aBreakInfo);
743 Kern::SemaphoreSignal(*iLock);
744 NKern::ThreadLeaveCS();
750 Private member function which modifies a previously set breakpoint, as per DoModifyBreak, but
751 does not serialise access.
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.
758 TInt D_RMD_Breakpoints::priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo)
760 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak()");
765 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a NULL argument");
769 //User side memory is not accessible directly
771 TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
774 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() was passed a bad argument");
778 // EThumb2EEMode breakpoints are not supported
779 if (EThumb2EEMode == info.iMode)
781 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - EThumb2EEMode breakpoints are not supported");
782 return KErrNotSupported;
785 // find the break entry matching this id. note that the breakpoints are already sorted in ascending order by id
787 entry.iBreakId = (TUint32)info.iBreakId;
788 TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
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);
796 //assert that the thread we're moving the break from is suspended
797 if(!TheDProcessTracker.CheckSuspended(iBreakPointList[index].iId))
799 LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Thread with id 0x%08x not suspended", iBreakPointList[index].iId);
803 //assert that the thread we're moving the break to is suspended
804 if(!TheDProcessTracker.CheckSuspended(info.iId))
806 LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak() - Thread with id 0x%08x not suspended", info.iId);
810 // first check its not obsolete
811 if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
813 // its still a valid breakpoint
815 // remove the old breakpoint
816 DThread* threadObj = DebugUtils::OpenThreadHandle(iBreakPointList[index].iId);
819 LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyBreak - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
821 XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
824 LOG_MSG("Failed to construct trap handler for DebugSupport::RestoreCode");
827 // Close the thread handle which has been opened by OpenThreadHandle
828 threadObj->Close(NULL);
833 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Could not identify the breakpoint thread id");
834 return KErrBadHandle;
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++)
841 // Ignore data for the breakpoint entry being modified.
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
849 // newInstSize = size in bytes of new breakpoint
850 TInt newInstSize = BreakSize(info.iMode);
851 if (newInstSize == 0)
853 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type for new breakpoint");
854 return KErrNotSupported;
857 // oldInstSize = size in bytes of the existing breakpoint
858 TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
859 if (oldInstSize == 0)
861 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - Unknown architecture type of existing breakpoint");
862 return KErrNotSupported;
865 // Overlap checking - temp is used as the new breakpoint description for checking purposes only
868 temp.iAddress = info.iAddress;
869 temp.iMode = info.iMode;
872 if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
875 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - New breakpoint overlaps an existing breakpoint");
876 return KErrAlreadyExists;
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;
886 TBreakEntry& newBreakEntry = iBreakPointList[index];
888 // Decide the size of the breakpoint instruction
889 TUint32 inst = BreakInst(newBreakEntry.iMode);
890 TInt instSize = BreakSize(newBreakEntry.iMode);
892 if (inst == 0 || instSize == 0)
894 // Unsupported architecture
895 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak - unsupported breakpoint architecture");
896 return KErrNotSupported;
900 //if thread id is 0xFFFFFFFF, then the breakpoint is not thread specific
901 if (newBreakEntry.iId != 0xFFFFFFFF)
903 newBreakEntry.iThreadSpecific = ETrue;
906 // Get thread id from the process that we are debugging
907 TProcessInfo * proc = NULL;
908 TUint64 threadId = NULL;
910 threadId = newBreakEntry.iId;
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())
917 proc = &iChannel->iDebugProcessList[0];
920 threadId = proc->iId+1;
922 threadObj = DebugUtils::OpenThreadHandle(threadId);
927 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyBreak() - bad handle. Could not identify a threadObj");
928 return KErrBadHandle;
931 // save the old instruction
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));
938 //consider the leave as more important than the error code so store the leave if it's not KErrNone
945 threadObj->Close(NULL);
949 newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
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)
959 // Close the thread handle which has been opened by OpenThreadHandle
960 threadObj->Close(NULL);
966 // D_RMD_Breakpoints::DoModifyProcessBreak
968 TInt D_RMD_Breakpoints::DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
970 // Ensure we have a valid semaphore
971 if (!iInitialised || !iLock)
977 NKern::ThreadEnterCS();
978 Kern::SemaphoreWait(*iLock);
980 // Really do the work
981 TInt err = priv_DoModifyProcessBreak(aBreakInfo);
984 Kern::SemaphoreSignal(*iLock);
985 NKern::ThreadLeaveCS();
990 TInt D_RMD_Breakpoints::priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo)
992 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak()");
997 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a NULL argument");
1001 //User side memory is not accessible directly
1003 TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TModifyProcessBreakInfo));
1004 if (err != KErrNone)
1006 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() was passed a bad argument");
1010 // EThumb2EEMode breakpoints are not supported
1011 if (EThumb2EEMode == info.iMode)
1013 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - EThumb2EEMode breakpoints are not supported");
1014 return KErrNotSupported;
1017 // find the break entry matching this id. note that the breakpoints are already sorted in ascending order by id
1019 entry.iBreakId = (TUint32)info.iBreakId;
1020 TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
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;
1028 // first check its not obsolete
1029 if (!iBreakPointList[index].iObsoleteLibraryBreakpoint)
1031 // its still a valid breakpoint
1033 // remove the old breakpoint
1034 DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[index].iId);
1035 DThread* threadObj = NULL;
1038 threadObj = process->FirstThread();
1041 threadObj = DebugUtils::OpenThreadHandle(threadObj->iId);
1043 process->Close(NULL);
1048 LOG_MSG2("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unsetting breakpoint at address 0x%08x",iBreakPointList[index].iAddress);
1050 XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[index].iAddress));
1053 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Failed to construct trap handler for DebugSupport::RestoreCode");
1056 // Close the thread handle which has been opened by OpenThreadHandle
1057 threadObj->Close(NULL);
1062 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Could not identify the breakpoint process id");
1063 return KErrBadHandle;
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++)
1070 // Ignore data for the breakpoint entry being modified.
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
1078 // newInstSize = size in bytes of new breakpoint
1079 TInt newInstSize = BreakSize(info.iMode);
1080 if (newInstSize == 0)
1082 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - Unknown architecture type for new breakpoint");
1083 return KErrNotSupported;
1086 // oldInstSize = size in bytes of the existing breakpoint
1087 TInt oldInstSize = BreakSize(iBreakPointList[i].iMode);
1088 if (oldInstSize == 0)
1090 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - : Unknown architecture type of existing breakpoint");
1091 return KErrNotSupported;
1094 // Overlap checking - temp is used as the new breakpoint description for checking purposes only
1097 temp.iAddress = info.iAddress;
1098 temp.iMode = info.iMode;
1101 if ( BreakpointsOverlap(temp,iBreakPointList[i]) )
1104 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - New breakpoint overlaps an existing breakpoint");
1105 return KErrAlreadyExists;
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;
1115 TBreakEntry& newBreakEntry = iBreakPointList[index];
1117 // Decide the size of the breakpoint instruction
1118 TUint32 inst = BreakInst(newBreakEntry.iMode);
1119 TInt instSize = BreakSize(newBreakEntry.iMode);
1121 if (inst == 0 || instSize == 0)
1123 // Unsupported architecture
1124 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - unsupported breakpoint architecture");
1125 return KErrNotSupported;
1128 newBreakEntry.iThreadSpecific = EFalse;
1130 DProcess* process = DebugUtils::OpenProcessHandle(newBreakEntry.iId);
1133 LOG_MSG("D_RMD_Breakpoints::priv_DoModifyProcessBreak() - bad handle. Could not identify a process");
1134 return KErrBadHandle;
1137 DThread* threadObj = process->FirstThread();
1140 threadObj = DebugUtils::OpenThreadHandle(threadObj->iId);
1142 process->Close(NULL);
1145 return KErrNotFound;
1147 // save the old instruction
1148 TUint32 instruction;
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));
1154 //consider the leave as more important than the error code so store the leave if it's not KErrNone
1161 threadObj->Close(NULL);
1165 newBreakEntry.iInstruction.Copy((TUint8 *)&instruction, instSize);
1167 XTRAPD(s, XT_DEFAULT, err = DebugSupport::ModifyCode(threadObj, newBreakEntry.iAddress, instSize, inst, DebugSupport::EBreakpointGlobal));
1168 if(s != DebugSupport::EBreakpointGlobal)
1173 // Close the thread handle which has been opened by OpenThreadHandle
1174 threadObj->Close(NULL);
1180 Public member function which returns information about a previously set breakpoint.
1183 This function ensures exclusive access to the breakpoint data structures
1184 by using a semaphore to serialise access.
1186 @see priv_DoBreakInfo
1189 As implied by Note 1, the caller must have previously called Init() or this
1190 function will return KErrNotReady;
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.
1195 TInt D_RMD_Breakpoints::DoBreakInfo(TGetBreakInfo* aBreakInfo)
1197 // Ensure we have a valid semaphore
1198 if (!iInitialised || !iLock)
1200 return KErrNotReady;
1204 NKern::ThreadEnterCS();
1205 Kern::SemaphoreWait(*iLock);
1207 // Really do the work
1208 TInt err = priv_DoBreakInfo(aBreakInfo);
1211 Kern::SemaphoreSignal(*iLock);
1212 NKern::ThreadLeaveCS();
1218 Private member function function which returns information about a previously set breakpoint..
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.
1225 TInt D_RMD_Breakpoints::priv_DoBreakInfo(TGetBreakInfo* aBreakInfo)
1227 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo()");
1231 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a NULL argument");
1233 return KErrArgument;
1236 //User side memory is not accessible directly
1238 TInt err = Kern::ThreadRawRead(iChannel->iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TGetBreakInfo));
1239 if (err != KErrNone)
1241 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() was passed a bad argument");
1246 // find the break entry matching this id. note that the breakpoints are already sorted in ascending order by id
1248 entry.iBreakId = (TUint32)info.iBreakId;
1249 TInt index = iBreakPointList.FindInSignedKeyOrder(entry);
1253 // get the thread id for this breakpoint
1254 TUint64 threadId = iBreakPointList[index].iId;
1256 err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iId,&threadId,sizeof(TUint64));
1257 if (err != KErrNone)
1259 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iThreadId information");
1263 // get the threadSpecific-ness
1264 TBool threadSpecific = iBreakPointList[index].iThreadSpecific;
1266 err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iThreadSpecific,&threadSpecific,sizeof(TBool));
1267 if (err != KErrNone)
1269 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return thread specific information");
1275 TUint32 address = iBreakPointList[index].iAddress;
1277 err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iAddress,&address,sizeof(TUint32));
1278 if (err != KErrNone)
1280 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iAddress information");
1285 // get the architecture
1286 TArchitectureMode mode = iBreakPointList[index].iMode;
1288 err = Kern::ThreadRawWrite(iChannel->iClientThread,(TUint8*)info.iMode,&mode,sizeof(TUint32));
1289 if (err != KErrNone)
1291 LOG_MSG("D_RMD_Breakpoints::priv_DoBreakInfo() - failed to return breakpoint iMode information");
1298 LOG_MSG2("D_RMD_Breakpoints::priv_DoBreakInfo - Could not find the breakpoint id specified 0x%08x", entry.iBreakId);
1299 return KErrNotFound;
1303 Public member function which clears all the breakpoints in the system. Generally used for shutting down
1304 the debug device driver.
1307 This function ensures exclusive access to the breakpoint data structures
1308 by using a semaphore to serialise access.
1310 @see priv_ClearAllBreakPoints
1313 As implied by Note 1, the caller must have previously called Init() or this
1314 function will return KErrNotReady;
1316 void D_RMD_Breakpoints::ClearAllBreakPoints()
1318 // Ensure we have a valid semaphore
1319 if (!iInitialised || !iLock)
1325 NKern::ThreadEnterCS();
1326 Kern::SemaphoreWait(*iLock);
1328 // Really do the work
1329 priv_ClearAllBreakPoints();
1332 Kern::SemaphoreSignal(*iLock);
1333 NKern::ThreadLeaveCS();
1337 Private member function which clears all the breakpoints in the system. Generally used for shutting down
1338 the debug device driver.
1340 @see DoClearAllBreakPoints
1342 void D_RMD_Breakpoints::priv_ClearAllBreakPoints()
1344 LOG_MSG("D_RMD_Breakpoints::priv_ClearAllBreakPoints()");
1346 TInt err = KErrNone;
1348 for (TInt i=0; i<iBreakPointList.Count(); i++)
1350 if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
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);
1357 XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, iBreakPointList[i].iAddress));
1358 err = (KErrNone == r) ? err : r;
1359 threadObj->Close(NULL);
1363 err = KErrBadHandle;
1366 if (KErrNone != err)
1368 LOG_MSG2("D_RMD_Breakpoints::priv_ClearAllBreakPoints() - Error 0x%08x while clearing breakpoint", err);
1373 iBreakPointList.Reset();
1377 Public member function which disables the breakpoint at the specified address.
1380 This function ensures exclusive access to the breakpoint data structures
1381 by using a semaphore to serialise access.
1383 @see priv_DisableBreakAtAddress
1386 As implied by Note 1, the caller must have previously called Init() or this
1387 function will return KErrNotReady;
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.
1392 TInt D_RMD_Breakpoints::DisableBreakAtAddress(TUint32 aAddress)
1394 // Ensure we have a valid semaphore
1395 if (!iInitialised || !iLock)
1397 return KErrNotReady;
1401 NKern::ThreadEnterCS();
1402 Kern::SemaphoreWait(*iLock);
1404 // Really do the work
1405 TInt err = priv_DisableBreakAtAddress(aAddress);
1408 Kern::SemaphoreSignal(*iLock);
1409 NKern::ThreadLeaveCS();
1415 Private member function which clears all the breakpoints in the system. Generally used for shutting down
1416 the debug device driver.
1418 @see DisableBreakAtAddress
1420 @param aAddress clears the breakpoint at the specified address
1421 @return KErrNone if successful, one of the other system wide error codes otherwise.
1423 TInt D_RMD_Breakpoints::priv_DisableBreakAtAddress(TUint32 aAddress)
1425 LOG_MSG("D_RMD_Breakpoints::priv_DisableBreakAtAddress()");
1427 TInt err = KErrNone;
1429 for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
1431 if (iBreakPointList[i].iAddress == aAddress)
1433 iBreakPointList[i].iDisabledForStep = ETrue;
1434 LOG_MSG2("D_RMD_Breakpoints::priv_DisableBreakAtAddress - Disabling breakpoint at address 0x%x", iBreakPointList[i].iAddress);
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)
1442 threadObj = DebugUtils::OpenThreadHandle(id);
1446 DProcess *process = DebugUtils::OpenProcessHandle(iBreakPointList[i].iId);
1449 threadObj = process->FirstThread();
1452 if(KErrNone != threadObj->Open())
1454 LOG_MSG("Couldn't open threadObj");
1460 LOG_MSG("threadObj is NULL");
1465 LOG_MSG("Process is NULL");
1470 XTRAPD(r, XT_DEFAULT, err = DebugSupport::RestoreCode(threadObj, aAddress));
1471 if(KErrNone != err || KErrNone != r)
1473 LOG_MSG3("Error from DebugSupport::RestoreCode: r: %d, err: %d", r, err);
1475 err = (KErrNone == r) ? err : r;
1476 threadObj->Close(NULL);
1480 err = KErrBadHandle;
1490 Public member function which enables previously disabled breakpoints within a given thread.
1493 This function ensures exclusive access to the breakpoint data structures
1494 by using a semaphore to serialise access.
1496 @see priv_DoEnableDisabledBreak
1499 As implied by Note 1, the caller must have previously called Init() or this
1500 function will return KErrNotReady;
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.
1505 TInt D_RMD_Breakpoints::DoEnableDisabledBreak(TUint64 aThreadId)
1507 // Ensure we have a valid semaphore
1508 if (!iInitialised || !iLock)
1510 return KErrNotReady;
1514 NKern::ThreadEnterCS();
1515 Kern::SemaphoreWait(*iLock);
1517 // Really do the work
1518 TInt err = priv_DoEnableDisabledBreak(aThreadId);
1521 Kern::SemaphoreSignal(*iLock);
1522 NKern::ThreadLeaveCS();
1528 Private member function which enables previously disabled breakpoints within a given thread.
1530 @see DoEnableDisabledBreak
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.
1535 TInt D_RMD_Breakpoints::priv_DoEnableDisabledBreak(TUint64 aThreadId)
1537 LOG_MSG("D_RMD_Breakpoints::priv_DoEnableDisabledBreak()");
1538 DThread* thread = DebugUtils::OpenThreadHandle(aThreadId);
1541 LOG_MSG2("Thread: 0x%08x does not exist", aThreadId);
1542 return KErrNotFound;
1544 TUint64 processId = thread->iOwningProcess->iId;
1545 thread->Close(NULL);
1547 for (TInt i = NUMBER_OF_TEMP_BREAKPOINTS; i < iBreakPointList.Count(); i++)
1549 TBool needsEnabling = EFalse;
1550 if(iBreakPointList[i].iDisabledForStep)
1552 if(iBreakPointList[i].iThreadSpecific)
1554 needsEnabling = (aThreadId == iBreakPointList[i].iId);
1558 needsEnabling = (processId == iBreakPointList[i].iId);
1563 LOG_MSG2("Re-enabling breakpoint at address %x", iBreakPointList[i].iAddress);
1564 TInt err = priv_DoEnableBreak(iBreakPointList[i], EFalse);
1567 LOG_MSG2("Error returned from DoEnableBreak: %d", err);
1568 iBreakPointList[i].iDisabledForStep = EFalse;
1578 Public member function which removes all the breakpoints within a given thread.
1581 This function ensures exclusive access to the breakpoint data structures
1582 by using a semaphore to serialise access.
1584 @see priv_DoRemoveThreadBreaks
1587 As implied by Note 1, the caller must have previously called Init() or this
1588 function will return KErrNotReady;
1590 @param aThreadId Thread from which to remove all existing breakpoints
1591 @return KErrNone if successful, one of the system wide error codes otherwise.
1593 void D_RMD_Breakpoints::DoRemoveThreadBreaks(TUint64 aThreadId)
1595 // Ensure we have a valid semaphore
1596 if (!iInitialised || !iLock)
1602 NKern::ThreadEnterCS();
1603 Kern::SemaphoreWait(*iLock);
1605 // Really do the work
1606 priv_DoRemoveThreadBreaks(aThreadId);
1609 Kern::SemaphoreSignal(*iLock);
1610 NKern::ThreadLeaveCS();
1614 Private member function which removes all the breakpoints particular to a particular thread
1616 @see DoRemoveThreadBreaks
1618 @param aThreadId Thread from which to remove all existing breakpoints
1619 @return KErrNone if successful, one of the system wide error codes otherwise.
1621 void D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(TUint64 aThreadId)
1623 LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks(aThreadId = 0x%016lx)\n",aThreadId);
1625 TInt err = KErrNone;
1628 for (TInt i=iBreakPointList.Count()-1; i >= 0; i--)
1630 if ((iBreakPointList[i].iAddress != 0) && !iBreakPointList[i].iObsoleteLibraryBreakpoint)
1632 threadId = iBreakPointList[i].iId + (iBreakPointList[i].iThreadSpecific ? 0 : 1);
1633 if (threadId == aThreadId)
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);
1637 err = priv_DoClearBreak(iBreakPointList[i].iBreakId, EFalse);
1639 if (err != KErrNone)
1641 LOG_MSG2("D_RMD_Breakpoints::priv_DoRemoveThreadBreaks() - failed to remove break id 0x%08x\n",iBreakPointList[i].iBreakId);
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)
1652 LOG_MSG("D_RMD_Breakpoints::RemoveBreaksForProcess()");
1653 for (TInt i=iBreakPointList.Count() - 1; i>=0; i--)
1655 TBreakEntry& breakEntry = iBreakPointList[i];
1656 if(!breakEntry.iThreadSpecific && breakEntry.iId == aProcessId)
1658 if ((breakEntry.iAddress >= aCodeAddress) && (breakEntry.iAddress < (aCodeAddress + aCodeSize)))
1660 LOG_MSG2("Removing process breakpoint at address %x", (TUint32)breakEntry.iAddress);
1661 TInt err = DoClearBreak(breakEntry.iBreakId, ETrue);
1664 LOG_MSG2("Error removing process breakpoint: %d", err);
1671 // mark the breakpoints in the range [aCodeAddress, aCodeAddress + aCodeSize)
1672 void D_RMD_Breakpoints::InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize)
1674 LOG_MSG("D_RMD_Breakpoints::InvalidateLibraryBreakPoints()");
1675 for (TInt i=0; i<iBreakPointList.Count(); i++)
1677 if ((iBreakPointList[i].iAddress >= aCodeAddress) && (iBreakPointList[i].iAddress < (aCodeAddress + aCodeSize)))
1679 LOG_EVENT_MSG2("Disabling library breakpoint at address %x", iBreakPointList[i].iAddress);
1680 iBreakPointList[i].iObsoleteLibraryBreakpoint = ETrue;
1685 TInt D_RMD_Breakpoints::BreakPointCount() const
1687 return iBreakPointList.Count();
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
1695 TBreakEntry* D_RMD_Breakpoints::GetNextBreak(const TBreakEntry* aBreakEntry) const
1699 return (TBreakEntry*)&(iBreakPointList[0]);
1701 TInt index = iBreakPointList.FindInSignedKeyOrder(*aBreakEntry) + 1;
1702 return (index < BreakPointCount()) ? (TBreakEntry*)&(iBreakPointList[index]) : NULL;
1705 TBool D_RMD_Breakpoints::IsTemporaryBreak(const TBreakEntry& aBreakEntry) const
1707 // Ensure we have a valid semaphore
1708 if (!iInitialised || !iLock)
1714 NKern::ThreadEnterCS();
1715 Kern::SemaphoreWait(*iLock);
1717 // Really do the work
1718 TBool tempBreak = priv_IsTemporaryBreak(aBreakEntry);
1721 Kern::SemaphoreSignal(*iLock);
1722 NKern::ThreadLeaveCS();
1728 Private member function which tells us if a breakpoint is temporary
1730 @see IsTemporaryBreak
1733 @return TBool indicating if the break is temporary or not
1735 TBool D_RMD_Breakpoints::priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const
1737 return aBreakEntry.iBreakId < NUMBER_OF_TEMP_BREAKPOINTS;
1741 // End of file - d_rmd_breakpoints.cpp