diff --git a/AK/BufferStream.h b/AK/BufferStream.h index b39b88339c..ca07dd102b 100644 --- a/AK/BufferStream.h +++ b/AK/BufferStream.h @@ -352,50 +352,6 @@ public: return *this; } - // LEB128 is a variable-length encoding for integers - BufferStream& read_LEB128_unsigned(size_t& result) - { - result = 0; - size_t num_bytes = 0; - while (true) { - if (m_offset > m_buffer.size()) { - m_read_failure = true; - break; - } - const u8 byte = m_buffer[m_offset]; - result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); - ++m_offset; - if (!(byte & (1 << 7))) - break; - ++num_bytes; - } - - return *this; - } - - // LEB128 is a variable-length encoding for integers - BufferStream& read_LEB128_signed(ssize_t& result) - { - result = 0; - size_t num_bytes = 0; - u8 byte = 0; - do { - if (m_offset > m_buffer.size()) { - m_read_failure = true; - break; - } - byte = m_buffer[m_offset]; - result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); - ++m_offset; - ++num_bytes; - } while (byte & (1 << 7)); - if (num_bytes * 7 < sizeof(size_t) * 4 && (byte & 0x40)) { - // sign extend - result |= ((size_t)(-1) << (num_bytes * 7)); - } - return *this; - } - BufferStream& advance(size_t amount) { if (m_offset + amount > m_buffer.size()) { diff --git a/AK/Stream.h b/AK/Stream.h index 6875578683..7a59b9b551 100644 --- a/AK/Stream.h +++ b/AK/Stream.h @@ -154,6 +154,67 @@ public: return m_bytes[m_offset]; } + // FIXME: Duplicated from AK::BufferStream::read_LEB128_unsigned. + // LEB128 is a variable-length encoding for integers + bool read_LEB128_unsigned(size_t& result) + { + const auto backup = m_offset; + + result = 0; + size_t num_bytes = 0; + while (true) { + // Note. The implementation in AK::BufferStream::read_LEB128_unsigned read one + // past the end, this is fixed here. + if (eof()) { + m_offset = backup; + m_error = true; + return false; + } + + const u8 byte = m_bytes[m_offset]; + result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); + ++m_offset; + if (!(byte & (1 << 7))) + break; + ++num_bytes; + } + + return true; + } + + // FIXME: Duplicated from AK::BufferStream::read_LEB128_signed. + // LEB128 is a variable-length encoding for integers + bool read_LEB128_signed(ssize_t& result) + { + const auto backup = m_offset; + + result = 0; + size_t num_bytes = 0; + u8 byte = 0; + + do { + // Note. The implementation in AK::BufferStream::read_LEB128_unsigned read one + // past the end, this is fixed here. + if (eof()) { + m_offset = backup; + m_error = true; + return false; + } + + byte = m_bytes[m_offset]; + result = (result) | (static_cast(byte & ~(1 << 7)) << (num_bytes * 7)); + ++m_offset; + ++num_bytes; + } while (byte & (1 << 7)); + + if (num_bytes * 7 < sizeof(size_t) * 4 && (byte & 0x40)) { + // sign extend + result |= ((size_t)(-1) << (num_bytes * 7)); + } + + return true; + } + ReadonlyBytes bytes() const { return m_bytes; } size_t offset() const { return m_offset; } size_t remaining() const { return m_bytes.size() - m_offset; } diff --git a/Libraries/LibDebug/DebugInfo.cpp b/Libraries/LibDebug/DebugInfo.cpp index bd6755f66e..16ee6131e4 100644 --- a/Libraries/LibDebug/DebugInfo.cpp +++ b/Libraries/LibDebug/DebugInfo.cpp @@ -26,6 +26,7 @@ #include "DebugInfo.h" #include +#include #include #include #include @@ -104,10 +105,10 @@ void DebugInfo::prepare_lines() return; auto buffer = section.wrapping_byte_buffer(); - BufferStream stream(buffer); + InputMemoryStream stream { buffer.span() }; Vector all_lines; - while (!stream.at_end()) { + while (!stream.eof()) { LineProgram program(stream); all_lines.append(program.lines()); } @@ -204,7 +205,7 @@ static void parse_variable_location(const Dwarf::DIE& variable_die, DebugInfo::V } if (location_info.value().type == Dwarf::DIE::AttributeValue::Type::DwarfExpression) { - auto expression_bytes = ByteBuffer::wrap(location_info.value().data.as_raw_bytes.bytes, location_info.value().data.as_raw_bytes.length); + auto expression_bytes = ReadonlyBytes { location_info.value().data.as_raw_bytes.bytes, location_info.value().data.as_raw_bytes.length }; auto value = Dwarf::Expression::evaluate(expression_bytes, regs); if (value.type != Dwarf::Expression::Type::None) { diff --git a/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp b/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp index 78c76caf1e..dadd9d97ed 100644 --- a/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp +++ b/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp @@ -27,6 +27,8 @@ #include "AbbreviationsMap.h" #include "DwarfInfo.h" +#include + namespace Dwarf { AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset) @@ -38,10 +40,10 @@ AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset) void AbbreviationsMap::populate_map() { - BufferStream abbreviation_stream(const_cast(m_dwarf_info.abbreviation_data())); - abbreviation_stream.advance(m_offset); + InputMemoryStream abbreviation_stream(m_dwarf_info.abbreviation_data().span()); + abbreviation_stream.discard_or_error(m_offset); - while (!abbreviation_stream.at_end()) { + while (!abbreviation_stream.eof()) { size_t abbreviation_code = 0; abbreviation_stream.read_LEB128_unsigned(abbreviation_code); // An abbrevation code of 0 marks the end of the diff --git a/Libraries/LibDebug/Dwarf/DIE.cpp b/Libraries/LibDebug/Dwarf/DIE.cpp index 2afab92920..c487f42c96 100644 --- a/Libraries/LibDebug/Dwarf/DIE.cpp +++ b/Libraries/LibDebug/Dwarf/DIE.cpp @@ -27,8 +27,8 @@ #include "DIE.h" #include "CompilationUnit.h" #include "DwarfInfo.h" -#include #include +#include namespace Dwarf { @@ -36,8 +36,8 @@ DIE::DIE(const CompilationUnit& unit, u32 offset) : m_compilation_unit(unit) , m_offset(offset) { - BufferStream stream(const_cast(m_compilation_unit.dwarf_info().debug_info_data())); - stream.advance(m_offset); + InputMemoryStream stream(m_compilation_unit.dwarf_info().debug_info_data().span()); + stream.discard_or_error(m_offset); stream.read_LEB128_unsigned(m_abbreviation_code); m_data_offset = stream.offset(); @@ -60,7 +60,7 @@ DIE::DIE(const CompilationUnit& unit, u32 offset) } DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, - BufferStream& debug_info_stream) const + InputMemoryStream& debug_info_stream) const { AttributeValue value; @@ -69,12 +69,12 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, value.data.as_raw_bytes.bytes = reinterpret_cast(m_compilation_unit.dwarf_info().debug_info_data().data() + debug_info_stream.offset()); - debug_info_stream.advance(length); + debug_info_stream.discard_or_error(length); }; switch (form) { case AttributeDataForm::StringPointer: { - u32 offset = 0; + u32 offset; debug_info_stream >> offset; value.type = AttributeValue::Type::String; @@ -83,42 +83,42 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, break; } case AttributeDataForm::Data1: { - u8 data = 0; + u8 data; debug_info_stream >> data; value.type = AttributeValue::Type::UnsignedNumber; value.data.as_u32 = data; break; } case AttributeDataForm::Data2: { - u16 data = 0; + u16 data; debug_info_stream >> data; value.type = AttributeValue::Type::UnsignedNumber; value.data.as_u32 = data; break; } case AttributeDataForm::Addr: { - u32 address = 0; + u32 address; debug_info_stream >> address; value.type = AttributeValue::Type::UnsignedNumber; value.data.as_u32 = address; break; } case AttributeDataForm::SecOffset: { - u32 data = 0; + u32 data; debug_info_stream >> data; value.type = AttributeValue::Type::SecOffset; value.data.as_u32 = data; break; } case AttributeDataForm::Data4: { - u32 data = 0; + u32 data; debug_info_stream >> data; value.type = AttributeValue::Type::UnsignedNumber; value.data.as_u32 = data; break; } case AttributeDataForm::Ref4: { - u32 data = 0; + u32 data; debug_info_stream >> data; value.type = AttributeValue::Type::DieReference; value.data.as_u32 = data + m_compilation_unit.offset(); @@ -130,7 +130,7 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, break; } case AttributeDataForm::ExprLoc: { - size_t length = 0; + size_t length; debug_info_stream.read_LEB128_unsigned(length); value.type = AttributeValue::Type::DwarfExpression; assign_raw_bytes_value(length); @@ -146,28 +146,28 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, } case AttributeDataForm::Block1: { value.type = AttributeValue::Type::RawBytes; - u8 length = 0; + u8 length; debug_info_stream >> length; assign_raw_bytes_value(length); break; } case AttributeDataForm::Block2: { value.type = AttributeValue::Type::RawBytes; - u16 length = 0; + u16 length; debug_info_stream >> length; assign_raw_bytes_value(length); break; } case AttributeDataForm::Block4: { value.type = AttributeValue::Type::RawBytes; - u32 length = 0; + u32 length; debug_info_stream >> length; assign_raw_bytes_value(length); break; } case AttributeDataForm::Block: { value.type = AttributeValue::Type::RawBytes; - size_t length = 0; + size_t length; debug_info_stream.read_LEB128_unsigned(length); assign_raw_bytes_value(length); break; @@ -181,8 +181,8 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, Optional DIE::get_attribute(const Attribute& attribute) const { - BufferStream stream(const_cast(m_compilation_unit.dwarf_info().debug_info_data())); - stream.advance(m_data_offset); + InputMemoryStream stream { m_compilation_unit.dwarf_info().debug_info_data().span() }; + stream.discard_or_error(m_data_offset); auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code); ASSERT(abbreviation_info.has_value()); diff --git a/Libraries/LibDebug/Dwarf/DIE.h b/Libraries/LibDebug/Dwarf/DIE.h index 85ac01a67c..2d2da9ea4f 100644 --- a/Libraries/LibDebug/Dwarf/DIE.h +++ b/Libraries/LibDebug/Dwarf/DIE.h @@ -28,7 +28,6 @@ #include "CompilationUnit.h" #include "DwarfTypes.h" -#include #include #include #include @@ -82,7 +81,7 @@ public: private: AttributeValue get_attribute_value(AttributeDataForm form, - BufferStream& debug_info_stream) const; + InputMemoryStream& debug_info_stream) const; const CompilationUnit& m_compilation_unit; u32 m_offset { 0 }; diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index e105099b4c..2c81e3e059 100644 --- a/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -26,6 +26,8 @@ #include "DwarfInfo.h" +#include + namespace Dwarf { DwarfInfo::DwarfInfo(NonnullRefPtr elf) @@ -50,22 +52,19 @@ void DwarfInfo::populate_compilation_units() { if (m_debug_info_data.is_null()) return; - // We have to const_cast here because there isn't a version of - // BufferStream that accepts a const ByteStream - // We take care not to use BufferStream operations that modify the underlying buffer - // TOOD: Add a variant of BufferStream that operates on a const ByteBuffer to AK - BufferStream stream(const_cast(m_debug_info_data)); - while (!stream.at_end()) { + + InputMemoryStream stream(m_debug_info_data.span()); + while (!stream.eof()) { auto unit_offset = stream.offset(); CompilationUnitHeader compilation_unit_header {}; - stream.read_raw(reinterpret_cast(&compilation_unit_header), sizeof(CompilationUnitHeader)); + stream >> Bytes { &compilation_unit_header, sizeof(compilation_unit_header) }; ASSERT(compilation_unit_header.address_size == sizeof(u32)); ASSERT(compilation_unit_header.version == 4); u32 length_after_header = compilation_unit_header.length - (sizeof(CompilationUnitHeader) - offsetof(CompilationUnitHeader, version)); m_compilation_units.empend(*this, unit_offset, compilation_unit_header); - stream.advance(length_after_header); + stream.discard_or_error(length_after_header); } } diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Libraries/LibDebug/Dwarf/DwarfInfo.h index f39d168790..e3927c2e61 100644 --- a/Libraries/LibDebug/Dwarf/DwarfInfo.h +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -28,7 +28,6 @@ #include "CompilationUnit.h" #include "DwarfTypes.h" -#include #include #include #include diff --git a/Libraries/LibDebug/Dwarf/Expression.cpp b/Libraries/LibDebug/Dwarf/Expression.cpp index ddc1dfcde4..a38b0fd2bd 100644 --- a/Libraries/LibDebug/Dwarf/Expression.cpp +++ b/Libraries/LibDebug/Dwarf/Expression.cpp @@ -24,18 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Expression.h" -#include + +#include + #include -namespace Dwarf { -namespace Expression { +namespace Dwarf::Expression { -Value evaluate(const ByteBuffer& bytes, const PtraceRegisters& regs) +Value evaluate(ReadonlyBytes bytes, const PtraceRegisters& regs) { - // TODO: we need a BufferStream variant that takes a const ByteBuffer - BufferStream stream(const_cast(bytes)); + InputMemoryStream stream(bytes); - while (!stream.at_end()) { + while (!stream.eof()) { u8 opcode = 0; stream >> opcode; @@ -61,5 +61,4 @@ Value evaluate(const ByteBuffer& bytes, const PtraceRegisters& regs) ASSERT_NOT_REACHED(); } -}; -}; +} diff --git a/Libraries/LibDebug/Dwarf/Expression.h b/Libraries/LibDebug/Dwarf/Expression.h index 235efdea8f..de9463901d 100644 --- a/Libraries/LibDebug/Dwarf/Expression.h +++ b/Libraries/LibDebug/Dwarf/Expression.h @@ -31,8 +31,7 @@ class PtraceRegisters; -namespace Dwarf { -namespace Expression { +namespace Dwarf::Expression { enum class Type { None, @@ -52,7 +51,6 @@ enum class Operations : u8 { FbReg = 0x91, }; -Value evaluate(const ByteBuffer&, const PtraceRegisters&); +Value evaluate(ReadonlyBytes, const PtraceRegisters&); } -} diff --git a/Libraries/LibDebug/Dwarf/LineProgram.cpp b/Libraries/LibDebug/Dwarf/LineProgram.cpp index 2bc629daff..66d72e31bd 100644 --- a/Libraries/LibDebug/Dwarf/LineProgram.cpp +++ b/Libraries/LibDebug/Dwarf/LineProgram.cpp @@ -26,7 +26,9 @@ #include "LineProgram.h" -LineProgram::LineProgram(BufferStream& stream) +#include + +LineProgram::LineProgram(InputMemoryStream& stream) : m_stream(stream) { m_unit_offset = m_stream.offset(); @@ -38,7 +40,7 @@ LineProgram::LineProgram(BufferStream& stream) void LineProgram::parse_unit_header() { - m_stream.read_raw((u8*)&m_unit_header, sizeof(m_unit_header)); + m_stream >> Bytes { &m_unit_header, sizeof(m_unit_header) }; ASSERT(m_unit_header.version == DWARF_VERSION); ASSERT(m_unit_header.opcode_base == SPECIAL_OPCODES_BASE); @@ -51,21 +53,23 @@ void LineProgram::parse_unit_header() void LineProgram::parse_source_directories() { m_source_directories.append("."); - while (m_stream.peek()) { - String directory; - m_stream >> directory; + + String directory; + while (m_stream >> directory) { #ifdef DWARF_DEBUG dbg() << "directory: " << directory; #endif m_source_directories.append(move(directory)); } - m_stream.advance(1); + m_stream.handle_error(); + m_stream.discard_or_error(1); + ASSERT(!m_stream.handle_error()); } void LineProgram::parse_source_files() { m_source_files.append({ ".", 0 }); - while (m_stream.peek()) { + while (!m_stream.eof() && m_stream.peek_or_error()) { String file_name; m_stream >> file_name; size_t directory_index = 0; @@ -78,8 +82,8 @@ void LineProgram::parse_source_files() #endif m_source_files.append({ file_name, directory_index }); } - m_stream.advance(1); - ASSERT(!m_stream.handle_read_failure()); + m_stream.discard_or_error(1); + ASSERT(!m_stream.handle_error()); } void LineProgram::append_to_line_info() @@ -129,7 +133,7 @@ void LineProgram::handle_extended_opcode() #ifdef DWARF_DEBUG dbg() << "SetDiscriminator"; #endif - m_stream.advance(1); + m_stream.discard_or_error(1); break; } default: diff --git a/Libraries/LibDebug/Dwarf/LineProgram.h b/Libraries/LibDebug/Dwarf/LineProgram.h index f49ec17390..092b2deba8 100644 --- a/Libraries/LibDebug/Dwarf/LineProgram.h +++ b/Libraries/LibDebug/Dwarf/LineProgram.h @@ -26,12 +26,13 @@ #pragma once -#include +#include +#include #include class LineProgram { public: - explicit LineProgram(BufferStream& stream); + explicit LineProgram(InputMemoryStream& stream); struct LineInfo { u32 address { 0 }; @@ -97,7 +98,7 @@ private: static constexpr u16 DWARF_VERSION = 3; static constexpr u8 SPECIAL_OPCODES_BASE = 13; - BufferStream& m_stream; + InputMemoryStream& m_stream; size_t m_unit_offset { 0 }; UnitHeader32 m_unit_header {};