1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 22:44:58 +00:00

LibDebug: Use InputMemoryStream instead of BufferStream.

This removes another call to ByteBuffer::wrap(const void*, size_t).
This commit is contained in:
asynts 2020-08-05 10:55:36 +02:00 committed by Andreas Kling
parent 5bfa7749c3
commit ac9f6fd1f8
12 changed files with 125 additions and 106 deletions

View file

@ -352,50 +352,6 @@ public:
return *this; 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<size_t>(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<size_t>(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) BufferStream& advance(size_t amount)
{ {
if (m_offset + amount > m_buffer.size()) { if (m_offset + amount > m_buffer.size()) {

View file

@ -154,6 +154,67 @@ public:
return m_bytes[m_offset]; 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<size_t>(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<size_t>(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; } ReadonlyBytes bytes() const { return m_bytes; }
size_t offset() const { return m_offset; } size_t offset() const { return m_offset; }
size_t remaining() const { return m_bytes.size() - m_offset; } size_t remaining() const { return m_bytes.size() - m_offset; }

View file

@ -26,6 +26,7 @@
#include "DebugInfo.h" #include "DebugInfo.h"
#include <AK/QuickSort.h> #include <AK/QuickSort.h>
#include <AK/Stream.h>
#include <LibDebug/Dwarf/CompilationUnit.h> #include <LibDebug/Dwarf/CompilationUnit.h>
#include <LibDebug/Dwarf/DwarfInfo.h> #include <LibDebug/Dwarf/DwarfInfo.h>
#include <LibDebug/Dwarf/Expression.h> #include <LibDebug/Dwarf/Expression.h>
@ -104,10 +105,10 @@ void DebugInfo::prepare_lines()
return; return;
auto buffer = section.wrapping_byte_buffer(); auto buffer = section.wrapping_byte_buffer();
BufferStream stream(buffer); InputMemoryStream stream { buffer.span() };
Vector<LineProgram::LineInfo> all_lines; Vector<LineProgram::LineInfo> all_lines;
while (!stream.at_end()) { while (!stream.eof()) {
LineProgram program(stream); LineProgram program(stream);
all_lines.append(program.lines()); 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) { 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); auto value = Dwarf::Expression::evaluate(expression_bytes, regs);
if (value.type != Dwarf::Expression::Type::None) { if (value.type != Dwarf::Expression::Type::None) {

View file

@ -27,6 +27,8 @@
#include "AbbreviationsMap.h" #include "AbbreviationsMap.h"
#include "DwarfInfo.h" #include "DwarfInfo.h"
#include <AK/Stream.h>
namespace Dwarf { namespace Dwarf {
AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset) AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset)
@ -38,10 +40,10 @@ AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset)
void AbbreviationsMap::populate_map() void AbbreviationsMap::populate_map()
{ {
BufferStream abbreviation_stream(const_cast<ByteBuffer&>(m_dwarf_info.abbreviation_data())); InputMemoryStream abbreviation_stream(m_dwarf_info.abbreviation_data().span());
abbreviation_stream.advance(m_offset); abbreviation_stream.discard_or_error(m_offset);
while (!abbreviation_stream.at_end()) { while (!abbreviation_stream.eof()) {
size_t abbreviation_code = 0; size_t abbreviation_code = 0;
abbreviation_stream.read_LEB128_unsigned(abbreviation_code); abbreviation_stream.read_LEB128_unsigned(abbreviation_code);
// An abbrevation code of 0 marks the end of the // An abbrevation code of 0 marks the end of the

View file

@ -27,8 +27,8 @@
#include "DIE.h" #include "DIE.h"
#include "CompilationUnit.h" #include "CompilationUnit.h"
#include "DwarfInfo.h" #include "DwarfInfo.h"
#include <AK/BufferStream.h>
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/Stream.h>
namespace Dwarf { namespace Dwarf {
@ -36,8 +36,8 @@ DIE::DIE(const CompilationUnit& unit, u32 offset)
: m_compilation_unit(unit) : m_compilation_unit(unit)
, m_offset(offset) , m_offset(offset)
{ {
BufferStream stream(const_cast<ByteBuffer&>(m_compilation_unit.dwarf_info().debug_info_data())); InputMemoryStream stream(m_compilation_unit.dwarf_info().debug_info_data().span());
stream.advance(m_offset); stream.discard_or_error(m_offset);
stream.read_LEB128_unsigned(m_abbreviation_code); stream.read_LEB128_unsigned(m_abbreviation_code);
m_data_offset = stream.offset(); m_data_offset = stream.offset();
@ -60,7 +60,7 @@ DIE::DIE(const CompilationUnit& unit, u32 offset)
} }
DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form, DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
BufferStream& debug_info_stream) const InputMemoryStream& debug_info_stream) const
{ {
AttributeValue value; AttributeValue value;
@ -69,12 +69,12 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
value.data.as_raw_bytes.bytes = reinterpret_cast<const u8*>(m_compilation_unit.dwarf_info().debug_info_data().data() value.data.as_raw_bytes.bytes = reinterpret_cast<const u8*>(m_compilation_unit.dwarf_info().debug_info_data().data()
+ debug_info_stream.offset()); + debug_info_stream.offset());
debug_info_stream.advance(length); debug_info_stream.discard_or_error(length);
}; };
switch (form) { switch (form) {
case AttributeDataForm::StringPointer: { case AttributeDataForm::StringPointer: {
u32 offset = 0; u32 offset;
debug_info_stream >> offset; debug_info_stream >> offset;
value.type = AttributeValue::Type::String; value.type = AttributeValue::Type::String;
@ -83,42 +83,42 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
break; break;
} }
case AttributeDataForm::Data1: { case AttributeDataForm::Data1: {
u8 data = 0; u8 data;
debug_info_stream >> data; debug_info_stream >> data;
value.type = AttributeValue::Type::UnsignedNumber; value.type = AttributeValue::Type::UnsignedNumber;
value.data.as_u32 = data; value.data.as_u32 = data;
break; break;
} }
case AttributeDataForm::Data2: { case AttributeDataForm::Data2: {
u16 data = 0; u16 data;
debug_info_stream >> data; debug_info_stream >> data;
value.type = AttributeValue::Type::UnsignedNumber; value.type = AttributeValue::Type::UnsignedNumber;
value.data.as_u32 = data; value.data.as_u32 = data;
break; break;
} }
case AttributeDataForm::Addr: { case AttributeDataForm::Addr: {
u32 address = 0; u32 address;
debug_info_stream >> address; debug_info_stream >> address;
value.type = AttributeValue::Type::UnsignedNumber; value.type = AttributeValue::Type::UnsignedNumber;
value.data.as_u32 = address; value.data.as_u32 = address;
break; break;
} }
case AttributeDataForm::SecOffset: { case AttributeDataForm::SecOffset: {
u32 data = 0; u32 data;
debug_info_stream >> data; debug_info_stream >> data;
value.type = AttributeValue::Type::SecOffset; value.type = AttributeValue::Type::SecOffset;
value.data.as_u32 = data; value.data.as_u32 = data;
break; break;
} }
case AttributeDataForm::Data4: { case AttributeDataForm::Data4: {
u32 data = 0; u32 data;
debug_info_stream >> data; debug_info_stream >> data;
value.type = AttributeValue::Type::UnsignedNumber; value.type = AttributeValue::Type::UnsignedNumber;
value.data.as_u32 = data; value.data.as_u32 = data;
break; break;
} }
case AttributeDataForm::Ref4: { case AttributeDataForm::Ref4: {
u32 data = 0; u32 data;
debug_info_stream >> data; debug_info_stream >> data;
value.type = AttributeValue::Type::DieReference; value.type = AttributeValue::Type::DieReference;
value.data.as_u32 = data + m_compilation_unit.offset(); value.data.as_u32 = data + m_compilation_unit.offset();
@ -130,7 +130,7 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
break; break;
} }
case AttributeDataForm::ExprLoc: { case AttributeDataForm::ExprLoc: {
size_t length = 0; size_t length;
debug_info_stream.read_LEB128_unsigned(length); debug_info_stream.read_LEB128_unsigned(length);
value.type = AttributeValue::Type::DwarfExpression; value.type = AttributeValue::Type::DwarfExpression;
assign_raw_bytes_value(length); assign_raw_bytes_value(length);
@ -146,28 +146,28 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
} }
case AttributeDataForm::Block1: { case AttributeDataForm::Block1: {
value.type = AttributeValue::Type::RawBytes; value.type = AttributeValue::Type::RawBytes;
u8 length = 0; u8 length;
debug_info_stream >> length; debug_info_stream >> length;
assign_raw_bytes_value(length); assign_raw_bytes_value(length);
break; break;
} }
case AttributeDataForm::Block2: { case AttributeDataForm::Block2: {
value.type = AttributeValue::Type::RawBytes; value.type = AttributeValue::Type::RawBytes;
u16 length = 0; u16 length;
debug_info_stream >> length; debug_info_stream >> length;
assign_raw_bytes_value(length); assign_raw_bytes_value(length);
break; break;
} }
case AttributeDataForm::Block4: { case AttributeDataForm::Block4: {
value.type = AttributeValue::Type::RawBytes; value.type = AttributeValue::Type::RawBytes;
u32 length = 0; u32 length;
debug_info_stream >> length; debug_info_stream >> length;
assign_raw_bytes_value(length); assign_raw_bytes_value(length);
break; break;
} }
case AttributeDataForm::Block: { case AttributeDataForm::Block: {
value.type = AttributeValue::Type::RawBytes; value.type = AttributeValue::Type::RawBytes;
size_t length = 0; size_t length;
debug_info_stream.read_LEB128_unsigned(length); debug_info_stream.read_LEB128_unsigned(length);
assign_raw_bytes_value(length); assign_raw_bytes_value(length);
break; break;
@ -181,8 +181,8 @@ DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
Optional<DIE::AttributeValue> DIE::get_attribute(const Attribute& attribute) const Optional<DIE::AttributeValue> DIE::get_attribute(const Attribute& attribute) const
{ {
BufferStream stream(const_cast<ByteBuffer&>(m_compilation_unit.dwarf_info().debug_info_data())); InputMemoryStream stream { m_compilation_unit.dwarf_info().debug_info_data().span() };
stream.advance(m_data_offset); stream.discard_or_error(m_data_offset);
auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code); auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code);
ASSERT(abbreviation_info.has_value()); ASSERT(abbreviation_info.has_value());

View file

@ -28,7 +28,6 @@
#include "CompilationUnit.h" #include "CompilationUnit.h"
#include "DwarfTypes.h" #include "DwarfTypes.h"
#include <AK/BufferStream.h>
#include <AK/Function.h> #include <AK/Function.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h> #include <AK/Optional.h>
@ -82,7 +81,7 @@ public:
private: private:
AttributeValue get_attribute_value(AttributeDataForm form, AttributeValue get_attribute_value(AttributeDataForm form,
BufferStream& debug_info_stream) const; InputMemoryStream& debug_info_stream) const;
const CompilationUnit& m_compilation_unit; const CompilationUnit& m_compilation_unit;
u32 m_offset { 0 }; u32 m_offset { 0 };

View file

@ -26,6 +26,8 @@
#include "DwarfInfo.h" #include "DwarfInfo.h"
#include <AK/Stream.h>
namespace Dwarf { namespace Dwarf {
DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf) DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf)
@ -50,22 +52,19 @@ void DwarfInfo::populate_compilation_units()
{ {
if (m_debug_info_data.is_null()) if (m_debug_info_data.is_null())
return; return;
// We have to const_cast here because there isn't a version of
// BufferStream that accepts a const ByteStream InputMemoryStream stream(m_debug_info_data.span());
// We take care not to use BufferStream operations that modify the underlying buffer while (!stream.eof()) {
// TOOD: Add a variant of BufferStream that operates on a const ByteBuffer to AK
BufferStream stream(const_cast<ByteBuffer&>(m_debug_info_data));
while (!stream.at_end()) {
auto unit_offset = stream.offset(); auto unit_offset = stream.offset();
CompilationUnitHeader compilation_unit_header {}; CompilationUnitHeader compilation_unit_header {};
stream.read_raw(reinterpret_cast<u8*>(&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.address_size == sizeof(u32));
ASSERT(compilation_unit_header.version == 4); ASSERT(compilation_unit_header.version == 4);
u32 length_after_header = compilation_unit_header.length - (sizeof(CompilationUnitHeader) - offsetof(CompilationUnitHeader, version)); u32 length_after_header = compilation_unit_header.length - (sizeof(CompilationUnitHeader) - offsetof(CompilationUnitHeader, version));
m_compilation_units.empend(*this, unit_offset, compilation_unit_header); m_compilation_units.empend(*this, unit_offset, compilation_unit_header);
stream.advance(length_after_header); stream.discard_or_error(length_after_header);
} }
} }

View file

@ -28,7 +28,6 @@
#include "CompilationUnit.h" #include "CompilationUnit.h"
#include "DwarfTypes.h" #include "DwarfTypes.h"
#include <AK/BufferStream.h>
#include <AK/ByteBuffer.h> #include <AK/ByteBuffer.h>
#include <AK/NonnullRefPtr.h> #include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>

View file

@ -24,18 +24,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "Expression.h" #include "Expression.h"
#include <AK/BufferStream.h>
#include <AK/Stream.h>
#include <sys/arch/i386/regs.h> #include <sys/arch/i386/regs.h>
namespace Dwarf { namespace Dwarf::Expression {
namespace 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 InputMemoryStream stream(bytes);
BufferStream stream(const_cast<ByteBuffer&>(bytes));
while (!stream.at_end()) { while (!stream.eof()) {
u8 opcode = 0; u8 opcode = 0;
stream >> opcode; stream >> opcode;
@ -61,5 +61,4 @@ Value evaluate(const ByteBuffer& bytes, const PtraceRegisters& regs)
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
}; }
};

View file

@ -31,8 +31,7 @@
class PtraceRegisters; class PtraceRegisters;
namespace Dwarf { namespace Dwarf::Expression {
namespace Expression {
enum class Type { enum class Type {
None, None,
@ -52,7 +51,6 @@ enum class Operations : u8 {
FbReg = 0x91, FbReg = 0x91,
}; };
Value evaluate(const ByteBuffer&, const PtraceRegisters&); Value evaluate(ReadonlyBytes, const PtraceRegisters&);
} }
}

View file

@ -26,7 +26,9 @@
#include "LineProgram.h" #include "LineProgram.h"
LineProgram::LineProgram(BufferStream& stream) #include <AK/String.h>
LineProgram::LineProgram(InputMemoryStream& stream)
: m_stream(stream) : m_stream(stream)
{ {
m_unit_offset = m_stream.offset(); m_unit_offset = m_stream.offset();
@ -38,7 +40,7 @@ LineProgram::LineProgram(BufferStream& stream)
void LineProgram::parse_unit_header() 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.version == DWARF_VERSION);
ASSERT(m_unit_header.opcode_base == SPECIAL_OPCODES_BASE); ASSERT(m_unit_header.opcode_base == SPECIAL_OPCODES_BASE);
@ -51,21 +53,23 @@ void LineProgram::parse_unit_header()
void LineProgram::parse_source_directories() void LineProgram::parse_source_directories()
{ {
m_source_directories.append("."); m_source_directories.append(".");
while (m_stream.peek()) {
String directory; String directory;
m_stream >> directory; while (m_stream >> directory) {
#ifdef DWARF_DEBUG #ifdef DWARF_DEBUG
dbg() << "directory: " << directory; dbg() << "directory: " << directory;
#endif #endif
m_source_directories.append(move(directory)); 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() void LineProgram::parse_source_files()
{ {
m_source_files.append({ ".", 0 }); m_source_files.append({ ".", 0 });
while (m_stream.peek()) { while (!m_stream.eof() && m_stream.peek_or_error()) {
String file_name; String file_name;
m_stream >> file_name; m_stream >> file_name;
size_t directory_index = 0; size_t directory_index = 0;
@ -78,8 +82,8 @@ void LineProgram::parse_source_files()
#endif #endif
m_source_files.append({ file_name, directory_index }); m_source_files.append({ file_name, directory_index });
} }
m_stream.advance(1); m_stream.discard_or_error(1);
ASSERT(!m_stream.handle_read_failure()); ASSERT(!m_stream.handle_error());
} }
void LineProgram::append_to_line_info() void LineProgram::append_to_line_info()
@ -129,7 +133,7 @@ void LineProgram::handle_extended_opcode()
#ifdef DWARF_DEBUG #ifdef DWARF_DEBUG
dbg() << "SetDiscriminator"; dbg() << "SetDiscriminator";
#endif #endif
m_stream.advance(1); m_stream.discard_or_error(1);
break; break;
} }
default: default:

View file

@ -26,12 +26,13 @@
#pragma once #pragma once
#include <AK/BufferStream.h> #include <AK/Stream.h>
#include <AK/String.h>
#include <AK/Vector.h> #include <AK/Vector.h>
class LineProgram { class LineProgram {
public: public:
explicit LineProgram(BufferStream& stream); explicit LineProgram(InputMemoryStream& stream);
struct LineInfo { struct LineInfo {
u32 address { 0 }; u32 address { 0 };
@ -97,7 +98,7 @@ private:
static constexpr u16 DWARF_VERSION = 3; static constexpr u16 DWARF_VERSION = 3;
static constexpr u8 SPECIAL_OPCODES_BASE = 13; static constexpr u8 SPECIAL_OPCODES_BASE = 13;
BufferStream& m_stream; InputMemoryStream& m_stream;
size_t m_unit_offset { 0 }; size_t m_unit_offset { 0 };
UnitHeader32 m_unit_header {}; UnitHeader32 m_unit_header {};