From c7c7dfe5c665dd78d6d5f027c79516c201421ee1 Mon Sep 17 00:00:00 2001 From: Neeraj Singh Date: Tue, 30 Nov 2021 21:29:57 -0800 Subject: read all dwarf5 main DIE forms Fill in Dwarf_InfoData for all DWARF5 forms excluding the new rnglists and loclists representations. --- src/readDwarf.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/readDwarf.h | 23 ++++++++++++- 2 files changed, 115 insertions(+), 5 deletions(-) diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp index 7f64ec9..415dac8 100644 --- a/src/readDwarf.cpp +++ b/src/readDwarf.cpp @@ -506,6 +506,64 @@ DIECursor DIECursor::getSubtreeCursor() } } +const char Cv2PdbInvalidString[] = ""; + +const char* DIECursor::resolveIndirectString(uint32_t index) const +{ + if (!cu->str_offset_base) + { + fprintf(stderr, "ERROR: %s:%d: no string base for cu_offs=%x die_offs=%x\n", __FUNCTION__, __LINE__, + cu->cu_offset, entryOff); + return Cv2PdbInvalidString; + } + + byte* refAddr = cu->str_offset_base + index * refSize(); + return (const char*)img->debug_str.byteAt(RDref(refAddr)); +} + +uint32_t DIECursor::readIndirectAddr(uint32_t index) const +{ + if (!cu->addr_base) + { + fprintf(stderr, "ERROR: %s:%d: no addr base for cu_offs=%x die_offs=%x\n", __FUNCTION__, __LINE__, + cu->cu_offset, entryOff); + + return 0; + } + + byte* refAddr = cu->addr_base + index * refSize(); + return RDAddr(refAddr); +} + +uint32_t DIECursor::resolveIndirectSecPtr(uint32_t index, const SectionDescriptor &secDesc, byte *baseAddress) const +{ + if (!baseAddress) + { + fprintf(stderr, "ERROR: %s:%d: no base address in section %s for cu_offs=%x die_offs=%x\n", __FUNCTION__, __LINE__, + secDesc.name, cu->cu_offset, entryOff); + + return 0; + } + + byte* refAddr = baseAddress + index * refSize(); + byte* targetAddr = baseAddress + RDref(refAddr); + return (img->*(secDesc.pSec)).sectOff(targetAddr); +} + +static byte* getPointerInSection(const PEImage &img, const SectionDescriptor &secDesc, uint32_t offset) +{ + const PESection &peSec = img.*(secDesc.pSec); + + if (!peSec.isPresent() || offset >= peSec.length) + { + fprintf(stderr, "%s:%d: WARNING: offset %x is not valid in section %s\n", __FUNCTION__, __LINE__, + offset, secDesc.name); + return nullptr; + } + + return peSec.byteAt(offset); +} + bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) { id.clear(); @@ -577,7 +635,12 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) DWARF_Attribute a; switch (form) { - case DW_FORM_addr: a.type = Addr; a.addr = (unsigned long)RDsize(ptr, cu->address_size); break; + case DW_FORM_addr: a.type = Addr; a.addr = RDAddr(ptr); break; + case DW_FORM_addrx: a.type = Addr; a.addr = readIndirectAddr(LEB128(ptr)); break; + case DW_FORM_addrx1: + case DW_FORM_addrx2: + case DW_FORM_addrx3: + case DW_FORM_addrx4: a.type = Addr; a.addr = readIndirectAddr(RDsize(ptr, 1 + (form - DW_FORM_addrx1))); break; case DW_FORM_block: a.type = Block; a.block.len = LEB128(ptr); a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_block1: a.type = Block; a.block.len = *ptr++; a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_block2: a.type = Block; a.block.len = RD2(ptr); a.block.ptr = ptr; ptr += a.block.len; break; @@ -586,10 +649,19 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) case DW_FORM_data2: a.type = Const; a.cons = RD2(ptr); break; case DW_FORM_data4: a.type = Const; a.cons = RD4(ptr); break; case DW_FORM_data8: a.type = Const; a.cons = RD8(ptr); break; + case DW_FORM_data16: a.type = Block; a.block.len = 16; a.block.ptr = ptr; ptr += a.block.len; break; case DW_FORM_sdata: a.type = Const; a.cons = SLEB128(ptr); break; case DW_FORM_udata: a.type = Const; a.cons = LEB128(ptr); break; + case DW_FORM_implicit_const: a.type = Const; a.cons = LEB128(abbrev); break; case DW_FORM_string: a.type = String; a.string = (const char*)ptr; ptr += strlen(a.string) + 1; break; - 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_strp: a.type = String; a.string = (const char*)img->debug_str.byteAt(RDref(ptr)); break; + case DW_FORM_line_strp: a.type = String; a.string = (const char*)img->debug_line_str.byteAt(RDref(ptr)); break; + case DW_FORM_strx: a.type = String; a.string = resolveIndirectString(LEB128(ptr)); break; + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: a.type = String; a.string = resolveIndirectString(RDsize(ptr, 1 + (form - DW_FORM_strx1))); break; + case DW_FORM_strp_sup: a.type = Invalid; assert(false && "Unsupported supplementary object"); ptr += refSize(); 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 = cu->start_ptr + *ptr++; break; @@ -597,10 +669,14 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) 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_addr: a.type = Ref; a.ref = img->debug_info.byteAt(RDref(ptr)); break; case DW_FORM_ref_sig8: a.type = Invalid; ptr += 8; break; + case DW_FORM_ref_sup4: a.type = Invalid; assert(false && "Unsupported supplementary object"); ptr += 4; break; + case DW_FORM_ref_sup8: a.type = Invalid; assert(false && "Unsupported supplementary object"); ptr += 8; break; case DW_FORM_exprloc: a.type = ExprLoc; a.expr.len = LEB128(ptr); a.expr.ptr = ptr; ptr += a.expr.len; break; - case DW_FORM_sec_offset: a.type = SecOffset; a.sec_offset = cu->isDWARF64() ? RD8(ptr) : RD4(ptr); break; + case DW_FORM_sec_offset: a.type = SecOffset; a.sec_offset = RDref(ptr); break; + case DW_FORM_loclistx: a.type = SecOffset; a.sec_offset = resolveIndirectSecPtr(LEB128(ptr), sec_desc_debug_loclists, cu->loclist_base); break; + case DW_FORM_rnglistx: a.type = SecOffset; a.sec_offset = resolveIndirectSecPtr(LEB128(ptr), sec_desc_debug_rnglists, cu->rnglist_base); break; default: assert(false && "Unsupported DWARF attribute form"); return false; } @@ -688,6 +764,19 @@ bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) id.has_artificial = true; id.is_artificial = true; break; + + case DW_AT_str_offsets_base: + cu->str_offset_base = getPointerInSection(*img, sec_desc_debug_str_offsets, a.sec_offset); + break; + case DW_AT_addr_base: + cu->addr_base = getPointerInSection(*img, sec_desc_debug_addr, a.sec_offset); + break; + case DW_AT_rnglists_base: + cu->rnglist_base = getPointerInSection(*img, sec_desc_debug_rnglists, a.sec_offset); + break; + case DW_AT_loclists_base: + cu->loclist_base = getPointerInSection(*img, sec_desc_debug_loclists, a.sec_offset); + break; } } diff --git a/src/readDwarf.h b/src/readDwarf.h index 1978bf0..67a5ed5 100644 --- a/src/readDwarf.h +++ b/src/readDwarf.h @@ -11,6 +11,7 @@ typedef unsigned char byte; class PEImage; class DIECursor; +struct SectionDescriptor; enum DebugLevel : unsigned { DbgBasic = 0x1, @@ -138,6 +139,18 @@ struct DWARF_CompilationUnitInfo // lists. uint32_t base_address; + // Indirect base address in .debug_addr for addrx forms + byte* addr_base; + + // Indirect base address in .debug_str_offsets for strx forms + byte* str_offset_base; + + // Indirect base address in .debug_loclists for loclistx forms + byte* loclist_base; + + // Indirect base address in the .debug_rnglists for rnglistx forms + byte* rnglist_base; + // Offset within the debug_info section uint32_t cu_offset; byte* start_ptr; @@ -148,7 +161,6 @@ struct DWARF_CompilationUnitInfo byte* read(DebugLevel debug, const PEImage& img, unsigned long *off); bool isDWARF64() const { return is_dwarf64; } - int refSize() const { return isDWARF64() ? 8 : 4; } }; struct DWARF_FileName @@ -526,6 +538,15 @@ public: return RD8(p); } + + unsigned long long RDref(byte* &ptr) const { return cu->isDWARF64() ? RD8(ptr) : RD4(ptr); } + int refSize() const { return cu->isDWARF64() ? 8 : 4; } + + // Obtain the address of a string for a strx form. + const char *resolveIndirectString(uint32_t index) const ; + uint32_t readIndirectAddr(uint32_t index) const ; + uint32_t resolveIndirectSecPtr(uint32_t index, const SectionDescriptor &secDesc, byte *baseAddress) const; + }; // iterate over DWARF debug_line information -- cgit v0.12