sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Refactored class containing breakpoint related code from rm_debug_kerneldriver.cpp sl@0: // sl@0: sl@0: sl@0: sl@0: /** sl@0: @file sl@0: @internalComponent sl@0: @released sl@0: */ sl@0: sl@0: #ifndef D_RMD_BREAKPOINTS_H sl@0: #define D_RMD_BREAKPOINTS_H sl@0: sl@0: #include sl@0: #include sl@0: #include "rm_debug_kerneldriver.h" sl@0: sl@0: // fwd declaration of friend classes needed due to re-factoring sl@0: class DRM_DebugChannel; sl@0: sl@0: class DRMDStepper; sl@0: sl@0: // sl@0: // Macros sl@0: // sl@0: const TUint32 KArmBreakPoint = 0xE7F123F4; sl@0: const TUint16 KThumbBreakPoint = 0xDE56; sl@0: const TUint16 KT2EEBreakPoint = 0xC100; // From ARM ARM DDI0406A, section A9.2.1 Undefined instruction encoding for Thumb2-EE. sl@0: sl@0: #define NUMBER_OF_TEMP_BREAKPOINTS 10 sl@0: sl@0: #define NUMBER_OF_MAX_BREAKPOINTS 100 sl@0: sl@0: // sl@0: // class TBreakEntry sl@0: // sl@0: class TBreakEntry sl@0: { sl@0: public: sl@0: sl@0: inline TBreakEntry() { Reset(); }; sl@0: sl@0: inline TBreakEntry(Debug::TBreakId aBreakId, TUint64 aId, TBool aThreadSpecific, TUint32 aAddress, Debug::TArchitectureMode aMode) sl@0: : iBreakId(aBreakId), sl@0: iId(aId), sl@0: iAddress(aAddress), sl@0: iMode(aMode), sl@0: iThreadSpecific(aThreadSpecific) sl@0: { sl@0: iInstruction.FillZ(4); sl@0: iPageAddress = 0; sl@0: iDisabledForStep = EFalse; sl@0: iObsoleteLibraryBreakpoint = EFalse; sl@0: iResumeOnceOutOfRange = EFalse; sl@0: iSteppingInto = EFalse; sl@0: iRangeStart = 0; sl@0: iRangeEnd = 0; sl@0: iStepTarget = EFalse; sl@0: iNumSteps = 0; sl@0: }; sl@0: sl@0: inline void Reset() sl@0: { sl@0: iId = 0; sl@0: iAddress = 0; sl@0: iMode = Debug::EArmMode; sl@0: iInstruction.FillZ(4); sl@0: iPageAddress = 0; sl@0: iDisabledForStep = EFalse; sl@0: iObsoleteLibraryBreakpoint = EFalse; sl@0: iResumeOnceOutOfRange = EFalse; sl@0: iSteppingInto = EFalse; sl@0: iRangeStart = 0; sl@0: iRangeEnd = 0; sl@0: iStepTarget = EFalse; sl@0: iNumSteps = 0; sl@0: }; sl@0: sl@0: public: sl@0: // Unique Id for this breakpoint. Assigned by D_RMD_Breakpoints::DoSetBreak(). @see D_RMD_Breakpoints::DoSetBreak sl@0: TInt32 iBreakId; sl@0: // Consider making the iId into a union of TProcessId, TThreadId, global etc. to make things more obvious sl@0: // Object Id in which this breakpoint should operate. sl@0: TUint64 iId; sl@0: // Address at which this breakpoint should operate sl@0: TUint32 iAddress; sl@0: // CPU ISA which this breakpoint uses, e.g. EArmMode/EThumbMode. sl@0: Debug::TArchitectureMode iMode; sl@0: // The original instruction which was stored at iAddress. sl@0: TBuf8<4> iInstruction; sl@0: TUint32 iPageAddress; //not used: BC if we remove it sl@0: sl@0: // Indicates whether this breakpoint has been temporarily replaced with original instruction to enable step-off this breakpoint sl@0: TBool iDisabledForStep; sl@0: /* This is used when libraries and processes are removed, so that sl@0: * the driver can say 'ok' when requested to remove breakpoints sl@0: * that existed in these cases, rather than 'Not Found'. sl@0: * sl@0: * Its not logical, but its a BC break if we change it :-( sl@0: */ sl@0: TBool iObsoleteLibraryBreakpoint; sl@0: // Indicates whether this thread should be resumed after stepping off this breakpoint sl@0: TBool iResumeOnceOutOfRange; sl@0: TBool iSteppingInto; sl@0: TUint32 iRangeStart; sl@0: TUint32 iRangeEnd; sl@0: TBool iThreadSpecific; sl@0: TBool iStepTarget; sl@0: sl@0: // Indicates how many more instruction steps should occur after hitting this breakpoint sl@0: TInt iNumSteps; sl@0: }; sl@0: /** sl@0: @internalTechnology sl@0: sl@0: This class encapsulates all the data concerning run-mode and stop mode breakpoints sl@0: as understood by the run-mode and stop-mode debug system. sl@0: sl@0: Note: sl@0: The internal list of breakpoints is currently divided into two sections. The range from sl@0: 0...NUMBER_OF_TEMP_BREAKPOINTS is used internally by the debug driver for implementing sl@0: stepping. The range from NUMBER_OF_TEMP_BREAKPOINTS to NUMBER_OF_MAX_BREAKPOINTS is used sl@0: to store information about breakpoints set by the client debug agents. sl@0: sl@0: In future, this should change, so that each breakpoint knows what kind of breakpoint it sl@0: is (user/temp etc). sl@0: sl@0: sl@0: */ sl@0: class D_RMD_Breakpoints : public DBase sl@0: { sl@0: public: sl@0: D_RMD_Breakpoints(DRM_DebugChannel* aChannel); sl@0: ~D_RMD_Breakpoints(); sl@0: sl@0: TInt Init(); sl@0: sl@0: // from rm_debug_driver.h sl@0: TInt DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode ); sl@0: TInt DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction); sl@0: TInt DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads=EFalse); sl@0: TInt DoModifyBreak(TModifyBreakInfo* aBreakInfo); sl@0: TInt DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo); sl@0: TInt DoBreakInfo(TGetBreakInfo* aBreakInfo); sl@0: void ClearAllBreakPoints(); sl@0: TInt DisableBreakAtAddress(TUint32 aAddress); sl@0: TInt DoEnableDisabledBreak(TUint64 aThreadId); sl@0: sl@0: void DoRemoveThreadBreaks(TUint64 aThreadId); sl@0: void RemoveBreaksForProcess(TUint64 aProcessId, TUint32 aCodeAddress, TUint32 aCodeSize); sl@0: void InvalidateLibraryBreakPoints(TUint32 aCodeAddress, TUint32 aCodeSize); sl@0: TInt BreakPointCount() const; sl@0: TBreakEntry* GetNextBreak(const TBreakEntry* aBreakEntry) const; sl@0: TBool IsTemporaryBreak(const TBreakEntry& aBreakEntry) const; sl@0: sl@0: TInt DoGetBreakList(TUint32* aBuffer, const TUint32 aBufSize, const TUint32 aElement, TUint32& aLastElement); sl@0: sl@0: private: sl@0: // Locked versions of public functions sl@0: TInt priv_DoSetBreak(TInt32 &aBreakId, const TUint64 aId, const TBool aThreadSpecific, const TUint32 aAddress, const Debug::TArchitectureMode aMode ); sl@0: TInt priv_DoEnableBreak(TBreakEntry &aEntry, TBool aSaveOldInstruction); sl@0: TInt priv_DoClearBreak(const TInt32 aBreakId, TBool aIgnoreTerminatedThreads); sl@0: TInt priv_DoModifyBreak(TModifyBreakInfo* aBreakInfo); sl@0: TInt priv_DoModifyProcessBreak(TModifyProcessBreakInfo* aBreakInfo); sl@0: TInt priv_DoBreakInfo(TGetBreakInfo* aBreakInfo); sl@0: TInt priv_DisableBreakAtAddress(TUint32 aAddress); sl@0: TInt priv_DoEnableDisabledBreak(TUint64 aThreadId); sl@0: void priv_DoRemoveThreadBreaks(TUint64 aThreadId); sl@0: void priv_ClearAllBreakPoints(); sl@0: TBool priv_IsTemporaryBreak(const TBreakEntry& aBreakEntry) const; sl@0: sl@0: // helper functions sl@0: TBool Aligned(TUint32 aAddress, Debug::TArchitectureMode aMode); sl@0: TInt BreakSize(Debug::TArchitectureMode aMode); sl@0: TBool BreakpointsOverlap(TBreakEntry& aFirst, TBreakEntry& aSecond); sl@0: TUint32 BreakInst(Debug::TArchitectureMode aMode); sl@0: sl@0: private: sl@0: RArray iBreakPointList; sl@0: TInt iNextBreakId; sl@0: sl@0: DRM_DebugChannel* iChannel; // temporary reference back to DRM_DebugChannel to help with refactoring sl@0: sl@0: /* Protect access to the breakpoint list with a DSemaphore sl@0: * sl@0: * This means that stop-mode debuggers know when the list is being updated by the run-mode debug subsystem. sl@0: */ sl@0: DSemaphore* iLock; sl@0: sl@0: TBool iInitialised; sl@0: }; sl@0: sl@0: #endif