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

192 lines
4.3 KiB
C++

//----------------------------------------------------------------------------
//
// Handles stepping, tracing, watching and go.
//
// Copyright (C) Microsoft Corporation, 1997-2000.
//
//----------------------------------------------------------------------------
#ifndef _STEPGO_HPP_
#define _STEPGO_HPP_
struct WatchFunction
{
ULONG64 StartOffset;
// Hash bucket list.
WatchFunction* Next;
// Sorted list.
WatchFunction* Sort;
ULONG Calls;
ULONG MinInstr, MaxInstr, TotalInstr;
// This counter is incremented every time a system call
// instruction is hit inside the function.
ULONG SystemCalls;
// There's no strong need to make this symbol buffer
// MAX_SYMBOL_LEN as the output only displays half a
// line's worth of the name. The only real reason to
// keep more is to reduce false sharing due to prefix
// matches. The buffer is large enough that this should
// be extremely rare, plus we keep the true length
// as a further check.
ULONG SymbolLength;
CHAR Symbol[256];
};
struct WatchCallStack
{
ADDR CallSite;
WatchFunction* Func;
WatchCallStack* Prev, *Next;
LONG Level;
ULONG InstrCount, ChildInstrCount;
};
//----------------------------------------------------------------------------
//
// WatchFunctions.
//
// Collects function information encountered during watch tracing.
//
//----------------------------------------------------------------------------
#define WF_BUCKETS 71
class WatchFunctions
{
public:
WatchFunctions(void);
void Start(void);
void End(PADDR PcAddr);
BOOL IsStarted(void)
{
return m_Started;
}
void OutputFunctions(void);
void OutputSysCallFunctions(void);
WatchFunction* FindAlways(PSTR Sym, ULONG64 Start);
WatchCallStack* GetTopCall(void)
{
return m_CallTop;
}
WatchCallStack* PushCall(WatchFunction* Func);
void PopCall(void);
WatchCallStack* PopCallsToCallSite(PADDR Pc);
WatchCallStack* PopCallsToFunctionStart(ULONG64 Start);
void ReuseCall(WatchCallStack* Call,
WatchFunction* ReinitFunc);
void OutputCall(WatchCallStack* Call);
LONG GetCallLevel(void)
{
return m_CallLevel;
}
LONG ChangeCallLevel(LONG Delta)
{
m_CallLevel += Delta;
if (m_CallLevel < 0)
{
m_CallLevel = 0;
}
return m_CallLevel;
}
ULONG RecordEvent(void)
{
return ++m_TotalWatchTraceEvents;
}
ULONG RecordThreadMismatch(void)
{
return ++m_TotalWatchThreadMismatches;
}
protected:
ULONG Hash(PSTR Sym, ULONG SymLen)
{
// Hash on the first and last letters of the symbol.
return ((ULONG)(UCHAR)Sym[0] +
(ULONG)(UCHAR)Sym[SymLen - 1]) % WF_BUCKETS;
}
WatchFunction* Add(PSTR Sym, ULONG64 Start);
WatchFunction* Find(PSTR Sym);
void Clear(void);
BOOL m_Started;
ULONG m_TotalInstr;
ULONG m_TotalWatchTraceEvents;
ULONG m_TotalWatchThreadMismatches;
WatchFunction* m_Funcs[WF_BUCKETS];
WatchFunction* m_Sorted;
WatchCallStack* m_CallTop, *m_CallBot;
LONG m_CallLevel;
};
extern WatchFunctions g_WatchFunctions;
extern ULONG g_StepTracePassCount;
extern ULONG64 g_StepTraceInRangeStart;
extern ULONG64 g_StepTraceInRangeEnd;
extern BOOL g_SrcLineValid;
extern BOOL g_WatchTrace;
extern BOOL g_WatchWhole;
extern ADDR g_WatchTarget;
extern ULONG64 g_WatchInitialSP;
extern ULONG64 g_WatchBeginCurFunc;
extern ULONG64 g_WatchEndCurFunc;
#define MAX_GO_BPS 16
extern Breakpoint* g_GoBreakpoints[MAX_GO_BPS];
extern ULONG g_NumGoBreakpoints;
BOOL StepTracePass(PADDR);
void
fnGoExecution (
ULONG ExecStatus,
PADDR startaddr,
ULONG bpcount,
PTHREAD_INFO pThread,
BOOL fThreadFreeze,
PADDR bparray
);
void
fnStepTrace (
PADDR addr,
ULONG64 count,
PTHREAD_INFO pThread,
BOOL fThreadFreeze,
UCHAR chStepType
);
void
parseGoCmd (
PTHREAD_INFO pThread,
BOOL fThreadFreeze
);
VOID
parseStepTrace (
PTHREAD_INFO pThread,
BOOL fThreadFreeze,
UCHAR chcmd
);
VOID SetupSpecialCalls(VOID);
#endif // #ifndef _STEPGO_HPP_