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