LibDebug: Handle DWARF 4 address ranges

The format of the address range section is different between DWARF
version 4 and version 5. This meant that we parsed programs compiled
with `-gdwarf-4` incorrectly.
This commit is contained in:
Daniel Bertalan 2021-12-05 08:45:05 +01:00 committed by Brian Gianforcaro
parent 7546295abe
commit 815f15f82c
5 changed files with 70 additions and 14 deletions

View file

@ -9,14 +9,14 @@
namespace Debug::Dwarf {
AddressRanges::AddressRanges(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit)
AddressRangesV5::AddressRangesV5(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit)
: m_range_lists_stream(range_lists_data)
, m_compilation_unit(compilation_unit)
{
m_range_lists_stream.seek(offset);
}
void AddressRanges::for_each_range(Function<void(Range)> callback)
void AddressRangesV5::for_each_range(Function<void(Range)> callback)
{
// Dwarf version 5, section 2.17.3 "Non-Contiguous Address Ranges"
@ -86,4 +86,32 @@ void AddressRanges::for_each_range(Function<void(Range)> callback)
}
}
AddressRangesV4::AddressRangesV4(ReadonlyBytes ranges_data, size_t offset, CompilationUnit const& compilation_unit)
: m_ranges_stream(ranges_data)
, m_compilation_unit(compilation_unit)
{
m_ranges_stream.seek(offset);
}
void AddressRangesV4::for_each_range(Function<void(Range)> callback)
{
// Dwarf version 4, section 2.17.3 "Non-Contiguous Address Ranges"
Optional<FlatPtr> current_base_address;
while (!m_ranges_stream.eof() && !m_ranges_stream.has_any_error()) {
FlatPtr begin, end;
m_ranges_stream >> begin >> end;
if (begin == 0 && end == 0) {
// end of list entry
return;
} else if (begin == explode_byte(0xff)) {
current_base_address = end;
} else {
FlatPtr base = current_base_address.value_or(m_compilation_unit.base_address().value_or(0));
callback({ base + begin, base + end });
}
}
}
}

View file

@ -14,17 +14,18 @@
namespace Debug::Dwarf {
class AddressRanges {
AK_MAKE_NONCOPYABLE(AddressRanges);
AK_MAKE_NONMOVABLE(AddressRanges);
struct Range {
FlatPtr start { 0 };
FlatPtr end { 0 };
};
class AddressRangesV5 {
AK_MAKE_NONCOPYABLE(AddressRangesV5);
AK_MAKE_NONMOVABLE(AddressRangesV5);
public:
AddressRanges(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit);
AddressRangesV5(ReadonlyBytes range_lists_data, size_t offset, CompilationUnit const& compilation_unit);
struct Range {
FlatPtr start { 0 };
FlatPtr end { 0 };
};
void for_each_range(Function<void(Range)>);
private:
@ -32,4 +33,18 @@ private:
CompilationUnit const& m_compilation_unit;
};
class AddressRangesV4 {
AK_MAKE_NONCOPYABLE(AddressRangesV4);
AK_MAKE_NONMOVABLE(AddressRangesV4);
public:
AddressRangesV4(ReadonlyBytes ranges_data, size_t offset, CompilationUnit const&);
void for_each_range(Function<void(Range)>);
private:
InputMemoryStream m_ranges_stream;
CompilationUnit const& m_compilation_unit;
};
}

View file

@ -34,6 +34,8 @@ public:
FlatPtr get_address(size_t index) const;
char const* get_string(size_t index) const;
u8 dwarf_version() const { return m_header.version(); }
DwarfInfo const& dwarf_info() const { return m_dwarf_info; }
AbbreviationsMap const& abbreviations_map() const { return m_abbreviations; }
LineProgram const& line_program() const { return *m_line_program; }

View file

@ -25,6 +25,7 @@ DwarfInfo::DwarfInfo(ELF::Image const& elf)
m_debug_range_lists_data = section_data(".debug_rnglists"sv);
m_debug_str_offsets_data = section_data(".debug_str_offsets"sv);
m_debug_addr_data = section_data(".debug_addr"sv);
m_debug_ranges_data = section_data(".debug_ranges"sv);
populate_compilation_units();
}
@ -346,11 +347,19 @@ void DwarfInfo::build_cached_dies() const
auto offsets = reinterpret_cast<u32 const*>(debug_range_lists_data().offset(base));
offset = offsets[index] + base;
}
AddressRanges address_ranges(debug_range_lists_data(), offset, die.compilation_unit());
Vector<DIERange> entries;
address_ranges.for_each_range([&entries](auto range) {
entries.empend(range.start, range.end);
});
if (die.compilation_unit().dwarf_version() == 5) {
AddressRangesV5 address_ranges(debug_range_lists_data(), offset, die.compilation_unit());
address_ranges.for_each_range([&entries](auto range) {
entries.empend(range.start, range.end);
});
} else {
AddressRangesV4 address_ranges(debug_ranges_data(), offset, die.compilation_unit());
address_ranges.for_each_range([&entries](auto range) {
entries.empend(range.start, range.end);
});
}
return entries;
}

View file

@ -33,6 +33,7 @@ public:
ReadonlyBytes debug_range_lists_data() const { return m_debug_range_lists_data; }
ReadonlyBytes debug_str_offsets_data() const { return m_debug_str_offsets_data; }
ReadonlyBytes debug_addr_data() const { return m_debug_addr_data; }
ReadonlyBytes debug_ranges_data() const { return m_debug_ranges_data; }
template<typename Callback>
void for_each_compilation_unit(Callback) const;
@ -64,6 +65,7 @@ private:
ReadonlyBytes m_debug_range_lists_data;
ReadonlyBytes m_debug_str_offsets_data;
ReadonlyBytes m_debug_addr_data;
ReadonlyBytes m_debug_ranges_data;
NonnullOwnPtrVector<Dwarf::CompilationUnit> m_compilation_units;