diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2021-10-29 11:33:52 (GMT) |
---|---|---|
committer | Johannes Schindelin <johannes.schindelin@gmx.de> | 2021-10-29 12:07:39 (GMT) |
commit | aa96c2e369b07d99c551124534459c289561a785 (patch) | |
tree | 652eca973e58b313db20971051d476518f8941c8 /src | |
parent | 4d80deff6d401c1aa4aef2877d89be01aba6bb11 (diff) | |
download | cv2pdb-aa96c2e369b07d99c551124534459c289561a785.zip cv2pdb-aa96c2e369b07d99c551124534459c289561a785.tar.gz cv2pdb-aa96c2e369b07d99c551124534459c289561a785.tar.bz2 |
Add rudimentary support for DWARF5
This allows `cv2pdb` to process executables produced by the mingw-w64
version of GCC v11.x.
The symptoms of the fixed issue would look like this:
error: cannot add line number info to module
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/PEImage.cpp | 2 | ||||
-rw-r--r-- | src/PEImage.h | 1 | ||||
-rw-r--r-- | src/dwarf.h | 12 | ||||
-rw-r--r-- | src/dwarflines.cpp | 163 | ||||
-rw-r--r-- | src/readDwarf.h | 23 |
5 files changed, 174 insertions, 27 deletions
diff --git a/src/PEImage.cpp b/src/PEImage.cpp index 4c4afff..99c6776 100644 --- a/src/PEImage.cpp +++ b/src/PEImage.cpp @@ -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)
diff --git a/src/PEImage.h b/src/PEImage.h index c014dd2..dd170bf 100644 --- a/src/PEImage.h +++ b/src/PEImage.h @@ -137,6 +137,7 @@ public: 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;
diff --git a/src/dwarf.h b/src/dwarf.h index b6fcacf..1565eb3 100644 --- a/src/dwarf.h +++ b/src/dwarf.h @@ -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
@@ -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
diff --git a/src/dwarflines.cpp b/src/dwarflines.cpp index 6ec557d..b061f79 100644 --- a/src/dwarflines.cpp +++ b/src/dwarflines.cpp @@ -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);
@@ -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;
@@ -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)
diff --git a/src/readDwarf.h b/src/readDwarf.h index c26bad9..7ad56e8 100644 --- a/src/readDwarf.h +++ b/src/readDwarf.h @@ -239,10 +239,33 @@ 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;
unsigned int header_length; // 8 byte in DWARF-64
byte minimum_instruction_length;
byte maximum_operations_per_instruction; // not in DWARF 2/3
|