192 lines
4.3 KiB
C++
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_
|