summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeeraj Singh <neerajsi@microsoft.com>2021-12-02 04:55:09 (GMT)
committerNeeraj Singh <neerajsi@microsoft.com>2021-12-02 06:11:13 (GMT)
commit35c615b756322f7755a5fbe1846129be8b9fa936 (patch)
treee18a8c20aef3ec8379371feeb134faa442f917f4
parent13e0840e109747378929bed7e5e59aa8a4eb9bcb (diff)
downloadcv2pdb-35c615b756322f7755a5fbe1846129be8b9fa936.zip
cv2pdb-35c615b756322f7755a5fbe1846129be8b9fa936.tar.gz
cv2pdb-35c615b756322f7755a5fbe1846129be8b9fa936.tar.bz2
Fix file names in dwarf5 line tables
-rw-r--r--src/dwarflines.cpp90
-rw-r--r--src/readDwarf.h9
2 files changed, 74 insertions, 25 deletions
diff --git a/src/dwarflines.cpp b/src/dwarflines.cpp
index 13106e5..11380ae 100644
--- a/src/dwarflines.cpp
+++ b/src/dwarflines.cpp
@@ -5,6 +5,7 @@
// see file LICENSE for further details
//
+#include <assert.h>
#include "PEImage.h"
#include "mspdb.h"
#include "dwarf.h"
@@ -25,6 +26,13 @@ bool isRelativePath(const std::string& s)
return true;
}
+static void addTrailingSlash(std::string& dir)
+{
+ // Make sure dirs always end in a trailing slash
+ if (!dir.size() || (dir.back() != '\\' && dir.back() != '/'))
+ dir += '\\';
+}
+
static int cmpAdr(const void* s1, const void* s2)
{
const mspdb::LineInfoEntry* e1 = (const mspdb::LineInfoEntry*) s1;
@@ -63,7 +71,7 @@ bool _flushDWARFLines(const PEImage& img, mspdb::Mod* mod, DWARF_LineState& stat
const DWARF_FileName* dfn;
if(state.lineInfo_file == 0)
- dfn = state.file_ptr;
+ dfn = &state.cur_file;
else if(state.lineInfo_file > 0 && state.lineInfo_file <= state.files.size())
dfn = &state.files[state.lineInfo_file - 1];
else
@@ -74,8 +82,6 @@ bool _flushDWARFLines(const PEImage& img, mspdb::Mod* mod, DWARF_LineState& stat
dfn->dir_index > 0 && dfn->dir_index <= state.include_dirs.size())
{
std::string dir = state.include_dirs[dfn->dir_index - 1];
- if(dir.length() > 0 && dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\')
- dir.append("\\");
fname = dir + fname;
}
for(size_t i = 0; i < fname.length(); i++)
@@ -241,7 +247,6 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
DWARF_LineState state;
state.seg_offset = img.getImageBase() + img.getSection(img.text.secNo).VirtualAddress;
- DWARF_FileName fname;
if (hdr->version <= 4)
{
// dirs
@@ -249,16 +254,19 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
{
if(*p == 0)
break;
- state.include_dirs.push_back((const char*) p);
- p += strlen((const char*) p) + 1;
+ state.include_dirs.emplace_back((const char*) p);
+ auto &dir = state.include_dirs.back();
+ p += dir.size() + 1;
+ addTrailingSlash(dir);
}
p++;
// files
while(p < end && *p)
{
+ DWARF_FileName fname;
fname.read(p);
- state.files.push_back(fname);
+ state.files.emplace_back(std::move(fname));
}
p++;
}
@@ -278,31 +286,48 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
unsigned int directories_count = LEB128(p);
for (int o = 0; o < directories_count; o++)
{
- for (int i = 0; i < directory_entry_format_count; i++)
+ for (const auto &typeForm : directory_entry_format)
{
- switch (directory_entry_format[i].type)
+ switch (typeForm.type)
{
case DW_LNCT_path:
- switch (directory_entry_format[i].form)
+ {
+ switch (typeForm.form)
{
case DW_FORM_line_strp:
{
size_t offset = cu.isDWARF64() ? RD8(p) : RD4(p);
- state.include_dirs.push_back((const char*)img.debug_line_str.byteAt(offset));
+ state.include_dirs.emplace_back((const char*)img.debug_line_str.byteAt(offset));
break;
}
case DW_FORM_string:
- state.include_dirs.push_back((const char*)p);
+ state.include_dirs.emplace_back((const char*)p);
p += strlen((const char*)p) + 1;
break;
default:
+ fprintf(stderr, "%s:%d: ERROR: invalid form=%d for path lineHdrOffs=%x\n", __FUNCTION__, __LINE__,
+ typeForm.form, off);
+
return false;
}
+
+ auto& dir = state.include_dirs.back();
+
+ // Relative dirs are relative to the first directory
+ // in the table.
+ if (state.include_dirs.size() > 1 && isRelativePath(dir))
+ dir = state.include_dirs.front() + dir;
+
+ addTrailingSlash(dir);
break;
+ }
case DW_LNCT_directory_index:
case DW_LNCT_timestamp:
case DW_LNCT_size:
default:
+ fprintf(stderr, "%s:%d: ERROR: unexpected type=%d form=%d for directory path lineHdrOffs=%x\n", __FUNCTION__, __LINE__,
+ typeForm.type, typeForm.form, off);
+
return false;
}
}
@@ -320,12 +345,14 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
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++)
+ DWARF_FileName fname;
+
+ for (const auto &typeForm : file_name_entry_format)
{
- switch (file_name_entry_format[i].type)
+ switch (typeForm.type)
{
case DW_LNCT_path:
- switch (directory_entry_format[i].form)
+ switch (typeForm.form)
{
case DW_FORM_line_strp:
{
@@ -338,22 +365,41 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
p += strlen((const char*)p) + 1;
break;
default:
+ fprintf(stderr, "%s:%d: ERROR: invalid form=%d for path lineHdrOffs=%x\n", __FUNCTION__, __LINE__,
+ typeForm.form, off);
+
+
+ assert(false, "invalid path form");
return false;
}
break;
case DW_LNCT_directory_index:
- if (file_name_entry_format[i].form == DW_FORM_udata)
- fname.dir_index = LEB128(p);
+ // bias the directory index by 1 since _flushDWARFLines
+ // will check for 0 and subtract one (which is
+ // useful for DWARF4).
+ if (typeForm.form == DW_FORM_udata)
+ {
+ fname.dir_index = LEB128(p) + 1;
+ }
else
+ {
+ fprintf(stderr, "%s:%d: ERROR: invalid form=%d for directory index lineHdrOffs=%x\n", __FUNCTION__, __LINE__,
+ typeForm.form, off);
+
return false;
+ }
break;
case DW_LNCT_timestamp:
case DW_LNCT_size:
default:
+ fprintf(stderr, "%s:%d: ERROR: unexpected type=%d form=%d for file path lineHdrOffs=%x\n", __FUNCTION__, __LINE__,
+ typeForm.type, typeForm.form, off);
+
return false;
}
}
- state.files.push_back(fname);
+
+ state.files.emplace_back(std::move(fname));
}
}
@@ -406,8 +452,7 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
break;
}
case DW_LNE_define_file:
- fname.read(p);
- state.file_ptr = &fname;
+ state.cur_file.read(p);
state.file = 0;
break;
case DW_LNE_set_discriminator:
@@ -433,6 +478,11 @@ bool interpretDWARFLines(const PEImage& img, mspdb::Mod* mod, DebugLevel debug_)
break;
case DW_LNS_set_file:
state.file = LEB128(p);
+ // DWARF5 numbers all files starting at zero. We will
+ // subtract one in _flushDWARFLines when indexing the files
+ // array.
+ if (hdr->version >= 5)
+ state.file += 1;
break;
case DW_LNS_set_column:
state.column = LEB128(p);
diff --git a/src/readDwarf.h b/src/readDwarf.h
index f9593f9..5e1db99 100644
--- a/src/readDwarf.h
+++ b/src/readDwarf.h
@@ -165,7 +165,7 @@ struct DWARF_CompilationUnitInfo
struct DWARF_FileName
{
- const char* file_name;
+ std::string file_name;
unsigned int dir_index;
unsigned long lastModification;
unsigned long fileLength;
@@ -173,7 +173,7 @@ struct DWARF_FileName
void read(byte* &p)
{
file_name = (const char*)p;
- p += strlen((const char*)p) + 1;
+ p += file_name.size() + 1;
dir_index = LEB128(p);
lastModification = LEB128(p);
fileLength = LEB128(p);
@@ -345,7 +345,7 @@ struct DWARF2_LineNumberProgramHeader
struct DWARF_LineState
{
// hdr info
- std::vector<const char*> include_dirs;
+ std::vector<std::string> include_dirs;
std::vector<DWARF_FileName> files;
unsigned long address;
@@ -362,7 +362,7 @@ struct DWARF_LineState
unsigned int discriminator;
// not part of the "documented" state
- DWARF_FileName* file_ptr;
+ DWARF_FileName cur_file;
unsigned long seg_offset;
unsigned long section;
unsigned long last_addr;
@@ -371,7 +371,6 @@ struct DWARF_LineState
DWARF_LineState()
{
- file_ptr = nullptr;
seg_offset = 0x400000;
last_addr = 0;
lineInfo_file = 0;