Forráskód Böngészése

LibDebug: Parse DWARF information entries

We can now iterate the tree structure of the DIEs, access attribute
values and parse some very basic DWARF expressions.
Itamar 5 éve
szülő
commit
c5eb20d0cc

+ 143 - 3
Libraries/LibDebug/DebugInfo.cpp

@@ -26,16 +26,66 @@
 
 #include "DebugInfo.h"
 #include <AK/QuickSort.h>
+#include <LibDebug/Dwarf/CompilationUnit.h>
+#include <LibDebug/Dwarf/DwarfInfo.h>
+#include <LibDebug/Dwarf/Expression.h>
 
 DebugInfo::DebugInfo(NonnullRefPtr<const ELF::Loader> elf)
     : m_elf(elf)
+    , m_dwarf_info(Dwarf::DwarfInfo::create(m_elf))
 {
+    prepare_variable_scopes();
     prepare_lines();
 }
 
-void DebugInfo::prepare_lines()
+void DebugInfo::prepare_variable_scopes()
 {
+    m_dwarf_info->for_each_compilation_unit([&](const Dwarf::CompilationUnit& unit) {
+        auto root = unit.root_die();
+        parse_scopes_impl(root);
+    });
+}
+
+void DebugInfo::parse_scopes_impl(const Dwarf::DIE& die)
+{
+    die.for_each_child([&](const Dwarf::DIE& child) {
+        if (child.is_null())
+            return;
+        if (!(child.tag() == Dwarf::EntryTag::SubProgram || child.tag() == Dwarf::EntryTag::LexicalBlock))
+            return;
+
+        if (child.get_attribute(Dwarf::Attribute::Inline).has_value()) {
+            dbg() << "DWARF inlined functions are not supported";
+            return;
+        }
+        if (child.get_attribute(Dwarf::Attribute::Ranges).has_value()) {
+            dbg() << "DWARF ranges are not supported";
+            return;
+        }
+        auto name = child.get_attribute(Dwarf::Attribute::Name);
+
+        VariablesScope scope {};
+        scope.is_function = (child.tag() == Dwarf::EntryTag::SubProgram);
+        if (name.has_value())
+            scope.name = name.value().data.as_string;
+
+        scope.address_low = child.get_attribute(Dwarf::Attribute::LowPc).value().data.as_u32;
+        // The attribute name HighPc is confusing. In this context, it seems to actually be a positive offset from LowPc
+        scope.address_high = scope.address_low + child.get_attribute(Dwarf::Attribute::HighPc).value().data.as_u32;
+
+        child.for_each_child([&](const Dwarf::DIE& variable_entry) {
+            if (variable_entry.tag() != Dwarf::EntryTag::Variable)
+                return;
+            scope.dies_of_variables.append(variable_entry);
+        });
+        m_scopes.append(scope);
+
+        parse_scopes_impl(child);
+    });
+}
 
