Skip to content

Commit

Permalink
Merge pull request #67 from dscho/dwarf5
Browse files Browse the repository at this point in the history
Add rudimentary support for DWARF5
  • Loading branch information
rainers authored Oct 30, 2021
2 parents 4d80def + aa96c2e commit 9c0e83f
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 27 deletions.
2 changes: 2 additions & 0 deletions src/PEImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,8 @@ void PEImage::initDWARFSegments()
debug_abbrev = DPV<char>(sec[s].PointerToRawData, debug_abbrev_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_line") == 0)
debug_line = DPV<char>(sec[linesSegment = s].PointerToRawData, debug_line_length = sizeInImage(sec[s]));
if (strcmp(name, ".debug_line_str") == 0)
debug_line_str = DPV<char>(sec[s].PointerToRawData, debug_line_str_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_frame") == 0)
debug_frame = DPV<char>(sec[s].PointerToRawData, debug_frame_length = sizeInImage(sec[s]));
if(strcmp(name, ".debug_str") == 0)
Expand Down
1 change: 1 addition & 0 deletions src/PEImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ class PEImage : public LastError
char* debug_info; unsigned long debug_info_length;
char* debug_abbrev; unsigned long debug_abbrev_length;
char* debug_line; unsigned long debug_line_length;
char* debug_line_str; unsigned long debug_line_str_length;
char* debug_frame; unsigned long debug_frame_length;
char* debug_str;
char* debug_loc; unsigned long debug_loc_length;
Expand Down
12 changes: 11 additions & 1 deletion src/dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@ extern "C" {
#define DW_children_yes 1


#define DW_LNCT_path 1
#define DW_LNCT_directory_index 2
#define DW_LNCT_timestamp 3
#define DW_LNCT_size 4
#define DW_LNCT_MD5 5


#define DW_FORM_addr 0x01
#define DW_FORM_block2 0x03
Expand All @@ -221,7 +227,11 @@ extern "C" {
#define DW_FORM_sec_offset 0x17 /* DWARF4 */
#define DW_FORM_exprloc 0x18 /* DWARF4 */
#define DW_FORM_flag_present 0x19 /* DWARF4 */
/* 0x1a thru 0x1f were left unused accidentally. Reserved for future use. */
#define DW_FORM_strx 0x1a /* DWARF5 */
#define DW_FORM_addrx 0x1b /* DWARF5 */
#define DW_FORM_strp_sup 0x1d /* DWARF5 */
#define DW_FORM_data16 0x1e /* DWARF5 */
#define DW_FORM_line_strp 0x1f /* DWARF5 */
#define DW_FORM_ref_sig8 0x20 /* DWARF4 */

#define DW_AT_sibling 0x01
Expand Down
163 changes: 137 additions & 26 deletions src/dwarflines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod)
DWARF_CompilationUnit* cu = (DWARF_CompilationUnit*)img.debug_info;
int ptrsize = cu ? cu->address_size : 4;

DWARF_LineNumberProgramHeader hdr3;
DWARF_LineNumberProgramHeader hdr5;
for(unsigned long off = 0; off < img.debug_line_length; )
{
DWARF_LineNumberProgramHeader* hdrver = (DWARF_LineNumberProgramHeader*) (img.debug_line + off);
Expand All @@ -195,20 +195,34 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod)
if (hdrver->version <= 3)
{
auto hdr2 = (DWARF2_LineNumberProgramHeader*)hdrver;
hdr3.default_is_stmt = hdr2->default_is_stmt;
hdr3.header_length = hdr2->header_length;
hdr3.line_base = hdr2->line_base;
hdr3.line_range = hdr2->line_range;
hdr3.minimum_instruction_length = hdr2->minimum_instruction_length;
hdr3.maximum_operations_per_instruction = 0xff;
hdr3.opcode_base = hdr2->opcode_base;
hdr3.unit_length = hdr2->unit_length;
hdr3.version = hdr2->version;
hdr = &hdr3;
hdr5.default_is_stmt = hdr2->default_is_stmt;
hdr5.header_length = hdr2->header_length;
hdr5.line_base = hdr2->line_base;
hdr5.line_range = hdr2->line_range;
hdr5.minimum_instruction_length = hdr2->minimum_instruction_length;
hdr5.maximum_operations_per_instruction = 0xff;
hdr5.opcode_base = hdr2->opcode_base;
hdr5.unit_length = hdr2->unit_length;
hdr5.version = hdr2->version;
hdr = &hdr5;
}
else if (hdrver->version == 4)
{
auto hdr4 = (DWARF4_LineNumberProgramHeader*)hdrver;
hdr5.default_is_stmt = hdr4->default_is_stmt;
hdr5.header_length = hdr4->header_length;
hdr5.line_base = hdr4->line_base;
hdr5.line_range = hdr4->line_range;
hdr5.minimum_instruction_length = hdr4->minimum_instruction_length;
hdr5.maximum_operations_per_instruction = hdr4->maximum_operations_per_instruction;
hdr5.opcode_base = hdr4->opcode_base;
hdr5.unit_length = hdr4->unit_length;
hdr5.version = hdr4->version;
hdr = &hdr5;
}
else
hdr = hdrver;
int hdrlength = hdr->version <= 3 ? sizeof(DWARF2_LineNumberProgramHeader) : sizeof(DWARF_LineNumberProgramHeader);
int hdrlength = hdr->version <= 3 ? sizeof(DWARF2_LineNumberProgramHeader) : hdr->version == 4 ? sizeof(DWARF4_LineNumberProgramHeader) : sizeof(DWARF_LineNumberProgramHeader);
unsigned char* p = (unsigned char*) hdrver + hdrlength;
unsigned char* end = (unsigned char*) hdrver + length;

Expand All @@ -224,24 +238,121 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod)
DWARF_LineState state;
state.seg_offset = img.getImageBase() + img.getSection(img.codeSegment).VirtualAddress;

// dirs
while(p < end)
DWARF_FileName fname;
if (hdr->version <= 4)
{
if(*p == 0)
break;
state.include_dirs.push_back((const char*) p);
p += strlen((const char*) p) + 1;
}
p++;
// dirs
while(p < end)
{
if(*p == 0)
break;
state.include_dirs.push_back((const char*) p);
p += strlen((const char*) p) + 1;
}
p++;

// files
DWARF_FileName fname;
while(p < end && *p)
// files
while(p < end && *p)
{
fname.read(p);
state.files.push_back(fname);
}
p++;
}
else
{
fname.read(p);
state.files.push_back(fname);
DWARF_TypeForm type_and_form;

byte directory_entry_format_count = *(p++);
std::vector<DWARF_TypeForm> directory_entry_format;
for (int i = 0; i < directory_entry_format_count; i++)
{
type_and_form.type = LEB128(p);
type_and_form.form = LEB128(p);
directory_entry_format.push_back(type_and_form);
}

unsigned int directories_count = LEB128(p);
for (int o = 0; o < directories_count; o++)
{
for (int i = 0; i < directory_entry_format_count; i++)
{
switch (directory_entry_format[i].type)
{
case DW_LNCT_path:
switch (directory_entry_format[i].form)
{
case DW_FORM_line_strp:
{
size_t offset = cu->isDWARF64() ? RD8(p) : RD4(p);
state.include_dirs.push_back(img.debug_line_str + offset);
break;
}
case DW_FORM_string:
state.include_dirs.push_back((const char*)p);
p += strlen((const char*)p) + 1;
break;
default:
return false;
}
break;
case DW_LNCT_directory_index:
case DW_LNCT_timestamp:
case DW_LNCT_size:
default:
return false;
}
}
}

byte file_name_entry_format_count = *(p++);
std::vector<DWARF_TypeForm> file_name_entry_format;
for (int i = 0; i < file_name_entry_format_count; i++)
{
type_and_form.type = LEB128(p);
type_and_form.form = LEB128(p);
file_name_entry_format.push_back(type_and_form);
}

unsigned int file_names_count = LEB128(p);
for (int o = 0; o < file_names_count; o++)
{
for (int i = 0; i < file_name_entry_format_count; i++)
{
switch (file_name_entry_format[i].type)
{
case DW_LNCT_path:
switch (directory_entry_format[i].form)
{
case DW_FORM_line_strp:
{
size_t offset = cu->isDWARF64() ? RD8(p) : RD4(p);
fname.file_name = img.debug_line_str + offset;
break;
}
case DW_FORM_string:
fname.file_name = (const char*)p;
p += strlen((const char*)p) + 1;
break;
default:
return false;
}
break;
case DW_LNCT_directory_index:
if (file_name_entry_format[i].form == DW_FORM_udata)
fname.dir_index = LEB128(p);
else
return false;
break;
case DW_LNCT_timestamp:
case DW_LNCT_size:
default:
return false;
}
}
state.files.push_back(fname);
}
}
p++;

state.init(hdr);
while(p < end)
Expand Down
23 changes: 23 additions & 0 deletions src/readDwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,30 @@ struct DWARF_InfoData

static const int maximum_operations_per_instruction = 1;

struct DWARF_TypeForm
{
unsigned int type, form;
};

struct DWARF_LineNumberProgramHeader
{
unsigned int unit_length; // 12 byte in DWARF-64
unsigned short version;
byte address_size; // new in DWARF5
byte segment_selector_size; // new in DWARF5
unsigned int header_length; // 8 byte in DWARF-64
byte minimum_instruction_length;
byte maximum_operations_per_instruction; // not in DWARF 2/3
byte default_is_stmt;
signed char line_base;
byte line_range;
byte opcode_base;
//LEB128 standard_opcode_lengths[opcode_base];
// string include_directories[] // zero byte terminated
// DWARF_FileNames file_names[] // zero byte terminated
};

struct DWARF4_LineNumberProgramHeader
{
unsigned int unit_length; // 12 byte in DWARF-64
unsigned short version;
Expand Down

0 comments on commit 9c0e83f

Please sign in to comment.