From ef038f3d24fe51e9338e7240f1f5a750386ba962 Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 21 Apr 2018 08:53:57 +0200 Subject: DWARF: - fix code only executed in debug builds - fix evaluation of DW_OP_const1u/DW_OP_const1s not advancing pointer - add support for local variables with location list via DW_FORM_sec_offset --- src/dwarf2pdb.cpp | 59 +++++++++++++++++++++++++++++++------------------------ src/readDwarf.cpp | 12 ++++++----- src/readDwarf.h | 8 ++++---- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 58cd936..0c8aa33 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -334,8 +334,9 @@ public: class CFACursor { public: - CFACursor(const CFIEntry& cfientry, unsigned long location) - : entry (cfientry) + CFACursor(const PEImage& image, const CFIEntry& cfientry, unsigned long location) + : img (image) + , entry (cfientry) { loc = location; cfa = { Location::RegRel, DW_REG_CFA, 0 }; @@ -418,7 +419,7 @@ public: attr.type = ExprLoc; attr.expr.len = LEB128(ptr); attr.expr.ptr = ptr; - cfa = decodeLocation(attr); + cfa = decodeLocation(img, attr); ptr += attr.expr.len; break; } @@ -457,7 +458,7 @@ public: attr.type = Block; attr.block.len = LEB128(ptr); attr.block.ptr = ptr; - cfa = decodeLocation(attr); // TODO: push cfa on stack + cfa = decodeLocation(img, attr); // TODO: push cfa on stack ptr += attr.expr.len; break; } @@ -474,6 +475,7 @@ public: return true; } + const PEImage& img; const CFIEntry& entry; byte* beg; byte* end; @@ -498,12 +500,15 @@ Location findBestCFA(const PEImage& img, const CFIIndex* index, unsigned int pcl CFICursor cursor(img); cursor.ptr = fde_ptr; - assert(cursor.readNext(entry)); - CFACursor cfa(entry, pclo); - while(cfa.processNext()) {} - cfa.setInstructions(entry.instructions, entry.instructions_length); - while(!cfa.beforeRestore() && cfa.processNext()) {} - return cfa.cfa; + if (cursor.readNext(entry)) + { + CFACursor cfa(img, entry, pclo); + while (cfa.processNext()) {} + cfa.setInstructions(entry.instructions, entry.instructions_length); + while (!cfa.beforeRestore() && cfa.processNext()) {} + return cfa.cfa; + } + return ebp; } // Location list entry @@ -522,15 +527,15 @@ public: class LOCCursor { public: - LOCCursor(const PEImage& img, DWARF_CompilationUnit* cu, unsigned long off) - : beg((byte*)img.debug_loc) + LOCCursor(const PEImage& image, unsigned long off) + : img (image) , end((byte*)img.debug_loc + img.debug_loc_length) - , ptr(beg + off) + , ptr((byte*)img.debug_loc + off) { default_address_size = img.isX64() ? 8 : 4; } - byte* beg; + const PEImage& img; byte* end; byte* ptr; byte default_address_size; @@ -548,16 +553,16 @@ public: attr.type = Block; attr.block.len = RD2(ptr); attr.block.ptr = ptr; - entry.loc = decodeLocation(attr); + entry.loc = decodeLocation(img, attr); ptr += attr.expr.len; return true; } }; -Location findBestFBLoc(const PEImage& img, DWARF_CompilationUnit* cu, unsigned long fblocoff) +Location findBestFBLoc(const PEImage& img, unsigned long fblocoff) { int regebp = img.isX64() ? 6 : 5; - LOCCursor cursor(img, cu, fblocoff); + LOCCursor cursor(img, fblocoff); LOCEntry entry; Location longest = { Location::RegRel, DW_REG_CFA, 0 }; unsigned long longest_range = 0; @@ -738,9 +743,9 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, DIE addStackVar("local_var", 0x1001, 8); #endif - Location frameBase = decodeLocation(procid.frame_base, 0, DW_AT_frame_base); + Location frameBase = decodeLocation(img, procid.frame_base, 0, DW_AT_frame_base); if (frameBase.is_abs()) // pointer into location list in .debug_loc? assume CFA - frameBase = findBestFBLoc(img, cu, frameBase.off); + frameBase = findBestFBLoc(img, frameBase.off); Location cfa = findBestCFA(img, cfi_index, procid.pclo, procid.pchi); @@ -753,11 +758,12 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, DIE DIECursor prev = cursor; while (cursor.readNext(id, true)) { - if (id.tag == DW_TAG_formal_parameter) + if (id.tag == DW_TAG_formal_parameter && id.name) { - if (id.name && (id.location.type == ExprLoc || id.location.type == Block)) + if (id.location.type == ExprLoc || id.location.type == Block || id.location.type == SecOffset) { - Location loc = decodeLocation(id.location, &frameBase); + Location loc = id.location.type == SecOffset ? findBestFBLoc(img, id.location.sec_offset) + : decodeLocation(img, id.location, &frameBase); if (loc.is_regrel()) appendStackVar(id.name, getTypeByDWARFPtr(cu, id.type), loc, cfa); } @@ -827,7 +833,8 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, DIE { if (id.name && (id.location.type == ExprLoc || id.location.type == Block)) { - Location loc = decodeLocation(id.location, &frameBase); + Location loc = id.location.type == SecOffset ? findBestFBLoc(img, id.location.sec_offset) + : decodeLocation(img, id.location, &frameBase); if (loc.is_regrel()) appendStackVar(id.name, getTypeByDWARFPtr(cu, id.type), loc, cfa); } @@ -888,7 +895,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c int off = 0; if (!isunion) { - Location loc = decodeLocation(id.member_location, 0, DW_AT_data_member_location); + Location loc = decodeLocation(img, id.member_location, 0, DW_AT_data_member_location); if (loc.is_abs()) { off = loc.off; @@ -907,7 +914,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c else if(id.tag == DW_TAG_inheritance) { int off; - Location loc = decodeLocation(id.member_location, 0, DW_AT_data_member_location); + Location loc = decodeLocation(img, id.member_location, 0, DW_AT_data_member_location); if (loc.is_abs()) { cvid = S_CONSTANT_V2; @@ -1510,7 +1517,7 @@ bool CV2PDB::createTypes() } else { - Location loc = decodeLocation(id.location); + Location loc = decodeLocation(img, id.location); if (loc.is_abs()) { segOff = loc.off; diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp index c91776c..6f5d04d 100644 --- a/src/readDwarf.cpp +++ b/src/readDwarf.cpp @@ -38,7 +38,7 @@ static Location mkRegRel(int reg, int off) return l; } -Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, int at) +Location decodeLocation(const PEImage& img, const DWARF_Attribute& attr, const Location* frameBase, int at) { static Location invalid = { Location::Invalid }; @@ -47,8 +47,10 @@ Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, if (attr.type != ExprLoc && attr.type != Block) // same memory layout return invalid; + + byte*p = attr.expr.ptr; + byte*end = attr.expr.ptr + attr.expr.len; - byte* p = attr.expr.ptr; Location stack[256]; int stackDepth = 0; if (at == DW_AT_data_member_location) @@ -56,7 +58,7 @@ Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, for (;;) { - if (p >= attr.expr.ptr + attr.expr.len) + if (p >= end) break; int op = *p++; @@ -79,10 +81,10 @@ Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, stack[stackDepth++] = mkInReg(LEB128(p)); break; - case DW_OP_const1u: stack[stackDepth++] = mkAbs(*p); break; + case DW_OP_const1u: stack[stackDepth++] = mkAbs(*p++); break; case DW_OP_const2u: stack[stackDepth++] = mkAbs(RD2(p)); break; case DW_OP_const4u: stack[stackDepth++] = mkAbs(RD4(p)); break; - case DW_OP_const1s: stack[stackDepth++] = mkAbs((char)*p); break; + case DW_OP_const1s: stack[stackDepth++] = mkAbs((char)*p++); break; case DW_OP_const2s: stack[stackDepth++] = mkAbs((short)RD2(p)); break; case DW_OP_const4s: stack[stackDepth++] = mkAbs((int)RD4(p)); break; case DW_OP_constu: stack[stackDepth++] = mkAbs(LEB128(p)); break; diff --git a/src/readDwarf.h b/src/readDwarf.h index a259e3c..532d1c2 100644 --- a/src/readDwarf.h +++ b/src/readDwarf.h @@ -349,12 +349,12 @@ struct Location bool is_regrel() const { return type == RegRel; } }; -// Attemots to partially evaluate DWARF location expressions. +class PEImage; + +// Attempts to partially evaluate DWARF location expressions. // The only supported expressions are those, whose result may be represented // as either an absolute value, a register, or a register-relative address. -Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase = 0, int at = 0); - -class PEImage; +Location decodeLocation(const PEImage& img, const DWARF_Attribute& attr, const Location* frameBase = 0, int at = 0); // Debug Information Entry Cursor class DIECursor -- cgit v0.12