+void DebugInfo::prepare_lines()
+{
     auto section = m_elf->image().lookup_section(".debug_line");
     ASSERT(!section.is_undefined());
 
@@ -45,7 +95,7 @@ void DebugInfo::prepare_lines()
     Vector<LineProgram::LineInfo> all_lines;
     while (!stream.at_end()) {
         LineProgram program(stream);
-        all_lines.append(move(program.lines()));
+        all_lines.append(program.lines());
     }
 
     for (auto& line_info : all_lines) {
@@ -65,7 +115,6 @@ void DebugInfo::prepare_lines()
 
 Optional<DebugInfo::SourcePosition> DebugInfo::get_source_position(u32 target_address) const
 {
-
     if (m_sorted_lines.is_empty())
         return {};
     if (target_address < m_sorted_lines[0].address)
@@ -88,3 +137,94 @@ Optional<u32> DebugInfo::get_instruction_from_source(const String& file, size_t
     }
     return {};
 }
+
+NonnullOwnPtrVector<DebugInfo::VariableInfo> DebugInfo::get_variables_in_current_scope(const PtraceRegisters& regs) const
+{
+    auto scope = get_scope(regs.eip);
+    if (!scope.has_value())
+        return {};
+
+    NonnullOwnPtrVector<DebugInfo::VariableInfo> variables;
+    for (const auto& die_entry : scope.value().dies_of_variables) {
+        variables.append(create_variable_info(die_entry, regs));
+    }
+    return variables;
+}
+
+Optional<DebugInfo::VariablesScope> DebugInfo::get_scope(u32 instruction_pointer) const
+{
+    Optional<VariablesScope> best_matching_scope;
+
+    // TODO: We can store the scopes in a better data strucutre
+    for (const auto& scope : m_scopes) {
+        if (instruction_pointer < scope.address_low || instruction_pointer >= scope.address_high)
+            continue;
+
+        if (!best_matching_scope.has_value()) {
+            best_matching_scope = scope;
+
+        } else if (scope.address_low > best_matching_scope.value().address_low || scope.address_high < best_matching_scope.value().address_high) {
+            best_matching_scope = scope;
+        }
+    }
+    return best_matching_scope;
+}
+
+NonnullOwnPtr<DebugInfo::VariableInfo> DebugInfo::create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters& regs) const
+{
+    ASSERT(variable_die.tag() == Dwarf::EntryTag::Variable || variable_die.tag() == Dwarf::EntryTag::Member);
+
+    NonnullOwnPtr<VariableInfo> variable_info = make<VariableInfo>();
+
+    variable_info->name = variable_die.get_attribute(Dwarf::Attribute::Name).value().data.as_string;
+    auto type_die_offset = variable_die.get_attribute(Dwarf::Attribute::Type);
+    ASSERT(type_die_offset.has_value());
+    ASSERT(type_die_offset.value().type == Dwarf::DIE::AttributeValue::Type::DieReference);
+
+    auto type_die = variable_die.get_die_at_offset(type_die_offset.value().data.as_u32);
+    auto type_name = type_die.get_attribute(Dwarf::Attribute::Name);
+    if (type_name.has_value()) {
+        variable_info->type = type_name.value().data.as_string;
+    } else {
+        dbg() << "Unnamed DWRAF type at offset: " << type_die.offset();
+        variable_info->name = "[Unnamed Type]";
+    }
+
+    auto location_info = variable_die.get_attribute(Dwarf::Attribute::Location);
+    if (!location_info.has_value()) {
+        location_info = variable_die.get_attribute(Dwarf::Attribute::MemberLocation);
+    }
+
+    if (location_info.has_value()) {
+        if (location_info.value().type == Dwarf::DIE::AttributeValue::Type::UnsignedNumber) {
+            variable_info->location_type = VariableInfo::LocationType::Address;
+            variable_info->location_data.address = location_info.value().data.as_u32;
+        }
+
+        if (location_info.value().type == Dwarf::DIE::AttributeValue::Type::DwarfExpression) {
+            auto expression_bytes = ByteBuffer::wrap(location_info.value().data.as_dwarf_expression.bytes, location_info.value().data.as_dwarf_expression.length);
+            auto value = Dwarf::Expression::evaluate(expression_bytes, regs);
+
+            if (value.type != Dwarf::Expression::Type::None) {
+                ASSERT(value.type == Dwarf::Expression::Type::UnsignedIntetger);
+                variable_info->location_type = VariableInfo::LocationType::Address;
+                variable_info->location_data.address = value.data.as_u32;
+            }
+        }
+    }
+
+    type_die.for_each_child([&](const Dwarf::DIE& member) {
+        if (member.is_null())
+            return;
+        auto member_variable = create_variable_info(member, regs);
+        ASSERT(member_variable->location_type == DebugInfo::VariableInfo::LocationType::Address);
+        ASSERT(variable_info->location_type == DebugInfo::VariableInfo::LocationType::Address);
+
+        member_variable->location_data.address += variable_info->location_data.address;
+        member_variable->parent = variable_info.ptr();
+
+        variable_info->members.append(move(member_variable));
+    });
+
+    return variable_info;
+}

+ 37 - 0
Libraries/LibDebug/DebugInfo.h

@@ -26,11 +26,15 @@
 
 #pragma once
 
+#include <AK/NonnullOwnPtrVector.h>
 #include <AK/NonnullRefPtr.h>
 #include <AK/Optional.h>
 #include <AK/Vector.h>
+#include <LibDebug/Dwarf/DwarfInfo.h>
 #include <LibELF/Loader.h>
+#include <Libraries/LibDebug/Dwarf/DIE.h>
 #include <Libraries/LibDebug/Dwarf/LineProgram.h>
+#include <sys/arch/i386/regs.h>
 
 class DebugInfo {
 public:
@@ -45,6 +49,33 @@ public:
         bool operator!=(const SourcePosition& other) const { return !(*this == other); }
     };
 
+    struct VariableInfo {
+        enum class LocationType {
+            None,
+            Address,
+            Regsiter,
+        };
+        String name;
+        String type;
+        LocationType location_type { LocationType::None };
+        union {
+            u32 address;
+        } location_data { 0 };
+
+        NonnullOwnPtrVector<VariableInfo> members;
+        VariableInfo* parent { nullptr };
+    };
+
+    struct VariablesScope {
+        bool is_function { false };
+        Optional<String> name;
+        u32 address_low { 0 };
+        u32 address_high { 0 };
+        Vector<Dwarf::DIE> dies_of_variables;
+    };
+
+    NonnullOwnPtrVector<VariableInfo> get_variables_in_current_scope(const PtraceRegisters&) const;
+
     Optional<SourcePosition> get_source_position(u32 address) const;
     Optional<u32> get_instruction_from_source(const String& file, size_t line) const;
 
@@ -63,9 +94,15 @@ public:
     }
 
 private:
