#include "Debuggers.h" #ifdef COMPILER_MSC #define LLOG(x) // LOG(x) VectorMap Pdb::DataMap(const ArrayCtrl& a) { VectorMap r; for(int i = 0; i < a.GetCount(); i++) r.Add(a.Get(i, 0), a.Get(i, 1)); return r; } Value Pdb::Vis(const String& key, const VectorMap& prev, pick_ Visual& vis, bool& ch) { int q = prev.Find(key); ch = false; for(int i = 0; i < vis.part.GetCount(); i++) { VisualPart& p = vis.part[i]; p.mark = false; if(q >= 0 && IsType(prev[q])) { const Visual& v = ValueTo(prev[q]); if(v.part.GetCount() == vis.part.GetCount() && v.part[i].text != p.text) ch = p.mark = true; } } return RawPickToValue(vis); } void Pdb::Vis(ArrayCtrl& a, const String& key, const VectorMap& prev, pick_ Visual& vis) { bool ch; a.Add(key, Vis(key, prev, vis, ch)); // if(ch) // a.SetDisplay(a.GetCount() - 1, 0, Single()); } void Pdb::Locals() { VectorMap prev = DataMap(locals); locals.Clear(); int q = ~framelist; if(q >= 0 && q < frame.GetCount()) { Frame& f = frame[q]; for(int i = 0; i < f.param.GetCount(); i++) Vis(locals, f.param.GetKey(i), prev, Visualise(f.param[i])); for(int i = 0; i < f.local.GetCount(); i++) Vis(locals, f.local.GetKey(i), prev, Visualise(f.local[i])); } } void Pdb::Watches() { VectorMap prev = DataMap(watches); for(int i = 0; i < watches.GetCount(); i++) { bool ch; watches.Set(i, 1, Vis((String)watches.Get(i, 0), prev, Visualise((String)watches.Get(i, 0)), ch)); if(ch) watches.SetDisplay(i, 0, Single()); else watches.SetDisplay(i, 0, StdDisplay()); } } void Pdb::Explore(const Val& val, const VectorMap& prev) { const Type& t = GetType(val.type); for(int i = 0; i < t.base.GetCount(); i++) { Val b = t.base[i]; b.address += val.address; Vis(explorer, ':' + GetType(b.type).name, prev, Visualise(b)); } for(int i = 0; i < t.member.GetCount(); i++) { Val r = t.member[i]; r.address += val.address; Vis(explorer, '.' + t.member.GetKey(i), prev, Visualise(r)); } for(int i = 0; i < t.static_member.GetCount(); i++) Vis(explorer, "::" + t.static_member.GetKey(i), prev, Visualise(t.static_member[i])); } void Pdb::Explorer() { VectorMap prev = DataMap(explorer); explorer.Clear(); try { String x = ~expexp; if(!IsNull(x)) { CParser p(x); Val v = Exp(p); Vis(explorer, "=", prev, Visualise(v)); if(v.type >= 0 && v.ref == 0 && !v.rvalue) Explore(v, prev); if(v.ref > 0 && GetRVal(v).address) for(int i = 0; i < 20; i++) Vis(explorer, Format("[%d]", i), prev, Visualise(DeRef(Compute(v, RValue(i), '+')))); } } catch(CParser::Error e) { Visual v; v.Cat(e, LtRed); explorer.Add("", RawPickToValue(v)); } exback.Enable(exprev.GetCount()); exfw.Enable(exnext.GetCount()); } void Pdb::Explore(const String& exp) { exprev.Add(~expexp); expexp = exp; Explorer(); DoExplorer(); } String Pdb::GetExpExp() { String w; if(explorer.IsCursor()) { w = expexp; for(const char *s = w; *s; s++) if(strchr("*/+-", *s)) { w = '(' + w + ')'; break; } String k = (String)explorer.GetKey(); if(k != "=") w = w + k; } return w; } void Pdb::ExpExp() { if(explorer.GetCursor() > 0) Explore(GetExpExp()); } void Pdb::ExplorerTree() { SetTree(GetExpExp()); } void Pdb::DoExplorer() { tab.Set(3); expexp.SetFocus(); expexp.SetSelection(); Explorer(); } void Pdb::ExBack() { if(exprev.GetCount()) { exnext.Add(~expexp); expexp <<= exprev.Pop(); Explorer(); } } void Pdb::ExFw() { if(exnext.GetCount()) { exprev.Add(~expexp); expexp <<= exnext.Pop(); Explorer(); } } void Pdb::ExploreKey(ArrayCtrl *a) { if(a && a->IsCursor()) { tab.Set(3); Explore(a->GetKey()); } } void Pdb::TryAuto(const String& exp, const VectorMap& prev) { if(autos.Find(exp) < 0) { Visual r; try { CParser p(exp); Val v = Exp(p); Visualise(r, v, 2, 20); } catch(CParser::Error) { r.Clear(); } if(r.part.GetCount()) Vis(autos, exp, prev, r); } } void Pdb::Autos() { VectorMap prev = DataMap(autos); autos.Clear(); CParser p(autotext); while(!p.IsEof()) if(p.IsId()) { String exp = p.ReadId(); TryAuto(exp, prev); for(;;) { if(p.Char('.') && p.IsId()) exp << '.'; else if(p.Char2('-', '>') && p.IsId()) exp << "->"; else break; exp << p.ReadId(); TryAuto(exp, prev); } } else p.SkipTerm(); autos.Sort(); // MarkChanged(prev, autos); } void Pdb::Data() { switch(tab.Get()) { case 0: Autos(); break; case 1: Locals(); break; case 2: Watches(); break; case 3: Explorer(); break; } } void Pdb::TreeNode(int parent, const String& name, Pdb::Val val) { NamedVal nv; nv.name = name; nv.val = val; tree.Add(parent, Null, RawToValue(nv), name + "=" + Visualise(val).GetString(), val.type >= 0 || val.ref > 0); } void Pdb::TreeExpand(int node) { if(tree.GetChildCount(node)) return; const NamedVal& nv = ValueTo(tree.Get(node)); Val val = nv.val; if(nv.val.ref > 0) { val = DeRef(val); if(val.type < 0 || val.ref > 0) { TreeNode(node, '*' + nv.name, val); SaveTree(); return; } } if(val.type < 0) { SaveTree(); return; } const Type& t = GetType(val.type); if(t.vtbl_typeindex == -2) { int count = GetSymInfo(t.modbase, type.GetKey(val.type), TI_GET_COUNT); Val prtti; prtti.ref = 1; prtti.type = UINT4; prtti.address = val.address - 4; Val rtti = GetRVal(prtti); FnInfo rtf = GetFnInfo(rtti.address); TreeNode(node, rtf.name, prtti); for(int i = 0; i < count; i++) { Val ventry; ventry.type = PFUNC; ventry.address = val.address + 4 * i; TreeNode(node, NFormat("[%d]", i), ventry); } return; } if(t.vtbl_typeindex >= 0) { Val vtbl; vtbl.ref = 1; vtbl.address = val.address + t.vtbl_offset; vtbl.type = t.vtbl_typeindex; TreeNode(node, "virtual", vtbl); /* Val vloc = GetRVal(vtbl); FnInfo vtbl_type = GetFnInfo(vloc.address); const char *p = vtbl_type.name, *e = p; while(*e && !(*e == ':' && e[1] == ':')) e++; String fullsym(p, e); FnInfo ffs = GetFnInfo(fullsym); if(ffs.pdbtype) { Val typeval; typeval.address = val.address; TypeVal(typeval, ffs.pdbtype, t.modbase); TreeNode(node, String().Cat() << '[' << ffs.name << ']', typeval); } */ } for(int i = 0; i < t.base.GetCount(); i++) { Val r = t.base[i]; r.address += val.address; if(r.type >= 0) { const Type& bt = GetType(r.type); TreeNode(node, bt.name, r); } } for(int i = 0; i < t.member.GetCount(); i++) { Val r = t.member[i]; r.address += val.address; TreeNode(node, t.member.GetKey(i), r); } for(int i = 0; i < t.static_member.GetCount(); i++) { Val r = t.static_member[i]; TreeNode(node, t.static_member.GetKey(i), r); } } String Pdb::StoreTree(int parent) { String result; int n = tree.GetChildCount(parent); for(int i = 0; i < n; i++) { int child = tree.GetChild(parent, i); if(tree.IsOpen(child)) { const NamedVal& nv = ValueTo(tree.Get(child)); if(!IsNull(result)) result << ';'; result << nv.name; String w = StoreTree(child); if(!IsNull(w)) result << '{' << w << '}'; } } return result; } void Pdb::SaveTree() { Value v = tree.Get(0); if(!IsType(v)) return; const NamedVal& nv = ValueTo(v); if(nv.val.type < 0) return; String w; Point p = tree.GetScroll(); w << p.x << ' ' << p.y << ' ' << tree.GetCursor() << ' ' << StoreTree(0); treetype.GetAdd(GetType(nv.val.type).name) = w; LOG("SaveTree " << GetType(nv.val.type).name << ' ' << w); } void Pdb::ExpandTreeType(int parent, CParser& p) { for(;;) { String id; if(p.Char('*')) id = "*"; if(p.IsId()) id << p.ReadId(); else break; for(;;) if(p.Char('<')) id << '<'; else if(p.Char('>')) id << '>'; else if(p.Char(',')) id << ','; else if(p.IsInt()) id << AsString(p.ReadInt()); else if(p.IsString()) id << '\"' << AsCString(p.ReadString()) << '\"'; else if(p.IsId()) id << p.ReadId(); else break; int n = tree.GetChildCount(parent); for(int i = 0; i < n; i++) { int child = tree.GetChild(parent, i); const NamedVal& nv = ValueTo(tree.Get(child)); if(nv.name == id) { tree.Open(child); if(p.Char('{')) { ExpandTreeType(child, p); p.PassChar('}'); } break; } } p.Char(';'); } } void Pdb::SetTree(const String& exp) { SaveTree(); tree.Clear(); NamedVal nv; try { CParser p(exp); nv.val = Exp(p); } catch(CParser::Error) { return; } nv.name = exp; String n = exp; if(nv.val.type >= 0) n = GetType(nv.val.type).name; tree.SetRoot(Null, RawToValue(nv), n + '=' + Visualise(nv.val).GetString()); if(nv.val.type >= 0) { String w = treetype.Get(n, Null); LOG("SetTree " << n << ' ' << w); tree.Open(0); CParser p(w); try { Point sc; sc.x = p.ReadInt(); sc.y = p.ReadInt(); int cursor = p.ReadInt(); ExpandTreeType(0, p); tree.ScrollTo(sc); if(cursor >= 0) tree.SetCursor(cursor); } catch(CParser::Error) {} } } void Pdb::SetTreeA(ArrayCtrl *array) { SetTree(array->Get(0)); } void Pdb::MemoryGoto(const String& exp) { CParser p(exp); try { Val v = Exp(p); adr_t adr = 0; if(v.ref > 0) adr = GetRVal(v).address; else if(v.rvalue) adr = (adr_t)GetInt(v); else adr = v.address; memory.SetCursor(adr); memory.SetSc(adr); tab.Set(4); } catch(CParser::Error e) { Exclamation("Invalid expression!&" + DeQtf(e)); } } void Pdb::MemMenu(ArrayCtrl& array, Bar& bar, const String& exp) { if(bar.IsScanKeys()) return; CParser p(exp); try { Val v = Exp(p); bool sep = true; if(v.ref > 0) { if(sep) bar.Separator(); sep = false; bar.Add("Memory at " + exp, THISBACK1(MemoryGoto, exp)); } else if(v.rvalue) { if(sep) bar.Separator(); sep = false; bar.Add("Memory at 0x" + FormatIntHex((dword)GetInt(v)), THISBACK1(MemoryGoto, "&" + exp)); } if(!v.rvalue) { if(sep) bar.Separator(); sep = false; bar.Add("Memory at &&" + exp, THISBACK1(MemoryGoto, "&" + exp)); } } catch(CParser::Error e) { } } void Pdb::DataMenu(ArrayCtrl& array, Bar& bar, const String& exp) { bar.Add("Explore", THISBACK1(ExploreKey, &array)); MemMenu(array, bar, exp); } void Pdb::AutosMenu(Bar& bar) { DataMenu(autos, bar, autos.GetKey()); } void Pdb::LocalsMenu(Bar& bar) { DataMenu(locals, bar, locals.GetKey()); } void Pdb::WatchesMenu(Bar& bar) { String exp = watches.GetKey(); if(!IsNull(exp)) exp = "(" + exp + ")"; DataMenu(watches, bar, exp); bar.Separator(); watches.StdBar(bar); } void Pdb::ExplorerMenu(Bar& bar) { bar.Add("Explore", THISBACK(ExpExp)); MemMenu(watches, bar, GetExpExp()); } void Pdb::SetTab(int i) { tab.Set(i); Tab(); } void Pdb::AddWatch() { SetTab(2); watches.DoAppend(); } #endif