diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp | 142 |
1 files changed, 113 insertions, 29 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index 317ea4c22c6..2ab37079f75 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -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 { |