+    void prepare_variable_scopes();
     void prepare_lines();
+    void parse_scopes_impl(const Dwarf::DIE& die);
+    Optional<VariablesScope> get_scope(u32 instruction_pointer) const;
+    NonnullOwnPtr<VariableInfo> create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&) const;
 
     NonnullRefPtr<const ELF::Loader> m_elf;
+    NonnullRefPtr<Dwarf::DwarfInfo> m_dwarf_info;
 
+    Vector<VariablesScope> m_scopes;
     Vector<LineProgram::LineInfo> m_sorted_lines;
 };

+ 86 - 0
Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp

@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "AbbreviationsMap.h"
+#include "DwarfInfo.h"
+
+namespace Dwarf {
+
+AbbreviationsMap::AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset)
+    : m_dwarf_info(dwarf_info)
+    , m_offset(offset)
+{
+    populate_map();
+}
+
+void AbbreviationsMap::populate_map()
+{
+    BufferStream abbreviation_stream(const_cast<ByteBuffer&>(m_dwarf_info.abbreviation_data()));
+    abbreviation_stream.advance(m_offset);
+
+    while (!abbreviation_stream.at_end()) {
+        size_t abbreviation_code = 0;
+        abbreviation_stream.read_LEB128_unsigned(abbreviation_code);
+        // An abbrevation code of 0 marks the end of the
+        // abbrevations for a given compilation unit
+        if (abbreviation_code == 0)
+            break;
+
+        size_t tag {};
+        abbreviation_stream.read_LEB128_unsigned(tag);
+
+        u8 has_children = 0;
+        abbreviation_stream >> has_children;
+
+        AbbreviationEntry abbrevation_entry {};
+        abbrevation_entry.tag = static_cast<EntryTag>(tag);
+        abbrevation_entry.has_children = (has_children == 1);
+
+        AttributeSpecification current_attribute_specification {};
+        do {
+            size_t attribute_value = 0;
+            size_t form_value = 0;
+            abbreviation_stream.read_LEB128_unsigned(attribute_value);
+            abbreviation_stream.read_LEB128_unsigned(form_value);
+
+            current_attribute_specification.attribute = static_cast<Attribute>(attribute_value);
+            current_attribute_specification.form = static_cast<AttributeDataForm>(form_value);
+
+            if (current_attribute_specification.attribute != Attribute::None) {
+                abbrevation_entry.attribute_specifications.append(current_attribute_specification);
+            }
+        } while (current_attribute_specification.attribute != Attribute::None || current_attribute_specification.form != AttributeDataForm::None);
+
+        m_entries.set((u32)abbreviation_code, abbrevation_entry);
+    }
+}
+
+Optional<AbbreviationsMap::AbbreviationEntry> AbbreviationsMap::get(u32 code) const
+{
+    return m_entries.get(code);
+}
+
+}

+ 58 - 0
Libraries/LibDebug/Dwarf/AbbreviationsMap.h

