summaryrefslogtreecommitdiffstats
path: root/src/dwarf2pdb.cpp
diff options
context:
space:
mode:
authorVadim Chugunov <vadimcn@gmail.com>2014-10-17 16:42:53 (GMT)
committerVadim Chugunov <vadimcn@gmail.com>2014-12-05 21:31:34 (GMT)
commitb5bb7f4c024cdedab46a4967433cdbc1e2af31a9 (patch)
tree7d1529e1d9540cfbcade5dd2c5714015d996dbf5 /src/dwarf2pdb.cpp
parentbd5029b0462023e27021c23ae1b7c50d00876d97 (diff)
downloadcv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.zip
cv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.tar.gz
cv2pdb-b5bb7f4c024cdedab46a4967433cdbc1e2af31a9.tar.bz2
Fixed O^n abbrev search.
DIE tree navigation without requiring DW_AT_sibling attributes, moved navigation logic into DIECursor class.
Diffstat (limited to 'src/dwarf2pdb.cpp')
-rw-r--r--src/dwarf2pdb.cpp998
1 files changed, 222 insertions, 776 deletions
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 <string>
#include <vector>
-///////////////////////////////////////////////////////////////////////////////
-
-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<const char*> include_dirs;
- std::vector<DWARF_FileName> 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<mspdb::LineInfoEntry> 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<unsigned char*> 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<DIECursor> 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<int,int>::iterator it = mapOffsetToType.find(cuoff + off);
+ std::unordered_map<int,int>::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<unsigned char*> 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<int,int>(off + id.entryOff, typeID));
+ mapOffsetToType.insert(std::pair<int, int>(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];