LibDebug: Implement symbolication for x86_64

This commit is contained in:
Gunnar Beutner 2021-07-13 18:16:36 +02:00 committed by Andreas Kling
parent 567fa4b2f0
commit 2c41e89d08
Notes: sideshowbarker 2024-07-18 09:06:53 +09:00
9 changed files with 33 additions and 43 deletions

View File

@ -35,10 +35,6 @@ ELFObjectInfo const* Backtrace::object_info_for_region(ELF::Core::MemoryRegionIn
return nullptr;
auto image = make<ELF::Image>(file_or_error.value()->bytes());
#if !ARCH(I386)
// FIXME: Fix LibDebug
return nullptr;
#endif
auto info = make<ELFObjectInfo>(file_or_error.release_value(), make<Debug::DebugInfo>(move(image)));
auto* info_ptr = info.ptr();
m_debug_info_cache.set(path, move(info));
@ -81,11 +77,11 @@ Backtrace::~Backtrace()
{
}
void Backtrace::add_entry(const Reader& coredump, FlatPtr eip)
void Backtrace::add_entry(const Reader& coredump, FlatPtr ip)
{
auto* region = coredump.region_containing((FlatPtr)eip);
auto* region = coredump.region_containing((FlatPtr)ip);
if (!region) {
m_entries.append({ eip, {}, {}, {} });
m_entries.append({ ip, {}, {}, {} });
return;
}
auto object_name = region->object_name();
@ -95,15 +91,9 @@ void Backtrace::add_entry(const Reader& coredump, FlatPtr eip)
if (!object_info)
return;
#if ARCH(I386)
auto function_name = object_info->debug_info->elf().symbolicate(eip - region->region_start);
auto source_position = object_info->debug_info->get_source_position_with_inlines(eip - region->region_start);
#else
// FIXME: Fix symbolication.
auto function_name = "";
Debug::DebugInfo::SourcePositionWithInlines source_position;
#endif
m_entries.append({ eip, object_name, function_name, source_position });
auto function_name = object_info->debug_info->elf().symbolicate(ip - region->region_start);
auto source_position = object_info->debug_info->get_source_position_with_inlines(ip - region->region_start);
m_entries.append({ ip, object_name, function_name, source_position });
}
String Backtrace::Entry::to_string(bool color) const

View File

@ -42,7 +42,7 @@ public:
const Vector<Entry> entries() const { return m_entries; }
private:
void add_entry(const Reader&, FlatPtr eip);
void add_entry(const Reader&, FlatPtr ip);
ELFObjectInfo const* object_info_for_region(ELF::Core::MemoryRegionInfo const&);
ELF::Core::ThreadInfo m_thread_info;

View File

@ -60,9 +60,9 @@ void DebugInfo::parse_scopes_impl(Dwarf::DIE const& die)
dbgln_if(SPAM_DEBUG, "DWARF: Couldn't find attribute LowPc for scope");
return;
}
scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().data.as_u32;
scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().data.as_addr;
// The attribute name HighPc is confusing. In this context, it seems to actually be a positive offset from LowPc
scope.address_high = scope.address_low + child.get_attribute(Dwarf::Attribute::HighPc).value().data.as_u32;
scope.address_high = scope.address_low + child.get_attribute(Dwarf::Attribute::HighPc).value().data.as_addr;
child.for_each_child([&](Dwarf::DIE const& variable_entry) {
if (!(variable_entry.tag() == Dwarf::EntryTag::Variable
@ -78,7 +78,6 @@ void DebugInfo::parse_scopes_impl(Dwarf::DIE const& die)
void DebugInfo::prepare_lines()
{
Vector<Dwarf::LineProgram::LineInfo> all_lines;
m_dwarf_info.for_each_compilation_unit([&all_lines](Dwarf::CompilationUnit const& unit) {
all_lines.extend(unit.line_program().lines());
@ -115,7 +114,7 @@ void DebugInfo::prepare_lines()
});
}
Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(u32 target_address) const
Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(FlatPtr target_address) const
{
if (m_sorted_lines.is_empty())
return {};
@ -219,7 +218,7 @@ static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::V
switch (location_info.value().type) {
case Dwarf::AttributeValue::Type::UnsignedNumber:
variable_info.location_type = DebugInfo::VariableInfo::LocationType::Address;
variable_info.location_data.address = location_info.value().data.as_u32;
variable_info.location_data.address = location_info.value().data.as_addr;
break;
case Dwarf::AttributeValue::Type::DwarfExpression: {
auto expression_bytes = ReadonlyBytes { location_info.value().data.as_raw_bytes.bytes, location_info.value().data.as_raw_bytes.length };
@ -228,7 +227,7 @@ static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::V
if (value.type != Dwarf::Expression::Type::None) {
VERIFY(value.type == Dwarf::Expression::Type::UnsignedInteger);
variable_info.location_type = DebugInfo::VariableInfo::LocationType::Address;
variable_info.location_data.address = value.data.as_u32;
variable_info.location_data.address = value.data.as_addr;
}
break;
}
@ -349,7 +348,7 @@ bool DebugInfo::is_variable_tag_supported(Dwarf::EntryTag const& tag)
|| tag == Dwarf::EntryTag::ArrayType;
}
String DebugInfo::name_of_containing_function(u32 address) const
String DebugInfo::name_of_containing_function(FlatPtr address) const
{
auto function = get_containing_function(address);
if (!function.has_value())
@ -357,7 +356,7 @@ String DebugInfo::name_of_containing_function(u32 address) const
return function.value().name;
}
Optional<DebugInfo::VariablesScope> DebugInfo::get_containing_function(u32 address) const
Optional<DebugInfo::VariablesScope> DebugInfo::get_containing_function(FlatPtr address) const
{
for (const auto& scope : m_scopes) {
if (!scope.is_function || address < scope.address_low || address >= scope.address_high)
@ -386,7 +385,7 @@ DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(Dwarf::LineP
return { line.file, line.line, line.address };
}
DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(u32 address) const
DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(FlatPtr address) const
{
// If the address is in an "inline chain", this is the inner-most inlined position.
auto inner_source_position = get_source_position(address);

View File

@ -31,7 +31,7 @@ public:
struct SourcePosition {
FlyString file_path;
size_t line_number { 0 };
Optional<u32> address_of_first_statement;
Optional<FlatPtr> address_of_first_statement;
SourcePosition()
: SourcePosition(String::empty(), 0)
@ -42,7 +42,7 @@ public:
, line_number(line_number)
{
}
SourcePosition(String file_path, size_t line_number, u32 address_of_first_statement)
SourcePosition(String file_path, size_t line_number, FlatPtr address_of_first_statement)
: file_path(file_path)
, line_number(line_number)
, address_of_first_statement(address_of_first_statement)
@ -65,7 +65,7 @@ public:
String type_name;
LocationType location_type { LocationType::None };
union {
u32 address;
FlatPtr address;
} location_data { 0 };
union {
@ -86,20 +86,20 @@ public:
struct VariablesScope {
bool is_function { false };
String name;
u32 address_low { 0 };
u32 address_high { 0 }; // Non-inclusive - the lowest address after address_low that's not in this scope
FlatPtr address_low { 0 };
FlatPtr address_high { 0 }; // Non-inclusive - the lowest address after address_low that's not in this scope
Vector<Dwarf::DIE> dies_of_variables;
};
NonnullOwnPtrVector<VariableInfo> get_variables_in_current_scope(PtraceRegisters const&) const;
Optional<SourcePosition> get_source_position(u32 address) const;
Optional<SourcePosition> get_source_position(FlatPtr address) const;
struct SourcePositionWithInlines {
Optional<SourcePosition> source_position;
Vector<SourcePosition> inline_chain;
};
SourcePositionWithInlines get_source_position_with_inlines(u32 address) const;
SourcePositionWithInlines get_source_position_with_inlines(FlatPtr address) const;
struct SourcePositionAndAddress {
String file;
@ -109,9 +109,9 @@ public:
Optional<SourcePositionAndAddress> get_address_from_source_position(const String& file, size_t line) const;
String name_of_containing_function(u32 address) const;
String name_of_containing_function(FlatPtr address) const;
Vector<SourcePosition> source_lines_in_scope(const VariablesScope&) const;
Optional<VariablesScope> get_containing_function(u32 address) const;
Optional<VariablesScope> get_containing_function(FlatPtr address) const;
private:
void prepare_variable_scopes();

View File

@ -25,6 +25,7 @@ struct AttributeValue {
} type;
union {
FlatPtr as_addr;
u32 as_u32;
i32 as_i32;
u64 as_u64;

View File

@ -47,7 +47,7 @@ void DwarfInfo::populate_compilation_units()
debug_info_stream >> compilation_unit_header;
VERIFY(compilation_unit_header.common.version <= 5);
VERIFY(compilation_unit_header.address_size() == sizeof(u32));
VERIFY(compilation_unit_header.address_size() == sizeof(FlatPtr));
u32 length_after_header = compilation_unit_header.length() - (compilation_unit_header.header_size() - offsetof(CompilationUnitHeader, common.version));
@ -102,11 +102,11 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im
break;
}
case AttributeDataForm::Addr: {
u32 address;
FlatPtr address;
debug_info_stream >> address;
VERIFY(!debug_info_stream.has_any_error());
value.type = AttributeValue::Type::UnsignedNumber;
value.data.as_u32 = address;
value.data.as_addr = address;
break;
}
case AttributeDataForm::SData: {
@ -250,7 +250,6 @@ void DwarfInfo::build_cached_dies() const
if (!start.has_value() || !end.has_value())
return {};
VERIFY(sizeof(FlatPtr) == sizeof(u32));
VERIFY(start->type == Dwarf::AttributeValue::Type::UnsignedNumber);
// DW_AT_high_pc attribute can have different meanings depending on the attribute form.
@ -258,7 +257,7 @@ void DwarfInfo::build_cached_dies() const
uint32_t range_end = 0;
if (end->form == Dwarf::AttributeDataForm::Addr)
range_end = end->data.as_u32;
range_end = end->data.as_addr;
else
range_end = start->data.as_u32 + end->data.as_u32;

View File

@ -22,6 +22,7 @@ enum class Type {
struct Value {
Type type;
union {
FlatPtr as_addr;
u32 as_u32;
} data { 0 };
};

View File

@ -174,7 +174,7 @@ void LineProgram::handle_extended_opcode()
break;
}
default:
dbgln_if(DWARF_DEBUG, "offset: {:p}", m_stream.offset());
dbgln("Encountered unknown sub opcode {} at stream offset {:p}", sub_opcode, m_stream.offset());
VERIFY_NOT_REACHED();
}
}

View File

@ -109,7 +109,7 @@ public:
explicit LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream);
struct LineInfo {
u32 address { 0 };
FlatPtr address { 0 };
FlyString file;
size_t line { 0 };
};
@ -176,7 +176,7 @@ private:
Vector<FileEntry> m_source_files;
// The registers of the "line program" virtual machine
u32 m_address { 0 };
FlatPtr m_address { 0 };
size_t m_line { 0 };
size_t m_file_index { 0 };
bool m_is_statement { false };