@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "DwarfTypes.h"
+#include <AK/HashMap.h>
+#include <AK/Optional.h>
+#include <AK/Types.h>
+
+namespace Dwarf {
+class DwarfInfo;
+
+class AbbreviationsMap {
+public:
+    AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset);
+
+    struct AbbreviationEntry {
+
+        EntryTag tag;
+        bool has_children;
+
+        Vector<AttributeSpecification> attribute_specifications;
+    };
+
+    Optional<AbbreviationEntry> get(u32 code) const;
+
+private:
+    void populate_map();
+
+    const DwarfInfo& m_dwarf_info;
+    u32 m_offset { 0 };
+    HashMap<u32, AbbreviationEntry> m_entries;
+};
+
+}

+ 44 - 0
Libraries/LibDebug/Dwarf/CompilationUnit.cpp

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "CompilationUnit.h"
+#include "DIE.h"
+
+namespace Dwarf {
+
+CompilationUnit::CompilationUnit(const DwarfInfo& dwarf_info, u32 offset, const CompilationUnitHeader& header)
+    : m_dwarf_info(dwarf_info)
+    , m_offset(offset)
+    , m_header(header)
+    , m_abbreviations(dwarf_info, header.abbrev_offset)
+{
+}
+
+DIE CompilationUnit::root_die() const
+{
+    return DIE(*this, m_offset + sizeof(CompilationUnitHeader));
+}
+
+}

+ 55 - 0
Libraries/LibDebug/Dwarf/CompilationUnit.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "AbbreviationsMap.h"
+#include <AK/Types.h>
+
+namespace Dwarf {
+
+class DwarfInfo;
+class DIE;
+
+class CompilationUnit {
+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); }
+
+    DIE root_die() const;
+
+    const DwarfInfo& dwarf_info() const { return m_dwarf_info; }
+    const AbbreviationsMap& abbreviations_map() const { return m_abbreviations; }
+
+private:
+    const DwarfInfo& m_dwarf_info;
+    u32 m_offset { 0 };
+    CompilationUnitHeader m_header;
+    AbbreviationsMap m_abbreviations;
+};
+
+}

+ 204 - 0
Libraries/LibDebug/Dwarf/DIE.cpp

