From b5bb7f4c024cdedab46a4967433cdbc1e2af31a9 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 17 Oct 2014 09:42:53 -0700 Subject: Fixed O^n abbrev search. DIE tree navigation without requiring DW_AT_sibling attributes, moved navigation logic into DIECursor class. --- src/cv2pdb.h | 19 +- src/cv2pdb.vcxproj | 245 +++++------ src/cv2pdb.vcxproj.filters | 129 +++--- src/dwarf2pdb.cpp | 998 ++++++++++----------------------------------- src/readDwarf.cpp | 392 ++++++++++++++++++ src/readDwarf.h | 308 ++++++++++++++ 6 files changed, 1125 insertions(+), 966 deletions(-) create mode 100644 src/readDwarf.cpp create mode 100644 src/readDwarf.h diff --git a/src/cv2pdb.h b/src/cv2pdb.h index 0153169..f5b2938 100644 --- a/src/cv2pdb.h +++ b/src/cv2pdb.h @@ -9,9 +9,11 @@ #include "LastError.h" #include "mspdb.h" +#include "readDwarf.h" #include #include +#include extern "C" { #include "mscvpdb.h" @@ -158,7 +160,6 @@ public: // DWARF bool createDWARFModules(); - unsigned char* getDWARFAbbrev(int off, int n); bool addDWARFTypes(); bool addDWARFLines(); bool addDWARFPublics(); @@ -166,16 +167,16 @@ public: bool writeDWARFImage(const TCHAR* opath); bool addDWARFSectionContrib(mspdb::Mod* mod, unsigned long pclo, unsigned long pchi); - bool addDWARFProc(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end); - int addDWARFStructure(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end); - int addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, unsigned char* &locals, unsigned char* end); + bool addDWARFProc(DWARF_InfoData& id, DWARF_CompilationUnit* cu, DIECursor cursor); + int addDWARFStructure(DWARF_InfoData& id, DWARF_CompilationUnit* cu, DIECursor cursor); + int addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, DIECursor cursor); int addDWARFBasicType(const char*name, int encoding, int byte_size); - bool iterateDWARFDebugInfo(int op); int getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off); int getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff); - int getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, - unsigned char* &locals, unsigned char* end, int& upperBound); - bool readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &p, bool mergeInfo = false); + int getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, DIECursor cursor, int& upperBound); + + bool mapTypes(); + bool createTypes(); // private: BYTE* libraries; @@ -255,7 +256,7 @@ public: // DWARF int codeSegOff; - std::map mapOffsetToType; + std::unordered_map mapOffsetToType; }; diff --git a/src/cv2pdb.vcxproj b/src/cv2pdb.vcxproj index 3694a5b..00e669e 100644 --- a/src/cv2pdb.vcxproj +++ b/src/cv2pdb.vcxproj @@ -1,122 +1,125 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {5E2BD27D-446A-4C99-9829-135F7C000D90} - cv2pdb - Win32Proj - - - - Application - v120_xp - Unicode - true - - - Application - v120_xp - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>12.0.21005.1 - - - ..\bin\$(Configuration)\ - ..\bin\$(Configuration)\$(ProjectName)\ - true - - - ..\bin\$(Configuration)\ - ..\bin\$(Configuration)\$(ProjectName)\ - false - - - - /wd4996 %(AdditionalOptions) - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - Level3 - EditAndContinue - - - dbghelp.lib;%(AdditionalDependencies) - $(OutDir)$(ProjectName).exe - true - Console - MachineX86 - 5.1 - - - - - /wd4996 %(AdditionalOptions) - MaxSpeed - true - Speed - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreaded - true - false - - Level3 - ProgramDatabase - - - true - Console - true - true - MachineX86 - true - 5.1 - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + {5E2BD27D-446A-4C99-9829-135F7C000D90} + cv2pdb + Win32Proj + + + + Application + v120_xp + Unicode + true + + + Application + v120_xp + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>12.0.21005.1 + + + ..\bin\$(Configuration)\ + ..\bin\$(Configuration)\$(ProjectName)\ + true + + + ..\bin\$(Configuration)\ + ..\bin\$(Configuration)\$(ProjectName)\ + false + + + + /wd4996 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + false + + Level3 + EditAndContinue + + + dbghelp.lib;%(AdditionalDependencies) + $(OutDir)$(ProjectName).exe + true + Console + MachineX86 + 5.1 + + + + + /wd4996 %(AdditionalOptions) + MaxSpeed + true + Speed + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreaded + true + false + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + true + 5.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/cv2pdb.vcxproj.filters b/src/cv2pdb.vcxproj.filters index 9807733..3bf032c 100644 --- a/src/cv2pdb.vcxproj.filters +++ b/src/cv2pdb.vcxproj.filters @@ -1,61 +1,70 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/src/dwarf2pdb.cpp b/src/dwarf2pdb.cpp index 13bb426..58228ab 100644 --- a/src/dwarf2pdb.cpp +++ b/src/dwarf2pdb.cpp @@ -21,546 +21,16 @@ #include #include -/////////////////////////////////////////////////////////////////////////////// - -unsigned int LEB128(unsigned char* &p) -{ - unsigned int x = 0; - int shift = 0; - while(*p & 0x80) - { - x |= (*p & 0x7f) << shift; - shift += 7; - p++; - } - x |= *p << shift; - p++; - return x; -} - -unsigned int LEB128(unsigned char* base, int& off) -{ - unsigned char* p = base + off; - unsigned int x = LEB128(p); - off = p - base; - return x; -} - -int SLEB128(unsigned char* &p) -{ - unsigned int x = 0; - int shift = 0; - while(*p & 0x80) - { - x |= (*p & 0x7f) << shift; - shift += 7; - p++; - } - x |= *p << shift; - if(*p & 0x40) - x |= -(1 << (shift + 7)); // sign extend - p++; - return x; -} - -unsigned int RD2(unsigned char* p) -{ - unsigned int x = *p++; - x |= *p++ << 8; - return x; -} - -unsigned int RD4(unsigned char* p) -{ - unsigned int x = *p++; - x |= *p++ << 8; - x |= *p++ << 16; - x |= *p++ << 24; - return x; -} - -unsigned long long RD8(unsigned char* p) -{ - unsigned long long x = *p++; - for(int shift = 8; shift < 64; shift += 8) - x |= (unsigned long long) *p++ << shift; - return x; -} - -unsigned long long RDsize(unsigned char* p, int size) -{ - if(size > 8) - size = 8; - unsigned long long x = *p++; - for(int shift = 8; shift < size * 8; shift += 8) - x |= (unsigned long long) *p++ << shift; - return x; -} - - -/////////////////////////////////////////////////////////////////////////////// - -#include "pshpack1.h" - -struct DWARF_CompilationUnit -{ - unsigned int unit_length; // 12 byte in DWARF-64 - unsigned short version; - unsigned int debug_abbrev_offset; // 8 byte in DWARF-64 - unsigned char address_size; - - bool isDWARF64() const { return unit_length == ~0; } - int refSize() const { return unit_length == ~0 ? 8 : 4; } -}; - -struct DWARF_FileName -{ - const char* file_name; - unsigned int dir_index; - unsigned long lastModification; - unsigned long fileLength; - - void read(unsigned char* &p) - { - file_name = (const char*) p; - p += strlen((const char*) p) + 1; - dir_index = LEB128(p); - lastModification = LEB128(p); - fileLength = LEB128(p); - } -}; - -struct DWARF_InfoData -{ - int entryOff; - int code; - int tag; - int hasChild; - - const char* name; - const char* linkage_name; - const char* dir; - unsigned long byte_size; - unsigned long sibling; - unsigned long encoding; - unsigned long pclo; - unsigned long pchi; - unsigned long ranges; - unsigned long type; - unsigned long containing_type; - unsigned long specification; - unsigned long inlined; - unsigned long external; - unsigned char*location_ptr; - unsigned long location_len; - unsigned char*member_location_ptr; - unsigned long member_location_len; - unsigned long member_location_data; - unsigned long locationlist; // offset into debug_loc - long frame_base; - long upper_bound; - long lower_bound; -}; - -static const int maximum_operations_per_instruction = 1; - -struct DWARF_LineNumberProgramHeader -{ - unsigned int unit_length; // 12 byte in DWARF-64 - unsigned short version; - unsigned int header_length; // 8 byte in DWARF-64 - unsigned char minimum_instruction_length; - //unsigned char maximum_operations_per_instruction; (// not in DWARF 2 - unsigned char default_is_stmt; - signed char line_base; - unsigned char line_range; - unsigned char opcode_base; - //LEB128 standard_opcode_lengths[opcode_base]; - // string include_directories[] // zero byte terminated - // DWARF_FileNames file_names[] // zero byte terminated -}; - -struct DWARF_LineState -{ - // hdr info - std::vector include_dirs; - std::vector files; - - unsigned long address; - unsigned int op_index; - unsigned int file; - unsigned int line; - unsigned int column; - bool is_stmt; - bool basic_block; - bool end_sequence; - bool prologue_end; - bool epilogue_end; - unsigned int isa; - unsigned int discriminator; - - // not part of the "documented" state - DWARF_FileName* file_ptr; - unsigned long seg_offset; - unsigned long last_addr; - std::vector lineInfo; - - DWARF_LineState() - { - seg_offset = 0x400000; - init(0); - } - - void init(DWARF_LineNumberProgramHeader* hdr) - { - address = 0; - op_index = 0; - file = 1; - line = 1; - column = 0; - is_stmt = hdr && hdr->default_is_stmt != 0; - basic_block = false; - end_sequence = false; - prologue_end = false; - epilogue_end = false; - isa = 0; - discriminator = 0; - } - - void advance_addr(DWARF_LineNumberProgramHeader* hdr, int operation_advance) - { - int address_advance = hdr->minimum_instruction_length * ((op_index + operation_advance) / maximum_operations_per_instruction); - address += address_advance; - op_index = (op_index + operation_advance) % maximum_operations_per_instruction; - } - - void addLineInfo() - { -#if 0 - const char* fname = (file == 0 ? file_ptr->file_name : files[file - 1].file_name); - printf("Adr:%08x Line: %5d File: %s\n", address, line, fname); -#endif - if(address < seg_offset) - return; - mspdb::LineInfoEntry entry; - entry.offset = address - seg_offset; - entry.line = line; - lineInfo.push_back(entry); - } -}; - -#include "poppack.h" - -/////////////////////////////////////////////////////////////////////////////// - -long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size) -{ - unsigned char* p = loc; - long stack[8] = {0}; - int stackDepth = push0 ? 1 : 0; - long data = 0; - id = push0 ? S_CONSTANT_V2 : -1; - do - { - if(p - loc >= len) - break; - - int op = *p++; - if(op == 0) - break; - size = 0; - - switch(op) - { - case DW_OP_addr: id = S_GDATA_V2; size = 4; stack[stackDepth++] = RD4(p); break; - case DW_OP_fbreg: id = S_BPREL_V2; stack[stackDepth++] = SLEB128(p); break; - case DW_OP_const1u: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = *p; break; - case DW_OP_const2u: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = RD2(p); break; - case DW_OP_const4u: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = RD4(p); break; - case DW_OP_const1s: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = (char)*p; break; - case DW_OP_const2s: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = (short)RD2(p); break; - case DW_OP_const4s: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = (int)RD4(p); break; - case DW_OP_constu: id = S_CONSTANT_V2; stack[stackDepth++] = LEB128(p); break; - case DW_OP_consts: id = S_CONSTANT_V2; stack[stackDepth++] = SLEB128(p); break; - case DW_OP_plus_uconst: stack[stackDepth-1] += LEB128(p); break; - case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: - case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: - case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: - case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: - case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: - case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: - case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27: - case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: - id = S_CONSTANT_V2; - stack[stackDepth++] = op - DW_OP_lit0; - break; - case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: - case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: - case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: - case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: - case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: - case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: - case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: - case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: - id = S_REGISTER_V2; - break; - case DW_OP_regx: - id = S_REGISTER_V2; - data = LEB128(p); // reg - break; - case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: - case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: - case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: - case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: - case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: - case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: - case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: - case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: - id = ( op == DW_OP_breg4 ? S_BPREL_XXXX_V3 : op == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2 ); - stack[stackDepth++] = SLEB128(p); - break; - case DW_OP_bregx: - data = LEB128(p); // reg - id = ( data == DW_OP_breg4 ? S_BPREL_XXXX_V3 : data == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2 ); - stack[stackDepth++] = SLEB128(p); - break; - - case DW_OP_deref: break; - case DW_OP_deref_size: size = 1; break; - case DW_OP_dup: stack[stackDepth] = stack[stackDepth-1]; stackDepth++; break; - case DW_OP_drop: stackDepth--; break; - case DW_OP_over: stack[stackDepth] = stack[stackDepth-2]; stackDepth++; break; - case DW_OP_pick: size = 1; stack[stackDepth++] = stack[*p]; break; - case DW_OP_swap: data = stack[stackDepth-1]; stack[stackDepth-1] = stack[stackDepth-2]; stack[stackDepth-2] = data; break; - case DW_OP_rot: data = stack[stackDepth-1]; stack[stackDepth-1] = stack[stackDepth-2]; stack[stackDepth-2] = stack[stackDepth-3]; stack[stackDepth-3] = data; break; - case DW_OP_xderef: stackDepth--; break; - case DW_OP_xderef_size: size = 1; stackDepth--; break; - - case DW_OP_push_object_address: stackDepth++; break; /* DWARF3 */ - case DW_OP_call2: size = 2; break; - case DW_OP_call4: size = 4; break; - case DW_OP_form_tls_address: break; - case DW_OP_call_frame_cfa: stack[stackDepth++] = -1; break; // default stack offset? - case DW_OP_call_ref: - case DW_OP_bit_piece: - case DW_OP_implicit_value: /* DWARF4 */ - case DW_OP_stack_value: - //assert(!"unsupported expression operations"); - id = -1; - return 0; - - // unary operations pop and push - case DW_OP_abs: stack[stackDepth-1] = abs(stack[stackDepth-1]); break; - case DW_OP_neg: stack[stackDepth-1] = -stack[stackDepth-1]; break; - case DW_OP_not: stack[stackDepth-1] = ~stack[stackDepth-1]; break; - break; - // binary operations pop twice and push - case DW_OP_and: stack[stackDepth-2] = stack[stackDepth-2] & stack[stackDepth-1]; stackDepth--; break; - case DW_OP_div: stack[stackDepth-2] = stack[stackDepth-2] / stack[stackDepth-1]; stackDepth--; break; - case DW_OP_minus: stack[stackDepth-2] = stack[stackDepth-2] - stack[stackDepth-1]; stackDepth--; break; - case DW_OP_mod: stack[stackDepth-2] = stack[stackDepth-2] % stack[stackDepth-1]; stackDepth--; break; - case DW_OP_mul: stack[stackDepth-2] = stack[stackDepth-2] * stack[stackDepth-1]; stackDepth--; break; - case DW_OP_or: stack[stackDepth-2] = stack[stackDepth-2] | stack[stackDepth-1]; stackDepth--; break; - case DW_OP_plus: stack[stackDepth-2] = stack[stackDepth-2] + stack[stackDepth-1]; stackDepth--; break; - case DW_OP_shl: stack[stackDepth-2] = stack[stackDepth-2] << stack[stackDepth-1]; stackDepth--; break; - case DW_OP_shr: stack[stackDepth-2] = stack[stackDepth-2] >> stack[stackDepth-1]; stackDepth--; break; - case DW_OP_shra: stack[stackDepth-2] = stack[stackDepth-2] >> stack[stackDepth-1]; stackDepth--; break; - case DW_OP_xor: stack[stackDepth-2] = stack[stackDepth-2] ^ stack[stackDepth-1]; stackDepth--; break; - case DW_OP_eq: stack[stackDepth-2] = stack[stackDepth-2] == stack[stackDepth-1]; stackDepth--; break; - case DW_OP_ge: stack[stackDepth-2] = stack[stackDepth-2] >= stack[stackDepth-1]; stackDepth--; break; - case DW_OP_gt: stack[stackDepth-2] = stack[stackDepth-2] > stack[stackDepth-1]; stackDepth--; break; - case DW_OP_le: stack[stackDepth-2] = stack[stackDepth-2] <= stack[stackDepth-1]; stackDepth--; break; - case DW_OP_lt: stack[stackDepth-2] = stack[stackDepth-2] < stack[stackDepth-1]; stackDepth--; break; - case DW_OP_ne: stack[stackDepth-2] = stack[stackDepth-2] != stack[stackDepth-1]; stackDepth--; break; - - case DW_OP_bra: - case DW_OP_skip: - size = RD2(p) + 2; - break; - } - p += size; - } - while(stackDepth > 0); - size = p - loc; - return stack[0]; -} - - -long decodeLocation(unsigned char*loc, long len, bool push0, int &id) -{ - int size; - return decodeLocation(loc, len, push0, id, size); -} - -unsigned char* CV2PDB::getDWARFAbbrev(int off, int findcode) -{ - if(!img.debug_abbrev) - return 0; - - unsigned char* p = (unsigned char*) img.debug_abbrev; - while(off < (int)img.debug_abbrev_length) - { - int code = LEB128(p, off); - if(code == findcode) - return p + off; - if(code == 0) - return 0; - int tag = LEB128(p, off); - int hasChild = p[off++]; - - // skip attributes - int attr, form; - do - { - attr = LEB128(p, off); - form = LEB128(p, off); - } - while(attr || form); - } - return 0; -} - -bool CV2PDB::readDWARFInfoData(DWARF_InfoData& id, DWARF_CompilationUnit* cu, unsigned char* &p, bool mergeInfo) -{ - int entryOff = p - (unsigned char*) cu; - int code = LEB128(p); - if(code == 0) - return false; // end of children list? - - unsigned char* abbrev = getDWARFAbbrev(cu->debug_abbrev_offset, code); - assert(abbrev); - if(!abbrev) - return false; - int tag = LEB128(abbrev); - int hasChild = *abbrev++; - - if(!mergeInfo) - { - id.entryOff = entryOff; - id.code = code; - id.tag = tag; - id.hasChild = hasChild; - - id.name = 0; - id.linkage_name = 0; - id.dir = 0; - id.byte_size = 0; - id.sibling = 0; - id.encoding = 0; - id.pclo = 0; - id.pchi = 0; - id.ranges = 0; - id.type = 0; - id.containing_type = 0; - id.specification = 0; - id.inlined = 0; - id.external = 0; - id.member_location_ptr = 0; - id.member_location_len = 0; - id.member_location_data = 0; - id.location_ptr = 0; - id.location_len = 0; - id.locationlist = 0; - id.frame_base = -1; - id.upper_bound = 0; - id.lower_bound = 0; - } - int attr, form; - for( ; ; ) - { - attr = LEB128(abbrev); - form = LEB128(abbrev); - - if(attr == 0 && form == 0) - break; - - const char* str = 0; - int size = 0; - unsigned long addr = 0; - unsigned long data = 0; - unsigned long long lldata = 0; - int locid; - bool isRef = false; - switch(form) - { - case DW_FORM_addr: addr = *(unsigned long *)p; size = cu->address_size; break; - case DW_FORM_block2: size = RD2(p) + 2; break; - case DW_FORM_block4: size = RD4(p) + 4; break; - case DW_FORM_data2: size = 2; lldata = data = RD2(p); break; - case DW_FORM_data4: size = 4; lldata = data = RD4(p); break; - case DW_FORM_data8: size = 8; lldata = RD8(p); data = (unsigned long) lldata; break; - case DW_FORM_string: str = (const char*) p; size = strlen(str) + 1; break; - case DW_FORM_block: size = LEB128(p); lldata = RDsize(p, size); data = (unsigned long) lldata; break; - case DW_FORM_block1: size = *p++; lldata = RDsize(p, size); data = (unsigned long) lldata; break; - case DW_FORM_data1: size = 1; lldata = data = *p; break; - case DW_FORM_flag: size = 1; lldata = data = *p; break; - case DW_FORM_sdata: lldata = data = SLEB128(p); size = 0; break; - case DW_FORM_strp: size = cu->refSize(); str = (const char*) (img.debug_str + RDsize(p, size)); break; - case DW_FORM_udata: lldata = data = LEB128(p); size = 0; break; - case DW_FORM_ref_addr: size = cu->address_size; lldata = RDsize(p, size); data = (unsigned long) lldata; isRef = true; break; - case DW_FORM_ref1: size = 1; lldata = data = *p; isRef = true; break; - case DW_FORM_ref2: size = 2; lldata = data = RD2(p); isRef = true; break; - case DW_FORM_ref4: size = 4; lldata = data = RD4(p); isRef = true; break; - case DW_FORM_ref8: size = 8; lldata = RD8(p); data = (unsigned long) lldata; isRef = true; break; - case DW_FORM_ref_udata: lldata = data = LEB128(p); size = 0; isRef = true; break; - case DW_FORM_exprloc: size = LEB128(p); lldata = decodeLocation(p, size, false, locid); data = (unsigned long) lldata; isRef = true; break; - case DW_FORM_flag_present: size = 0; lldata = data = 1; break; - case DW_FORM_ref_sig8: size = 8; break; - case DW_FORM_sec_offset: size = img.isX64() ? 8 : 4; lldata = RDsize(p, size); data = (unsigned long) lldata; isRef = true; break; - case DW_FORM_indirect: - default: return setError("unknown DWARF form entry"); - } - switch(attr) - { - case DW_AT_byte_size: id.byte_size = data; break; - case DW_AT_sibling: id.sibling = data; break; - case DW_AT_encoding: id.encoding = data; break; - case DW_AT_name: id.name = str; break; - case DW_AT_MIPS_linkage_name: id.linkage_name = str; break; - case DW_AT_comp_dir: id.dir = str; break; - case DW_AT_low_pc: id.pclo = addr; break; - case DW_AT_high_pc: - if(form == DW_FORM_addr) - id.pchi = addr; - else - id.pchi = id.pclo + data; - break; - case DW_AT_ranges: id.ranges = data; break; - case DW_AT_type: id.type = data; break; - case DW_AT_inline: id.inlined = data; break; - case DW_AT_external: id.external = data; break; - case DW_AT_upper_bound: id.upper_bound = data; break; - case DW_AT_lower_bound: id.lower_bound = data; break; - case DW_AT_containing_type: id.containing_type = data; break; - case DW_AT_specification: id.specification = data; break; - case DW_AT_data_member_location: - if(form == DW_FORM_block1 || form == DW_FORM_exprloc) - id.member_location_ptr = p, id.member_location_len = size; - else - id.member_location_data = data; - break; - case DW_AT_location: - if(form == DW_FORM_block1 || form == DW_FORM_exprloc) - id.location_ptr = p, id.location_len = size; - else - id.locationlist = data; - break; - case DW_AT_frame_base: - if(form != DW_FORM_block2 && form != DW_FORM_block4 && form != DW_FORM_block1 && form != DW_FORM_block) - id.frame_base = data; - break; - } - p += size; - } - return true; -} void CV2PDB::checkDWARFTypeAlloc(int size, int add) { if (cbDwarfTypes + size > allocDwarfTypes) { - allocDwarfTypes += size + add; + //allocDwarfTypes += size + add; + allocDwarfTypes += allocDwarfTypes/2 + size + add; dwarfTypes = (BYTE*) realloc(dwarfTypes, allocDwarfTypes); + if (dwarfTypes == nullptr) + __debugbreak(); } } @@ -664,13 +134,11 @@ void CV2PDB::appendLexicalBlock(DWARF_InfoData& id, unsigned int proclo) cbUdtSymbols += len; } -bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, - unsigned char* &locals, unsigned char* end) +bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, DIECursor cursor) { unsigned int pclo = procid.pclo - codeSegOff; unsigned int pchi = procid.pchi - codeSegOff; - int length = procid.hasChild ? end - locals : 0; unsigned int len; unsigned int align = 4; @@ -739,75 +207,64 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, } #endif } - if(cu && locals && length) + + if (cu) { bool endarg = false; - unsigned char* p = locals; - unsigned char* end = locals + length; DWARF_InfoData id; int off = 8; int cvid; - std::vector lexicalBlockEnd; - lexicalBlockEnd.push_back(end); - while(lexicalBlockEnd.size() > 0) + DIECursor prev = cursor; + while (cursor.readSibling(id) && id.tag == DW_TAG_formal_parameter) { - if(p >= lexicalBlockEnd.back()) - { - if (!endarg) - endarg = appendEndArg(); - appendEnd(); - lexicalBlockEnd.pop_back(); - continue; - } - if(!readDWARFInfoData(id, cu, p)) - continue; - if (id.tag == DW_TAG_formal_parameter) { - if(id.name) + if (id.name) { off = decodeLocation(id.location_ptr, id.location_len, false, cvid); - if(cvid == S_BPREL_V2) + if (cvid == S_BPREL_V2) appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false); - else if(cvid == S_BPREL_XXXX_V3) + else if (cvid == S_BPREL_XXXX_V3) appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true); } } - else + prev = cursor; + } + appendEndArg(); + + std::vector lexicalBlocks; + lexicalBlocks.push_back(prev); + + while (!lexicalBlocks.empty()) + { + cursor = lexicalBlocks.back(); + lexicalBlocks.pop_back(); + + while (cursor.readSibling(id)) { - if(!endarg) - endarg = appendEndArg(); - switch(id.tag) + if (id.tag == DW_TAG_variable) { - case DW_TAG_variable: - if(id.name) - { - off = decodeLocation(id.location_ptr, id.location_len, false, cvid); - if(cvid == S_BPREL_V2) - appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false); - else if(cvid == S_BPREL_XXXX_V3) - appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true); - } - break; - case DW_TAG_subprogram: - if(id.hasChild && !id.inlined) - p = (id.sibling ? (unsigned char*) cu + id.sibling : end); - break; - case DW_TAG_lexical_block: - if(id.hasChild && id.pchi != id.pclo) - { - appendLexicalBlock(id, pclo + codeSegOff); - if(id.sibling) - lexicalBlockEnd.push_back((unsigned char*) cu + id.sibling); - else - lexicalBlockEnd.push_back(lexicalBlockEnd.back()); - } - break; - default: - break; + if (id.name) + { + off = decodeLocation(id.location_ptr, id.location_len, false, cvid); + if (cvid == S_BPREL_V2) + appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off + frameOff, false); + else if (cvid == S_BPREL_XXXX_V3) + appendStackVar(id.name, getTypeByDWARFOffset(cu, id.type), off, true); + } + } + else if (id.tag == DW_TAG_lexical_block) + { + if (id.hasChild && id.pchi != id.pclo) + { + appendLexicalBlock(id, pclo + codeSegOff); + lexicalBlocks.push_back(cursor); + cursor = cursor.getSubtreeCursor(); + } } } + appendEnd(); } } else @@ -818,15 +275,15 @@ bool CV2PDB::addDWARFProc(DWARF_InfoData& procid, DWARF_CompilationUnit* cu, return true; } -int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* cu, - unsigned char* &locals, unsigned char* end) +int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* cu, DIECursor cursor) { + printf("Adding struct %s, entryoff %d, abbrev %d\n", structid.name, structid.entryOff, structid.abbrev); + bool isunion = structid.tag == DW_TAG_union_type; - int length = structid.hasChild ? end - locals : 0; int fieldlistType = 0; int nfields = 0; - if(cu && locals && length) + if (cu) { checkDWARFTypeAlloc(100); codeview_reftype* fl = (codeview_reftype*) (dwarfTypes + cbDwarfTypes); @@ -848,19 +305,15 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c nfields++; } #endif - unsigned char* p = locals; - unsigned char* end = locals + length; DWARF_InfoData id; int len = 0; - while(p < end) + while (cursor.readSibling(id)) { - if(!readDWARFInfoData(id, cu, p)) - continue; - int cvid = -1; if (id.tag == DW_TAG_member && id.name) { - int off = 0; + printf(" Adding field %s\n", id.name); + int off = 0; if(!isunion) { if(id.member_location_ptr) @@ -881,7 +334,7 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c } else if(id.tag == DW_TAG_inheritance) { - int off = decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid); + int off = decodeLocation(id.member_location_ptr, id.member_location_len, true, cvid); if(cvid == S_CONSTANT_V2) { codeview_fieldtype* bc = (codeview_fieldtype*) (dwarfTypes + cbDwarfTypes); @@ -895,8 +348,6 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c nfields++; } } - if(id.sibling) - p = (unsigned char*) cu + id.sibling; } fl = (codeview_reftype*) (dwarfTypes + flbegin); fl->fieldlist.len = cbDwarfTypes - flbegin - 2; @@ -918,39 +369,30 @@ int CV2PDB::addDWARFStructure(DWARF_InfoData& structid, DWARF_CompilationUnit* c } int CV2PDB::getDWARFArrayBounds(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, - unsigned char* &locals, unsigned char* end, int& upperBound) + DIECursor cursor, int& upperBound) { - int length = arrayid.hasChild ? end - locals : 0; int lowerBound = 0; - if(cu && locals && length) + if (cu) { - unsigned char* p = locals; - unsigned char* end = locals + length; DWARF_InfoData id; - int len = 0; - while(p < end) + while (cursor.readSibling(id)) { - if(!readDWARFInfoData(id, cu, p)) - continue; - int cvid = -1; if (id.tag == DW_TAG_subrange_type) { lowerBound = id.lower_bound; upperBound = id.upper_bound; } - if(id.sibling) - p = (unsigned char*) cu + id.sibling; } } return lowerBound; } int CV2PDB::addDWARFArray(DWARF_InfoData& arrayid, DWARF_CompilationUnit* cu, - unsigned char* &locals, unsigned char* end) + DIECursor cursor) { - int upperBound, lowerBound = getDWARFArrayBounds(arrayid, cu, locals, end, upperBound); + int upperBound, lowerBound = getDWARFArrayBounds(arrayid, cu, cursor, upperBound); checkUserTypeAlloc(kMaxNameLen + 100); codeview_type* cvt = (codeview_type*) (userTypes + cbUserTypes); @@ -1100,7 +542,7 @@ int CV2PDB::addDWARFBasicType(const char*name, int encoding, int byte_size) int CV2PDB::getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off) { int cuoff = (char*) cu - img.debug_info; - std::map::iterator it = mapOffsetToType.find(cuoff + off); + std::unordered_map::iterator it = mapOffsetToType.find(cuoff + off); if(it == mapOffsetToType.end()) return 0x03; // void return it->second; @@ -1109,8 +551,9 @@ int CV2PDB::getTypeByDWARFOffset(DWARF_CompilationUnit* cu, int off) int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff) { DWARF_InfoData id; - unsigned char* p = (unsigned char*) cu + typeOff; - if(!readDWARFInfoData(id, cu, p)) + DIECursor cursor(cu, typeOff); + + if (!cursor.readNext(id)) return 0; if(id.byte_size > 0) return id.byte_size; @@ -1123,7 +566,7 @@ int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff) return cu->address_size; case DW_TAG_array_type: { - int upperBound, lowerBound = getDWARFArrayBounds(id, cu, p, p + 1, upperBound); + int upperBound, lowerBound = getDWARFArrayBounds(id, cu, cursor, upperBound); return (upperBound + lowerBound + 1) * getDWARFTypeSize(cu, id.type); } default: @@ -1134,51 +577,22 @@ int CV2PDB::getDWARFTypeSize(DWARF_CompilationUnit* cu, int typeOff) return 0; } -enum iterateOp { kOpMapTypes, kOpCreateTypes }; - -bool CV2PDB::iterateDWARFDebugInfo(int op) +bool CV2PDB::mapTypes() { - mspdb::Mod* mod = globalMod(); int typeID = nextUserType; - - int pointerAttr = img.isX64() ? 0x1000C : 0x800A; - for(unsigned long off = 0; off < img.debug_info_length; ) + unsigned long off = 0; + while (off < img.debug_info_length) { - DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*) (img.debug_info + off); - int length = cu->unit_length; - if(length < 0) - break; + DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)(img.debug_info + off); - length += sizeof(length); - unsigned char* end = (unsigned char*) cu + length; - std::vector endStack; - endStack.push_back(end); - - for(unsigned char* p = (unsigned char*) (cu + 1); endStack.size() > 0; ) + DIECursor cursor(cu, sizeof(DWARF_CompilationUnit)); + DWARF_InfoData id; + while (cursor.readNext(id)) { - if(p >= endStack.back()) - { - endStack.pop_back(); - continue; - } - DWARF_InfoData id; - if(!readDWARFInfoData(id, cu, p)) - continue; - if(id.specification) + //printf("0x%08x, level = %d, id.code = %d, id.tag = %d\n", + // (unsigned char*)cu + id.entryOff - (unsigned char*)img.debug_info, cursor.level, id.code, id.tag); + switch (id.tag) { - unsigned char* q = (unsigned char*) cu + id.specification; - readDWARFInfoData(id, cu, q, true); - } - if(id.hasChild) - if(id.sibling) - endStack.push_back((unsigned char*) cu + id.sibling); - else - endStack.push_back(endStack.back()); - - if(op == kOpMapTypes) - { - switch(id.tag) - { case DW_TAG_base_type: case DW_TAG_typedef: case DW_TAG_pointer_type: @@ -1205,144 +619,167 @@ bool CV2PDB::iterateDWARFDebugInfo(int op) case DW_TAG_mutable_type: // withdrawn case DW_TAG_shared_type: case DW_TAG_rvalue_reference_type: - mapOffsetToType.insert(std::pair(off + id.entryOff, typeID)); + mapOffsetToType.insert(std::pair(off + id.entryOff, typeID)); typeID++; - } } - else - { - int cvtype = -1; - switch(id.tag) - { - case DW_TAG_base_type: - cvtype = addDWARFBasicType(id.name, id.encoding, id.byte_size); - break; - case DW_TAG_typedef: - cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 0); - addUdtSymbol(cvtype, id.name); - break; - case DW_TAG_pointer_type: - cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr); - break; - case DW_TAG_const_type: - cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 1); - break; - case DW_TAG_reference_type: - cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr | 0x20); - break; + } - case DW_TAG_class_type: - case DW_TAG_structure_type: - case DW_TAG_union_type: - cvtype = addDWARFStructure(id, cu, p, endStack.back()); - break; - case DW_TAG_array_type: - cvtype = addDWARFArray(id, cu, p, endStack.back()); - break; - case DW_TAG_subroutine_type: - case DW_TAG_subrange_type: + off += sizeof(cu->unit_length) + cu->unit_length; + } - case DW_TAG_enumeration_type: - case DW_TAG_string_type: - case DW_TAG_ptr_to_member_type: - case DW_TAG_set_type: - case DW_TAG_file_type: - case DW_TAG_packed_type: - case DW_TAG_thrown_type: - case DW_TAG_volatile_type: - case DW_TAG_restrict_type: // DWARF3 - case DW_TAG_interface_type: - case DW_TAG_unspecified_type: - case DW_TAG_mutable_type: // withdrawn - case DW_TAG_shared_type: - case DW_TAG_rvalue_reference_type: - cvtype = appendPointerType(0x74, pointerAttr); - break; + nextDwarfType = typeID; + return true; +} - case DW_TAG_subprogram: - if(id.name && id.pclo && id.pchi) - { - addDWARFProc(id, cu, p, endStack.back()); - int rc = mod->AddPublic2(id.name, img.codeSegment + 1, id.pclo - codeSegOff, 0); - } - break; +bool CV2PDB::createTypes() +{ + mspdb::Mod* mod = globalMod(); + int typeID = nextUserType; + int pointerAttr = img.isX64() ? 0x1000C : 0x800A; - case DW_TAG_compile_unit: - #if !FULL_CONTRIB - if(id.dir && id.name) + unsigned long off = 0; + while (off < img.debug_info_length) + { + DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)(img.debug_info + off); + + DIECursor cursor(cu, sizeof(DWARF_CompilationUnit)); + DWARF_InfoData id; + while (cursor.readNext(id)) + { + //printf("0x%08x, level = %d, id.code = %d, id.tag = %d\n", + // (unsigned char*)cu + id.entryOff - (unsigned char*)img.debug_info, cursor.level, id.code, id.tag); + + int cvtype = -1; + switch (id.tag) + { + case DW_TAG_base_type: + cvtype = addDWARFBasicType(id.name, id.encoding, id.byte_size); + break; + case DW_TAG_typedef: + cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 0); + addUdtSymbol(cvtype, id.name); + break; + case DW_TAG_pointer_type: + cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr); + break; + case DW_TAG_const_type: + cvtype = appendModifierType(getTypeByDWARFOffset(cu, id.type), 1); + break; + case DW_TAG_reference_type: + cvtype = appendPointerType(getTypeByDWARFOffset(cu, id.type), pointerAttr | 0x20); + break; + + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + cvtype = addDWARFStructure(id, cu, cursor.getSubtreeCursor()); + break; + case DW_TAG_array_type: + cvtype = addDWARFArray(id, cu, cursor.getSubtreeCursor()); + break; + case DW_TAG_subroutine_type: + case DW_TAG_subrange_type: + + case DW_TAG_enumeration_type: + case DW_TAG_string_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_set_type: + case DW_TAG_file_type: + case DW_TAG_packed_type: + case DW_TAG_thrown_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: // DWARF3 + case DW_TAG_interface_type: + case DW_TAG_unspecified_type: + case DW_TAG_mutable_type: // withdrawn + case DW_TAG_shared_type: + case DW_TAG_rvalue_reference_type: + cvtype = appendPointerType(0x74, pointerAttr); + break; + + case DW_TAG_subprogram: + if (id.name && id.pclo && id.pchi) + { + addDWARFProc(id, cu, cursor.getSubtreeCursor()); + int rc = mod->AddPublic2(id.name, img.codeSegment + 1, id.pclo - codeSegOff, 0); + } + break; + + case DW_TAG_compile_unit: +#if !FULL_CONTRIB + if (id.dir && id.name) + { + if (id.ranges > 0 && id.ranges < img.debug_ranges_length) { - if(id.ranges > 0 && id.ranges < img.debug_ranges_length) - { - unsigned char* r = (unsigned char*)img.debug_ranges + id.ranges; - unsigned char* rend = (unsigned char*)img.debug_ranges + img.debug_ranges_length; - while(r < rend) - { - unsigned long pclo = RD4(r); r += 4; - unsigned long pchi = RD4(r); r += 4; - if(pclo == 0 && pchi == 0) - break; - //printf("%s %s %x - %x\n", dir, name, pclo, pchi); - if(!addDWARFSectionContrib(mod, pclo, pchi)) - return false; - } - } - else + unsigned char* r = (unsigned char*)img.debug_ranges + id.ranges; + unsigned char* rend = (unsigned char*)img.debug_ranges + img.debug_ranges_length; + while (r < rend) { + unsigned long pclo = RD4(r); r += 4; + unsigned long pchi = RD4(r); r += 4; + if (pclo == 0 && pchi == 0) + break; //printf("%s %s %x - %x\n", dir, name, pclo, pchi); - if(!addDWARFSectionContrib(mod, id.pclo, id.pchi)) + if (!addDWARFSectionContrib(mod, pclo, pchi)) return false; } } - #endif - break; - - case DW_TAG_variable: - if(id.name) + else { - int seg = -1; - unsigned long segOff; - if(id.location_ptr == 0 && id.external && id.linkage_name) - { - seg = img.findSymbol(id.linkage_name, segOff); - } - else - { - int cvid; - segOff = decodeLocation(id.location_ptr, id.location_len, false, cvid); - if(cvid == S_GDATA_V2) - seg = img.findSection(segOff); - if(seg >= 0) - segOff -= img.getImageBase() + img.getSection(seg).VirtualAddress; - } - if(seg >= 0) - { - int type = getTypeByDWARFOffset(cu, id.type); - appendGlobalVar(id.name, type, seg + 1, segOff); - int rc = mod->AddPublic2(id.name, seg + 1, segOff, type); - } + //printf("%s %s %x - %x\n", dir, name, pclo, pchi); + if (!addDWARFSectionContrib(mod, id.pclo, id.pchi)) + return false; } - break; - case DW_TAG_formal_parameter: - case DW_TAG_unspecified_parameters: - case DW_TAG_inheritance: - case DW_TAG_member: - case DW_TAG_inlined_subroutine: - case DW_TAG_lexical_block: - default: - break; } - if(cvtype >= 0) +#endif + break; + + case DW_TAG_variable: + if (id.name) { - assert(cvtype == typeID); typeID++; - assert(mapOffsetToType[off + id.entryOff] == cvtype); + int seg = -1; + unsigned long segOff; + if (id.location_ptr == 0 && id.external && id.linkage_name) + { + seg = img.findSymbol(id.linkage_name, segOff); + } + else + { + int cvid; + segOff = decodeLocation(id.location_ptr, id.location_len, false, cvid); + if (cvid == S_GDATA_V2) + seg = img.findSection(segOff); + if (seg >= 0) + segOff -= img.getImageBase() + img.getSection(seg).VirtualAddress; + } + if (seg >= 0) + { + int type = getTypeByDWARFOffset(cu, id.type); + appendGlobalVar(id.name, type, seg + 1, segOff); + int rc = mod->AddPublic2(id.name, seg + 1, segOff, type); + } } + break; + case DW_TAG_formal_parameter: + case DW_TAG_unspecified_parameters: + case DW_TAG_inheritance: + case DW_TAG_member: + case DW_TAG_inlined_subroutine: + case DW_TAG_lexical_block: + default: + break; + } + + if (cvtype >= 0) + { + assert(cvtype == typeID); typeID++; + int x = mapOffsetToType[off + id.entryOff]; + assert(mapOffsetToType[off + id.entryOff] == cvtype); } } - off += length; + + off += sizeof(cu->unit_length) + cu->unit_length; } - - if(op == kOpMapTypes) - nextDwarfType = typeID; return true; } @@ -1387,11 +824,20 @@ bool CV2PDB::createDWARFModules() appendComplex(0x52, 0x42, 12, "creal"); } + DIECursor::setContext(&img); + countEntries = 0; + if (!mapTypes()) + return false; + if (!createTypes()) + return false; + + /* if(!iterateDWARFDebugInfo(kOpMapTypes)) return false; if(!iterateDWARFDebugInfo(kOpCreateTypes)) return false; + */ #if 0 modules = new mspdb::Mod* [countEntries]; diff --git a/src/readDwarf.cpp b/src/readDwarf.cpp new file mode 100644 index 0000000..0d298bb --- /dev/null +++ b/src/readDwarf.cpp @@ -0,0 +1,392 @@ +#include "readDwarf.h" +#include +#include +#include +#include + +#include "PEImage.h" +#include "dwarf.h" +#include "mspdb.h" +extern "C" { + #include "mscvpdb.h" +} + +long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size) +{ + unsigned char* p = loc; + long stack[8] = { 0 }; + int stackDepth = push0 ? 1 : 0; + long data = 0; + id = push0 ? S_CONSTANT_V2 : -1; + do + { + if (p - loc >= len) + break; + + int op = *p++; + if (op == 0) + break; + size = 0; + + switch (op) + { + case DW_OP_addr: id = S_GDATA_V2; size = 4; stack[stackDepth++] = RD4(p); break; + case DW_OP_fbreg: id = S_BPREL_V2; stack[stackDepth++] = SLEB128(p); break; + case DW_OP_const1u: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = *p; break; + case DW_OP_const2u: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = RD2(p); break; + case DW_OP_const4u: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = RD4(p); break; + case DW_OP_const1s: id = S_CONSTANT_V2; size = 1; stack[stackDepth++] = (char)*p; break; + case DW_OP_const2s: id = S_CONSTANT_V2; size = 2; stack[stackDepth++] = (short)RD2(p); break; + case DW_OP_const4s: id = S_CONSTANT_V2; size = 4; stack[stackDepth++] = (int)RD4(p); break; + case DW_OP_constu: id = S_CONSTANT_V2; stack[stackDepth++] = LEB128(p); break; + case DW_OP_consts: id = S_CONSTANT_V2; stack[stackDepth++] = SLEB128(p); break; + case DW_OP_plus_uconst: stack[stackDepth - 1] += LEB128(p); break; + case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: + case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: + case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: + case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: + case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: + case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: + case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27: + case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: + id = S_CONSTANT_V2; + stack[stackDepth++] = op - DW_OP_lit0; + break; + case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: + case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: + case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: + case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: + case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: + case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: + case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: + case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: + id = S_REGISTER_V2; + break; + case DW_OP_regx: + id = S_REGISTER_V2; + data = LEB128(p); // reg + break; + case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: + case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: + case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: + case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: + case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: + case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: + case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: + case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: + id = (op == DW_OP_breg4 ? S_BPREL_XXXX_V3 : op == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2); + stack[stackDepth++] = SLEB128(p); + break; + case DW_OP_bregx: + data = LEB128(p); // reg + id = (data == DW_OP_breg4 ? S_BPREL_XXXX_V3 : data == DW_OP_breg5 ? S_BPREL_V2 : S_REGISTER_V2); + stack[stackDepth++] = SLEB128(p); + break; + + case DW_OP_deref: break; + case DW_OP_deref_size: size = 1; break; + case DW_OP_dup: stack[stackDepth] = stack[stackDepth - 1]; stackDepth++; break; + case DW_OP_drop: stackDepth--; break; + case DW_OP_over: stack[stackDepth] = stack[stackDepth - 2]; stackDepth++; break; + case DW_OP_pick: size = 1; stack[stackDepth++] = stack[*p]; break; + case DW_OP_swap: data = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = data; break; + case DW_OP_rot: data = stack[stackDepth - 1]; stack[stackDepth - 1] = stack[stackDepth - 2]; stack[stackDepth - 2] = stack[stackDepth - 3]; stack[stackDepth - 3] = data; break; + case DW_OP_xderef: stackDepth--; break; + case DW_OP_xderef_size: size = 1; stackDepth--; break; + + case DW_OP_push_object_address: stackDepth++; break; /* DWARF3 */ + case DW_OP_call2: size = 2; break; + case DW_OP_call4: size = 4; break; + case DW_OP_form_tls_address: break; + case DW_OP_call_frame_cfa: stack[stackDepth++] = -1; break; // default stack offset? + case DW_OP_call_ref: + case DW_OP_bit_piece: + case DW_OP_implicit_value: /* DWARF4 */ + case DW_OP_stack_value: + //assert(!"unsupported expression operations"); + id = -1; + return 0; + + // unary operations pop and push + case DW_OP_abs: stack[stackDepth - 1] = abs(stack[stackDepth - 1]); break; + case DW_OP_neg: stack[stackDepth - 1] = -stack[stackDepth - 1]; break; + case DW_OP_not: stack[stackDepth - 1] = ~stack[stackDepth - 1]; break; + break; + // binary operations pop twice and push + case DW_OP_and: stack[stackDepth - 2] = stack[stackDepth - 2] & stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_div: stack[stackDepth - 2] = stack[stackDepth - 2] / stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_minus: stack[stackDepth - 2] = stack[stackDepth - 2] - stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_mod: stack[stackDepth - 2] = stack[stackDepth - 2] % stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_mul: stack[stackDepth - 2] = stack[stackDepth - 2] * stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_or: stack[stackDepth - 2] = stack[stackDepth - 2] | stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_plus: stack[stackDepth - 2] = stack[stackDepth - 2] + stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_shl: stack[stackDepth - 2] = stack[stackDepth - 2] << stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_shr: stack[stackDepth - 2] = stack[stackDepth - 2] >> stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_shra: stack[stackDepth - 2] = stack[stackDepth - 2] >> stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_xor: stack[stackDepth - 2] = stack[stackDepth - 2] ^ stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_eq: stack[stackDepth - 2] = stack[stackDepth - 2] == stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_ge: stack[stackDepth - 2] = stack[stackDepth - 2] >= stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_gt: stack[stackDepth - 2] = stack[stackDepth - 2] > stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_le: stack[stackDepth - 2] = stack[stackDepth - 2] <= stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_lt: stack[stackDepth - 2] = stack[stackDepth - 2] < stack[stackDepth - 1]; stackDepth--; break; + case DW_OP_ne: stack[stackDepth - 2] = stack[stackDepth - 2] != stack[stackDepth - 1]; stackDepth--; break; + + case DW_OP_bra: + case DW_OP_skip: + size = RD2(p) + 2; + break; + } + p += size; + } while (stackDepth > 0); + size = p - loc; + return stack[0]; +} + + +// declare hasher for pair +namespace std +{ + template + struct hash> + { + size_t operator()(const std::pair& t) + { + return std::hash()(t.first) ^ std::hash()(t.second); + } + }; +} + +typedef std::unordered_map, unsigned char*> abbrevMap_t; + +static PEImage* img; +static abbrevMap_t abbrevMap; + +void DIECursor::setContext(PEImage* img_) +{ + img = img_; + abbrevMap.clear(); +} + + +DIECursor::DIECursor(DWARF_CompilationUnit* cu_, unsigned long offset) +{ + cu = cu_; + ptr = (unsigned char*)cu + offset; + level = 0; + hasChild = false; + sibling = 0; +} + + +bool DIECursor::readSibling(DWARF_InfoData& id) +{ + if (sibling) + { + // use sibling pointer, if available + ptr = (unsigned char*)cu + sibling; + hasChild = false; + } + else if (hasChild) + { + int currLevel = level; + level = currLevel + 1; + hasChild = false; + + DWARF_InfoData dummy; + // read untill we pop back to the level we were at + while (level > currLevel) + readNext(dummy); + } + + return readNext(id, true); +} + +DIECursor DIECursor::getSubtreeCursor() +{ + if (hasChild) + { + DIECursor subtree = *this; + subtree.level = 0; + subtree.hasChild = false; + return subtree; + } + else // Return invalid cursor + { + DIECursor subtree = *this; + subtree.level = -1; + return subtree; + } +} + +bool DIECursor::readNext(DWARF_InfoData& id, bool stopAtNull) +{ + id.clear(); + + if (hasChild) + ++level; + + for (;;) + { + if (level == -1) + return false; // we were already at the end of the subtree + + if (ptr >= ((unsigned char*)cu + sizeof(cu->unit_length) + cu->unit_length)) + return false; // root of the tree does not have a null terminator, but we know the length + + id.entryOff = ptr - (unsigned char*)cu; + id.code = LEB128(ptr); + if (id.code == 0) + { + --level; // pop up one level + if (stopAtNull) + { + hasChild = false; + return false; + } + continue; // read the next DIE + } + + break; + } + + unsigned char* abbrev = getDWARFAbbrev(cu->debug_abbrev_offset, id.code); + assert(abbrev); + if (!abbrev) + return false; + + id.abbrev = abbrev; + id.tag = LEB128(abbrev); + id.hasChild = *abbrev++; + + int attr, form; + for (;;) + { + attr = LEB128(abbrev); + form = LEB128(abbrev); + + if (attr == 0 && form == 0) + break; + + const char* str = 0; + int size = 0; + unsigned long addr = 0; + unsigned long data = 0; + unsigned long long lldata = 0; + int locid; + bool isRef = false; + switch (form) + { + case DW_FORM_addr: addr = *(unsigned long *)ptr; size = cu->address_size; break; + case DW_FORM_block2: size = RD2(ptr) + 2; break; + case DW_FORM_block4: size = RD4(ptr) + 4; break; + case DW_FORM_data2: size = 2; lldata = data = RD2(ptr); break; + case DW_FORM_data4: size = 4; lldata = data = RD4(ptr); break; + case DW_FORM_data8: size = 8; lldata = RD8(ptr); data = (unsigned long)lldata; break; + case DW_FORM_string: str = (const char*)ptr; size = strlen(str) + 1; break; + case DW_FORM_block: size = LEB128(ptr); lldata = RDsize(ptr, size); data = (unsigned long)lldata; break; + case DW_FORM_block1: size = *ptr++; lldata = RDsize(ptr, size); data = (unsigned long)lldata; break; + case DW_FORM_data1: size = 1; lldata = data = *ptr; break; + case DW_FORM_flag: size = 1; lldata = data = *ptr; break; + case DW_FORM_sdata: lldata = data = SLEB128(ptr); size = 0; break; + case DW_FORM_strp: size = cu->refSize(); str = (const char*)(img->debug_str + RDsize(ptr, size)); break; + case DW_FORM_udata: lldata = data = LEB128(ptr); size = 0; break; + case DW_FORM_ref_addr: size = cu->address_size; lldata = RDsize(ptr, size); data = (unsigned long)lldata; isRef = true; break; + case DW_FORM_ref1: size = 1; lldata = data = *ptr; isRef = true; break; + case DW_FORM_ref2: size = 2; lldata = data = RD2(ptr); isRef = true; break; + case DW_FORM_ref4: size = 4; lldata = data = RD4(ptr); isRef = true; break; + case DW_FORM_ref8: size = 8; lldata = RD8(ptr); data = (unsigned long)lldata; isRef = true; break; + case DW_FORM_ref_udata: lldata = data = LEB128(ptr); size = 0; isRef = true; break; + case DW_FORM_exprloc: size = LEB128(ptr); lldata = decodeLocation(ptr, size, false, locid); data = (unsigned long)lldata; isRef = true; break; + case DW_FORM_flag_present: size = 0; lldata = data = 1; break; + case DW_FORM_ref_sig8: size = 8; break; + case DW_FORM_sec_offset: size = img->isX64() ? 8 : 4; lldata = RDsize(ptr, size); data = (unsigned long)lldata; isRef = true; break; + case DW_FORM_indirect: + default: assert(false && "Unsupported DWARF attribute form"); return false; + } + switch (attr) + { + case DW_AT_byte_size: id.byte_size = data; break; + case DW_AT_sibling: id.sibling = data; break; + case DW_AT_encoding: id.encoding = data; break; + case DW_AT_name: id.name = str; break; + case DW_AT_MIPS_linkage_name: id.linkage_name = str; break; + case DW_AT_comp_dir: id.dir = str; break; + case DW_AT_low_pc: id.pclo = addr; break; + case DW_AT_high_pc: + if (form == DW_FORM_addr) + id.pchi = addr; + else + id.pchi = id.pclo + data; + break; + case DW_AT_ranges: id.ranges = data; break; + case DW_AT_type: id.type = data; break; + case DW_AT_inline: id.inlined = data; break; + case DW_AT_external: id.external = data; break; + case DW_AT_upper_bound: id.upper_bound = data; break; + case DW_AT_lower_bound: id.lower_bound = data; break; + case DW_AT_containing_type: id.containing_type = data; break; + case DW_AT_specification: id.specification = data; break; + case DW_AT_data_member_location: + if (form == DW_FORM_block1 || form == DW_FORM_exprloc) + id.member_location_ptr = ptr, id.member_location_len = size; + else + id.member_location_data = data; + break; + case DW_AT_location: + if (form == DW_FORM_block1 || form == DW_FORM_exprloc) + id.location_ptr = ptr, id.location_len = size; + else + id.locationlist = data; + break; + case DW_AT_frame_base: + if (form != DW_FORM_block2 && form != DW_FORM_block4 && form != DW_FORM_block1 && form != DW_FORM_block) + id.frame_base = data; + break; + } + ptr += size; + } + + hasChild = id.hasChild != 0; + sibling = id.sibling; + + return true; +} + +unsigned char* DIECursor::getDWARFAbbrev(unsigned off, unsigned findcode) +{ + if (!img->debug_abbrev) + return 0; + + std::pair key = std::make_pair(off, findcode); + abbrevMap_t::iterator it = abbrevMap.find(key); + if (it != abbrevMap.end()) + { + return it->second; + } + + unsigned char* p = (unsigned char*)img->debug_abbrev + off; + unsigned char* end = (unsigned char*)img->debug_abbrev + img->debug_abbrev_length; + while (p < end) + { + int code = LEB128(p); + if (code == findcode) + { + abbrevMap.insert(std::make_pair(key, p)); + return p; + } + if (code == 0) + return 0; + + int tag = LEB128(p); + int hasChild = *p++; + + // skip attributes + int attr, form; + do + { + attr = LEB128(p); + form = LEB128(p); + } while (attr || form); + } + return 0; +} diff --git a/src/readDwarf.h b/src/readDwarf.h new file mode 100644 index 0000000..c0587b4 --- /dev/null +++ b/src/readDwarf.h @@ -0,0 +1,308 @@ +#ifndef __READDWARF_H__ +#define __READDWARF_H__ + +#include +#include +#include "mspdb.h" + +inline unsigned int LEB128(unsigned char* &p) +{ + unsigned int x = 0; + int shift = 0; + while (*p & 0x80) + { + x |= (*p & 0x7f) << shift; + shift += 7; + p++; + } + x |= *p << shift; + p++; + return x; +} + +inline int SLEB128(unsigned char* &p) +{ + unsigned int x = 0; + int shift = 0; + while (*p & 0x80) + { + x |= (*p & 0x7f) << shift; + shift += 7; + p++; + } + x |= *p << shift; + if (*p & 0x40) + x |= -(1 << (shift + 7)); // sign extend + p++; + return x; +} + +inline unsigned int RD2(unsigned char* p) +{ + unsigned int x = *p++; + x |= *p++ << 8; + return x; +} + +inline unsigned int RD4(unsigned char* p) +{ + unsigned int x = *p++; + x |= *p++ << 8; + x |= *p++ << 16; + x |= *p++ << 24; + return x; +} + +inline unsigned long long RD8(unsigned char* p) +{ + unsigned long long x = *p++; + for (int shift = 8; shift < 64; shift += 8) + x |= (unsigned long long) *p++ << shift; + return x; +} + +inline unsigned long long RDsize(unsigned char* p, int size) +{ + if (size > 8) + size = 8; + unsigned long long x = *p++; + for (int shift = 8; shift < size * 8; shift += 8) + x |= (unsigned long long) *p++ << shift; + return x; +} + + +/////////////////////////////////////////////////////////////////////////////// + +#include "pshpack1.h" + +struct DWARF_CompilationUnit +{ + unsigned int unit_length; // 12 byte in DWARF-64 + unsigned short version; + unsigned int debug_abbrev_offset; // 8 byte in DWARF-64 + unsigned char address_size; + + bool isDWARF64() const { return unit_length == ~0; } + int refSize() const { return unit_length == ~0 ? 8 : 4; } +}; + +struct DWARF_FileName +{ + const char* file_name; + unsigned int dir_index; + unsigned long lastModification; + unsigned long fileLength; + + void read(unsigned char* &p) + { + file_name = (const char*)p; + p += strlen((const char*)p) + 1; + dir_index = LEB128(p); + lastModification = LEB128(p); + fileLength = LEB128(p); + } +}; + +struct DWARF_InfoData +{ + int entryOff; + int code; + int tag; + int hasChild; + + const char* name; + const char* linkage_name; + const char* dir; + unsigned long byte_size; + unsigned long sibling; + unsigned long encoding; + unsigned long pclo; + unsigned long pchi; + unsigned long ranges; + unsigned long type; + unsigned long containing_type; + unsigned long specification; + unsigned long inlined; + unsigned long external; + unsigned char*location_ptr; + unsigned long location_len; + unsigned char*member_location_ptr; + unsigned long member_location_len; + unsigned long member_location_data; + unsigned long locationlist; // offset into debug_loc + long frame_base; + long upper_bound; + long lower_bound; + unsigned char* abbrev; + + void clear() + { + entryOff = 0; + code = 0; + tag = 0; + hasChild = 0; + + name = 0; + linkage_name = 0; + dir = 0; + byte_size = 0; + sibling = 0; + encoding = 0; + pclo = 0; + pchi = 0; + ranges = 0; + type = 0; + containing_type = 0; + specification = 0; + inlined = 0; + external = 0; + member_location_ptr = 0; + member_location_len = 0; + member_location_data = 0; + location_ptr = 0; + location_len = 0; + locationlist = 0; + frame_base = -1; + upper_bound = 0; + lower_bound = 0; + abbrev = 0; + } +}; + +static const int maximum_operations_per_instruction = 1; + +struct DWARF_LineNumberProgramHeader +{ + unsigned int unit_length; // 12 byte in DWARF-64 + unsigned short version; + unsigned int header_length; // 8 byte in DWARF-64 + unsigned char minimum_instruction_length; + //unsigned char maximum_operations_per_instruction; (// not in DWARF 2 + unsigned char default_is_stmt; + signed char line_base; + unsigned char line_range; + unsigned char opcode_base; + //LEB128 standard_opcode_lengths[opcode_base]; + // string include_directories[] // zero byte terminated + // DWARF_FileNames file_names[] // zero byte terminated +}; + +struct DWARF_LineState +{ + // hdr info + std::vector include_dirs; + std::vector files; + + unsigned long address; + unsigned int op_index; + unsigned int file; + unsigned int line; + unsigned int column; + bool is_stmt; + bool basic_block; + bool end_sequence; + bool prologue_end; + bool epilogue_end; + unsigned int isa; + unsigned int discriminator; + + // not part of the "documented" state + DWARF_FileName* file_ptr; + unsigned long seg_offset; + unsigned long last_addr; + std::vector lineInfo; + + DWARF_LineState() + { + seg_offset = 0x400000; + init(0); + } + + void init(DWARF_LineNumberProgramHeader* hdr) + { + address = 0; + op_index = 0; + file = 1; + line = 1; + column = 0; + is_stmt = hdr && hdr->default_is_stmt != 0; + basic_block = false; + end_sequence = false; + prologue_end = false; + epilogue_end = false; + isa = 0; + discriminator = 0; + } + + void advance_addr(DWARF_LineNumberProgramHeader* hdr, int operation_advance) + { + int address_advance = hdr->minimum_instruction_length * ((op_index + operation_advance) / maximum_operations_per_instruction); + address += address_advance; + op_index = (op_index + operation_advance) % maximum_operations_per_instruction; + } + + void addLineInfo() + { +#if 0 + const char* fname = (file == 0 ? file_ptr->file_name : files[file - 1].file_name); + printf("Adr:%08x Line: %5d File: %s\n", address, line, fname); +#endif + if (address < seg_offset) + return; + mspdb::LineInfoEntry entry; + entry.offset = address - seg_offset; + entry.line = line; + lineInfo.push_back(entry); + } +}; + +#include "poppack.h" + +/////////////////////////////////////////////////////////////////////////////// + + +long decodeLocation(unsigned char* loc, long len, bool push0, int &id, int& size); + +inline long decodeLocation(unsigned char*loc, long len, bool push0, int &id) +{ + int size; + return decodeLocation(loc, len, push0, id, size); +} + + +class PEImage; + +// Debug Information Entry Cursor +class DIECursor +{ +public: + DWARF_CompilationUnit* cu; + unsigned char* ptr; + int level; + bool hasChild; // indicates whether the last read DIE has children + unsigned int sibling; + + unsigned char* getDWARFAbbrev(unsigned off, unsigned findcode); + +public: + + static void setContext(PEImage* img_); + + // Create a new DIECursor from compilation unit with offset relative to the CU. + DIECursor(DWARF_CompilationUnit* cu_, unsigned long offset); + + // Reads next sibling DIE. If the last read DIE had any children, they will be skipped over. + // Returns 'false' upon reaching the last sibling on the current level. + bool readSibling(DWARF_InfoData& id); + + // Returns cursor that will enumerate children of the last read DIE. + DIECursor getSubtreeCursor(); + + // Reads the next DIE in physical order, returns 'true' if succeeds. + // If stopAtNull is true, readNext() will stop upon reaching a null DIE (end of the current tree level). + // Otherwise, it will skip null DIEs and stop only at the end of the subtree for which this DIECursor was created. + bool readNext(DWARF_InfoData& id, bool stopAtNull = false); +}; + +#endif \ No newline at end of file -- cgit v0.12