Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

513 lines
14 KiB

//----------------------------------------------------------------------------
//
// Breakpoint support.
//
// Copyright (C) Microsoft Corporation, 1997-2002.
//
//----------------------------------------------------------------------------
#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 | DEBUG_BREAKPOINT_ONE_SHOT)
#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
};
enum BreakpointEvalResult
{
BPEVAL_RESOLVED,
BPEVAL_RESOLVED_NO_MODULE,
BPEVAL_UNRESOLVED,
BPEVAL_ERROR,
BPEVAL_UNKNOWN,
};
class Breakpoint
: public IDebugBreakpoint
{
public:
Breakpoint* m_Next;
Breakpoint* m_Prev;
ULONG m_Refs;
ULONG m_Id;
ULONG m_BreakType;
ULONG m_Flags;
ULONG m_CodeFlags;
ULONG m_DataSize;
ULONG m_DataAccessType;
ULONG m_PassCount;
ULONG m_CurPassCount;
PCSTR m_Command;
ThreadInfo* m_MatchThread;
ProcessInfo* 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;
// Internal refcounting which does true counting,
// as opposed to the disabled public AddRef/Release.
void Preserve(void)
{
m_Refs++;
}
void Relinquish(void)
{
if (--m_Refs == 0)
{
delete this;
}
}
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 NotifyChanged(void)
{
if (!(m_Flags & BREAKPOINT_HIDDEN))
{
NotifyChangeEngineState(DEBUG_CES_BREAKPOINTS, m_Id, TRUE);
}
}
HRESULT SetEvaluatedOffsetExpression(PCSTR Expr,
BreakpointEvalResult Valid,
PADDR Addr);
void LinkIntoList(void);
void UnlinkFromList(void);
void UpdateInternal(void);
BOOL EvalOffsetExpr(BreakpointEvalResult Valid, PADDR Addr);
HRESULT CheckAddr(PADDR Addr);
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(ThreadInfo* Thread);
void AddToThread(ThreadInfo* 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;
HRESULT BreakpointInit(void);
HRESULT InsertBreakpoints(void);
HRESULT RemoveBreakpoints(void);
HRESULT AddBreakpoint(DebugClient* Client,
MachineInfo* Machine,
ULONG Type,
ULONG DesiredId,
Breakpoint** Bp);
void RemoveBreakpoint(Breakpoint* Bp);
void RemoveProcessBreakpoints(ProcessInfo* Process);
void RemoveThreadBreakpoints(ThreadInfo* Thread);
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(ProcessInfo* Process,
Breakpoint* Start, PADDR Addr,
ULONG ExbsType, ULONG IncFlags, ULONG ExcFlags,
PULONG HitType,
BOOL SetLastBreakpointHit);
ULONG NotifyHitBreakpoints(ULONG EventStatus);
void EvaluateOffsetExpressions(ProcessInfo* 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, ProcessInfo* ForProcess,
ULONG Id, UCHAR StateChange);
void ListBreakpoints(DebugClient* Client, ProcessInfo* ForProcess,
ULONG Id);
void ListBreakpointsAsCommands(DebugClient* Client, ProcessInfo* Process,
ULONG Flags);
PDEBUG_BREAKPOINT ParseBpCmd(DebugClient* Client, UCHAR Type,
ThreadInfo* Thread);
BOOL CheckBreakpointInsertedInRange(ProcessInfo* Process,
ULONG64 Start, ULONG64 End);
#endif // #ifndef _BRKPT_HPP_