From e62269650a9b1d48ff06bd51eb2d82073ec1c274 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Sun, 22 Jan 2023 00:32:08 +0100 Subject: [PATCH] LibDebug: Propagate errors throughout DWARF parsing Splitting this into a separate commit was an afterthought, so this does not yet feature any fallible operations. --- .../HackStudio/Debugger/VariablesModel.cpp | 2 +- .../DevTools/Profiler/DisassemblyModel.cpp | 3 +- Userland/Libraries/LibCoredump/Backtrace.cpp | 2 +- Userland/Libraries/LibDebug/DebugInfo.cpp | 169 ++++++++++-------- Userland/Libraries/LibDebug/DebugInfo.h | 18 +- .../LibDebug/Dwarf/AddressRanges.cpp | 10 +- .../LibDebug/Dwarf/AttributeValue.cpp | 4 +- .../Libraries/LibDebug/Dwarf/AttributeValue.h | 4 +- .../LibDebug/Dwarf/CompilationUnit.cpp | 26 +-- .../LibDebug/Dwarf/CompilationUnit.h | 12 +- Userland/Libraries/LibDebug/Dwarf/DIE.cpp | 32 ++-- Userland/Libraries/LibDebug/Dwarf/DIE.h | 6 +- .../Libraries/LibDebug/Dwarf/DwarfInfo.cpp | 76 ++++---- Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h | 17 +- .../Libraries/LibDebug/Dwarf/LineProgram.cpp | 50 ++++-- .../Libraries/LibDebug/Dwarf/LineProgram.h | 14 +- .../LibSymbolication/Symbolication.cpp | 2 +- 17 files changed, 243 insertions(+), 204 deletions(-) diff --git a/Userland/DevTools/HackStudio/Debugger/VariablesModel.cpp b/Userland/DevTools/HackStudio/Debugger/VariablesModel.cpp index 97e5189388..c97bcaa799 100644 --- a/Userland/DevTools/HackStudio/Debugger/VariablesModel.cpp +++ b/Userland/DevTools/HackStudio/Debugger/VariablesModel.cpp @@ -168,7 +168,7 @@ RefPtr VariablesModel::create(Debug::ProcessInspector& inspector auto lib = inspector.library_at(regs.ip()); if (!lib) return nullptr; - auto variables = lib->debug_info->get_variables_in_current_scope(regs); + auto variables = lib->debug_info->get_variables_in_current_scope(regs).release_value_but_fixme_should_propagate_errors(); return adopt_ref(*new VariablesModel(inspector, move(variables), regs)); } diff --git a/Userland/DevTools/Profiler/DisassemblyModel.cpp b/Userland/DevTools/Profiler/DisassemblyModel.cpp index 0501224ac1..447fb4f125 100644 --- a/Userland/DevTools/Profiler/DisassemblyModel.cpp +++ b/Userland/DevTools/Profiler/DisassemblyModel.cpp @@ -116,8 +116,9 @@ DisassemblyModel::DisassemblyModel(Profile& profile, ProfileNode& node) StringView instruction_bytes = view.substring_view(offset_into_symbol, insn.value().length()); u32 samples_at_this_instruction = m_node.events_per_address().get(address_in_profiled_program).value_or(0); float percent = ((float)samples_at_this_instruction / (float)m_node.event_count()) * 100.0f; + auto source_position = debug_info->get_source_position_with_inlines(address_in_profiled_program - base_address).release_value_but_fixme_should_propagate_errors(); - m_instructions.append({ insn.value(), disassembly, instruction_bytes, address_in_profiled_program, samples_at_this_instruction, percent, debug_info->get_source_position_with_inlines(address_in_profiled_program - base_address) }); + m_instructions.append({ insn.value(), disassembly, instruction_bytes, address_in_profiled_program, samples_at_this_instruction, percent, source_position }); offset_into_symbol += insn.value().length(); } diff --git a/Userland/Libraries/LibCoredump/Backtrace.cpp b/Userland/Libraries/LibCoredump/Backtrace.cpp index 92c521f94d..0ec7527365 100644 --- a/Userland/Libraries/LibCoredump/Backtrace.cpp +++ b/Userland/Libraries/LibCoredump/Backtrace.cpp @@ -121,7 +121,7 @@ void Backtrace::add_entry(Reader const& coredump, FlatPtr ip) } 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); + auto source_position = object_info->debug_info->get_source_position_with_inlines(ip - region->region_start).release_value_but_fixme_should_propagate_errors(); m_entries.append({ ip, object_name, function_name, source_position }); } diff --git a/Userland/Libraries/LibDebug/DebugInfo.cpp b/Userland/Libraries/LibDebug/DebugInfo.cpp index 4df6cb3fb3..5a78253c9e 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.cpp +++ b/Userland/Libraries/LibDebug/DebugInfo.cpp @@ -21,70 +21,77 @@ DebugInfo::DebugInfo(ELF::Image const& elf, DeprecatedString source_root, FlatPt , m_base_address(base_address) , m_dwarf_info(m_elf) { - prepare_variable_scopes(); - prepare_lines(); + prepare_variable_scopes().release_value_but_fixme_should_propagate_errors(); + prepare_lines().release_value_but_fixme_should_propagate_errors(); } -void DebugInfo::prepare_variable_scopes() +ErrorOr DebugInfo::prepare_variable_scopes() { - m_dwarf_info.for_each_compilation_unit([&](Dwarf::CompilationUnit const& unit) { + TRY(m_dwarf_info.for_each_compilation_unit([&](Dwarf::CompilationUnit const& unit) -> ErrorOr { auto root = unit.root_die(); - parse_scopes_impl(root); - }); + TRY(parse_scopes_impl(root)); + return {}; + })); + return {}; } -void DebugInfo::parse_scopes_impl(Dwarf::DIE const& die) +ErrorOr DebugInfo::parse_scopes_impl(Dwarf::DIE const& die) { - die.for_each_child([&](Dwarf::DIE const& child) { + TRY(die.for_each_child([&](Dwarf::DIE const& child) -> ErrorOr { if (child.is_null()) - return; + return {}; if (!(child.tag() == Dwarf::EntryTag::SubProgram || child.tag() == Dwarf::EntryTag::LexicalBlock)) - return; + return {}; - if (child.get_attribute(Dwarf::Attribute::Inline).has_value()) { + if (TRY(child.get_attribute(Dwarf::Attribute::Inline)).has_value()) { dbgln_if(SPAM_DEBUG, "DWARF inlined functions are not supported"); - return; + return {}; } - if (child.get_attribute(Dwarf::Attribute::Ranges).has_value()) { + if (TRY(child.get_attribute(Dwarf::Attribute::Ranges)).has_value()) { dbgln_if(SPAM_DEBUG, "DWARF ranges are not supported"); - return; + return {}; } - auto name = child.get_attribute(Dwarf::Attribute::Name); + auto name = TRY(child.get_attribute(Dwarf::Attribute::Name)); VariablesScope scope {}; scope.is_function = (child.tag() == Dwarf::EntryTag::SubProgram); if (name.has_value()) - scope.name = name.value().as_string(); + scope.name = TRY(name.value().as_string()); - if (!child.get_attribute(Dwarf::Attribute::LowPc).has_value()) { + if (!TRY(child.get_attribute(Dwarf::Attribute::LowPc)).has_value()) { dbgln_if(SPAM_DEBUG, "DWARF: Couldn't find attribute LowPc for scope"); - return; + return {}; } - scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().as_addr(); - auto high_pc = child.get_attribute(Dwarf::Attribute::HighPc); + scope.address_low = TRY(TRY(child.get_attribute(Dwarf::Attribute::LowPc)).value().as_addr()); + auto high_pc = TRY(child.get_attribute(Dwarf::Attribute::HighPc)); if (high_pc->type() == Dwarf::AttributeValue::Type::Address) - scope.address_high = high_pc->as_addr(); + scope.address_high = TRY(high_pc->as_addr()); else scope.address_high = scope.address_low + high_pc->as_unsigned(); - child.for_each_child([&](Dwarf::DIE const& variable_entry) { + TRY(child.for_each_child([&](Dwarf::DIE const& variable_entry) -> ErrorOr { if (!(variable_entry.tag() == Dwarf::EntryTag::Variable || variable_entry.tag() == Dwarf::EntryTag::FormalParameter)) - return; + return {}; scope.dies_of_variables.append(variable_entry); - }); + return {}; + })); m_scopes.append(scope); - parse_scopes_impl(child); - }); + TRY(parse_scopes_impl(child)); + + return {}; + })); + return {}; } -void DebugInfo::prepare_lines() +ErrorOr DebugInfo::prepare_lines() { Vector all_lines; - m_dwarf_info.for_each_compilation_unit([&all_lines](Dwarf::CompilationUnit const& unit) { + TRY(m_dwarf_info.for_each_compilation_unit([&all_lines](Dwarf::CompilationUnit const& unit) -> ErrorOr { all_lines.extend(unit.line_program().lines()); - }); + return {}; + })); HashMap> memoized_full_paths; auto compute_full_path = [&](DeprecatedFlyString const& file_path) -> Optional { @@ -111,6 +118,7 @@ void DebugInfo::prepare_lines() quick_sort(m_sorted_lines, [](auto& a, auto& b) { return a.address < b.address; }); + return {}; } Optional DebugInfo::get_source_position(FlatPtr target_address) const @@ -160,7 +168,7 @@ Optional DebugInfo::get_address_from_source return result; } -NonnullOwnPtrVector DebugInfo::get_variables_in_current_scope(PtraceRegisters const& regs) const +ErrorOr> DebugInfo::get_variables_in_current_scope(PtraceRegisters const& regs) const { NonnullOwnPtrVector variables; @@ -178,7 +186,7 @@ NonnullOwnPtrVector DebugInfo::get_variables_in_current continue; for (auto const& die_entry : scope.dies_of_variables) { - auto variable_info = create_variable_info(die_entry, regs); + auto variable_info = TRY(create_variable_info(die_entry, regs)); if (!variable_info) continue; variables.append(variable_info.release_nonnull()); @@ -187,18 +195,18 @@ NonnullOwnPtrVector DebugInfo::get_variables_in_current return variables; } -static Optional parse_variable_type_die(Dwarf::DIE const& variable_die, DebugInfo::VariableInfo& variable_info) +static ErrorOr> parse_variable_type_die(Dwarf::DIE const& variable_die, DebugInfo::VariableInfo& variable_info) { - auto type_die_offset = variable_die.get_attribute(Dwarf::Attribute::Type); + auto type_die_offset = TRY(variable_die.get_attribute(Dwarf::Attribute::Type)); if (!type_die_offset.has_value()) - return {}; + return Optional {}; VERIFY(type_die_offset.value().type() == Dwarf::AttributeValue::Type::DieReference); auto type_die = variable_die.compilation_unit().get_die_at_offset(type_die_offset.value().as_unsigned()); - auto type_name = type_die.get_attribute(Dwarf::Attribute::Name); + auto type_name = TRY(type_die.get_attribute(Dwarf::Attribute::Name)); if (type_name.has_value()) { - variable_info.type_name = type_name.value().as_string(); + variable_info.type_name = TRY(type_name.value().as_string()); } else { dbgln("Unnamed DWARF type at offset: {}", type_die.offset()); variable_info.type_name = "[Unnamed Type]"; @@ -207,15 +215,15 @@ static Optional parse_variable_type_die(Dwarf::DIE const& variable_d return type_die; } -static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::VariableInfo& variable_info, PtraceRegisters const& regs) +static ErrorOr parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::VariableInfo& variable_info, PtraceRegisters const& regs) { - auto location_info = variable_die.get_attribute(Dwarf::Attribute::Location); + auto location_info = TRY(variable_die.get_attribute(Dwarf::Attribute::Location)); if (!location_info.has_value()) { - location_info = variable_die.get_attribute(Dwarf::Attribute::MemberLocation); + location_info = TRY(variable_die.get_attribute(Dwarf::Attribute::MemberLocation)); } if (!location_info.has_value()) - return; + return {}; switch (location_info.value().type()) { case Dwarf::AttributeValue::Type::UnsignedNumber: @@ -236,27 +244,29 @@ static void parse_variable_location(Dwarf::DIE const& variable_die, DebugInfo::V default: dbgln("Warning: unhandled Dwarf location type: {}", to_underlying(location_info.value().type())); } + + return {}; } -OwnPtr DebugInfo::create_variable_info(Dwarf::DIE const& variable_die, PtraceRegisters const& regs, u32 address_offset) const +ErrorOr> DebugInfo::create_variable_info(Dwarf::DIE const& variable_die, PtraceRegisters const& regs, u32 address_offset) const { VERIFY(is_variable_tag_supported(variable_die.tag())); if (variable_die.tag() == Dwarf::EntryTag::FormalParameter - && !variable_die.get_attribute(Dwarf::Attribute::Name).has_value()) { + && !TRY(variable_die.get_attribute(Dwarf::Attribute::Name)).has_value()) { // We don't want to display info for unused parameters - return {}; + return OwnPtr {}; } NonnullOwnPtr variable_info = make(); - auto name_attribute = variable_die.get_attribute(Dwarf::Attribute::Name); + auto name_attribute = TRY(variable_die.get_attribute(Dwarf::Attribute::Name)); if (name_attribute.has_value()) - variable_info->name = name_attribute.value().as_string(); + variable_info->name = TRY(name_attribute.value().as_string()); - auto type_die = parse_variable_type_die(variable_die, *variable_info); + auto type_die = TRY(parse_variable_type_die(variable_die, *variable_info)); if (variable_die.tag() == Dwarf::EntryTag::Enumerator) { - auto constant = variable_die.get_attribute(Dwarf::Attribute::ConstValue); + auto constant = TRY(variable_die.get_attribute(Dwarf::Attribute::ConstValue)); VERIFY(constant.has_value()); switch (constant.value().type()) { case Dwarf::AttributeValue::Type::UnsignedNumber: @@ -266,23 +276,23 @@ OwnPtr DebugInfo::create_variable_info(Dwarf::DIE const variable_info->constant_data.as_i32 = constant.value().as_signed(); break; case Dwarf::AttributeValue::Type::String: - variable_info->constant_data.as_string = constant.value().as_string(); + variable_info->constant_data.as_string = TRY(constant.value().as_string()); break; default: VERIFY_NOT_REACHED(); } } else { - parse_variable_location(variable_die, *variable_info, regs); + TRY(parse_variable_location(variable_die, *variable_info, regs)); variable_info->location_data.address += address_offset; } if (type_die.has_value()) - add_type_info_to_variable(type_die.value(), regs, variable_info); + TRY(add_type_info_to_variable(type_die.value(), regs, variable_info)); return variable_info; } -void DebugInfo::add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegisters const& regs, DebugInfo::VariableInfo* parent_variable) const +ErrorOr DebugInfo::add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegisters const& regs, DebugInfo::VariableInfo* parent_variable) const { OwnPtr type_info; auto is_array_type = type_die.tag() == Dwarf::EntryTag::ArrayType; @@ -290,25 +300,25 @@ void DebugInfo::add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegi if (type_die.tag() == Dwarf::EntryTag::EnumerationType || type_die.tag() == Dwarf::EntryTag::StructureType || is_array_type) { - type_info = create_variable_info(type_die, regs); + type_info = TRY(create_variable_info(type_die, regs)); } - type_die.for_each_child([&](Dwarf::DIE const& member) { + TRY(type_die.for_each_child([&](Dwarf::DIE const& member) -> ErrorOr { if (member.is_null()) - return; + return {}; if (is_array_type && member.tag() == Dwarf::EntryTag::SubRangeType) { - auto upper_bound = member.get_attribute(Dwarf::Attribute::UpperBound); + auto upper_bound = TRY(member.get_attribute(Dwarf::Attribute::UpperBound)); VERIFY(upper_bound.has_value()); auto size = upper_bound.value().as_unsigned() + 1; type_info->dimension_sizes.append(size); - return; + return {}; } if (!is_variable_tag_supported(member.tag())) - return; + return {}; - auto member_variable = create_variable_info(member, regs, parent_variable->location_data.address); + auto member_variable = TRY(create_variable_info(member, regs, parent_variable->location_data.address)); VERIFY(member_variable); if (type_die.tag() == Dwarf::EntryTag::EnumerationType) { @@ -316,12 +326,14 @@ void DebugInfo::add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegi type_info->members.append(member_variable.release_nonnull()); } else { if (parent_variable->location_type != DebugInfo::VariableInfo::LocationType::Address) - return; + return {}; member_variable->parent = parent_variable; parent_variable->members.append(member_variable.release_nonnull()); } - }); + + return {}; + })); if (type_info) { if (is_array_type) { @@ -337,6 +349,8 @@ void DebugInfo::add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegi parent_variable->type = move(type_info); parent_variable->type->type_tag = type_die.tag(); } + + return {}; } bool DebugInfo::is_variable_tag_supported(Dwarf::EntryTag const& tag) @@ -387,12 +401,12 @@ DebugInfo::SourcePosition DebugInfo::SourcePosition::from_line_info(Dwarf::LineP return { line.file, line.line, line.address }; } -DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines(FlatPtr address) const +ErrorOr 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); - auto die = m_dwarf_info.get_die_at_address(address); + auto die = TRY(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, {} }; @@ -400,25 +414,26 @@ DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines Vector inline_chain; - auto insert_to_chain = [&](Dwarf::DIE const& die) { - auto caller_source_path = get_source_path_of_inline(die); - auto caller_line = get_line_of_inline(die); + auto insert_to_chain = [&](Dwarf::DIE const& die) -> ErrorOr { + auto caller_source_path = TRY(get_source_path_of_inline(die)); + auto caller_line = TRY(get_line_of_inline(die)); if (!caller_source_path.has_value() || !caller_line.has_value()) { - return; + return {}; } inline_chain.append({ DeprecatedString::formatted("{}/{}", caller_source_path->directory, caller_source_path->filename), caller_line.value() }); + return {}; }; while (die->tag() == Dwarf::EntryTag::InlinedSubroutine) { - insert_to_chain(*die); + TRY(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()); + auto parent = TRY(die->compilation_unit().dwarf_info().get_cached_die_at_offset(die->parent_offset().value())); if (!parent.has_value()) { break; } @@ -428,9 +443,9 @@ DebugInfo::SourcePositionWithInlines DebugInfo::get_source_position_with_inlines return SourcePositionWithInlines { inner_source_position, inline_chain }; } -Optional DebugInfo::get_source_path_of_inline(Dwarf::DIE const& die) const +ErrorOr> DebugInfo::get_source_path_of_inline(Dwarf::DIE const& die) const { - auto caller_file = die.get_attribute(Dwarf::Attribute::CallFile); + auto caller_file = TRY(die.get_attribute(Dwarf::Attribute::CallFile)); if (caller_file.has_value()) { size_t file_index = 0; @@ -443,23 +458,23 @@ Optional DebugInfo::get_source_path_of_inl VERIFY(static_cast(signed_file_index) <= NumericLimits::max()); file_index = static_cast(caller_file->as_signed()); } else { - return {}; + return Optional {}; } return die.compilation_unit().line_program().get_directory_and_file(file_index); } - return {}; + return Optional {}; } -Optional DebugInfo::get_line_of_inline(Dwarf::DIE const& die) const +ErrorOr> DebugInfo::get_line_of_inline(Dwarf::DIE const& die) const { - auto caller_line = die.get_attribute(Dwarf::Attribute::CallLine); + auto caller_line = TRY(die.get_attribute(Dwarf::Attribute::CallLine)); if (!caller_line.has_value()) - return {}; + return Optional {}; if (caller_line->type() != Dwarf::AttributeValue::Type::UnsignedNumber) - return {}; - return caller_line.value().as_unsigned(); + return Optional {}; + return Optional { caller_line.value().as_unsigned() }; } } diff --git a/Userland/Libraries/LibDebug/DebugInfo.h b/Userland/Libraries/LibDebug/DebugInfo.h index 7bb8ff1de5..ffab654318 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.h +++ b/Userland/Libraries/LibDebug/DebugInfo.h @@ -90,7 +90,7 @@ public: Vector dies_of_variables; }; - NonnullOwnPtrVector get_variables_in_current_scope(PtraceRegisters const&) const; + ErrorOr> get_variables_in_current_scope(PtraceRegisters const&) const; Optional get_source_position(FlatPtr address) const; @@ -98,7 +98,7 @@ public: Optional source_position; Vector inline_chain; }; - SourcePositionWithInlines get_source_position_with_inlines(FlatPtr address) const; + ErrorOr get_source_position_with_inlines(FlatPtr address) const; struct SourcePositionAndAddress { DeprecatedString file; @@ -113,15 +113,15 @@ public: Optional get_containing_function(FlatPtr address) const; private: - void prepare_variable_scopes(); - void prepare_lines(); - void parse_scopes_impl(Dwarf::DIE const& die); - OwnPtr create_variable_info(Dwarf::DIE const& variable_die, PtraceRegisters const&, u32 address_offset = 0) const; + ErrorOr prepare_variable_scopes(); + ErrorOr prepare_lines(); + ErrorOr parse_scopes_impl(Dwarf::DIE const& die); + ErrorOr> create_variable_info(Dwarf::DIE const& variable_die, PtraceRegisters const&, u32 address_offset = 0) const; static bool is_variable_tag_supported(Dwarf::EntryTag const& tag); - void add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegisters const& regs, DebugInfo::VariableInfo* parent_variable) const; + ErrorOr add_type_info_to_variable(Dwarf::DIE const& type_die, PtraceRegisters const& regs, DebugInfo::VariableInfo* parent_variable) const; - Optional get_source_path_of_inline(Dwarf::DIE const&) const; - Optional get_line_of_inline(Dwarf::DIE const&) const; + ErrorOr> get_source_path_of_inline(Dwarf::DIE const&) const; + ErrorOr> get_line_of_inline(Dwarf::DIE const&) const; ELF::Image const& m_elf; DeprecatedString m_source_root; diff --git a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp index d1c5f648a4..8f00556978 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.cpp @@ -34,13 +34,13 @@ ErrorOr AddressRangesV5::for_each_range(Function callback) case RangeListEntryType::BaseAddressX: { FlatPtr index; LEB128::read_unsigned(wrapped_range_lists_stream, index); - current_base_address = m_compilation_unit.get_address(index); + current_base_address = TRY(m_compilation_unit.get_address(index)); break; } case RangeListEntryType::OffsetPair: { Optional base_address = current_base_address; if (!base_address.has_value()) { - base_address = m_compilation_unit.base_address(); + base_address = TRY(m_compilation_unit.base_address()); } if (!base_address.has_value()) @@ -63,14 +63,14 @@ ErrorOr AddressRangesV5::for_each_range(Function callback) size_t start, end; LEB128::read_unsigned(wrapped_range_lists_stream, start); LEB128::read_unsigned(wrapped_range_lists_stream, end); - callback(Range { m_compilation_unit.get_address(start), m_compilation_unit.get_address(end) }); + callback(Range { TRY(m_compilation_unit.get_address(start)), TRY(m_compilation_unit.get_address(end)) }); break; } case RangeListEntryType::StartXLength: { size_t start, length; LEB128::read_unsigned(wrapped_range_lists_stream, start); LEB128::read_unsigned(wrapped_range_lists_stream, length); - auto start_addr = m_compilation_unit.get_address(start); + auto start_addr = TRY(m_compilation_unit.get_address(start)); callback(Range { start_addr, start_addr + length }); break; } @@ -106,7 +106,7 @@ ErrorOr AddressRangesV4::for_each_range(Function callback) } 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)); + FlatPtr base = current_base_address.value_or(TRY(m_compilation_unit.base_address()).value_or(0)); callback({ base + begin, base + end }); } } diff --git a/Userland/Libraries/LibDebug/Dwarf/AttributeValue.cpp b/Userland/Libraries/LibDebug/Dwarf/AttributeValue.cpp index c81809f04f..966820b8c6 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AttributeValue.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/AttributeValue.cpp @@ -9,7 +9,7 @@ namespace Debug::Dwarf { -FlatPtr AttributeValue::as_addr() const +ErrorOr AttributeValue::as_addr() const { switch (m_form) { case AttributeDataForm::Addr: @@ -27,7 +27,7 @@ FlatPtr AttributeValue::as_addr() const } } -char const* AttributeValue::as_string() const +ErrorOr AttributeValue::as_string() const { switch (m_form) { case AttributeDataForm::String: diff --git a/Userland/Libraries/LibDebug/Dwarf/AttributeValue.h b/Userland/Libraries/LibDebug/Dwarf/AttributeValue.h index c46979c877..6e2e6fcfb1 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AttributeValue.h +++ b/Userland/Libraries/LibDebug/Dwarf/AttributeValue.h @@ -33,10 +33,10 @@ public: Type type() const { return m_type; } AttributeDataForm form() const { return m_form; } - FlatPtr as_addr() const; + ErrorOr as_addr() const; u64 as_unsigned() const { return m_data.as_unsigned; } i64 as_signed() const { return m_data.as_signed; } - char const* as_string() const; + ErrorOr as_string() const; bool as_bool() const { return m_data.as_bool; } ReadonlyBytes as_raw_bytes() const { return m_data.as_raw_bytes; } diff --git a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp index 7f206ad63a..fd74dea5b2 100644 --- a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp @@ -40,27 +40,27 @@ LineProgram const& CompilationUnit::line_program() const return *m_line_program; } -Optional CompilationUnit::base_address() const +ErrorOr> CompilationUnit::base_address() const { if (m_has_cached_base_address) return m_cached_base_address; auto die = root_die(); - auto res = die.get_attribute(Attribute::LowPc); + auto res = TRY(die.get_attribute(Attribute::LowPc)); if (res.has_value()) { - m_cached_base_address = res->as_addr(); + m_cached_base_address = TRY(res->as_addr()); } m_has_cached_base_address = true; return m_cached_base_address; } -u64 CompilationUnit::address_table_base() const +ErrorOr CompilationUnit::address_table_base() const { if (m_has_cached_address_table_base) return m_cached_address_table_base; auto die = root_die(); - auto res = die.get_attribute(Attribute::AddrBase); + auto res = TRY(die.get_attribute(Attribute::AddrBase)); if (res.has_value()) { VERIFY(res->form() == AttributeDataForm::SecOffset); m_cached_address_table_base = res->as_unsigned(); @@ -69,13 +69,13 @@ u64 CompilationUnit::address_table_base() const return m_cached_address_table_base; } -u64 CompilationUnit::string_offsets_base() const +ErrorOr CompilationUnit::string_offsets_base() const { if (m_has_cached_string_offsets_base) return m_cached_string_offsets_base; auto die = root_die(); - auto res = die.get_attribute(Attribute::StrOffsetsBase); + auto res = TRY(die.get_attribute(Attribute::StrOffsetsBase)); if (res.has_value()) { VERIFY(res->form() == AttributeDataForm::SecOffset); m_cached_string_offsets_base = res->as_unsigned(); @@ -84,13 +84,13 @@ u64 CompilationUnit::string_offsets_base() const return m_cached_string_offsets_base; } -u64 CompilationUnit::range_lists_base() const +ErrorOr CompilationUnit::range_lists_base() const { if (m_has_cached_range_lists_base) return m_cached_range_lists_base; auto die = root_die(); - auto res = die.get_attribute(Attribute::RngListsBase); + auto res = TRY(die.get_attribute(Attribute::RngListsBase)); if (res.has_value()) { VERIFY(res->form() == AttributeDataForm::SecOffset); m_cached_range_lists_base = res->as_unsigned(); @@ -99,9 +99,9 @@ u64 CompilationUnit::range_lists_base() const return m_cached_range_lists_base; } -FlatPtr CompilationUnit::get_address(size_t index) const +ErrorOr CompilationUnit::get_address(size_t index) const { - auto base = address_table_base(); + auto base = TRY(address_table_base()); auto debug_addr_data = dwarf_info().debug_addr_data(); VERIFY(base < debug_addr_data.size()); auto addresses = debug_addr_data.slice(base); @@ -111,9 +111,9 @@ FlatPtr CompilationUnit::get_address(size_t index) const return value; } -char const* CompilationUnit::get_string(size_t index) const +ErrorOr CompilationUnit::get_string(size_t index) const { - auto base = string_offsets_base(); + auto base = TRY(string_offsets_base()); auto debug_str_offsets_data = dwarf_info().debug_str_offsets_data(); VERIFY(base < debug_str_offsets_data.size()); // FIXME: This assumes DWARF32 diff --git a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h index e2157f2517..138f49c80d 100644 --- a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h +++ b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h @@ -31,22 +31,22 @@ public: DIE root_die() const; DIE get_die_at_offset(u32 offset) const; - FlatPtr get_address(size_t index) const; - char const* get_string(size_t index) const; + ErrorOr get_address(size_t index) const; + ErrorOr 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; - Optional base_address() const; + ErrorOr> base_address() const; // DW_AT_addr_base - u64 address_table_base() const; + ErrorOr address_table_base() const; // DW_AT_str_offsets_base - u64 string_offsets_base() const; + ErrorOr string_offsets_base() const; // DW_AT_rnglists_base - u64 range_lists_base() const; + ErrorOr range_lists_base() const; private: DwarfInfo const& m_dwarf_info; diff --git a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp index 1577d98fd7..5cfc8499e9 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp @@ -15,10 +15,10 @@ namespace Debug::Dwarf { DIE::DIE(CompilationUnit const& unit, u32 offset, Optional parent_offset) : m_compilation_unit(unit) { - rehydrate_from(offset, parent_offset); + rehydrate_from(offset, parent_offset).release_value_but_fixme_should_propagate_errors(); } -void DIE::rehydrate_from(u32 offset, Optional parent_offset) +ErrorOr DIE::rehydrate_from(u32 offset, Optional parent_offset) { m_offset = offset; @@ -39,14 +39,15 @@ void DIE::rehydrate_from(u32 offset, Optional parent_offset) // We iterate the attributes data only to calculate this DIE's size for (auto& attribute_spec : abbreviation_info->attribute_specifications) { - m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit); + TRY(m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit)); } } m_size = stream.offset() - m_offset; m_parent_offset = parent_offset; + return {}; } -Optional DIE::get_attribute(Attribute const& attribute) const +ErrorOr> DIE::get_attribute(Attribute const& attribute) const { InputMemoryStream stream { m_compilation_unit.dwarf_info().debug_info_data() }; stream.discard_or_error(m_data_offset); @@ -55,42 +56,45 @@ Optional DIE::get_attribute(Attribute const& attribute) const VERIFY(abbreviation_info); for (auto const& attribute_spec : abbreviation_info->attribute_specifications) { - auto value = m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit); + auto value = TRY(m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit)); if (attribute_spec.attribute == attribute) { return value; } } - return {}; + return Optional {}; } -void DIE::for_each_child(Function callback) const +ErrorOr DIE::for_each_child(Function(DIE const& child)> callback) const { if (!m_has_children) - return; + return {}; auto current_child = DIE(m_compilation_unit, m_offset + m_size, m_offset); while (true) { - callback(current_child); + TRY(callback(current_child)); if (current_child.is_null()) break; if (!current_child.has_children()) { - current_child.rehydrate_from(current_child.offset() + current_child.size(), m_offset); + TRY(current_child.rehydrate_from(current_child.offset() + current_child.size(), m_offset)); continue; } - auto sibling = current_child.get_attribute(Attribute::Sibling); + auto sibling = TRY(current_child.get_attribute(Attribute::Sibling)); u32 sibling_offset = 0; if (sibling.has_value()) { sibling_offset = sibling.value().as_unsigned(); } else { // NOTE: According to the spec, the compiler doesn't have to supply the sibling information. // When it doesn't, we have to recursively iterate the current child's children to find where they end - current_child.for_each_child([&](DIE const& sub_child) { + TRY(current_child.for_each_child([&](DIE const& sub_child) -> ErrorOr { sibling_offset = sub_child.offset() + sub_child.size(); - }); + return {}; + })); } - current_child.rehydrate_from(sibling_offset, m_offset); + TRY(current_child.rehydrate_from(sibling_offset, m_offset)); } + + return {}; } } diff --git a/Userland/Libraries/LibDebug/Dwarf/DIE.h b/Userland/Libraries/LibDebug/Dwarf/DIE.h index 2f0ef61b74..56d3819591 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DIE.h +++ b/Userland/Libraries/LibDebug/Dwarf/DIE.h @@ -27,16 +27,16 @@ public: bool has_children() const { return m_has_children; } EntryTag tag() const { return m_tag; } - Optional get_attribute(Attribute const&) const; + ErrorOr> get_attribute(Attribute const&) const; - void for_each_child(Function callback) const; + ErrorOr for_each_child(Function(DIE const& child)> callback) const; bool is_null() const { return m_tag == EntryTag::None; } CompilationUnit const& compilation_unit() const { return m_compilation_unit; } Optional parent_offset() const { return m_parent_offset; } private: - void rehydrate_from(u32 offset, Optional parent_offset); + ErrorOr rehydrate_from(u32 offset, Optional parent_offset); CompilationUnit const& m_compilation_unit; u32 m_offset { 0 }; u32 m_data_offset { 0 }; diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index 3c2fc212dd..a9a95e0487 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -29,7 +29,7 @@ DwarfInfo::DwarfInfo(ELF::Image const& elf) m_debug_addr_data = section_data(".debug_addr"sv); m_debug_ranges_data = section_data(".debug_ranges"sv); - populate_compilation_units(); + populate_compilation_units().release_value_but_fixme_should_propagate_errors(); } DwarfInfo::~DwarfInfo() = default; @@ -42,10 +42,10 @@ ReadonlyBytes DwarfInfo::section_data(StringView section_name) const return section->bytes(); } -void DwarfInfo::populate_compilation_units() +ErrorOr DwarfInfo::populate_compilation_units() { if (!m_debug_info_data.data()) - return; + return {}; InputMemoryStream debug_info_stream { m_debug_info_data }; InputMemoryStream line_info_stream { m_debug_line_data }; @@ -77,20 +77,22 @@ void DwarfInfo::populate_compilation_units() } VERIFY(line_info_stream.eof()); + return {}; } -AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, +ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, InputMemoryStream& debug_info_stream, CompilationUnit const* unit) const { AttributeValue value; value.m_form = form; value.m_compilation_unit = unit; - auto assign_raw_bytes_value = [&](size_t length) { + auto assign_raw_bytes_value = [&](size_t length) -> ErrorOr { value.m_data.as_raw_bytes = { debug_info_data().offset_pointer(debug_info_stream.offset()), length }; debug_info_stream.discard_or_error(length); VERIFY(!debug_info_stream.has_any_error()); + return {}; }; switch (form) { @@ -170,7 +172,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im } case AttributeDataForm::Data16: { value.m_type = AttributeValue::Type::RawBytes; - assign_raw_bytes_value(16); + TRY(assign_raw_bytes_value(16)); VERIFY(!debug_info_stream.has_any_error()); break; } @@ -193,7 +195,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im debug_info_stream.read_LEB128_unsigned(length); VERIFY(!debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::DwarfExpression; - assign_raw_bytes_value(length); + TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::String: { @@ -210,7 +212,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im u8 length; debug_info_stream >> length; VERIFY(!debug_info_stream.has_any_error()); - assign_raw_bytes_value(length); + TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block2: { @@ -218,7 +220,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im u16 length; debug_info_stream >> length; VERIFY(!debug_info_stream.has_any_error()); - assign_raw_bytes_value(length); + TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block4: { @@ -226,7 +228,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im u32 length; debug_info_stream >> length; VERIFY(!debug_info_stream.has_any_error()); - assign_raw_bytes_value(length); + TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block: { @@ -234,7 +236,7 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im size_t length; debug_info_stream.read_LEB128_unsigned(length); VERIFY(!debug_info_stream.has_any_error()); - assign_raw_bytes_value(length); + TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::LineStrP: { @@ -332,21 +334,21 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t im return value; } -void DwarfInfo::build_cached_dies() const +ErrorOr DwarfInfo::build_cached_dies() const { auto insert_to_cache = [this](DIE const& die, DIERange const& range) { m_cached_dies_by_range.insert(range.start_address, DIEAndRange { die, range }); m_cached_dies_by_offset.insert(die.offset(), die); }; auto get_ranges_of_die = [this](DIE const& die) -> ErrorOr> { - auto ranges = die.get_attribute(Attribute::Ranges); + auto ranges = TRY(die.get_attribute(Attribute::Ranges)); if (ranges.has_value()) { size_t offset; if (ranges->form() == AttributeDataForm::SecOffset) { offset = ranges->as_unsigned(); } else { auto index = ranges->as_unsigned(); - auto base = die.compilation_unit().range_lists_base(); + auto base = TRY(die.compilation_unit().range_lists_base()); // FIXME: This assumes that the format is DWARf32 auto offsets = debug_range_lists_data().slice(base); offset = ByteReader::load32(offsets.offset_pointer(index * sizeof(u32))) + base; @@ -371,8 +373,8 @@ void DwarfInfo::build_cached_dies() const return entries; } - auto start = die.get_attribute(Attribute::LowPc); - auto end = die.get_attribute(Attribute::HighPc); + auto start = TRY(die.get_attribute(Attribute::LowPc)); + auto end = TRY(die.get_attribute(Attribute::HighPc)); if (!start.has_value() || !end.has_value()) return Vector {}; @@ -384,40 +386,44 @@ void DwarfInfo::build_cached_dies() const uint32_t range_end = 0; if (end->form() == Dwarf::AttributeDataForm::Addr) - range_end = end->as_addr(); + range_end = TRY(end->as_addr()); else - range_end = start->as_addr() + end->as_unsigned(); + range_end = TRY(start->as_addr()) + end->as_unsigned(); - return Vector { DIERange { start.value().as_addr(), range_end } }; + return Vector { DIERange { TRY(start.value().as_addr()), range_end } }; }; // If we simply use a lambda, type deduction fails because it's used recursively. - Function insert_to_cache_recursively; - insert_to_cache_recursively = [&](DIE const& die) { + Function(DIE const& die)> insert_to_cache_recursively; + insert_to_cache_recursively = [&](DIE const& die) -> ErrorOr { if (die.offset() == 0 || die.parent_offset().has_value()) { - auto ranges = get_ranges_of_die(die).release_value_but_fixme_should_propagate_errors(); + auto ranges = TRY(get_ranges_of_die(die)); for (auto& range : ranges) { insert_to_cache(die, range); } } - die.for_each_child([&](DIE const& child) { + TRY(die.for_each_child([&](DIE const& child) -> ErrorOr { if (!child.is_null()) { - insert_to_cache_recursively(child); + TRY(insert_to_cache_recursively(child)); } - }); + return {}; + })); + return {}; }; - for_each_compilation_unit([&](CompilationUnit const& compilation_unit) { - insert_to_cache_recursively(compilation_unit.root_die()); - }); + TRY(for_each_compilation_unit([&](CompilationUnit const& compilation_unit) -> ErrorOr { + TRY(insert_to_cache_recursively(compilation_unit.root_die())); + return {}; + })); m_built_cached_dies = true; + return {}; } -Optional DwarfInfo::get_die_at_address(FlatPtr address) const +ErrorOr> DwarfInfo::get_die_at_address(FlatPtr address) const { if (!m_built_cached_dies) - build_cached_dies(); + TRY(build_cached_dies()); auto iter = m_cached_dies_by_range.find_largest_not_above_iterator(address); while (!iter.is_end() && !iter.is_begin() && iter->range.end_address < address) { @@ -425,23 +431,23 @@ Optional DwarfInfo::get_die_at_address(FlatPtr address) const } if (iter.is_end()) - return {}; + return Optional {}; if (iter->range.start_address > address || iter->range.end_address < address) { - return {}; + return Optional {}; } return iter->die; } -Optional DwarfInfo::get_cached_die_at_offset(FlatPtr offset) const +ErrorOr> DwarfInfo::get_cached_die_at_offset(FlatPtr offset) const { if (!m_built_cached_dies) - build_cached_dies(); + TRY(build_cached_dies()); auto* die = m_cached_dies_by_offset.find(offset); if (!die) - return {}; + return Optional {}; return *die; } diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h index 2298bdc7b4..0834e74954 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -39,23 +39,23 @@ public: ReadonlyBytes debug_ranges_data() const { return m_debug_ranges_data; } template - void for_each_compilation_unit(Callback) const; + ErrorOr for_each_compilation_unit(Callback) const; - AttributeValue get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, + ErrorOr get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, InputMemoryStream& debug_info_stream, CompilationUnit const* unit = nullptr) const; - Optional get_die_at_address(FlatPtr) const; + ErrorOr> get_die_at_address(FlatPtr) const; // Note that even if there is a DIE at the given offset, // but it does not exist in the DIE cache (because for example // it does not contain an address range), then this function will not return it. // To get any DIE object at a given offset in a compilation unit, // use CompilationUnit::get_die_at_offset. - Optional get_cached_die_at_offset(FlatPtr) const; + ErrorOr> get_cached_die_at_offset(FlatPtr) const; private: - void populate_compilation_units(); - void build_cached_dies() const; + ErrorOr populate_compilation_units(); + ErrorOr build_cached_dies() const; ReadonlyBytes section_data(StringView section_name) const; @@ -90,11 +90,12 @@ private: }; template -void DwarfInfo::for_each_compilation_unit(Callback callback) const +ErrorOr DwarfInfo::for_each_compilation_unit(Callback callback) const { for (auto const& unit : m_compilation_units) { - callback(unit); + TRY(callback(unit)); } + return {}; } } diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp index fd2d02a680..d3981799d5 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp @@ -18,13 +18,13 @@ LineProgram::LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream) , m_stream(stream) { m_unit_offset = m_stream.offset(); - parse_unit_header(); - parse_source_directories(); - parse_source_files(); - run_program(); + parse_unit_header().release_value_but_fixme_should_propagate_errors(); + parse_source_directories().release_value_but_fixme_should_propagate_errors(); + parse_source_files().release_value_but_fixme_should_propagate_errors(); + run_program().release_value_but_fixme_should_propagate_errors(); } -void LineProgram::parse_unit_header() +ErrorOr LineProgram::parse_unit_header() { m_stream >> m_unit_header; @@ -32,9 +32,10 @@ void LineProgram::parse_unit_header() VERIFY(m_unit_header.opcode_base() <= sizeof(m_unit_header.std_opcode_lengths) / sizeof(m_unit_header.std_opcode_lengths[0]) + 1); dbgln_if(DWARF_DEBUG, "unit length: {}", m_unit_header.length()); + return {}; } -void LineProgram::parse_path_entries(Function callback, PathListType list_type) +ErrorOr LineProgram::parse_path_entries(Function callback, PathListType list_type) { if (m_unit_header.version() >= 5) { u8 path_entry_format_count = 0; @@ -58,10 +59,10 @@ void LineProgram::parse_path_entries(Function callback, for (size_t i = 0; i < paths_count; i++) { PathEntry entry; for (auto& format_description : format_descriptions) { - auto value = m_dwarf_info.get_attribute_value(format_description.form, 0, m_stream); + auto value = TRY(m_dwarf_info.get_attribute_value(format_description.form, 0, m_stream)); switch (format_description.type) { case ContentType::Path: - entry.path = value.as_string(); + entry.path = TRY(value.as_string()); break; case ContentType::DirectoryIndex: entry.directory_index = value.as_unsigned(); @@ -96,30 +97,35 @@ void LineProgram::parse_path_entries(Function callback, } VERIFY(!m_stream.has_any_error()); + return {}; } -void LineProgram::parse_source_directories() +ErrorOr LineProgram::parse_source_directories() { if (m_unit_header.version() < 5) { m_source_directories.append("."); } - parse_path_entries([this](PathEntry& entry) { + TRY(parse_path_entries([this](PathEntry& entry) { m_source_directories.append(entry.path); }, - PathListType::Directories); + PathListType::Directories)); + + return {}; } -void LineProgram::parse_source_files() +ErrorOr LineProgram::parse_source_files() { if (m_unit_header.version() < 5) { m_source_files.append({ ".", 0 }); } - parse_path_entries([this](PathEntry& entry) { + TRY(parse_path_entries([this](PathEntry& entry) { m_source_files.append({ entry.path, entry.directory_index }); }, - PathListType::Filenames); + PathListType::Filenames)); + + return {}; } void LineProgram::append_to_line_info() @@ -149,7 +155,7 @@ void LineProgram::reset_registers() m_is_statement = m_unit_header.default_is_stmt() == 1; } -void LineProgram::handle_extended_opcode() +ErrorOr LineProgram::handle_extended_opcode() { size_t length = 0; m_stream.read_LEB128_unsigned(length); @@ -179,8 +185,10 @@ void LineProgram::handle_extended_opcode() dbgln("Encountered unknown sub opcode {} at stream offset {:p}", sub_opcode, m_stream.offset()); VERIFY_NOT_REACHED(); } + + return {}; } -void LineProgram::handle_standard_opcode(u8 opcode) +ErrorOr LineProgram::handle_standard_opcode(u8 opcode) { switch (opcode) { case StandardOpcodes::Copy: { @@ -256,6 +264,8 @@ void LineProgram::handle_standard_opcode(u8 opcode) dbgln("Unhandled LineProgram opcode {}", opcode); VERIFY_NOT_REACHED(); } + + return {}; } void LineProgram::handle_special_opcode(u8 opcode) { @@ -277,7 +287,7 @@ void LineProgram::handle_special_opcode(u8 opcode) m_prologue_end = false; } -void LineProgram::run_program() +ErrorOr LineProgram::run_program() { reset_registers(); @@ -288,13 +298,15 @@ void LineProgram::run_program() dbgln_if(DWARF_DEBUG, "{:p}: opcode: {}", m_stream.offset() - 1, opcode); if (opcode == 0) { - handle_extended_opcode(); + TRY(handle_extended_opcode()); } else if (opcode >= 1 && opcode <= 12) { - handle_standard_opcode(opcode); + TRY(handle_standard_opcode(opcode)); } else { handle_special_opcode(opcode); } } + + return {}; } LineProgram::DirectoryAndFile LineProgram::get_directory_and_file(size_t file_index) const diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.h b/Userland/Libraries/LibDebug/Dwarf/LineProgram.h index a0d7038d25..4a1847d8f9 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.h +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.h @@ -133,19 +133,19 @@ public: bool looks_like_embedded_resource() const; private: - void parse_unit_header(); - void parse_source_directories(); - void parse_source_files(); - void run_program(); + ErrorOr parse_unit_header(); + ErrorOr parse_source_directories(); + ErrorOr parse_source_files(); + ErrorOr run_program(); void append_to_line_info(); void reset_registers(); - void handle_extended_opcode(); - void handle_standard_opcode(u8 opcode); + ErrorOr handle_extended_opcode(); + ErrorOr handle_standard_opcode(u8 opcode); void handle_special_opcode(u8 opcode); - void parse_path_entries(Function callback, PathListType list_type); + ErrorOr parse_path_entries(Function callback, PathListType list_type); enum StandardOpcodes { Copy = 1, diff --git a/Userland/Libraries/LibSymbolication/Symbolication.cpp b/Userland/Libraries/LibSymbolication/Symbolication.cpp index 181677f419..a187b78a90 100644 --- a/Userland/Libraries/LibSymbolication/Symbolication.cpp +++ b/Userland/Libraries/LibSymbolication/Symbolication.cpp @@ -105,7 +105,7 @@ Optional symbolicate(DeprecatedString const& path, FlatPtr address, Incl Vector positions; if (include_source_positions == IncludeSourcePosition::Yes) { - auto source_position_with_inlines = cached_elf->debug_info->get_source_position_with_inlines(address); + auto source_position_with_inlines = cached_elf->debug_info->get_source_position_with_inlines(address).release_value_but_fixme_should_propagate_errors(); for (auto& position : source_position_with_inlines.inline_chain) { if (!positions.contains_slow(position))