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;
}
// 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()) {

View file

@ -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; }

View file

@ -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) {

View file

@ -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

View file

@ -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());

View file

@ -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 };

View file

@ -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);
}
}

View file

@ -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>

View file

@ -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();
}
};
};
}

View file

@ -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&);
}
}

View file

@ -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:

View file

@ -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 {};