@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DIE.h"
+#include "CompilationUnit.h"
+#include "DwarfInfo.h"
+#include <AK/BufferStream.h>
+#include <AK/ByteBuffer.h>
+
+namespace Dwarf {
+
+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);
+    stream.read_LEB128_unsigned(m_abbreviation_code);
+    m_data_offset = stream.offset();
+
+    if (m_abbreviation_code == 0) {
+        // An abbrevation code of 0 ( = null DIE entry) means the end of a chain of sibilings
+        m_tag = EntryTag::None;
+    } else {
+        auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code);
+        ASSERT(abbreviation_info.has_value());
+
+        m_tag = abbreviation_info.value().tag;
+        m_has_children = abbreviation_info.value().has_children;
+
+        // We iterate the attributes data only to calculate this DIE's size
+        for (auto attribute_spec : abbreviation_info.value().attribute_specifications) {
+            get_attribute_value(attribute_spec.form, stream);
+        }
+    }
+    m_size = stream.offset() - m_offset;
+}
+
+DIE::AttributeValue DIE::get_attribute_value(AttributeDataForm form,
+    BufferStream& debug_info_stream) const
+{
+    AttributeValue value;
+    switch (form) {
+    case AttributeDataForm::StringPointer: {
+        u32 offset = 0;
+        debug_info_stream >> offset;
+        value.type = AttributeValue::Type::String;
+
+        auto strings_data = m_compilation_unit.dwarf_info().debug_strings_data();
+        value.data.as_string = reinterpret_cast<const char*>(strings_data.data() + offset);
+        break;
+    }
+    case AttributeDataForm::Data1: {
+        u8 data = 0;
+        debug_info_stream >> data;
+        value.type = AttributeValue::Type::UnsignedNumber;
+        value.data.as_u32 = data;
+        break;
+    }
+    case AttributeDataForm::Data2: {
+        u16 data = 0;
+        debug_info_stream >> data;
+        value.type = AttributeValue::Type::UnsignedNumber;
+        value.data.as_u32 = data;
+        break;
+    }
+    case AttributeDataForm::Addr: {
+        u32 address = 0;
+        debug_info_stream >> address;
+        value.type = AttributeValue::Type::UnsignedNumber;
+        value.data.as_u32 = address;
+        break;
+    }
+    case AttributeDataForm::SecOffset: {
+        u32 data = 0;
+        debug_info_stream >> data;
+        value.type = AttributeValue::Type::SecOffset;
+        value.data.as_u32 = data;
+        break;
+    }
+    case AttributeDataForm::Data4: {
+        u32 data = 0;
+        debug_info_stream >> data;
+        value.type = AttributeValue::Type::UnsignedNumber;
+        value.data.as_u32 = data;
+        break;
+    }
+    case AttributeDataForm::Ref4: {
+        u32 data = 0;
+        debug_info_stream >> data;
+        value.type = AttributeValue::Type::DieReference;
+        value.data.as_u32 = data + m_compilation_unit.offset();
+        break;
+    }
+    case AttributeDataForm::FlagPresent: {
+        value.type = AttributeValue::Type::Boolean;
+        value.data.as_bool = true;
+        break;
+    }
+    case AttributeDataForm::ExprLoc: {
+        size_t length = 0;
+        debug_info_stream.read_LEB128_unsigned(length);
+        value.type = AttributeValue::Type::DwarfExpression;
+
+        value.data.as_dwarf_expression.length = length;
+        value.data.as_dwarf_expression.bytes = reinterpret_cast<const u8*>(m_compilation_unit.dwarf_info().debug_info_data().data() + debug_info_stream.offset());
+
+        debug_info_stream.advance(length);
+        break;
+    }
+    case AttributeDataForm::String: {
+        String str;
+        u32 str_offset = debug_info_stream.offset();
+        debug_info_stream >> str;
+        value.type = AttributeValue::Type::String;
+        value.data.as_string = reinterpret_cast<const char*>(str_offset + m_compilation_unit.dwarf_info().debug_info_data().data());
+        break;
+    }
+    default:
+        dbg() << "Unimplemented AttributeDataForm: " << (u32)form;
+        ASSERT_NOT_REACHED();
+    }
+    return value;
+}
+
+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);
+
+    auto abbreviation_info = m_compilation_unit.abbreviations_map().get(m_abbreviation_code);
+    ASSERT(abbreviation_info.has_value());
+
+    for (const auto& attribute_spec : abbreviation_info.value().attribute_specifications) {
+        auto value = get_attribute_value(attribute_spec.form, stream);
+        if (attribute_spec.attribute == attribute) {
+            return value;
+        }
+    }
+    return {};
+}
+
+void DIE::for_each_child(Function<void(const DIE& child)> callback) const
+{
+    if (!m_has_children)
+        return;
+
+    NonnullOwnPtr<DIE> current_child = make<DIE>(m_compilation_unit, m_offset + m_size);
+    while (true) {
+        callback(*current_child);
+        if (current_child->is_null())
+            break;
+        if (!current_child->has_children()) {
+            current_child = make<DIE>(m_compilation_unit, current_child->offset() + current_child->size());
+            continue;
+        }
+
+        auto sibling = current_child->get_attribute(Attribute::Sibling);
+        u32 sibling_offset = 0;
+        if (sibling.has_value()) {
+            sibling_offset = sibling.value().data.as_u32;
+        }
+
+        if (!sibling.has_value()) {
+            // NOTE: According to the spec, the compiler does't have to supply the sibling information.
+            // When it doesn't, we have to recursively iterate the current child's children to find where they end
+            current_child->for_each_child([&](const DIE& sub_child) {
+                sibling_offset = sub_child.offset() + sub_child.size();
+            });
+        }
+        current_child = make<DIE>(m_compilation_unit, sibling_offset);
+    }
+}
+
+DIE DIE::get_die_at_offset(u32 offset) const
+{
+    ASSERT(offset >= m_compilation_unit.offset() && offset < m_compilation_unit.offset() + m_compilation_unit.size());
+    return DIE(m_compilation_unit, offset);
+}
+
+}

