mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-22 12:35:14 +00:00
LibDebug: Use InputMemoryStream instead of BufferStream.
This removes another call to ByteBuffer::wrap(const void*, size_t).
This commit is contained in:
parent
5bfa7749c3
commit
ac9f6fd1f8
Notes:
sideshowbarker
2024-07-19 04:14:19 +09:00
Author: https://github.com/asynts Commit: https://github.com/SerenityOS/serenity/commit/ac9f6fd1f8e Pull-request: https://github.com/SerenityOS/serenity/pull/3007 Reviewed-by: https://github.com/awesomekling Reviewed-by: https://github.com/nico
12 changed files with 125 additions and 106 deletions
|
@ -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<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)
|
||||
{
|
||||
if (m_offset + amount > m_buffer.size()) {
|
||||
|
|
61
AK/Stream.h
61
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<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; }
|
||||
size_t offset() const { return m_offset; }
|
||||
size_t remaining() const { return m_bytes.size() - m_offset; }
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "DebugInfo.h"
|
||||
#include <AK/QuickSort.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <LibDebug/Dwarf/CompilationUnit.h>
|
||||
#include <LibDebug/Dwarf/DwarfInfo.h>
|
||||
#include <LibDebug/Dwarf/Expression.h>
|
||||
|
@ -104,10 +105,10 @@ void DebugInfo::prepare_lines()
|
|||
return;
|
||||
|
||||
auto buffer = section.wrapping_byte_buffer();
|
||||
BufferStream stream(buffer);
|
||||
InputMemoryStream stream { buffer.span() };
|
||||
|
||||
Vector<LineProgram::LineInfo> 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) {
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "AbbreviationsMap.h"
|
||||
#include "DwarfInfo.h"
|
||||
|
||||
#include <AK/Stream.h>
|
||||
|
||||
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<ByteBuffer&>(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
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
#include "DIE.h"
|
||||
#include "CompilationUnit.h"
|
||||
#include "DwarfInfo.h"
|
||||
#include <AK/BufferStream.h>
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/Stream.h>
|
||||
|
||||
namespace Dwarf {
|
||||
|
||||
|
@ -36,8 +36,8 @@ DIE::DIE(const CompilationUnit& unit, u32 offset)
|
|||
: m_compilation_unit(unit)
|
||||
, m_offset(offset)
|
||||
{
|
||||
BufferStream stream(const_cast<ByteBuffer&>(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<const u8*>(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::AttributeValue> DIE::get_attribute(const Attribute& attribute) const
|
||||
{
|
||||
BufferStream stream(const_cast<ByteBuffer&>(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());
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "CompilationUnit.h"
|
||||
#include "DwarfTypes.h"
|
||||
#include <AK/BufferStream.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
|
@ -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 };
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "DwarfInfo.h"
|
||||
|
||||
#include <AK/Stream.h>
|
||||
|
||||
namespace Dwarf {
|
||||
|
||||
DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> 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<ByteBuffer&>(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<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.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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "CompilationUnit.h"
|
||||
#include "DwarfTypes.h"
|
||||
#include <AK/BufferStream.h>
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/RefCounted.h>
|
||||
|
|
|
@ -24,18 +24,18 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "Expression.h"
|
||||
#include <AK/BufferStream.h>
|
||||
|
||||
#include <AK/Stream.h>
|
||||
|
||||
#include <sys/arch/i386/regs.h>
|
||||
|
||||
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<ByteBuffer&>(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();
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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&);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
|
||||
#include "LineProgram.h"
|
||||
|
||||
LineProgram::LineProgram(BufferStream& stream)
|
||||
#include <AK/String.h>
|
||||
|
||||
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:
|
||||
|
|
|
@ -26,12 +26,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/BufferStream.h>
|
||||
#include <AK/Stream.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
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 {};
|
||||
|
|
Loading…
Add table
Reference in a new issue