aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp204
1 files changed, 155 insertions, 49 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 9964cf4b893c..22e3e40dac93 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -32,9 +32,9 @@ extern int g_verbose;
DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
+ DIERef::Section section, bool is_dwo)
: UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
- m_cancel_scopes(false), m_section(section) {}
+ m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo) {}
DWARFUnit::~DWARFUnit() = default;
@@ -287,15 +287,27 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
DWARFAttributes attributes;
size_t num_attributes = cu_die.GetAttributes(this, attributes);
+
+ // Extract DW_AT_addr_base first, as other attributes may need it.
+ for (size_t i = 0; i < num_attributes; ++i) {
+ if (attributes.AttributeAtIndex(i) != DW_AT_addr_base)
+ continue;
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ addr_base = form_value.Unsigned();
+ SetAddrBase(*addr_base);
+ break;
+ }
+ }
+
for (size_t i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (!attributes.ExtractFormValueAtIndex(i, form_value))
continue;
switch (attr) {
- case DW_AT_addr_base:
- addr_base = form_value.Unsigned();
- SetAddrBase(*addr_base);
+ case DW_AT_loclists_base:
+ SetLoclistsBase(form_value.Unsigned());
break;
case DW_AT_rnglists_base:
ranges_base = form_value.Unsigned();
@@ -324,6 +336,9 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
}
}
+ if (m_is_dwo)
+ return;
+
std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
if (!dwo_symbol_file)
@@ -358,10 +373,18 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
else if (gnu_addr_base)
dwo_cu->SetAddrBase(*gnu_addr_base);
- if (ranges_base)
- dwo_cu->SetRangesBase(*ranges_base);
- else if (gnu_ranges_base)
+ if (GetVersion() <= 4 && gnu_ranges_base)
dwo_cu->SetRangesBase(*gnu_ranges_base);
+ else if (m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadRngListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+
+ if (GetVersion() >= 5 && m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadLocListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+ dwo_cu->SetBaseAddress(GetBaseAddress());
for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) {
DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i);
@@ -380,24 +403,6 @@ DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
return DWARFDIE();
}
-size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
- std::vector<DWARFDIE> &dies,
- uint32_t depth) const {
- size_t old_size = dies.size();
- {
- llvm::sys::ScopedReader lock(m_die_array_mutex);
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
- for (pos = m_die_array.begin(); pos != end; ++pos) {
- if (pos->Tag() == tag)
- dies.emplace_back(this, &(*pos));
- }
- }
-
- // Return the number of DIEs added to the collection
- return dies.size() - old_size;
-}
-
size_t DWARFUnit::GetDebugInfoSize() const {
return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
}
@@ -417,8 +422,79 @@ dw_offset_t DWARFUnit::GetLineTableOffset() {
void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; }
+// Parse the rangelist table header, including the optional array of offsets
+// following it (DWARF v5 and later).
+template <typename ListTableType>
+static llvm::Expected<ListTableType>
+ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,
+ DwarfFormat format) {
+ // We are expected to be called with Offset 0 or pointing just past the table
+ // header. Correct Offset in the latter case so that it points to the start
+ // of the header.
+ if (offset > 0) {
+ uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format);
+ if (offset < HeaderSize)
+ return llvm::createStringError(errc::invalid_argument,
+ "did not detect a valid"
+ " list table with base = 0x%" PRIx64 "\n",
+ offset);
+ offset -= HeaderSize;
+ }
+ ListTableType Table;
+ if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset))
+ return std::move(E);
+ return Table;
+}
+
+void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) {
+ m_loclists_base = loclists_base;
+
+ uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32);
+ if (loclists_base < header_size)
+ return;
+
+ m_loclist_table_header.emplace(".debug_loclists", "locations");
+ uint64_t offset = loclists_base - header_size;
+ if (llvm::Error E = m_loclist_table_header->extract(
+ m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(),
+ &offset)) {
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract location list table at offset 0x%" PRIx64 ": %s",
+ loclists_base, toString(std::move(E)).c_str());
+ }
+}
+
+std::unique_ptr<llvm::DWARFLocationTable>
+DWARFUnit::GetLocationTable(const DataExtractor &data) const {
+ llvm::DWARFDataExtractor llvm_data(
+ toStringRef(data.GetData()),
+ data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize());
+
+ if (m_is_dwo || GetVersion() >= 5)
+ return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion());
+ return std::make_unique<llvm::DWARFDebugLoc>(llvm_data);
+}
+
+const DWARFDataExtractor &DWARFUnit::GetLocationData() const {
+ DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext();
+ return GetVersion() >= 5 ? Ctx.getOrLoadLocListsData()
+ : Ctx.getOrLoadLocData();
+}
+
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
m_ranges_base = ranges_base;
+
+ if (GetVersion() < 5)
+ return;
+
+ if (auto table_or_error = ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
+ ranges_base, DWARF32))
+ m_rnglist_table = std::move(table_or_error.get());
+ else
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract range list table at offset 0x%" PRIx64 ": %s",
+ ranges_base, toString(table_or_error.takeError()).c_str());
}
void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
@@ -646,6 +722,8 @@ FileSpec DWARFUnit::GetFile(size_t file_idx) {
// Remove the host part if present.
static llvm::StringRef
removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
+ if (!path_from_dwarf.contains(':'))
+ return path_from_dwarf;
llvm::StringRef host, path;
std::tie(host, path) = path_from_dwarf.split(':');
@@ -715,7 +793,8 @@ void DWARFUnit::ComputeAbsolutePath() {
m_file_spec->MakeAbsolute(GetCompilationDirectory());
}
-SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
+SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() {
+ ExtractUnitDIEIfNeeded();
return m_dwo_symbol_file.get();
}
@@ -816,11 +895,12 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
return llvm::make_error<llvm::object::GenericBinaryError>(
"No abbrev exists at the specified offset.");
+ bool is_dwo = dwarf.GetDWARFContext().isDwo();
if (expected_header->IsTypeUnit())
- return DWARFUnitSP(
- new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, section));
- return DWARFUnitSP(
- new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs, section));
+ return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs,
+ section, is_dwo));
+ return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header,
+ *abbrevs, section, is_dwo));
}
const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
@@ -845,30 +925,56 @@ uint32_t DWARFUnit::GetHeaderByteSize() const {
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const {
- const DWARFDebugRangesBase *debug_ranges;
- llvm::StringRef section;
+DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
if (GetVersion() <= 4) {
- debug_ranges = m_dwarf.GetDebugRanges();
- section = "debug_ranges";
- } else {
- debug_ranges = m_dwarf.GetDebugRngLists();
- section = "debug_rnglists";
+ const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges();
+ if (!debug_ranges)
+ return llvm::make_error<llvm::object::GenericBinaryError>(
+ "No debug_ranges section");
+ DWARFRangeList ranges;
+ debug_ranges->FindRanges(this, offset, ranges);
+ return ranges;
}
- if (!debug_ranges)
- return llvm::make_error<llvm::object::GenericBinaryError>("No " + section +
- " section");
+
+ if (!m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
+
+ auto range_list_or_error = m_rnglist_table->findList(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset);
+ if (!range_list_or_error)
+ return range_list_or_error.takeError();
+
+ llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges =
+ range_list_or_error->getAbsoluteRanges(
+ llvm::object::SectionedAddress{GetBaseAddress()},
+ [&](uint32_t index) {
+ uint32_t index_size = GetAddressByteSize();
+ dw_offset_t addr_base = GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return llvm::object::SectionedAddress{
+ m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
+ &offset, index_size)};
+ });
+ if (!llvm_ranges)
+ return llvm_ranges.takeError();
DWARFRangeList ranges;
- debug_ranges->FindRanges(this, offset, ranges);
+ for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) {
+ ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC,
+ llvm_range.HighPC - llvm_range.LowPC));
+ }
return ranges;
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromIndex(uint32_t index) const {
- const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists();
- if (!debug_rnglists)
- return llvm::make_error<llvm::object::GenericBinaryError>(
- "No debug_rnglists section");
- return FindRnglistFromOffset(debug_rnglists->GetOffset(index));
+DWARFUnit::FindRnglistFromIndex(uint32_t index) {
+ if (llvm::Optional<uint64_t> offset = GetRnglistOffset(index))
+ return FindRnglistFromOffset(*offset);
+ if (m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "invalid range list table index %d", index);
+
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
}