+ 94 - 0
Libraries/LibDebug/Dwarf/DIE.h

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "CompilationUnit.h"
+#include "DwarfTypes.h"
+#include <AK/BufferStream.h>
+#include <AK/Function.h>
+#include <AK/NonnullOwnPtr.h>
+#include <AK/Optional.h>
+#include <AK/Types.h>
+
+namespace Dwarf {
+
+class CompilationUnit;
+
+// DIE = Dwarf Information Entry
+class DIE {
+public:
+    DIE(const CompilationUnit&, u32 offset);
+
+    struct AttributeValue {
+        enum class Type {
+            UnsignedNumber,
+            SignedNumber,
+            String,
+            DieReference, // Reference to another DIE in the same compilation unit
+            Boolean,
+            DwarfExpression,
+            SecOffset,
+        } type;
+
+        union {
+            u32 as_u32;
+            i32 as_i32;
+            const char* as_string; // points to bytes in the memory mapped elf image
+            bool as_bool;
+            struct {
+                u32 length;
+                const u8* bytes; // points to bytes in the memory mapped elf image
+            } as_dwarf_expression;
+        } data {};
+    };
+
+    u32 offset() const { return m_offset; }
+    u32 size() const { return m_size; }
+    bool has_children() const { return m_has_children; }
+    EntryTag tag() const { return m_tag; }
+
+    Optional<AttributeValue> get_attribute(const Attribute&) const;
+
+    void for_each_child(Function<void(const DIE& child)> callback) const;
+
+    bool is_null() const { return m_tag == EntryTag::None; }
+
+    DIE get_die_at_offset(u32 offset) const;
+
+private:
+    AttributeValue get_attribute_value(AttributeDataForm form,
+        BufferStream& debug_info_stream) const;
+
+    const CompilationUnit& m_compilation_unit;
+    u32 m_offset { 0 };
+    u32 m_data_offset { 0 };
+    size_t m_abbreviation_code { 0 };
+    EntryTag m_tag { EntryTag::None };
+    bool m_has_children { false };
+    u32 m_size { 0 };
+};
+
+}

+ 69 - 0
Libraries/LibDebug/Dwarf/DwarfInfo.cpp

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "DwarfInfo.h"
+
+namespace Dwarf {
+
+DwarfInfo::DwarfInfo(NonnullRefPtr<const ELF::Loader> elf)
+    : m_elf(elf)
+{
+    m_debug_info_data = section_data(".debug_info");
+    m_abbreviation_data = section_data(".debug_abbrev");
+    m_debug_strings_data = section_data(".debug_str");
+
+    populate_compilation_units();
+}
+
+ByteBuffer DwarfInfo::section_data(const String& section_name)
+{
+    auto section = m_elf->image().lookup_section(section_name);
+    ASSERT(!section.is_undefined());
+    return ByteBuffer::wrap(reinterpret_cast<const u8*>(section.raw_data()), section.size());
+}
+
+void DwarfInfo::populate_compilation_units()
+{
+    // 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()) {
+        auto unit_offset = stream.offset();
+        CompilationUnitHeader compilation_unit_header {};
+
+        stream.read_raw(reinterpret_cast<u8*>(&compilation_unit_header), sizeof(CompilationUnitHeader));
+        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);
+    }
+}
+
+}

+ 72 - 0
Libraries/LibDebug/Dwarf/DwarfInfo.h

@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "CompilationUnit.h"
+#include "DwarfTypes.h"
+#include <AK/BufferStream.h>
+#include <AK/ByteBuffer.h>
+#include <AK/NonnullRefPtr.h>
+#include <AK/RefCounted.h>
+#include <AK/String.h>
+#include <Libraries/LibELF/Loader.h>
+
+namespace Dwarf {
+
+class DwarfInfo : public RefCounted<DwarfInfo> {
+public:
+    static NonnullRefPtr<DwarfInfo> create(NonnullRefPtr<const ELF::Loader> elf) { return adopt(*new DwarfInfo(elf)); }
+
+    const ByteBuffer& debug_info_data() const { return m_debug_info_data; }
+    const ByteBuffer& abbreviation_data() const { return m_abbreviation_data; }
+    const ByteBuffer& debug_strings_data() const { return m_debug_strings_data; }
+
+    template<typename Callback>
+    void for_each_compilation_unit(Callback) const;
+
+private:
+    explicit DwarfInfo(NonnullRefPtr<const ELF::Loader> elf);
+    void populate_compilation_units();
+
+    ByteBuffer section_data(const String& section_name);
+
+    NonnullRefPtr<const ELF::Loader> m_elf;
+    ByteBuffer m_debug_info_data;
+    ByteBuffer m_abbreviation_data;
+    ByteBuffer m_debug_strings_data;
+
+    Vector<Dwarf::CompilationUnit> m_compilation_units;
+};
+
+template<typename Callback>
+void DwarfInfo::for_each_compilation_unit(Callback callback) const
+{
+    for (const auto& unit : m_compilation_units) {
+        callback(unit);
+    }
+}
+
+}

