From 6b4448b62301fcb1faf47ccd34c94b162c05981d Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 28 Apr 2021 22:13:58 +0200 Subject: [PATCH] LibDebug: Implement support for DWARF 5 compilation unit headers --- .../LibDebug/Dwarf/CompilationUnit.cpp | 5 +- .../LibDebug/Dwarf/CompilationUnit.h | 2 +- .../Libraries/LibDebug/Dwarf/DwarfInfo.cpp | 8 ++-- .../Libraries/LibDebug/Dwarf/DwarfTypes.h | 47 ++++++++++++++++++- 4 files changed, 54 insertions(+), 8 deletions(-) diff --git a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp index 2b6062639f..9f6e163d87 100644 --- a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp @@ -12,13 +12,14 @@ CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const : m_dwarf_info(dwarf_info) , m_offset(offset) , m_header(header) - , m_abbreviations(dwarf_info, header.abbrev_offset) + , m_abbreviations(dwarf_info, header.abbrev_offset()) { + VERIFY(header.version() < 5 || header.unit_type() == CompilationUnitType::Full); } DIE CompilationUnit::root_die() const { - return DIE(*this, m_offset + sizeof(CompilationUnitHeader)); + return DIE(*this, m_offset + m_header.header_size()); } } diff --git a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h index 7a74c4eac5..d48c781b67 100644 --- a/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h +++ b/Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h @@ -19,7 +19,7 @@ public: CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader&); u32 offset() const { return m_offset; } - u32 size() const { return m_header.length + sizeof(u32); } + u32 size() const { return m_header.length() + sizeof(u32); } DIE root_die() const; diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index 19d1793099..0ecc613596 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -38,11 +38,11 @@ void DwarfInfo::populate_compilation_units() auto unit_offset = stream.offset(); CompilationUnitHeader compilation_unit_header {}; - stream >> Bytes { &compilation_unit_header, sizeof(compilation_unit_header) }; - VERIFY(compilation_unit_header.address_size == sizeof(u32)); - VERIFY(compilation_unit_header.version <= 4); + stream >> compilation_unit_header; + VERIFY(compilation_unit_header.common.version <= 5); + VERIFY(compilation_unit_header.address_size() == sizeof(u32)); - u32 length_after_header = compilation_unit_header.length - (sizeof(CompilationUnitHeader) - offsetof(CompilationUnitHeader, version)); + u32 length_after_header = compilation_unit_header.length() - (compilation_unit_header.header_size() - offsetof(CompilationUnitHeader, common.version)); m_compilation_units.empend(*this, unit_offset, compilation_unit_header); stream.discard_or_error(length_after_header); } diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h index c11827e40d..19de2ea809 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h @@ -6,17 +6,62 @@ #pragma once +#include #include namespace Debug::Dwarf { -struct [[gnu::packed]] CompilationUnitHeader { +enum class CompilationUnitType { + Full = 1, + Partial = 3 +}; + +struct [[gnu::packed]] CompilationUnitHeaderCommon { u32 length; u16 version; +}; + +struct [[gnu::packed]] CompilationUnitHeaderV4Ext { u32 abbrev_offset; u8 address_size; }; +struct [[gnu::packed]] CompilationUnitHeaderV5Ext { + u8 unit_type; + u8 address_size; + u32 abbrev_offset; +}; + +struct [[gnu::packed]] CompilationUnitHeader { + CompilationUnitHeaderCommon common; + + union { + CompilationUnitHeaderV4Ext v4; + CompilationUnitHeaderV5Ext v5; + }; + + size_t header_size() const + { + return sizeof(common) + ((common.version <= 4) ? sizeof(v4) : sizeof(v5)); + } + + u32 length() const { return common.length; } + u16 version() const { return common.version; } + CompilationUnitType unit_type() const { return (common.version <= 4) ? CompilationUnitType::Full : (CompilationUnitType)v5.unit_type; } + 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; +} + enum class EntryTag : u16 { None = 0, ArrayType = 0x1,