From 27a6223aecfc6914f49c13ee737c8ce59b09c55b Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 30 Nov 2021 00:01:51 -0800 Subject: more pre-DWARF5 refactoring: unit headers, location cursor, range cursor Read the compilation unit header byte-by-byte rather than by casting the data to a structure. Add the currentBaseAddress contextual info to the compilation unit data. Move the LOCCursor into readDwarf.cpp. Implement a RangeCursor similar to the LOCCursor. Add more debug printing. --- src/cv2pdb.h | 5 -- src/dwarf2pdb.cpp | 165 ++++++++++++++++------------------------------------- src/dwarflines.cpp | 13 +++-- src/readDwarf.cpp | 112 +++++++++++++++++++++++++++++++++--- src/readDwarf.h | 100 ++++++++++++++++++++++++++------ 5 files changed, 243 insertions(+), 152 deletions(-) diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 1c0b3b2..4b58140 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -279,11 +279,6 @@ public: // Default lower bound for the current compilation unit. This depends on // the language of the current unit. unsigned currentDefaultLowerBound; - - // Value of the DW_AT_low_pc attribute for the current compilation unit. - // Specify the default base address for use in location lists and range - // lists. - uint32_t currentBaseAddress; }; #endif //__CV2PDB_H__ diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 88670e2..3750702 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -419,7 +419,7 @@ public: attr.type = ExprLoc; attr.expr.len = LEB128(ptr); attr.expr.ptr = ptr; - cfa = decodeLocation(img, attr); + cfa = decodeLocation(attr); ptr += attr.expr.len; break; } @@ -458,7 +458,7 @@ public: attr.type = Block; attr.block.len = LEB128(ptr); attr.block.ptr = ptr; - cfa = decodeLocation(img, attr); // TODO: push cfa on stack + cfa = decodeLocation(attr); // TODO: push cfa on stack ptr += attr.expr.len; break; } @@ -511,61 +511,14 @@ Location findBestCFA(const PEImage& img, const CFIIndex* index, unsigned int pcl return ebp; } -// Location list entry -class LOCEntry -{ -public: - unsigned long beg_offset; - unsigned long end_offset; - Location loc; - - bool eol() const { return beg_offset == 0 && end_offset == 0; } -}; - -// Location list cursor -class LOCCursor -{ -public: - LOCCursor(const PEImage& image, unsigned long off) - : img (image) - , end(img.debug_loc.endByte()) - , ptr(img.debug_loc.byteAt(off)) - { - default_address_size = img.isX64() ? 8 : 4; - } - - const PEImage& img; - byte* end; - byte* ptr; - byte default_address_size; - - bool readNext(LOCEntry& entry) - { - if(ptr >= end) - return false; - entry.beg_offset = (unsigned long) RDsize(ptr, default_address_size); - entry.end_offset = (unsigned long) RDsize(ptr, default_address_size); - if (entry.eol()) - return true; - - DWARF_Attribute attr; - attr.type = Block; - attr.block.len = RD2(ptr); - attr.block.ptr = ptr; - entry.loc = decodeLocation(img, attr); - ptr += attr.expr.len; - return true; - } -}; - Location findBestFBLoc(const DIECursor& parent, unsigned long fblocoff) { int regebp = parent.img->isX64() ? 6 : 5; - LOCCursor cursor(*parent.img, fblocoff); + LOCCursor cursor(parent, fblocoff); LOCEntry entry; Location longest = { Location::RegRel, DW_REG_CFA, 0 }; unsigned long longest_range = 0; - while(cursor.readNext(entry) && !entry.eol()) + while(cursor.readNext(entry)) { if(entry.loc.is_regrel() && entry.loc.reg == regebp) return entry.loc; @@ -745,7 +698,7 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) addStackVar("local_var", 0x1001, 8); #endif - Location frameBase = decodeLocation(img, procid.frame_base, 0, DW_AT_frame_base); + Location frameBase = decodeLocation(procid.frame_base, 0, DW_AT_frame_base); if (frameBase.is_abs()) // pointer into location list in .debug_loc? assume CFA frameBase = findBestFBLoc(cursor, frameBase.off); @@ -765,7 +718,7 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) if (id.location.type == ExprLoc || id.location.type == Block || id.location.type == SecOffset) { Location loc = id.location.type == SecOffset ? findBestFBLoc(cursor, id.location.sec_offset) - : decodeLocation(img, id.location, &frameBase); + : decodeLocation(id.location, &frameBase); if (loc.is_regrel()) appendStackVar(id.name, getTypeByDWARFPtr(id.type), loc, cfa); } @@ -795,28 +748,12 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) id.pchi = 0; // TODO: handle base address selection - byte *r = img.debug_ranges.byteAt(id.ranges); - byte *rend = img.debug_ranges.endByte(); - while (r < rend) + RangeEntry range; + RangeCursor rangeCursor(cursor, id.ranges); + while (rangeCursor.readNext(range)) { - uint64_t pclo, pchi; - - if (img.isX64()) - { - pclo = RD8(r); - pchi = RD8(r); - } - else - { - pclo = RD4(r); - pchi = RD4(r); - } - if (pclo == 0 && pchi == 0) - break; - if (pclo >= pchi) - continue; - id.pclo = min(id.pclo, pclo + currentBaseAddress); - id.pchi = max(id.pchi, pchi + currentBaseAddress); + id.pclo = min(id.pclo, range.pclo); + id.pchi = max(id.pchi, range.pchi); } } @@ -836,7 +773,7 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DIECursor cursor) if (id.name && (id.location.type == ExprLoc || id.location.type == Block)) { Location loc = id.location.type == SecOffset ? findBestFBLoc(cursor, id.location.sec_offset) - : decodeLocation(img, id.location, &frameBase); + : decodeLocation(id.location, &frameBase); if (loc.is_regrel()) appendStackVar(id.name, getTypeByDWARFPtr(id.type), loc, cfa); } @@ -872,7 +809,7 @@ int CV2PDB::addDWARFFields(DWARF_InfoData& structid, DIECursor cursor, int baseo int off = 0; if (!isunion) { - Location loc = decodeLocation(img, id.member_location, 0, DW_AT_data_member_location); + Location loc = decodeLocation(id.member_location, 0, DW_AT_data_member_location); if (loc.is_abs()) { off = loc.off; @@ -917,7 +854,7 @@ int CV2PDB::addDWARFFields(DWARF_InfoData& structid, DIECursor cursor, int baseo else if (id.tag == DW_TAG_inheritance) { int off = 0; - Location loc = decodeLocation(img, id.member_location, 0, DW_AT_data_member_location); + Location loc = decodeLocation(id.member_location, 0, DW_AT_data_member_location); if (loc.is_abs()) { cvid = S_CONSTANT_V2; @@ -1350,11 +1287,18 @@ bool CV2PDB::mapTypes() { int typeID = nextUserType; unsigned long off = 0; + + if (debug & DbgBasic) + fprintf(stderr, "%s:%d: mapTypes()\n", __FUNCTION__, __LINE__); + while (off < img.debug_info.length) { - DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)img.debug_info.byteAt(off); + DWARF_CompilationUnitInfo cu{}; + byte* ptr = cu.read(img, &off); + if (!ptr) + continue; - DIECursor cursor(cu, (byte*)cu + sizeof(*cu)); + DIECursor cursor(&cu, ptr); DWARF_InfoData id; while (cursor.readNext(id)) { @@ -1392,8 +1336,6 @@ bool CV2PDB::mapTypes() typeID++; } } - - off += sizeof(cu->unit_length) + cu->unit_length; } if (debug & DbgBasic) @@ -1416,9 +1358,12 @@ bool CV2PDB::createTypes() unsigned long off = 0; while (off < img.debug_info.length) { - DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)img.debug_info.byteAt(off); + DWARF_CompilationUnitInfo cu{}; + byte* ptr = cu.read(img, &off); + if (!ptr) + continue; - DIECursor cursor(cu, (byte*)cu + sizeof(DWARF_CompilationUnit)); + DIECursor cursor(&cu, ptr); DWARF_InfoData id; while (cursor.readNext(id)) { @@ -1504,28 +1449,13 @@ bool CV2PDB::createTypes() else if (id.ranges != ~0) { entry_point = ~0; - byte* r = (byte*)img.debug_ranges.byteAt(id.ranges); - byte* rend = (byte*)img.debug_ranges.endByte(); - while (r < rend) + RangeEntry range; + RangeCursor rangeCursor(cursor, id.ranges); + while (rangeCursor.readNext(range)) { - uint64_t pclo, pchi; - - if (img.isX64()) - { - pclo = RD8(r); - pchi = RD8(r); - } - else - { - pclo = RD4(r); - pchi = RD4(r); - } - if (pclo == 0 && pchi == 0) - break; - if (pclo >= pchi) - continue; - entry_point = min(entry_point, pclo + currentBaseAddress); + entry_point = min(entry_point, range.pclo); } + if (entry_point == ~0) entry_point = 0; } @@ -1545,7 +1475,8 @@ bool CV2PDB::createTypes() break; case DW_TAG_compile_unit: - currentBaseAddress = id.pclo; + // Set the implicit base address for range lists. + cu.base_address = id.pclo; switch (id.language) { case DW_LANG_Ada83: @@ -1569,22 +1500,24 @@ bool CV2PDB::createTypes() { if (id.ranges > 0 && id.ranges < img.debug_ranges.length) { - unsigned char* r = img.debug_ranges.byteAt(id.ranges); - unsigned char* rend = img.debug_ranges.endByte(); - while (r < rend) + RangeEntry range; + RangeCursor rangeCursor(cursor, id.ranges); + while (rangeCursor.readNext(range)) { - unsigned long pclo = RD4(r); - unsigned long pchi = RD4(r); - if (pclo == 0 && pchi == 0) - break; - //printf("%s %s %x - %x\n", dir, name, pclo, pchi); - if (!addDWARFSectionContrib(mod, pclo, pchi)) + if (debug & DbgPdbContrib) + fprintf(stderr, "%s:%d: Adding a section contrib: %I64x-%I64x\n", __FUNCTION__, __LINE__, + range.pclo, range.pchi); + + if (!addDWARFSectionContrib(mod, range.pclo, range.pchi)) return false; } } else { - //printf("%s %s %x - %x\n", dir, name, pclo, pchi); + if (debug & DbgPdbContrib) + fprintf(stderr, "%s:%d: Adding a section contrib: %x-%x\n", __FUNCTION__, __LINE__, + id.pclo, id.pchi); + if (!addDWARFSectionContrib(mod, id.pclo, id.pchi)) return false; } @@ -1608,7 +1541,7 @@ bool CV2PDB::createTypes() } else { - Location loc = decodeLocation(img, id.location); + Location loc = decodeLocation(id.location); if (loc.is_abs()) { segOff = loc.off; @@ -1647,8 +1580,6 @@ bool CV2PDB::createTypes() assert(mapOffsetToType[id.entryPtr] == cvtype); } } - - off += sizeof(cu->unit_length) + cu->unit_length; } return true; diff --git a/src/dwarflines.cpp b/src/dwarflines.cpp index 2e0570d..dd48995 100644 --- a/src/dwarflines.cpp +++ b/src/dwarflines.cpp @@ -169,8 +169,13 @@ bool addLineInfo(const PEImage& img, mspdb::Mod* mod, DWARF_LineState& state) bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_) { - DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)img.debug_info.startByte(); - int ptrsize = cu ? cu->address_size : 4; + DWARF_CompilationUnitInfo cu{}; + + if (!cu.read(img, 0)) { + return false; + } + + int ptrsize = cu.address_size; debug = debug_; @@ -280,7 +285,7 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_) { case DW_FORM_line_strp: { - size_t offset = cu->isDWARF64() ? RD8(p) : RD4(p); + size_t offset = cu.isDWARF64() ? RD8(p) : RD4(p); state.include_dirs.push_back((const char*)img.debug_line_str.byteAt(offset)); break; } @@ -322,7 +327,7 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_) { case DW_FORM_line_strp: { - size_t offset = cu->isDWARF64() ? RD8(p) : RD4(p); + size_t offset = cu.isDWARF64() ? RD8(p) : RD4(p); fname.file_name = (const char*)img.debug_line_str.byteAt(offset); break; } diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp index f712b29..12fc84d 100644 --- a/src/readDwarf.cpp +++ b/src/readDwarf.cpp @@ -34,6 +34,41 @@ void DIECursor::setContext(PEImage* img_, DebugLevel debug_) debug = debug_; } +byte* DWARF_CompilationUnitInfo::read(const PEImage& img, unsigned long *off) +{ + byte* ptr = img.debug_info.byteAt(*off); + + start_ptr = ptr; + cu_offset = *off; + is_dwarf64 = false; + base_address = 0; + unit_length = RD4(ptr); + if (unit_length == ~0) { + // DWARF64 doesn't make sense in the context of the PE format since the + // section size is limited to 32 bits. + fprintf(stderr, "%s:%d: WARNING: DWARF64 compilation unit at offset=%x is not supported\n", __FUNCTION__, __LINE__, + cu_offset); + + uint64_t len64 = RD8(ptr); + *off = img.debug_info.sectOff(ptr + (intptr_t)len64); + return nullptr; + } + + end_ptr = ptr + unit_length; + *off = img.debug_info.sectOff(end_ptr); + version = RD2(ptr); + if (version >= 5) { + fprintf(stderr, "%s:%d: WARNING: Unsupported dwarf version %d for compilation unit at offset=%x\n", __FUNCTION__, __LINE__, + version, cu_offset); + + return nullptr; + } + + debug_abbrev_offset = RD4(ptr); + address_size = *ptr++; + return ptr; +} + static Location mkInReg(unsigned reg) { Location l; @@ -61,7 +96,7 @@ static Location mkRegRel(int reg, int off) return l; } -Location decodeLocation(const PEImage& img, const DWARF_Attribute& attr, const Location* frameBase, int at) +Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase, int at) { static Location invalid = { Location::Invalid }; @@ -343,7 +378,66 @@ void mergeSpecification(DWARF_InfoData& id, const DIECursor& parent) id.merge(idspec); } -DIECursor::DIECursor(DWARF_CompilationUnit* cu_, byte* ptr_) +LOCCursor::LOCCursor(const DIECursor& parent, unsigned long off) + : parent(parent) + , end(parent.img->debug_loc.endByte()) + , ptr(parent.img->debug_loc.byteAt(off)) +{ +} + +bool LOCCursor::readNext(LOCEntry& entry) +{ + if (ptr >= end) + return false; + + if (parent.debug & DbgDwarfLocLists) + fprintf(stderr, "%s:%d: loclist off=%x DIEoff=%x:\n", __FUNCTION__, __LINE__, + parent.img->debug_loc.sectOff(ptr), parent.entryOff); + + entry.beg_offset = (unsigned long) parent.RDAddr(ptr); + entry.end_offset = (unsigned long) parent.RDAddr(ptr); + if (!entry.beg_offset && !entry.end_offset) + return false; + + DWARF_Attribute attr; + attr.type = Block; + attr.block.len = RD2(ptr); + attr.block.ptr = ptr; + entry.loc = decodeLocation(attr); + ptr += attr.expr.len; + return true; +} + +RangeCursor::RangeCursor(const DIECursor& parent, unsigned long off) + : parent(parent) + , end(parent.img->debug_ranges.endByte()) + , ptr(parent.img->debug_ranges.byteAt(off)) +{ +} + +bool RangeCursor::readNext(RangeEntry& entry) +{ + while (ptr < end) { + if (parent.debug & DbgDwarfRangeLists) + fprintf(stderr, "%s:%d: rangelist off=%x DIEoff=%x:\n", __FUNCTION__, __LINE__, + parent.img->debug_ranges.sectOff(ptr), parent.entryOff); + + entry.pclo = parent.RDAddr(ptr); + entry.pchi = parent.RDAddr(ptr); + if (!entry.pclo && !entry.pchi) + return false; + + if (entry.pclo >= entry.pchi) + continue; + + entry.addBase(parent.cu->base_address); + return true; + } + + return false; +} + +DIECursor::DIECursor(DWARF_CompilationUnitInfo* cu_, byte* ptr_) { cu = cu_; ptr = ptr_; @@ -414,7 +508,7 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) if (level == -1) return false; // we were already at the end of the subtree - if (ptr >= ((byte*)cu + sizeof(cu->unit_length) + cu->unit_length)) + if (ptr >= cu->end_ptr) return false; // root of the tree does not have a null terminator, but we know the length id.entryPtr = ptr; @@ -447,7 +541,7 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) id.hasChild = *abbrev++; if (debug & DbgDwarfAttrRead) - fprintf(stderr, "%s:%d: offs=%d level=%d tag=%d abbrev=%d\n", __FUNCTION__, __LINE__, + fprintf(stderr, "%s:%d: offs=%x level=%d tag=%d abbrev=%d\n", __FUNCTION__, __LINE__, entryOff, level, id.tag, id.code); int attr, form; @@ -488,11 +582,11 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) case DW_FORM_strp: a.type = String; a.string = (const char*)img->debug_str.byteAt(RDsize(ptr, cu->isDWARF64() ? 8 : 4)); break; case DW_FORM_flag: a.type = Flag; a.flag = (*ptr++ != 0); break; case DW_FORM_flag_present: a.type = Flag; a.flag = true; break; - case DW_FORM_ref1: a.type = Ref; a.ref = (byte*)cu + *ptr++; break; - case DW_FORM_ref2: a.type = Ref; a.ref = (byte*)cu + RD2(ptr); break; - case DW_FORM_ref4: a.type = Ref; a.ref = (byte*)cu + RD4(ptr); break; - case DW_FORM_ref8: a.type = Ref; a.ref = (byte*)cu + RD8(ptr); break; - case DW_FORM_ref_udata: a.type = Ref; a.ref = (byte*)cu + LEB128(ptr); break; + case DW_FORM_ref1: a.type = Ref; a.ref = cu->start_ptr + *ptr++; break; + case DW_FORM_ref2: a.type = Ref; a.ref = cu->start_ptr + RD2(ptr); break; + case DW_FORM_ref4: a.type = Ref; a.ref = cu->start_ptr + RD4(ptr); break; + case DW_FORM_ref8: a.type = Ref; a.ref = cu->start_ptr + RD8(ptr); break; + case DW_FORM_ref_udata: a.type = Ref; a.ref = cu->start_ptr + LEB128(ptr); break; case DW_FORM_ref_addr: a.type = Ref; a.ref = img->debug_info.byteAt(cu->isDWARF64() ? RD8(ptr) : RD4(ptr)); break; case DW_FORM_ref_sig8: a.type = Invalid; ptr += 8; break; case DW_FORM_exprloc: a.type = ExprLoc; a.expr.len = LEB128(ptr); a.expr.ptr = ptr; ptr += a.expr.len; break; diff --git a/src/readDwarf.h b/src/readDwarf.h index bb78285..3bc7d09 100644 --- a/src/readDwarf.h +++ b/src/readDwarf.h @@ -17,10 +17,12 @@ enum DebugLevel : unsigned { DbgPdbTypes = 0x2, DbgPdbSyms = 0x4, DbgPdbLines = 0x8, - DbgDwarfTagRead = 0x10, - DbgDwarfAttrRead = 0x20, - DbgDwarfLocLists = 0x40, - DbgDwarfLines = 0x80 + DbgPdbContrib = 0x10, + DbgDwarfTagRead = 0x100, + DbgDwarfAttrRead = 0x200, + DbgDwarfLocLists = 0x400, + DbgDwarfRangeLists = 0x800, + DbgDwarfLines = 0x1000 }; DEFINE_ENUM_FLAG_OPERATORS(DebugLevel); @@ -57,7 +59,7 @@ inline int SLEB128(byte* &p) return x; } -inline unsigned int RD2(byte* &p) +inline unsigned short RD2(byte* &p) { unsigned int x = *p++; x |= *p++ << 8; @@ -122,17 +124,30 @@ struct DWARF_Attribute /////////////////////////////////////////////////////////////////////////////// -#include "pshpack1.h" - -struct DWARF_CompilationUnit +struct DWARF_CompilationUnitInfo { - unsigned int unit_length; // 12 byte in DWARF-64 + uint32_t unit_length; // 12 byte in DWARF-64 unsigned short version; - unsigned int debug_abbrev_offset; // 8 byte in DWARF-64 byte address_size; + byte unit_type; + unsigned int debug_abbrev_offset; // 8 byte in DWARF-64 - bool isDWARF64() const { return unit_length == ~0; } - int refSize() const { return unit_length == ~0 ? 8 : 4; } + // Value of the DW_AT_low_pc attribute for the current compilation unit. + // Specify the default base address for use in location lists and range + // lists. + uint32_t base_address; + + // Offset within the debug_info section + uint32_t cu_offset; + byte* start_ptr; + byte* end_ptr; + + bool is_dwarf64; + + byte* read(const PEImage& img, unsigned long *off); + + bool isDWARF64() const { return is_dwarf64; } + int refSize() const { return isDWARF64() ? 8 : 4; } }; struct DWARF_FileName @@ -260,6 +275,8 @@ struct DWARF_TypeForm unsigned int type, form; }; +#include "pshpack1.h" + struct DWARF_LineNumberProgramHeader { unsigned int unit_length; // 12 byte in DWARF-64 @@ -310,6 +327,8 @@ struct DWARF2_LineNumberProgramHeader // DWARF_FileNames file_names[] // zero byte terminated }; +#include "poppack.h" + struct DWARF_LineState { // hdr info @@ -372,7 +391,6 @@ struct DWARF_LineState } }; -#include "poppack.h" /////////////////////////////////////////////////////////////////////////////// @@ -398,13 +416,61 @@ struct Location bool is_regrel() const { return type == RegRel; } }; -typedef std::unordered_map, byte*> abbrevMap_t; +// Location list entry +class LOCEntry +{ +public: + unsigned long beg_offset; + unsigned long end_offset; + Location loc; +}; +// Location list cursor +class LOCCursor +{ +public: + LOCCursor(const DIECursor& parent, unsigned long off); + + const DIECursor& parent; + byte* end; + byte* ptr; + + bool readNext(LOCEntry& entry); +}; + +// Range list entry +class RangeEntry +{ +public: + uint64_t pclo; + uint64_t pchi; + + void addBase(uint64_t base) + { + pclo += base; + pchi += base; + } +}; + +// Range list cursor +class RangeCursor +{ +public: + RangeCursor(const DIECursor& parent, unsigned long off); + + const DIECursor& parent; + byte *end; + byte *ptr; + + bool readNext(RangeEntry& entry); +}; + +typedef std::unordered_map, byte*> abbrevMap_t; // 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 PEImage& img, const DWARF_Attribute& attr, const Location* frameBase = 0, int at = 0); +Location decodeLocation(const DWARF_Attribute& attr, const Location* frameBase = 0, int at = 0); void mergeAbstractOrigin(DWARF_InfoData& id, const DIECursor& parent); void mergeSpecification(DWARF_InfoData& id, const DIECursor& parent); @@ -413,7 +479,7 @@ void mergeSpecification(DWARF_InfoData& id, const DIECursor& parent); class DIECursor { public: - DWARF_CompilationUnit* cu; + DWARF_CompilationUnitInfo* cu; byte* ptr; unsigned int entryOff; int level; @@ -431,7 +497,7 @@ public: static void setContext(PEImage* img_, DebugLevel debug_); // Create a new DIECursor - DIECursor(DWARF_CompilationUnit* cu_, byte* ptr); + DIECursor(DWARF_CompilationUnitInfo* cu_, byte* ptr); // Create a child DIECursor DIECursor(const DIECursor& parent, byte* ptr_); -- cgit v0.12