summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-04-28 22:13:58 +0200
committerAndreas Kling <kling@serenityos.org>2021-04-28 23:10:48 +0200
commit6b4448b62301fcb1faf47ccd34c94b162c05981d (patch)
tree62e079ee0a35274a7289dbdc01d7dda65160b7e4
parenta3f2af49f9dee706265016796a80c32076ee5569 (diff)
downloadserenity-6b4448b62301fcb1faf47ccd34c94b162c05981d.zip
LibDebug: Implement support for DWARF 5 compilation unit headers
-rw-r--r--Userland/Libraries/LibDebug/Dwarf/CompilationUnit.cpp5
-rw-r--r--Userland/Libraries/LibDebug/Dwarf/CompilationUnit.h2
-rw-r--r--Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp8
-rw-r--r--Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h47
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 <AK/Stream.h>
#include <AK/Types.h>
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,