diff --git a/Userland/Libraries/LibDebug/DebugInfo.cpp b/Userland/Libraries/LibDebug/DebugInfo.cpp index 5a78253c9e..d1c69120fe 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.cpp +++ b/Userland/Libraries/LibDebug/DebugInfo.cpp @@ -7,7 +7,6 @@ #include "DebugInfo.h" #include #include -#include #include #include #include diff --git a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.h b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.h index cb440832c2..6439d42bd4 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AddressRanges.h +++ b/Userland/Libraries/LibDebug/Dwarf/AddressRanges.h @@ -9,7 +9,6 @@ #include "CompilationUnit.h" #include #include -#include #include #include diff --git a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp index 5cfc8499e9..29aee09a5d 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp @@ -8,7 +8,8 @@ #include "CompilationUnit.h" #include "DwarfInfo.h" #include -#include +#include +#include namespace Debug::Dwarf { @@ -22,10 +23,12 @@ ErrorOr DIE::rehydrate_from(u32 offset, Optional parent_offset) { m_offset = offset; - InputMemoryStream stream(m_compilation_unit.dwarf_info().debug_info_data()); - stream.discard_or_error(m_offset); - stream.read_LEB128_unsigned(m_abbreviation_code); - m_data_offset = stream.offset(); + auto stream = TRY(Core::Stream::FixedMemoryStream::construct(m_compilation_unit.dwarf_info().debug_info_data())); + // Note: We can't just slice away from the input data here, since get_attribute_value will try to recover the original offset using seek(). + TRY(stream->seek(m_offset)); + Core::Stream::WrapInAKInputStream wrapped_stream { *stream }; + LEB128::read_unsigned(wrapped_stream, m_abbreviation_code); + m_data_offset = TRY(stream->tell()); if (m_abbreviation_code == 0) { // An abbreviation code of 0 ( = null DIE entry) means the end of a chain of siblings @@ -39,24 +42,25 @@ ErrorOr 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) { - TRY(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_size = TRY(stream->tell()) - m_offset; m_parent_offset = parent_offset; return {}; } 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); + auto stream = TRY(Core::Stream::FixedMemoryStream::construct(m_compilation_unit.dwarf_info().debug_info_data())); + // Note: We can't just slice away from the input data here, since get_attribute_value will try to recover the original offset using seek(). + TRY(stream->seek(m_data_offset)); auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code); VERIFY(abbreviation_info); for (auto const& attribute_spec : abbreviation_info->attribute_specifications) { - auto value = TRY(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; } diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index a9a95e0487..eecfa2d0b3 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -10,7 +10,7 @@ #include "CompilationUnit.h" #include -#include +#include #include #include @@ -47,59 +47,54 @@ ErrorOr DwarfInfo::populate_compilation_units() if (!m_debug_info_data.data()) return {}; - InputMemoryStream debug_info_stream { m_debug_info_data }; - InputMemoryStream line_info_stream { m_debug_line_data }; + auto debug_info_stream = TRY(Core::Stream::FixedMemoryStream::construct(m_debug_info_data)); + auto line_info_stream = TRY(Core::Stream::FixedMemoryStream::construct(m_debug_line_data)); - while (!debug_info_stream.eof()) { - auto unit_offset = debug_info_stream.offset(); - CompilationUnitHeader compilation_unit_header {}; + while (!debug_info_stream->is_eof()) { + auto unit_offset = TRY(debug_info_stream->tell()); - debug_info_stream >> compilation_unit_header; + auto compilation_unit_header = TRY(CompilationUnitHeader::read_from_stream(*debug_info_stream)); VERIFY(compilation_unit_header.common.version <= 5); 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)); - auto line_program = make(*this, line_info_stream); + auto line_program = make(*this, *line_info_stream); // HACK: Clang generates line programs for embedded resource assembly files, but not compile units. // Meaning that for graphical applications, some line info data would be unread, triggering the assertion below. // As a fix, we don't create compilation units for line programs that come from resource files. #if defined(AK_COMPILER_CLANG) if (line_program->looks_like_embedded_resource()) { - debug_info_stream.seek(unit_offset); + TRY(debug_info_stream->seek(unit_offset)); } else #endif { m_compilation_units.append(make(*this, unit_offset, compilation_unit_header, move(line_program))); - debug_info_stream.discard_or_error(length_after_header); + TRY(debug_info_stream->discard(length_after_header)); } } - VERIFY(line_info_stream.eof()); + VERIFY(line_info_stream->is_eof()); return {}; } ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, - InputMemoryStream& debug_info_stream, CompilationUnit const* unit) const + Core::Stream::SeekableStream& 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) -> 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()); + value.m_data.as_raw_bytes = { debug_info_data().offset_pointer(TRY(debug_info_stream.tell())), length }; + TRY(debug_info_stream.discard(length)); return {}; }; switch (form) { case AttributeDataForm::StringPointer: { - u32 offset; - debug_info_stream >> offset; - VERIFY(!debug_info_stream.has_any_error()); + auto offset = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::String; auto strings_data = debug_strings_data(); @@ -107,65 +102,55 @@ ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::Data1: { - u8 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = data; break; } case AttributeDataForm::Data2: { - u16 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_signed = data; break; } case AttributeDataForm::Addr: { - FlatPtr address; - debug_info_stream >> address; - VERIFY(!debug_info_stream.has_any_error()); + auto address = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::Address; value.m_data.as_addr = address; break; } case AttributeDataForm::SData: { i64 data; - debug_info_stream.read_LEB128_signed(data); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_signed(wrapped_debug_info_stream, data); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::SignedNumber; value.m_data.as_signed = data; break; } case AttributeDataForm::UData: { u64 data; - debug_info_stream.read_LEB128_unsigned(data); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, data); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = data; break; } case AttributeDataForm::SecOffset: { - u32 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::SecOffset; value.m_data.as_unsigned = data; break; } case AttributeDataForm::Data4: { - u32 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = data; break; } case AttributeDataForm::Data8: { - u64 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = data; break; @@ -173,13 +158,10 @@ ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, s case AttributeDataForm::Data16: { value.m_type = AttributeValue::Type::RawBytes; TRY(assign_raw_bytes_value(16)); - VERIFY(!debug_info_stream.has_any_error()); break; } case AttributeDataForm::Ref4: { - u32 data; - debug_info_stream >> data; - VERIFY(!debug_info_stream.has_any_error()); + auto data = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::DieReference; VERIFY(unit); value.m_data.as_unsigned = data + unit->offset(); @@ -192,57 +174,49 @@ ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, s } case AttributeDataForm::ExprLoc: { size_t length; - debug_info_stream.read_LEB128_unsigned(length); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, length); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::DwarfExpression; TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::String: { - DeprecatedString str; - u32 str_offset = debug_info_stream.offset(); - debug_info_stream >> str; - VERIFY(!debug_info_stream.has_any_error()); + u32 str_offset = TRY(debug_info_stream.tell()); value.m_type = AttributeValue::Type::String; value.m_data.as_string = bit_cast(debug_info_data().offset_pointer(str_offset)); + TRY(debug_info_stream.discard(strlen(value.m_data.as_string) + 1)); break; } case AttributeDataForm::Block1: { value.m_type = AttributeValue::Type::RawBytes; - u8 length; - debug_info_stream >> length; - VERIFY(!debug_info_stream.has_any_error()); + auto length = TRY(debug_info_stream.read_value()); TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block2: { value.m_type = AttributeValue::Type::RawBytes; - u16 length; - debug_info_stream >> length; - VERIFY(!debug_info_stream.has_any_error()); + auto length = TRY(debug_info_stream.read_value()); TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block4: { value.m_type = AttributeValue::Type::RawBytes; - u32 length; - debug_info_stream >> length; - VERIFY(!debug_info_stream.has_any_error()); + auto length = TRY(debug_info_stream.read_value()); TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::Block: { value.m_type = AttributeValue::Type::RawBytes; size_t length; - debug_info_stream.read_LEB128_unsigned(length); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, length); + VERIFY(!wrapped_debug_info_stream.has_any_error()); TRY(assign_raw_bytes_value(length)); break; } case AttributeDataForm::LineStrP: { - u32 offset; - debug_info_stream >> offset; - VERIFY(!debug_info_stream.has_any_error()); + auto offset = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::String; auto strings_data = debug_line_strings_data(); @@ -256,73 +230,64 @@ ErrorOr DwarfInfo::get_attribute_value(AttributeDataForm form, s break; } case AttributeDataForm::StrX1: { - u8 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::String; value.m_data.as_unsigned = index; break; } case AttributeDataForm::StrX2: { - u16 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::String; value.m_data.as_unsigned = index; break; } case AttributeDataForm::StrX4: { - u32 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::String; value.m_data.as_unsigned = index; break; } case AttributeDataForm::StrX: { size_t index; - debug_info_stream.read_LEB128_unsigned(index); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, index); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::String; value.m_data.as_unsigned = index; break; } case AttributeDataForm::AddrX1: { - u8 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::Address; value.m_data.as_unsigned = index; break; } case AttributeDataForm::AddrX2: { - u16 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::Address; value.m_data.as_unsigned = index; break; } case AttributeDataForm::AddrX4: { - u32 index; - debug_info_stream >> index; - VERIFY(!debug_info_stream.has_any_error()); + auto index = TRY(debug_info_stream.read_value()); value.m_type = AttributeValue::Type::Address; value.m_data.as_unsigned = index; break; } case AttributeDataForm::AddrX: { size_t index; - debug_info_stream.read_LEB128_unsigned(index); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, index); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::Address; value.m_data.as_unsigned = index; break; } case AttributeDataForm::RngListX: { size_t index; - debug_info_stream.read_LEB128_unsigned(index); - VERIFY(!debug_info_stream.has_any_error()); + Core::Stream::WrapInAKInputStream wrapped_debug_info_stream { debug_info_stream }; + LEB128::read_unsigned(wrapped_debug_info_stream, index); + VERIFY(!wrapped_debug_info_stream.has_any_error()); value.m_type = AttributeValue::Type::UnsignedNumber; value.m_data.as_unsigned = index; break; diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h index 0834e74954..48282f20d7 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,7 @@ public: ErrorOr for_each_compilation_unit(Callback) const; ErrorOr get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, - InputMemoryStream& debug_info_stream, CompilationUnit const* unit = nullptr) const; + Core::Stream::SeekableStream& debug_info_stream, CompilationUnit const* unit = nullptr) const; ErrorOr> get_die_at_address(FlatPtr) const; diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h index 8d10f1d215..44257995e4 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h @@ -6,8 +6,8 @@ #pragma once -#include #include +#include namespace Debug::Dwarf { @@ -53,17 +53,18 @@ struct [[gnu::packed]] CompilationUnitHeader { } u32 abbrev_offset() const { return (common.version <= 4) ? v4.abbrev_offset : v5.abbrev_offset; } u8 address_size() const { return (common.version <= 4) ? v4.address_size : v5.address_size; } -}; -inline InputStream& operator>>(InputStream& stream, CompilationUnitHeader& header) -{ - stream.read_or_error(Bytes { &header.common, sizeof(header.common) }); - if (header.common.version <= 4) - stream.read_or_error(Bytes { &header.v4, sizeof(header.v4) }); - else - stream.read_or_error(Bytes { &header.v5, sizeof(header.v5) }); - return stream; -} + static ErrorOr read_from_stream(Core::Stream::Stream& stream) + { + CompilationUnitHeader header; + TRY(stream.read_entire_buffer(Bytes { &header.common, sizeof(header.common) })); + if (header.common.version <= 4) + TRY(stream.read_entire_buffer(Bytes { &header.v4, sizeof(header.v4) })); + else + TRY(stream.read_entire_buffer(Bytes { &header.v5, sizeof(header.v5) })); + return header; + } +}; enum class EntryTag : u16 { None = 0, diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp index d3981799d5..12d0fa4c5d 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp @@ -8,16 +8,17 @@ #include #include #include +#include #include #include namespace Debug::Dwarf { -LineProgram::LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream) +LineProgram::LineProgram(DwarfInfo& dwarf_info, Core::Stream::SeekableStream& stream) : m_dwarf_info(dwarf_info) , m_stream(stream) { - m_unit_offset = m_stream.offset(); + m_unit_offset = m_stream.tell().release_value_but_fixme_should_propagate_errors(); 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(); @@ -26,7 +27,7 @@ LineProgram::LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream) ErrorOr LineProgram::parse_unit_header() { - m_stream >> m_unit_header; + m_unit_header = TRY(LineProgramUnitHeader32::read_from_stream(m_stream)); VERIFY(m_unit_header.version() >= MIN_DWARF_VERSION && m_unit_header.version() <= MAX_DWARF_VERSION); VERIFY(m_unit_header.opcode_base() <= sizeof(m_unit_header.std_opcode_lengths) / sizeof(m_unit_header.std_opcode_lengths[0]) + 1); @@ -37,24 +38,25 @@ ErrorOr LineProgram::parse_unit_header() ErrorOr LineProgram::parse_path_entries(Function callback, PathListType list_type) { + Core::Stream::WrapInAKInputStream wrapped_stream { m_stream }; + if (m_unit_header.version() >= 5) { - u8 path_entry_format_count = 0; - m_stream >> path_entry_format_count; + auto path_entry_format_count = TRY(m_stream.read_value()); Vector format_descriptions; for (u8 i = 0; i < path_entry_format_count; i++) { UnderlyingType content_type; - m_stream.read_LEB128_unsigned(content_type); + LEB128::read_unsigned(wrapped_stream, content_type); UnderlyingType data_form; - m_stream.read_LEB128_unsigned(data_form); + LEB128::read_unsigned(wrapped_stream, data_form); format_descriptions.empend(static_cast(content_type), static_cast(data_form)); } size_t paths_count = 0; - m_stream.read_LEB128_unsigned(paths_count); + LEB128::read_unsigned(wrapped_stream, paths_count); for (size_t i = 0; i < paths_count; i++) { PathEntry entry; @@ -74,29 +76,30 @@ ErrorOr LineProgram::parse_path_entries(Function c callback(entry); } } else { - while (m_stream.peek_or_error()) { - DeprecatedString path; - m_stream >> path; + while (true) { + StringBuilder builder; + while (auto c = TRY(m_stream.read_value())) + TRY(builder.try_append(c)); + auto path = builder.to_deprecated_string(); + if (path.length() == 0) + break; dbgln_if(DWARF_DEBUG, "path: {}", path); PathEntry entry; entry.path = path; if (list_type == PathListType::Filenames) { size_t directory_index = 0; - m_stream.read_LEB128_unsigned(directory_index); + LEB128::read_unsigned(wrapped_stream, directory_index); size_t _unused = 0; - m_stream.read_LEB128_unsigned(_unused); // skip modification time - m_stream.read_LEB128_unsigned(_unused); // skip file size + LEB128::read_unsigned(wrapped_stream, _unused); // skip modification time + LEB128::read_unsigned(wrapped_stream, _unused); // skip file size entry.directory_index = directory_index; dbgln_if(DWARF_DEBUG, "file: {}, directory index: {}", path, directory_index); } callback(entry); } - - m_stream.handle_recoverable_error(); - m_stream.discard_or_error(1); } - VERIFY(!m_stream.has_any_error()); + VERIFY(!wrapped_stream.has_any_error()); return {}; } @@ -157,11 +160,13 @@ void LineProgram::reset_registers() ErrorOr LineProgram::handle_extended_opcode() { - size_t length = 0; - m_stream.read_LEB128_unsigned(length); + Core::Stream::WrapInAKInputStream wrapped_stream { m_stream }; - u8 sub_opcode = 0; - m_stream >> sub_opcode; + size_t length = 0; + LEB128::read_unsigned(wrapped_stream, length); + TRY(wrapped_stream.try_handle_any_error()); + + auto sub_opcode = TRY(m_stream.read_value()); switch (sub_opcode) { case ExtendedOpcodes::EndSequence: { @@ -171,18 +176,19 @@ ErrorOr LineProgram::handle_extended_opcode() } case ExtendedOpcodes::SetAddress: { VERIFY(length == sizeof(size_t) + 1); - m_stream >> m_address; + m_address = TRY(m_stream.read_value()); dbgln_if(DWARF_DEBUG, "SetAddress: {:p}", m_address); break; } case ExtendedOpcodes::SetDiscriminator: { dbgln_if(DWARF_DEBUG, "SetDiscriminator"); size_t discriminator; - m_stream.read_LEB128_unsigned(discriminator); + LEB128::read_unsigned(wrapped_stream, discriminator); + TRY(wrapped_stream.try_handle_any_error()); break; } default: - dbgln("Encountered unknown sub opcode {} at stream offset {:p}", sub_opcode, m_stream.offset()); + dbgln("Encountered unknown sub opcode {} at stream offset {:p}", sub_opcode, TRY(m_stream.tell())); VERIFY_NOT_REACHED(); } @@ -190,6 +196,8 @@ ErrorOr LineProgram::handle_extended_opcode() } ErrorOr LineProgram::handle_standard_opcode(u8 opcode) { + Core::Stream::WrapInAKInputStream wrapped_stream { m_stream }; + switch (opcode) { case StandardOpcodes::Copy: { append_to_line_info(); @@ -197,7 +205,8 @@ ErrorOr LineProgram::handle_standard_opcode(u8 opcode) } case StandardOpcodes::AdvancePc: { size_t operand = 0; - m_stream.read_LEB128_unsigned(operand); + LEB128::read_unsigned(wrapped_stream, operand); + TRY(wrapped_stream.try_handle_any_error()); size_t delta = operand * m_unit_header.min_instruction_length(); dbgln_if(DWARF_DEBUG, "AdvancePC by: {} to: {:p}", delta, m_address + delta); m_address += delta; @@ -205,7 +214,8 @@ ErrorOr LineProgram::handle_standard_opcode(u8 opcode) } case StandardOpcodes::SetFile: { size_t new_file_index = 0; - m_stream.read_LEB128_unsigned(new_file_index); + LEB128::read_unsigned(wrapped_stream, new_file_index); + TRY(wrapped_stream.try_handle_any_error()); dbgln_if(DWARF_DEBUG, "SetFile: new file index: {}", new_file_index); m_file_index = new_file_index; break; @@ -214,13 +224,15 @@ ErrorOr LineProgram::handle_standard_opcode(u8 opcode) // not implemented dbgln_if(DWARF_DEBUG, "SetColumn"); size_t new_column; - m_stream.read_LEB128_unsigned(new_column); + LEB128::read_unsigned(wrapped_stream, new_column); + TRY(wrapped_stream.try_handle_any_error()); break; } case StandardOpcodes::AdvanceLine: { ssize_t line_delta; - m_stream.read_LEB128_signed(line_delta); + LEB128::read_signed(wrapped_stream, line_delta); + TRY(wrapped_stream.try_handle_any_error()); VERIFY(line_delta >= 0 || m_line >= (size_t)(-line_delta)); m_line += line_delta; dbgln_if(DWARF_DEBUG, "AdvanceLine: {}", m_line); @@ -241,13 +253,13 @@ ErrorOr LineProgram::handle_standard_opcode(u8 opcode) } case StandardOpcodes::SetIsa: { size_t isa; - m_stream.read_LEB128_unsigned(isa); + LEB128::read_unsigned(wrapped_stream, isa); + TRY(wrapped_stream.try_handle_any_error()); dbgln_if(DWARF_DEBUG, "SetIsa: {}", isa); break; } case StandardOpcodes::FixAdvancePc: { - u16 delta = 0; - m_stream >> delta; + auto delta = TRY(m_stream.read_value()); dbgln_if(DWARF_DEBUG, "FixAdvancePC by: {} to: {:p}", delta, m_address + delta); m_address += delta; break; @@ -291,11 +303,10 @@ ErrorOr LineProgram::run_program() { reset_registers(); - while (m_stream.offset() < m_unit_offset + sizeof(u32) + m_unit_header.length()) { - u8 opcode = 0; - m_stream >> opcode; + while (TRY(m_stream.tell()) < m_unit_offset + sizeof(u32) + m_unit_header.length()) { + auto opcode = TRY(m_stream.read_value()); - dbgln_if(DWARF_DEBUG, "{:p}: opcode: {}", m_stream.offset() - 1, opcode); + dbgln_if(DWARF_DEBUG, "{:p}: opcode: {}", TRY(m_stream.tell()) - 1, opcode); if (opcode == 0) { TRY(handle_extended_opcode()); diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.h b/Userland/Libraries/LibDebug/Dwarf/LineProgram.h index 4a1847d8f9..b12a206f9e 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.h +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.h @@ -7,8 +7,8 @@ #pragma once #include -#include #include +#include #include namespace Debug::Dwarf { @@ -65,6 +65,18 @@ struct [[gnu::packed]] LineProgramUnitHeader32 { i8 line_base() const { return (common.version <= 4) ? v4.line_base : v5.line_base; } u8 line_range() const { return (common.version <= 4) ? v4.line_range : v5.line_range; } u8 opcode_base() const { return (common.version <= 4) ? v4.opcode_base : v5.opcode_base; } + + static ErrorOr read_from_stream(Core::Stream::Stream& stream) + { + LineProgramUnitHeader32 header; + TRY(stream.read_entire_buffer(Bytes { &header.common, sizeof(header.common) })); + if (header.common.version <= 4) + TRY(stream.read_entire_buffer(Bytes { &header.v4, sizeof(header.v4) })); + else + TRY(stream.read_entire_buffer(Bytes { &header.v5, sizeof(header.v5) })); + TRY(stream.read_entire_buffer(Bytes { &header.std_opcode_lengths, min(sizeof(header.std_opcode_lengths), (header.opcode_base() - 1) * sizeof(header.std_opcode_lengths[0])) })); + return header; + } }; enum class ContentType { @@ -92,23 +104,12 @@ enum class PathListType { Filenames, }; -inline InputStream& operator>>(InputStream& stream, LineProgramUnitHeader32& header) -{ - stream.read_or_error(Bytes { &header.common, sizeof(header.common) }); - if (header.common.version <= 4) - stream.read_or_error(Bytes { &header.v4, sizeof(header.v4) }); - else - stream.read_or_error(Bytes { &header.v5, sizeof(header.v5) }); - stream.read_or_error(Bytes { &header.std_opcode_lengths, min(sizeof(header.std_opcode_lengths), (header.opcode_base() - 1) * sizeof(header.std_opcode_lengths[0])) }); - return stream; -} - class LineProgram { AK_MAKE_NONCOPYABLE(LineProgram); AK_MAKE_NONMOVABLE(LineProgram); public: - explicit LineProgram(DwarfInfo& dwarf_info, InputMemoryStream& stream); + explicit LineProgram(DwarfInfo& dwarf_info, Core::Stream::SeekableStream& stream); struct LineInfo { FlatPtr address { 0 }; @@ -173,7 +174,7 @@ private: static constexpr u16 MAX_DWARF_VERSION = 5; DwarfInfo& m_dwarf_info; - InputMemoryStream& m_stream; + Core::Stream::SeekableStream& m_stream; size_t m_unit_offset { 0 }; LineProgramUnitHeader32 m_unit_header {};