mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-10 22:04:25 -06:00
ide: PDB improvements
git-svn-id: svn://ultimatepp.org/upp/trunk@13762 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
caf9b82767
commit
7cf675d69e
6 changed files with 186 additions and 155 deletions
|
|
@ -219,31 +219,40 @@ void Pdb::MemoryGoto(const String& exp)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void Pdb::MemMenu(ArrayCtrl& array, Bar& bar, const String& exp)
|
||||
{
|
||||
if(bar.IsScanKeys())
|
||||
return;
|
||||
auto CopyLine = [&](int i, ArrayCtrl& array) {
|
||||
return String() << array.Get(i, 0) << '=' << array.Get(i, 1).To<Visual>().GetString();
|
||||
};
|
||||
ArrayCtrl *ap = &array;
|
||||
bar.Add(array.IsCursor(), "Copy", [=] {
|
||||
ClearClipboard();
|
||||
AppendClipboardText(CopyLine(ap->GetCursor(), *ap));
|
||||
});
|
||||
bar.Add("Copy all", [=] {
|
||||
ClearClipboard();
|
||||
String s;
|
||||
for(int i = 0; i < ap->GetCount(); i++)
|
||||
MergeWith(s, "\n", CopyLine(i, *ap));
|
||||
AppendClipboardText(s);
|
||||
});
|
||||
bar.Separator();
|
||||
try {
|
||||
CParser p(exp);
|
||||
Val v = Exp(p);
|
||||
bool sep = true;
|
||||
if(v.ref > 0 && !v.reference) {
|
||||
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)GetInt64(v)), THISBACK1(MemoryGoto, "&" + exp));
|
||||
}
|
||||
if(!v.rvalue) {
|
||||
if(sep)
|
||||
bar.Separator();
|
||||
sep = false;
|
||||
bar.Add("Memory at &&" + exp, THISBACK1(MemoryGoto, "&" + exp));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ Pdb::Val Pdb::GetRVal(Pdb::Val v)
|
|||
}
|
||||
else {
|
||||
if(v.address < 10000 && !v.context)
|
||||
ThrowError("Register value is missing context");
|
||||
ThrowError("??"); // Register value is missing context
|
||||
switch(v.type) { // resolve primitive value
|
||||
READINT(BOOL1, bool)
|
||||
READINT(UINT1, byte);
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ struct Pdb : Debugger, ParentCtrl {
|
|||
bool first_exception = true;
|
||||
|
||||
VectorMap<String, String> treetype;
|
||||
int restoring_tree = 0;
|
||||
|
||||
Vector<String> exprev, exnext;
|
||||
|
||||
|
|
@ -471,8 +472,9 @@ struct Pdb : Debugger, ParentCtrl {
|
|||
void PrettyTreeNode(int parent, Pdb::Val val, int64 from = 0);
|
||||
bool TreeNode(int parent, const String& name, Val val, int64 from = 0);
|
||||
void TreeExpand(int node);
|
||||
String StoreTree(int parent);
|
||||
void StoreTree(StringBuffer& r, int parent);
|
||||
void SaveTree();
|
||||
int FindChild(int parent, String id);
|
||||
void ExpandTreeType(int parent, CParser& p);
|
||||
|
||||
void CopyStack();
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ BOOL CALLBACK Pdb::EnumLocals(PSYMBOL_INFO pSym, ULONG SymbolSize, PVOID UserCon
|
|||
|
||||
LLOG("LOCAL " << pSym->Name << ": " << Format64Hex(v.address));
|
||||
c.pdb->TypeVal(v, pSym->TypeIndex, (adr_t)pSym->ModBase);
|
||||
if(param && v.udt && v.ref == 0) { // dbghelp.dll incorrectly does not report pointer for (copied) value struct params
|
||||
if(param && v.udt && v.ref == 0 && c.pdb->win64) { // dbghelp.dll incorrectly does not report pointer for (copied) value struct params
|
||||
v.ref++;
|
||||
v.reference = true;
|
||||
}
|
||||
|
|
@ -282,16 +282,6 @@ BOOL CALLBACK Pdb::EnumGlobals(PSYMBOL_INFO pSym, ULONG SymbolSize, PVOID UserCo
|
|||
|
||||
LLOG("GLOBAL: " << pSym->Name << " " << Format64Hex(pSym->Address));
|
||||
|
||||
#if 0
|
||||
|
||||
DWORD dummy;
|
||||
IMAGEHLP_LINE ln;
|
||||
ln.SizeOfStruct = sizeof(ln);
|
||||
ln.Address = pSym->Address;
|
||||
if(SymGetLineFromAddr(c.pdb->hProcess, (uintptr_t)pSym->Address, &dummy, &ln)) {
|
||||
}
|
||||
else
|
||||
#endif
|
||||
Val& v = c.pdb->global.GetAdd(pSym->Name);
|
||||
v.address = (adr_t)pSym->Address;
|
||||
v.reported_size = pSym->Size;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,24 @@ void Pdb::PrettyTreeNode(int parent, Pdb::Val val, int64 from)
|
|||
{
|
||||
try {
|
||||
Pretty pp;
|
||||
if(PrettyVal(val, 0, 0, pp) && pp.kind == CONTAINER) {
|
||||
if(!PrettyVal(val, 0, 0, pp))
|
||||
return;
|
||||
if(pp.kind == SINGLE_VALUE) {
|
||||
Pretty p;
|
||||
PrettyVal(val, 0, 1, p);
|
||||
if(p.text.part.GetCount()) {
|
||||
NamedVal nv;
|
||||
Visual result;
|
||||
nv.name = "$$";
|
||||
for(const VisualPart& vp : p.text.part)
|
||||
result.Cat(vp.text, vp.ink);
|
||||
tree.Add(parent, Null, RawToValue(nv), RawPickToValue(pick(result)), false);
|
||||
}
|
||||
else
|
||||
if(p.data_type.GetCount() && p.data_ptr.GetCount())
|
||||
PrettyTreeNode(parent, MakeVal(p.data_type[0], p.data_ptr[0]), from);
|
||||
}
|
||||
if(pp.kind == CONTAINER) {
|
||||
int n = int(min(pp.data_count, from + 10000) - from);
|
||||
Pretty p;
|
||||
PrettyVal(val, from, n, p);
|
||||
|
|
@ -94,164 +111,164 @@ void Pdb::TreeExpand(int node)
|
|||
{
|
||||
if(tree.GetChildCount(node))
|
||||
return;
|
||||
Value v = tree.Get(node);
|
||||
if(!v.Is<NamedVal>())
|
||||
return;
|
||||
const NamedVal& nv = ValueTo<NamedVal>(tree.Get(node));
|
||||
Val val = nv.val;
|
||||
if(nv.key.type != UNKNOWN) {
|
||||
TreeNode(node, "key", nv.key);
|
||||
TreeNode(node, "value", val);
|
||||
return;
|
||||
}
|
||||
if(nv.val.ref > 0) {
|
||||
Val val0 = val;
|
||||
val = DeRef(val);
|
||||
if(val.type < 0 || val.ref > 0) {
|
||||
int sz = SizeOfType(val.type);
|
||||
val.address += sz * nv.from;
|
||||
for(int i = 0; i < (nv.from ? 10000 : 20); i++) {
|
||||
if(!TreeNode(node, String() << "[" << i + nv.from << "]" , val)) {
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
val.address += sz;
|
||||
}
|
||||
TreeNode(node, "[more]", val0, nv.from ? nv.from + 10000 : 20);
|
||||
try {
|
||||
Value v = tree.Get(node);
|
||||
if(!v.Is<NamedVal>())
|
||||
return;
|
||||
const NamedVal& nv = ValueTo<NamedVal>(tree.Get(node));
|
||||
Val val = nv.val;
|
||||
if(nv.key.type != UNKNOWN) {
|
||||
TreeNode(node, "key", nv.key);
|
||||
TreeNode(node, "value", val);
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(nv.from > 0) {
|
||||
PrettyTreeNode(node, val, nv.from);
|
||||
return;
|
||||
}
|
||||
if(val.type < 0) {
|
||||
if(nv.val.ref > 0) {
|
||||
Val val0 = val;
|
||||
val = DeRef(val);
|
||||
if(val.type < 0 || val.ref > 0) {
|
||||
int sz = SizeOfType(val.type);
|
||||
val.address += sz * nv.from;
|
||||
for(int i = 0; i < (nv.from ? 10000 : 40); i++) {
|
||||
if(!TreeNode(node, String() << "[" << i + nv.from << "]" , val)) {
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
val.address += sz;
|
||||
}
|
||||
TreeNode(node, "[more]", val0, nv.from ? nv.from + 10000 : 20);
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(nv.from > 0) {
|
||||
PrettyTreeNode(node, val, nv.from);
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
if(val.type < 0) {
|
||||
SaveTree();
|
||||
return;
|
||||
}
|
||||
PrettyTreeNode(node, val, 0);
|
||||
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);
|
||||
}
|
||||
SaveTree();
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
catch(LengthLimit) {}
|
||||
catch(CParser::Error e) {}
|
||||
}
|
||||
|
||||
String Pdb::StoreTree(int parent)
|
||||
void Pdb::StoreTree(StringBuffer& result, int parent)
|
||||
{
|
||||
String result;
|
||||
int n = tree.GetChildCount(parent);
|
||||
for(int i = 0; i < n; i++) {
|
||||
int child = tree.GetChild(parent, i);
|
||||
bool first = true;
|
||||
if(tree.IsOpen(child)) {
|
||||
const NamedVal& nv = ValueTo<NamedVal>(tree.Get(child));
|
||||
if(!IsNull(result))
|
||||
result << ';';
|
||||
result << nv.name;
|
||||
String w = StoreTree(child);
|
||||
if(!IsNull(w))
|
||||
result << '{' << w << '}';
|
||||
if(!first)
|
||||
result << ";";
|
||||
first = false;
|
||||
result << " " << AsCString(nv.name) << " {";
|
||||
StoreTree(result, child);
|
||||
result << "}";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Pdb::SaveTree()
|
||||
{
|
||||
if(restoring_tree)
|
||||
return;
|
||||
Value v = tree.Get(0);
|
||||
if(!IsType<NamedVal>(v))
|
||||
return;
|
||||
const NamedVal& nv = ValueTo<NamedVal>(v);
|
||||
if(nv.val.type < 0)
|
||||
return;
|
||||
String w;
|
||||
StringBuffer 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);
|
||||
w << p.x << ' ' << p.y << ' ';
|
||||
int id = tree.GetCursor();
|
||||
Vector<String> cursor;
|
||||
while(id >= 0) {
|
||||
const NamedVal& nv = ValueTo<NamedVal>(tree.Get(id));
|
||||
cursor.Add(AsCString(nv.name));
|
||||
id = tree.GetParent(id);
|
||||
}
|
||||
Reverse(cursor);
|
||||
w << Join(cursor, ";") << ": ";
|
||||
StoreTree(w, 0);
|
||||
String r = w;
|
||||
treetype.GetAdd(GetType(nv.val.type).name) = r;
|
||||
LOG("SaveTree " << GetType(nv.val.type).name << ' ' << r);
|
||||
}
|
||||
|
||||
int Pdb::FindChild(int parent, String id)
|
||||
{
|
||||
int n = tree.GetChildCount(parent);
|
||||
for(int i = 0; i < n; i++) {
|
||||
int child = tree.GetChild(parent, i);
|
||||
const NamedVal& nv = ValueTo<NamedVal>(tree.Get(child));
|
||||
if(nv.name == id)
|
||||
return child;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 << '\"' << FormatString(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<NamedVal>(tree.Get(child));
|
||||
if(nv.name == id) {
|
||||
tree.Open(child);
|
||||
if(p.Char('{')) {
|
||||
ExpandTreeType(child, p);
|
||||
p.PassChar('}');
|
||||
}
|
||||
break;
|
||||
}
|
||||
while(p.IsString()) {
|
||||
int child = FindChild(parent, p.ReadString());
|
||||
if(child >= 0) {
|
||||
tree.Open(child);
|
||||
p.Char('{');
|
||||
ExpandTreeType(child, p);
|
||||
p.Char('}');
|
||||
}
|
||||
p.Char(';');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -290,21 +307,34 @@ void Pdb::SetTree(const String& exp)
|
|||
}
|
||||
|
||||
tree.SetRoot(Null, RawToValue(nv), RawPickToValue(pick(v)));
|
||||
PrettyTreeNode(0, nv.val);
|
||||
if(nv.val.type >= 0) {
|
||||
String w = treetype.Get(n, Null);
|
||||
LLOG("SetTree " << n << ' ' << w);
|
||||
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();
|
||||
Vector<String> cursor;
|
||||
while(!p.Char(':')) {
|
||||
cursor.Add(p.ReadString());
|
||||
p.Char(';');
|
||||
}
|
||||
restoring_tree++;
|
||||
ExpandTreeType(0, p);
|
||||
restoring_tree--;
|
||||
tree.ScrollTo(sc);
|
||||
if(cursor >= 0 && tree.IsValid(cursor))
|
||||
tree.SetCursor(cursor);
|
||||
if(cursor.GetCount()) {
|
||||
int ii = 0;
|
||||
for(int i = 1; i < cursor.GetCount(); i++) {
|
||||
ii = FindChild(ii, cursor[i]);
|
||||
if(ii < 0)
|
||||
break;
|
||||
}
|
||||
if(ii >= 0)
|
||||
tree.SetCursor(ii);
|
||||
}
|
||||
}
|
||||
catch(CParser::Error) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ void Pdb::Visualise(Visual& result, Pdb::Val val, dword flags)
|
|||
dt.Clear();
|
||||
}
|
||||
else
|
||||
if(val.reported_size > sz && sz > 0) {
|
||||
if(val.reported_size > sz && sz > 0 && val.array) {
|
||||
n = val.reported_size / sz;
|
||||
if(n <= 40)
|
||||
dt.Clear();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue