mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
LibDebug: Add DebugInfo::get_source_position_with_inlines
This function returns the source position of a given address in the program. If that address exists in an inline chain, then it also returns the source positions that are in the chain.
This commit is contained in:
parent
835efa1b6a
commit
a45b5ccd96
Notes:
sideshowbarker
2024-07-18 12:01:11 +09:00
Author: https://github.com/itamar8910 Commit: https://github.com/SerenityOS/serenity/commit/a45b5ccd969 Pull-request: https://github.com/SerenityOS/serenity/pull/8149 Reviewed-by: https://github.com/gunnarbeutner
2 changed files with 84 additions and 2 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2021, Itamar S. <itamar8910@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -380,4 +380,77 @@ DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(const Dwarf:
|
|||
return { line.file, line.line, { line.address } };
|
||||
}
|
||||
|
||||
DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(u32 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);
|
||||
|
||||
auto die = m_dwarf_info.get_die_at_address(address);
|
||||
if (!die.has_value() || die->tag() == Dwarf::EntryTag::SubroutineType) {
|
||||
// Inline chain is empty
|
||||
return SourcePositionWithInlines { inner_source_position, {} };
|
||||
}
|
||||
|
||||
Vector<SourcePosition> inline_chain;
|
||||
|
||||
auto insert_to_chain = [&](const Dwarf::DIE& die) {
|
||||
auto caller_source_path = get_source_path_of_inline(die);
|
||||
auto caller_line = get_line_of_inline(die);
|
||||
|
||||
if (!caller_source_path.has_value() || !caller_line.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
inline_chain.append({ String::formatted("{}/{}", caller_source_path->directory, caller_source_path->filename), caller_line.value() });
|
||||
};
|
||||
|
||||
while (die->tag() == Dwarf::EntryTag::InlinedSubroutine) {
|
||||
insert_to_chain(*die);
|
||||
|
||||
if (!die->parent_offset().has_value()) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto parent = die->compilation_unit().dwarf_info().get_cached_die_at_offset(die->parent_offset().value());
|
||||
if (!parent.has_value()) {
|
||||
break;
|
||||
}
|
||||
die = *parent;
|
||||
}
|
||||
|
||||
return SourcePositionWithInlines { inner_source_position, inline_chain };
|
||||
}
|
||||
|
||||
Optional<Dwarf::LineProgram::DirectoryAndFile> DebugInfo::get_source_path_of_inline(const Dwarf::DIE& die) const
|
||||
{
|
||||
auto caller_file = die.get_attribute(Dwarf::Attribute::CallFile);
|
||||
if (caller_file.has_value()) {
|
||||
u32 file_index = 0;
|
||||
|
||||
if (caller_file->type == Dwarf::AttributeValue::Type::UnsignedNumber) {
|
||||
file_index = caller_file->data.as_u32;
|
||||
} else if (caller_file->type == Dwarf::AttributeValue::Type::SignedNumber) {
|
||||
// For some reason, the file_index is sometimes stored as a signed number.
|
||||
VERIFY(caller_file->data.as_i32 >= 0);
|
||||
file_index = (u32)caller_file->data.as_i32;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
||||
return die.compilation_unit().line_program().get_directory_and_file(file_index);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Optional<uint32_t> DebugInfo::get_line_of_inline(const Dwarf::DIE& die) const
|
||||
{
|
||||
auto caller_line = die.get_attribute(Dwarf::Attribute::CallLine);
|
||||
if (!caller_line.has_value())
|
||||
return {};
|
||||
|
||||
if (caller_line->type != Dwarf::AttributeValue::Type::UnsignedNumber)
|
||||
return {};
|
||||
return caller_line.value().data.as_u32;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
|
||||
* Copyright (c) 2020-2021, Itamar S. <itamar8910@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -95,6 +95,12 @@ public:
|
|||
|
||||
Optional<SourcePosition> get_source_position(u32 address) const;
|
||||
|
||||
struct SourcePositionWithInlines {
|
||||
Optional<SourcePosition> source_position;
|
||||
Vector<SourcePosition> inline_chain;
|
||||
};
|
||||
SourcePositionWithInlines get_source_position_with_inlines(u32 address) const;
|
||||
|
||||
struct SourcePositionAndAddress {
|
||||
String file;
|
||||
size_t line;
|
||||
|
@ -115,6 +121,9 @@ private:
|
|||
static bool is_variable_tag_supported(const Dwarf::EntryTag& tag);
|
||||
void add_type_info_to_variable(const Dwarf::DIE& type_die, const PtraceRegisters& regs, DebugInfo::VariableInfo* parent_variable) const;
|
||||
|
||||
Optional<Dwarf::LineProgram::DirectoryAndFile> get_source_path_of_inline(const Dwarf::DIE&) const;
|
||||
Optional<uint32_t> get_line_of_inline(const Dwarf::DIE&) const;
|
||||
|
||||
NonnullOwnPtr<const ELF::Image> m_elf;
|
||||
String m_source_root;
|
||||
FlatPtr m_base_address { 0 };
|
||||
|
|
Loading…
Reference in a new issue