#include #include #include #include "cvconst.h" #include using namespace PdbKeys; struct Pdb : Debugger, ParentCtrl { virtual void Stop(); virtual bool IsFinished(); virtual bool Key(dword key, int count); virtual void DebugBar(Bar& bar); virtual bool SetBreakpoint(const String& filename, int line, const String& bp); virtual bool RunTo(); virtual void Run(); virtual bool Tip(const String& exp, CodeEditor::MouseTip& mt); virtual void Serialize(Stream& s); struct ModuleInfo : Moveable { adr_t base; dword size; String path; bool symbols; ModuleInfo() { base = size = 0; symbols = false; } }; struct FilePos { String path; int line; adr_t address; operator bool() const { return !IsNull(path); } FilePos() { line = 0; address = 0; } FilePos(const String& p, int l) : path(p), line(l) { address = 0; } }; enum CpuRegisterKind { REG_L, REG_H, REG_X, REG_E, REG_R }; struct CpuRegister : Moveable { int sym; // DbgHelp register symbol const char *name; // NULL: Do not list (e.g. al, as it is printed as EAX or RAX int kind; // CpuRegisterKind dword flags; // Unused }; struct MemPg : Moveable { char data[1024]; }; struct PdbHexView : HexView { Pdb *pdb; virtual int Byte(int64 addr) { return pdb ? pdb->Byte((adr_t)addr) : 0; } PdbHexView() { pdb = NULL; } } memory; struct FnInfo : Moveable { String name; adr_t address; dword size; dword pdbtype; FnInfo() { address = size = pdbtype = 0; } }; enum { UNKNOWN = -99, BOOL1, SINT1, UINT1, SINT2, UINT2, SINT4, UINT4, SINT8, UINT8, FLT, DBL, PFUNC }; struct Val : Moveable { int type; int ref; bool array:1; bool rvalue:1; byte bitpos; byte bitcnt; union { adr_t address; int64 ival; double fval; }; #ifdef _DEBUG String ToString() const; #endif Val() { type = UNKNOWN; rvalue = false; ref = 0; array = false; bitcnt = 0; address = 0; } }; struct NamedVal : Moveable { String name; Val val; }; struct Type : Moveable { Type() : size(-1), vtbl_typeindex(-1) {} adr_t modbase; String name; int size; int vtbl_typeindex; int vtbl_offset; Vector base; VectorMap member; VectorMap static_member; }; struct Frame : Moveable { adr_t pc, frame, stack; FnInfo fn; VectorMap param; VectorMap local; String text; }; struct VisualPart : Moveable { String text; Color ink; bool mark; }; struct Visual { int length; Vector part; void Cat(const String& text, Color ink = SColorText); void Cat(const char *text, Color ink = SColorText); String GetString() const; void Clear() { part.Clear(); length = 0; } Size GetSize() const; Visual() { length = 0; } }; struct VisualDisplay : Display { virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const; }; struct Context { #ifdef CPU_64 union { CONTEXT context64; WOW64_CONTEXT context32; }; #else CONTEXT context32; #endif }; struct Thread : Context { HANDLE hThread; adr_t sp; }; int lock; bool running; bool stop; HANDLE hProcess; HANDLE mainThread; DWORD processid; DWORD hProcessId; DWORD mainThreadId; ArrayMap threads; bool terminated; bool refreshmodules; Vector module; DEBUG_EVENT event; DWORD debug_threadid; HWND hWnd; VectorMap bp_set; // breakpoints active for single RunToException bool win64; // debugee is 64-bit, always false in 32-bit exe Context context; Index invalidpage; VectorMap mempage; Index breakpoint; Vector breakpoint_cond; ArrayMap type; String disas_name; Array frame; Frame *current_frame; String autotext; VectorMap fninfo_cache; DbgDisas disas; EditString watchedit; enum { // Order in this enum has to be same as order of tab.Add TAB_AUTOS, TAB_LOCALS, TAB_THIS, TAB_WATCHES, TAB_EXPLORER, TAB_CPU, TAB_MEMORY }; TabCtrl tab; DropList threadlist; DropList framelist; Button frame_up, frame_down; Label dlock; ArrayCtrl locals; ArrayCtrl self; ArrayCtrl watches; ArrayCtrl autos; ArrayCtrl explorer; ColumnList cpu; EditString expexp; Button exback, exfw; StaticRect explorer_pane; StaticRect pane; Splitter split; TreeCtrl tree; bool first_exception = true; VectorMap treetype; Vector exprev, exnext; Index noglobal; VectorMap global; bool break_running; // Needed for Wow64 BreakRunning to avoid ignoring breakpoint void Error(const char *s = NULL); String Hex(adr_t); // CPU registers uint32 GetRegister32(const Context& ctx, int sym); uint64 GetRegister64(const Context& ctx, int sym); const VectorMap& GetRegisterList(); uint64 GetCpuRegister(const Context& ctx, int sym); // debug Context ReadContext(HANDLE hThread); void WriteContext(HANDLE hThread, Context& context); void LoadModuleInfo(); int FindModuleIndex(adr_t base); void UnloadModuleSymbols(); void AddThread(dword dwThreadId, HANDLE hThread); void RemoveThread(dword dwThreadId); void Lock(); void Unlock(); void ToForeground(); bool RunToException(); bool AddBp(adr_t address); bool RemoveBp(adr_t address); bool RemoveBp(); bool IsBpSet(adr_t address) const { return bp_set.Find(address) >= 0; } bool Continue(); bool SingleStep(); void BreakRunning(); bool ConditionalPass(); void SetBreakpoints(); void SaveForeground(); void RestoreForeground(); adr_t GetIP(); void WriteContext(); // mem int Byte(adr_t addr); bool Copy(adr_t addr, void *ptr, int count); String ReadString(adr_t addr, int maxlen = INT_MAX); WString ReadWString(adr_t addr, int maxlen = INT_MAX); // sym struct LocalsCtx; static BOOL CALLBACK EnumLocals(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext); static BOOL CALLBACK EnumGlobals(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext); void TypeVal(Pdb::Val& v, int typeId, adr_t modbase); String GetSymName(adr_t modbase, dword typeindex); dword GetSymInfo(adr_t modbase, dword typeindex, IMAGEHLP_SYMBOL_TYPE_INFO info); const Type& GetType(int ti); int GetTypeIndex(adr_t modbase, dword typeindex); Val GetGlobal(const String& name); adr_t GetAddress(FilePos p); FilePos GetFilePos(adr_t address); FnInfo GetFnInfo0(adr_t address); FnInfo GetFnInfo(adr_t address); void GetLocals(Frame& frame, Context& context, VectorMap& param, VectorMap& local); String TypeAsString(int ti, bool deep = true); // exp void ThrowError(const char *s); int SizeOfType(int ti); Val GetRVal(Val v, Thread& ctx); Val DeRef(Val v, Thread& ctx); Val Ref(Val v); int64 GetInt(Val v, Thread& ctx); double GetFlt(Val v, Thread& ctx); void ZeroDiv(double x); Val Compute(Val v1, Val v2, int oper, Thread& ctx); Val RValue(int64 v); Val Field0(Pdb::Val v, const String& field); Val Field(Pdb::Val v, const String& field); Val Term(CParser& p, Thread& ctx); Val Post(CParser& p, Thread& ctx); Val Unary(CParser& p, Thread& ctx); Val Additive(CParser& p, Thread& ctx); Val Multiplicative(CParser& p, Thread& ctx); Val Compare(Val v, CParser& p, int r1, int r2, Thread& ctx); void GetBools(Val v1, Val v2, bool& a, bool& b, Thread& ctx); Val LogAnd(CParser& p, Thread& ctx); Val LogOr(CParser& p, Thread& ctx); Val Comparison(CParser& p, Thread& ctx); Val Exp0(CParser& p, Thread& ctx); Val Exp(CParser& p, Thread& ctx); void CatInt(Visual& result, int64 val); void BaseFields(Visual& result, const Type& t, Pdb::Val val, Thread& ctx, int expandptr, int slen, bool& cm, int depth); void Visualise(Visual& result, Pdb::Val val, Thread& ctx, int expandptr, int slen); void Visualise(Visual& result, Pdb::Val val, Thread& ctx, int expandptr); Visual Visualise(Val v, Thread& ctx); Visual Visualise(const String& rexp, Thread& ctx); // code Thread& Current(); Array Backtrace(Thread& ctx, bool single_frame = false); int Disassemble(adr_t ip); bool IsValidFrame(adr_t eip); void Sync0(Thread& ctx); void Sync(); void SetThread(); void FrameUpDown(int dir); void SetFrame(); bool Step(bool over); void Trace(bool over); void StepOut(); void DoRunTo() { RunTo(); } adr_t CursorAdr(); void SetIp(); void Break(); // data static VectorMap DataMap(const ArrayCtrl& a); static Value Vis(const String& key, const VectorMap& prev, Visual&& vis, bool& ch); static void Vis(ArrayCtrl& a, const String& key, const VectorMap& prev, Visual&& vis); void DisasCursor() {} void DisasFocus() {} void Locals(); void Watches(); void TryAuto(const String& exp, const VectorMap& prev); void Autos(); void AddThis(const VectorMap& m, adr_t address, const VectorMap& prev); void AddThis(int type, adr_t address, const VectorMap& prev); void This(); void Explore(const Val& val, const VectorMap& prev); void Explore(const String& exp); void ExploreKey(ArrayCtrl *a); void Explorer(); void ExpExp(); void ExBack(); void ExFw(); void DoExplorer(); String GetExpExp(); void ExplorerTree(); void Data(); void ClearWatches(); void DropWatch(PasteClip& clip); void AddWatch(); void EditWatch(); void RemoveWatch(); void SetTab(int i); void SetTree(const String& exp); void SetTreeA(ArrayCtrl *data); void TreeNode(int parent, const String& name, Val val); void TreeExpand(int node); String StoreTree(int parent); void SaveTree(); void ExpandTreeType(int parent, CParser& p); void CopyStack(); void CopyStackAll(); void CopyDisas(); void MemoryGoto(const String& exp); void MemMenu(ArrayCtrl& array, Bar& bar, const String& exp); void DataMenu(ArrayCtrl& array, Bar& bar, const String& exp); void AutosMenu(Bar& bar); void LocalsMenu(Bar& bar); void WatchesMenu(Bar& bar); void ExplorerMenu(Bar& bar); void Tab(); bool Create(One host, const String& exefile, const String& cmdline); void SerializeSession(Stream& s); typedef Pdb CLASSNAME; Pdb(); virtual ~Pdb(); void LoadGlobals(DWORD64 base); }; bool EditPDBExpression(const char *title, String& brk, Pdb *pdb);