windows-nt/Source/XPSP1/NT/sdktools/debuggers/ntsd64/brkpt.hpp
2020-09-26 16:20:57 +08:00

470 lines
12 KiB
C++

//----------------------------------------------------------------------------
//
// Breakpoint support.
//
// Copyright (C) Microsoft Corporation, 1997-2001.
//
//----------------------------------------------------------------------------
#ifndef _BRKPT_HPP_
#define _BRKPT_HPP_
// Ways in which a breakpoint can be hit. There's full
// match, hit but ignored and not hit.
#define BREAKPOINT_HIT 0
#define BREAKPOINT_HIT_IGNORED 1
#define BREAKPOINT_NOT_HIT 2
//----------------------------------------------------------------------------
//
// Breakpoint.
//
//----------------------------------------------------------------------------
#define BREAKPOINT_EXTERNAL_MODIFY_FLAGS \
(DEBUG_BREAKPOINT_GO_ONLY | DEBUG_BREAKPOINT_ENABLED | \
DEBUG_BREAKPOINT_ADDER_ONLY)
#define BREAKPOINT_EXTERNAL_FLAGS \
(BREAKPOINT_EXTERNAL_MODIFY_FLAGS | DEBUG_BREAKPOINT_DEFERRED)
// Internal flags.
#define BREAKPOINT_KD_INTERNAL 0x80000000
#define BREAKPOINT_KD_COUNT_ONLY 0x40000000
#define BREAKPOINT_VIRT_ADDR 0x20000000
#define BREAKPOINT_INSERTED 0x10000000
#define BREAKPOINT_IN_LIST 0x08000000
#define BREAKPOINT_HIDDEN 0x04000000
#define BREAKPOINT_NOTIFY 0x02000000
// Internal types.
#define EXBS_NONE 0x00000000
#define EXBS_BREAKPOINT_DATA 0x00000001
#define EXBS_BREAKPOINT_CODE 0x00000002
#define EXBS_BREAKPOINT_ANY 0x00000003
#define EXBS_STEP_INSTRUCTION 0x00000004
#define EXBS_STEP_BRANCH 0x00000008
#define EXBS_STEP_ANY 0x0000000c
#define EXBS_ANY 0xffffffff
enum BreakpointMatchAction
{
BREAKPOINT_ALLOW_MATCH,
BREAKPOINT_WARN_MATCH,
BREAKPOINT_REMOVE_MATCH
};
class Breakpoint
: public IDebugBreakpoint
{
public:
Breakpoint* m_Next;
Breakpoint* m_Prev;
ULONG m_Id;
ULONG m_BreakType;
ULONG m_Flags;
ULONG m_DataSize;
ULONG m_DataAccessType;
ULONG m_PassCount;
ULONG m_CurPassCount;
PCSTR m_Command;
PTHREAD_INFO m_MatchThread;
PPROCESS_INFO m_Process;
PCSTR m_OffsetExpr;
DebugClient* m_Adder;
ULONG64 m_MatchThreadData;
ULONG64 m_MatchProcessData;
Breakpoint(DebugClient* Adder, ULONG Id, ULONG Type, ULONG ProcType);
~Breakpoint(void);
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
// IDebugBreakpoint.
STDMETHOD(GetId)(
THIS_
OUT PULONG Id
);
STDMETHOD(GetType)(
THIS_
OUT PULONG BreakType,
OUT PULONG ProcType
);
STDMETHOD(GetAdder)(
THIS_
OUT PDEBUG_CLIENT* Adder
);
STDMETHOD(GetFlags)(
THIS_
OUT PULONG Flags
);
STDMETHOD(AddFlags)(
THIS_
IN ULONG Flags
);
STDMETHOD(RemoveFlags)(
THIS_
IN ULONG Flags
);
STDMETHOD(SetFlags)(
THIS_
IN ULONG Flags
);
STDMETHOD(GetOffset)(
THIS_
OUT PULONG64 Offset
);
STDMETHOD(SetOffset)(
THIS_
IN ULONG64 Offset
);
STDMETHOD(GetDataParameters)(
THIS_
OUT PULONG Size,
OUT PULONG AccessType
);
STDMETHOD(SetDataParameters)(
THIS_
IN ULONG Size,
IN ULONG AccessType
);
STDMETHOD(GetPassCount)(
THIS_
OUT PULONG Count
);
STDMETHOD(SetPassCount)(
THIS_
IN ULONG Count
);
STDMETHOD(GetCurrentPassCount)(
THIS_
OUT PULONG Count
);
STDMETHOD(GetMatchThreadId)(
THIS_
OUT PULONG Id
);
STDMETHOD(SetMatchThreadId)(
THIS_
IN ULONG Id
);
STDMETHOD(GetCommand)(
THIS_
OUT OPTIONAL PSTR Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG CommandSize
);
STDMETHOD(SetCommand)(
THIS_
IN PCSTR Command
);
STDMETHOD(GetOffsetExpression)(
THIS_
OUT OPTIONAL PSTR Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG ExpressionSize
);
STDMETHOD(SetOffsetExpression)(
THIS_
IN PCSTR Expression
);
STDMETHOD(GetParameters)(
THIS_
OUT PDEBUG_BREAKPOINT_PARAMETERS Params
);
// Breakpoint.
virtual HRESULT Validate(void) = 0;
virtual HRESULT Insert(void) = 0;
virtual HRESULT Remove(void) = 0;
virtual ULONG IsHit(PADDR Addr) = 0;
// Must resturn true if in case of THIS breakpoint hit
// Pc points to the instruction caused the hit
virtual BOOL PcAtHit() = 0;
PADDR GetAddr(void)
{
return &m_Addr;
}
BOOL PassHit(void)
{
if (--m_CurPassCount == 0)
{
m_CurPassCount = 1;
return TRUE;
}
else
{
return FALSE;
}
}
ULONG GetProcType(void)
{
return m_ProcType;
}
void SetProcType(ULONG ProcType)
{
m_ProcType = ProcType;
m_ProcIndex = MachineTypeIndex(ProcType);
}
ULONG GetProcIndex(void)
{
return m_ProcIndex;
}
void ForceFlatAddr(void)
{
NotFlat(m_Addr);
ComputeFlatAddress(&m_Addr, NULL);
}
// Breakpoint is enabled, not deferred, not internal.
BOOL IsNormalEnabled(void)
{
return (m_Flags & (DEBUG_BREAKPOINT_ENABLED |
BREAKPOINT_KD_INTERNAL |
DEBUG_BREAKPOINT_DEFERRED)) ==
DEBUG_BREAKPOINT_ENABLED;
}
void LinkIntoList(void);
void UnlinkFromList(void);
void UpdateInternal(void);
BOOL EvalOffsetExpr(void);
HRESULT SetAddr(PADDR Addr, BreakpointMatchAction MatchAction);
// Matches breakpoints if they have the same insertion effect.
// Used when determining whether a breakpoint needs to be
// inserted or if another breakpoint is already covering the break.
BOOL IsInsertionMatch(Breakpoint* Match);
// Matches breakpoints if they have an insertion match and
// if they match publicly, such as between flags, hiddenness
// and so on. Used when determining whether a user breakpoint
// redefines an existing breakpoint.
BOOL IsPublicMatch(Breakpoint* Match);
// Check m_Match* fields against current state.
BOOL MatchesCurrentState(void);
protected:
// ProcType is private so that ProcType and ProcIndex can
// be kept in sync.
ULONG m_ProcType;
MachineIndex m_ProcIndex;
// Address is private to force users to go through SetAddr.
ADDR m_Addr;
ULONG m_CommandLen;
ULONG m_OffsetExprLen;
UCHAR m_InsertStorage[MAX_BREAKPOINT_LENGTH];
};
//----------------------------------------------------------------------------
//
// CodeBreakpoint.
//
//----------------------------------------------------------------------------
class CodeBreakpoint :
public Breakpoint
{
public:
CodeBreakpoint(DebugClient* Adder, ULONG Id, ULONG ProcType)
: Breakpoint(Adder, Id, DEBUG_BREAKPOINT_CODE, ProcType)
{
m_Flags |= BREAKPOINT_VIRT_ADDR;
}
// Breakpoint.
virtual HRESULT Validate(void);
virtual HRESULT Insert(void);
virtual HRESULT Remove(void);
virtual ULONG IsHit(PADDR Addr);
virtual BOOL PcAtHit()
{
return TRUE;
}
};
//----------------------------------------------------------------------------
//
// DataBreakpoint.
//
//----------------------------------------------------------------------------
class DataBreakpoint :
public Breakpoint
{
public:
DataBreakpoint(DebugClient* Adder, ULONG Id, ULONG ProcType)
: Breakpoint(Adder, Id, DEBUG_BREAKPOINT_DATA, ProcType) {}
// Breakpoint.
virtual HRESULT Insert(void);
virtual HRESULT Remove(void);
// DataBreakpoint.
static void ClearThreadDataBreaks(PTHREAD_INFO Thread);
void AddToThread(PTHREAD_INFO Thread);
};
//----------------------------------------------------------------------------
//
// X86DataBreakpoint.
//
//----------------------------------------------------------------------------
class X86DataBreakpoint :
public DataBreakpoint
{
public:
X86DataBreakpoint(DebugClient* Adder, ULONG Id,
ULONG Cr4Reg, ULONG Dr6Reg, ULONG ProcType)
: DataBreakpoint(Adder, Id, ProcType)
{
m_Dr7Bits = 0;
m_Cr4Reg = Cr4Reg;
m_Dr6Reg = Dr6Reg;
}
// Breakpoint.
virtual HRESULT Validate(void);
virtual ULONG IsHit(PADDR Addr);
virtual BOOL PcAtHit()
{
return FALSE;
}
private:
// Precomputed enable bits.
ULONG m_Dr7Bits;
// Register indices for getting breakpoint-related information.
ULONG m_Cr4Reg;
ULONG m_Dr6Reg;
friend class X86MachineInfo;
friend class Amd64MachineInfo;
};
//----------------------------------------------------------------------------
//
// Ia64DataBreakpoint.
//
//----------------------------------------------------------------------------
class Ia64DataBreakpoint :
public DataBreakpoint
{
public:
Ia64DataBreakpoint(DebugClient* Adder, ULONG Id)
: DataBreakpoint(Adder, Id, IMAGE_FILE_MACHINE_IA64)
{
m_Control = 0;
}
// Breakpoint.
virtual HRESULT Validate(void);
virtual ULONG IsHit(PADDR Addr);
virtual BOOL PcAtHit()
{
return TRUE;
}
static ULONG64 GetControl(ULONG AccessType, ULONG Size);
private:
ULONG64 m_Control;
friend class Ia64MachineInfo;
};
//----------------------------------------------------------------------------
//
// X86OnIa64DataBreakpoint.
//
//----------------------------------------------------------------------------
class X86OnIa64DataBreakpoint :
public X86DataBreakpoint
{
public:
X86OnIa64DataBreakpoint(DebugClient* Adder, ULONG Id);
// Breakpoint.
virtual HRESULT Validate(void);
virtual ULONG IsHit(PADDR Addr);
private:
ULONG64 m_Control;
friend class Ia64MachineInfo;
};
extern BOOL g_BreakpointListChanged;
extern BOOL g_UpdateDataBreakpoints;
extern BOOL g_DataBreakpointsChanged;
extern BOOL g_BreakpointsSuspended;
extern BOOL g_DeferDefined;
extern Breakpoint* g_DeferBp;
extern Breakpoint* g_StepTraceBp;
extern CHAR g_StepTraceCmdState;
extern ADDR g_PrevRelatedPc;
HRESULT BreakpointInit(void);
HRESULT InsertBreakpoints(void);
BOOL RemoveBreakpoints(void);
HRESULT AddBreakpoint(DebugClient* Client,
ULONG Type,
ULONG DesiredId,
Breakpoint** Bp);
void RemoveBreakpoint(Breakpoint* Bp);
void RemoveProcessBreakpoints(PPROCESS_INFO Process);
void RemoveThreadBreakpoints(PTHREAD_INFO Thread);
void RemoveAllKernelBreakpoints(void);
void RemoveAllBreakpoints(ULONG Reason);
Breakpoint* GetBreakpointByIndex(DebugClient* Client, ULONG Index);
Breakpoint* GetBreakpointById(DebugClient* Client, ULONG Id);
Breakpoint* CheckMatchingBreakpoints(Breakpoint* Match, BOOL PUBLIC,
ULONG IncFlags);
Breakpoint* CheckBreakpointHit(PPROCESS_INFO Process,
Breakpoint* Start, PADDR Addr,
ULONG ExbsType, ULONG IncFlags, ULONG ExcFlags,
PULONG HitType,
BOOL SetLastBreakpointHit);
ULONG NotifyHitBreakpoints(ULONG EventStatus);
void EvaluateOffsetExpressions(PPROCESS_INFO Process, ULONG Flags);
#define BPCMDS_FORCE_DISABLE 0x00000001
#define BPCMDS_ONE_LINE 0x00000002
#define BPCMDS_EXPR_ONLY 0x00000004
#define BPCMDS_MODULE_HINT 0x00000008
void ChangeBreakpointState(DebugClient* Client, PPROCESS_INFO ForProcess,
ULONG Id, UCHAR StateChange);
void ListBreakpoints(DebugClient* Client, PPROCESS_INFO ForProcess,
ULONG Id);
void ListBreakpointsAsCommands(DebugClient* Client, PPROCESS_INFO Process,
ULONG Flags);
PDEBUG_BREAKPOINT ParseBpCmd(DebugClient* Client, UCHAR Type,
PTHREAD_INFO Thread);
BOOL CheckBreakpointInsertedInRange(PPROCESS_INFO Process,
ULONG64 Start, ULONG64 End);
void DbgKdpAcquireHardwareBp(PDBGKD_CONTROL_REQUEST BpRequest);
void DbgKdpReleaseHardwareBp(PDBGKD_CONTROL_REQUEST BpRequest);
#endif // #ifndef _BRKPT_HPP_