+ 79 - 0
Libraries/LibDebug/Dwarf/DwarfTypes.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#pragma once
+#include <AK/Types.h>
+
+namespace Dwarf {
+
+struct [[gnu::packed]] CompilationUnitHeader
+{
+    u32 length;
+    u16 version;
+    u32 abbrev_offset;
+    u8 address_size;
+};
+
+enum class EntryTag : u32 {
+    None = 0,
+    LexicalBlock = 0xb,
+    Member = 0xd,
+    SubProgram = 0x2e,
+    Variable = 0x34,
+};
+
+enum class Attribute : u32 {
+    None = 0,
+    Sibling = 0x1,
+    Location = 0x2,
+    Name = 0x3,
+    LowPc = 0x11,
+    HighPc = 0x12,
+    Inline = 0x20,
+    MemberLocation = 0x38,
+    Type = 0x49,
+    Ranges = 0x55,
+};
+
+enum class AttributeDataForm : u32 {
+    None = 0,
+    Addr = 0x1,
+    Data2 = 0x5,
+    Data4 = 0x6,
+    String = 0x8,
+    Data1 = 0xb,
+    StringPointer = 0xe,
+    Ref4 = 0x13,
+    SecOffset = 0x17,
+    ExprLoc = 0x18,
+    FlagPresent = 0x19,
+};
+
+struct AttributeSpecification {
+    Attribute attribute;
+    AttributeDataForm form;
+};
+
+}

+ 65 - 0
Libraries/LibDebug/Dwarf/Expression.cpp

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "Expression.h"
+#include <AK/BufferStream.h>
+#include <sys/arch/i386/regs.h>
+
+namespace Dwarf {
+namespace Expression {
+
+Value evaluate(const ByteBuffer& bytes, const PtraceRegisters& regs)
+{
+    // TODO: we need a BufferStream variant that takes a const ByteBuffer
+    BufferStream stream(const_cast<ByteBuffer&>(bytes));
+
+    while (!stream.at_end()) {
+        u8 opcode = 0;
+        stream >> opcode;
+
+        switch (static_cast<Operations>(opcode)) {
+        case Operations::RegEbp: {
+            int offset = 0;
+            stream.read_LEB128_signed(offset);
+            return Value { Type::UnsignedIntetger, regs.ebp + offset };
+        }
+
+        case Operations::FbReg: {
+            int offset = 0;
+            stream.read_LEB128_signed(offset);
+            return Value { Type::UnsignedIntetger, regs.ebp + 2 * sizeof(size_t) + offset };
+        }
+
+        default:
+            dbg() << "DWARF expr addr: " << (const void*)bytes.data();
+            dbg() << "unsupported opcode: " << (u8)opcode;
+            ASSERT_NOT_REACHED();
+        }
+    }
+    ASSERT_NOT_REACHED();
+}
+
+};
+};

+ 56 - 0
Libraries/LibDebug/Dwarf/Expression.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+#include "AK/ByteBuffer.h"
+#include "AK/Types.h"
+
+class PtraceRegisters;
+
+namespace Dwarf {
+namespace Expression {
+enum class Type {
+    None,
+    UnsignedIntetger,
+    Register,
+};
+
+struct Value {
+    Type type;
+    union {
+        u32 as_u32;
+    } data { 0 };
+};
+
+enum class Operations : u8 {
+    RegEbp = 0x75,
+    FbReg = 0x91,
+};
+
+Value evaluate(const ByteBuffer&, const PtraceRegisters&);
+
+};
+};

+ 5 - 0
Libraries/LibDebug/Makefile

@@ -2,6 +2,11 @@ OBJS = \
     DebugSession.o \
 	DebugInfo.o \
 	Dwarf/LineProgram.o \
+	Dwarf/DwarfInfo.o \
+	Dwarf/CompilationUnit.o \
+	Dwarf/AbbreviationsMap.o \
+	Dwarf/Expression.o \
+	Dwarf/DIE.o \
 
 
 LIBRARY = libdebug.a