[LLDB] - Improved DWARF5 support.

This patch improves the support of DWARF5.
Particularly the reporting of source code locations.

Differential revision: https://reviews.llvm.org/D51935

llvm-svn: 342153
This commit is contained in:
George Rimar
2018-09-13 17:06:47 +00:00
parent f353ae1848
commit c6c7bfc4d2
18 changed files with 393 additions and 81 deletions

View File

@@ -41,7 +41,7 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) {
if (line_table_sp.get() == NULL)
break;
if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get())) {
if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) {
// Make sure we don't don't loop infinitely
if (offset <= debug_line_offset)
break;
@@ -127,7 +127,7 @@ DWARFDebugLine::DumpStatementTable(Log *log,
"--------\n",
debug_line_offset);
if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log))
if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log, nullptr))
return offset;
else
return debug_line_offset + 1; // Skip to next byte in .debug_line section
@@ -366,17 +366,38 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data,
void *userData) {
lldb::offset_t offset = 0;
if (debug_line_data.ValidOffset(offset)) {
if (!ParseStatementTable(debug_line_data, &offset, callback, userData))
if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr))
++offset; // Skip to next byte in .debug_line section
}
}
namespace {
struct EntryDescriptor {
dw_sleb128_t code;
dw_sleb128_t form;
};
static std::vector<EntryDescriptor>
ReadDescriptors(const DWARFDataExtractor &debug_line_data,
lldb::offset_t *offset_ptr) {
std::vector<EntryDescriptor> ret;
uint8_t n = debug_line_data.GetU8(offset_ptr);
for (uint8_t i = 0; i < n; ++i) {
EntryDescriptor ent;
ent.code = debug_line_data.GetULEB128(offset_ptr);
ent.form = debug_line_data.GetULEB128(offset_ptr);
ret.push_back(ent);
}
return ret;
}
} // namespace
//----------------------------------------------------------------------
// DWARFDebugLine::ParsePrologue
//----------------------------------------------------------------------
bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
lldb::offset_t *offset_ptr,
Prologue *prologue) {
Prologue *prologue, DWARFUnit *dwarf_cu) {
const lldb::offset_t prologue_offset = *offset_ptr;
// DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
@@ -386,9 +407,14 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
const char *s;
prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr);
prologue->version = debug_line_data.GetU16(offset_ptr);
if (prologue->version < 2 || prologue->version > 4)
if (prologue->version < 2 || prologue->version > 5)
return false;
if (prologue->version >= 5) {
prologue->address_size = debug_line_data.GetU8(offset_ptr);
prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr);
}
prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
const lldb::offset_t end_prologue_offset =
prologue->prologue_length + *offset_ptr;
@@ -410,25 +436,83 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
prologue->standard_opcode_lengths.push_back(op_len);
}
while (*offset_ptr < end_prologue_offset) {
s = debug_line_data.GetCStr(offset_ptr);
if (s && s[0])
prologue->include_directories.push_back(s);
else
break;
}
if (prologue->version >= 5) {
std::vector<EntryDescriptor> dirEntryFormatV =
ReadDescriptors(debug_line_data, offset_ptr);
uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr);
for (int i = 0; i < dirCount; ++i) {
for (EntryDescriptor &ent : dirEntryFormatV) {
DWARFFormValue value(dwarf_cu, ent.form);
if (ent.code != DW_LNCT_path) {
if (!value.SkipValue(debug_line_data, offset_ptr))
return false;
continue;
}
while (*offset_ptr < end_prologue_offset) {
const char *name = debug_line_data.GetCStr(offset_ptr);
if (name && name[0]) {
FileNameEntry fileEntry;
fileEntry.name = name;
fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
prologue->file_names.push_back(fileEntry);
} else
break;
if (!value.ExtractValue(debug_line_data, offset_ptr))
return false;
prologue->include_directories.push_back(value.AsCString());
}
}
std::vector<EntryDescriptor> filesEntryFormatV =
ReadDescriptors(debug_line_data, offset_ptr);
llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen;
uint8_t n = debug_line_data.GetULEB128(offset_ptr);
for (int i = 0; i < n; ++i) {
FileNameEntry entry;
for (EntryDescriptor &ent : filesEntryFormatV) {
DWARFFormValue value(dwarf_cu, ent.form);
if (!value.ExtractValue(debug_line_data, offset_ptr))
return false;
switch (ent.code) {
case DW_LNCT_path:
entry.name = value.AsCString();
break;
case DW_LNCT_directory_index:
entry.dir_idx = value.Unsigned();
break;
case DW_LNCT_timestamp:
entry.mod_time = value.Unsigned();
break;
case DW_LNCT_size:
entry.length = value.Unsigned();
break;
case DW_LNCT_MD5:
assert(value.Unsigned() == 16);
std::uninitialized_copy_n(value.BlockData(), 16,
entry.checksum.Bytes.begin());
break;
default:
break;
}
}
if (seen.insert(entry.checksum.words()).second)
prologue->file_names.push_back(entry);
}
} else {
while (*offset_ptr < end_prologue_offset) {
s = debug_line_data.GetCStr(offset_ptr);
if (s && s[0])
prologue->include_directories.push_back(s);
else
break;
}
while (*offset_ptr < end_prologue_offset) {
const char *name = debug_line_data.GetCStr(offset_ptr);
if (name && name[0]) {
FileNameEntry fileEntry;
fileEntry.name = name;
fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
prologue->file_names.push_back(fileEntry);
} else
break;
}
}
// XXX GNU as is broken for 64-Bit DWARF
@@ -445,11 +529,11 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
bool DWARFDebugLine::ParseSupportFiles(
const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
FileSpecList &support_files) {
FileSpecList &support_files, DWARFUnit *dwarf_cu) {
lldb::offset_t offset = stmt_list;
Prologue prologue;
if (!ParsePrologue(debug_line_data, &offset, &prologue)) {
if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) {
Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue "
"at 0x%8.8x (parsing ended around "
"0x%8.8" PRIx64 "\n",
@@ -478,7 +562,7 @@ bool DWARFDebugLine::ParseSupportFiles(
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
DWARFDebugLine::State::Callback callback, void *userData) {
DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE));
Prologue::shared_ptr prologue(new Prologue());
@@ -489,7 +573,7 @@ bool DWARFDebugLine::ParseStatementTable(
func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
debug_line_offset);
if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get())) {
if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) {
if (log)
log->Error("failed to parse DWARF line table prologue");
// Restore our offset and return false to indicate failure!
@@ -775,9 +859,9 @@ static void ParseStatementTableCallback(dw_offset_t offset,
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
LineTable *line_table) {
LineTable *line_table, DWARFUnit *dwarf_cu) {
return ParseStatementTable(debug_line_data, offset_ptr,
ParseStatementTableCallback, line_table);
ParseStatementTableCallback, line_table, dwarf_cu);
}
inline bool DWARFDebugLine::Prologue::IsValid() const {