From c5eb20d0cc8cdd1abeb0392506ffa4c4ef2cb855 Mon Sep 17 00:00:00 2001 From: Itamar Date: Mon, 4 May 2020 12:14:39 +0300 Subject: [PATCH] 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. --- Libraries/LibDebug/DebugInfo.cpp | 146 ++++++++++++- Libraries/LibDebug/DebugInfo.h | 37 ++++ Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp | 86 ++++++++ Libraries/LibDebug/Dwarf/AbbreviationsMap.h | 58 +++++ Libraries/LibDebug/Dwarf/CompilationUnit.cpp | 44 ++++ Libraries/LibDebug/Dwarf/CompilationUnit.h | 55 +++++ Libraries/LibDebug/Dwarf/DIE.cpp | 204 ++++++++++++++++++ Libraries/LibDebug/Dwarf/DIE.h | 94 ++++++++ Libraries/LibDebug/Dwarf/DwarfInfo.cpp | 69 ++++++ Libraries/LibDebug/Dwarf/DwarfInfo.h | 72 +++++++ Libraries/LibDebug/Dwarf/DwarfTypes.h | 79 +++++++ Libraries/LibDebug/Dwarf/Expression.cpp | 65 ++++++ Libraries/LibDebug/Dwarf/Expression.h | 56 +++++ Libraries/LibDebug/Makefile | 5 + 14 files changed, 1067 insertions(+), 3 deletions(-) create mode 100644 Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp create mode 100644 Libraries/LibDebug/Dwarf/AbbreviationsMap.h create mode 100644 Libraries/LibDebug/Dwarf/CompilationUnit.cpp create mode 100644 Libraries/LibDebug/Dwarf/CompilationUnit.h create mode 100644 Libraries/LibDebug/Dwarf/DIE.cpp create mode 100644 Libraries/LibDebug/Dwarf/DIE.h create mode 100644 Libraries/LibDebug/Dwarf/DwarfInfo.cpp create mode 100644 Libraries/LibDebug/Dwarf/DwarfInfo.h create mode 100644 Libraries/LibDebug/Dwarf/DwarfTypes.h create mode 100644 Libraries/LibDebug/Dwarf/Expression.cpp create mode 100644 Libraries/LibDebug/Dwarf/Expression.h diff --git a/Libraries/LibDebug/DebugInfo.cpp b/Libraries/LibDebug/DebugInfo.cpp index c684b190ec..0b5d98bbe1 100644 --- a/Libraries/LibDebug/DebugInfo.cpp +++ b/Libraries/LibDebug/DebugInfo.cpp @@ -26,16 +26,66 @@ #include "DebugInfo.h" #include +#include +#include +#include DebugInfo::DebugInfo(NonnullRefPtr elf) : m_elf(elf) + , m_dwarf_info(Dwarf::DwarfInfo::create(m_elf)) { + prepare_variable_scopes(); 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 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::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 DebugInfo::get_instruction_from_source(const String& file, size_t } return {}; } + +NonnullOwnPtrVector DebugInfo::get_variables_in_current_scope(const PtraceRegisters& regs) const +{ + auto scope = get_scope(regs.eip); + if (!scope.has_value()) + return {}; + + NonnullOwnPtrVector variables; + for (const auto& die_entry : scope.value().dies_of_variables) { + variables.append(create_variable_info(die_entry, regs)); + } + return variables; +} + +Optional DebugInfo::get_scope(u32 instruction_pointer) const +{ + Optional 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::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 variable_info = make(); + + 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; +} diff --git a/Libraries/LibDebug/DebugInfo.h b/Libraries/LibDebug/DebugInfo.h index 825a27e073..51a5b62b9c 100644 --- a/Libraries/LibDebug/DebugInfo.h +++ b/Libraries/LibDebug/DebugInfo.h @@ -26,11 +26,15 @@ #pragma once +#include #include #include #include +#include #include +#include #include +#include 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 members; + VariableInfo* parent { nullptr }; + }; + + struct VariablesScope { + bool is_function { false }; + Optional name; + u32 address_low { 0 }; + u32 address_high { 0 }; + Vector dies_of_variables; + }; + + NonnullOwnPtrVector get_variables_in_current_scope(const PtraceRegisters&) const; + Optional get_source_position(u32 address) const; Optional 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 get_scope(u32 instruction_pointer) const; + NonnullOwnPtr create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&) const; NonnullRefPtr m_elf; + NonnullRefPtr m_dwarf_info; + Vector m_scopes; Vector m_sorted_lines; }; diff --git a/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp b/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp new file mode 100644 index 0000000000..78c76caf1e --- /dev/null +++ b/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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(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(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_value); + current_attribute_specification.form = static_cast(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::get(u32 code) const +{ + return m_entries.get(code); +} + +} diff --git a/Libraries/LibDebug/Dwarf/AbbreviationsMap.h b/Libraries/LibDebug/Dwarf/AbbreviationsMap.h new file mode 100644 index 0000000000..97764741a9 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/AbbreviationsMap.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 +#include +#include + +namespace Dwarf { +class DwarfInfo; + +class AbbreviationsMap { +public: + AbbreviationsMap(const DwarfInfo& dwarf_info, u32 offset); + + struct AbbreviationEntry { + + EntryTag tag; + bool has_children; + + Vector attribute_specifications; + }; + + Optional get(u32 code) const; + +private: + void populate_map(); + + const DwarfInfo& m_dwarf_info; + u32 m_offset { 0 }; + HashMap m_entries; +}; + +} diff --git a/Libraries/LibDebug/Dwarf/CompilationUnit.cpp b/Libraries/LibDebug/Dwarf/CompilationUnit.cpp new file mode 100644 index 0000000000..c22f3f34cd --- /dev/null +++ b/Libraries/LibDebug/Dwarf/CompilationUnit.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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)); +} + +} diff --git a/Libraries/LibDebug/Dwarf/CompilationUnit.h b/Libraries/LibDebug/Dwarf/CompilationUnit.h new file mode 100644 index 0000000000..97c4892915 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/CompilationUnit.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 + +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; +}; + +} diff --git a/Libraries/LibDebug/Dwarf/DIE.cpp b/Libraries/LibDebug/Dwarf/DIE.cpp new file mode 100644 index 0000000000..e8f957d432 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/DIE.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 +#include + +namespace Dwarf { + +DIE::DIE(const CompilationUnit& unit, u32 offset) + : m_compilation_unit(unit) + , m_offset(offset) +{ + BufferStream stream(const_cast(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(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(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(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::get_attribute(const Attribute& attribute) const +{ + BufferStream stream(const_cast(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 callback) const +{ + if (!m_has_children) + return; + + NonnullOwnPtr current_child = make(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(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(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); +} + +} diff --git a/Libraries/LibDebug/Dwarf/DIE.h b/Libraries/LibDebug/Dwarf/DIE.h new file mode 100644 index 0000000000..ec37443117 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/DIE.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 +#include +#include +#include +#include + +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 get_attribute(const Attribute&) const; + + void for_each_child(Function 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 }; +}; + +} diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp new file mode 100644 index 0000000000..c04e4b8a72 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 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(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(m_debug_info_data)); + while (!stream.at_end()) { + auto unit_offset = stream.offset(); + CompilationUnitHeader compilation_unit_header {}; + + stream.read_raw(reinterpret_cast(&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); + } +} + +} diff --git a/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Libraries/LibDebug/Dwarf/DwarfInfo.h new file mode 100644 index 0000000000..1dc5de1845 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 +#include +#include +#include +#include +#include + +namespace Dwarf { + +class DwarfInfo : public RefCounted { +public: + static NonnullRefPtr create(NonnullRefPtr 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 + void for_each_compilation_unit(Callback) const; + +private: + explicit DwarfInfo(NonnullRefPtr elf); + void populate_compilation_units(); + + ByteBuffer section_data(const String& section_name); + + NonnullRefPtr m_elf; + ByteBuffer m_debug_info_data; + ByteBuffer m_abbreviation_data; + ByteBuffer m_debug_strings_data; + + Vector m_compilation_units; +}; + +template +void DwarfInfo::for_each_compilation_unit(Callback callback) const +{ + for (const auto& unit : m_compilation_units) { + callback(unit); + } +} + +} diff --git a/Libraries/LibDebug/Dwarf/DwarfTypes.h b/Libraries/LibDebug/Dwarf/DwarfTypes.h new file mode 100644 index 0000000000..cd8efb04d8 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/DwarfTypes.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 + +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; +}; + +} diff --git a/Libraries/LibDebug/Dwarf/Expression.cpp b/Libraries/LibDebug/Dwarf/Expression.cpp new file mode 100644 index 0000000000..b9d57628fb --- /dev/null +++ b/Libraries/LibDebug/Dwarf/Expression.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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 +#include + +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(bytes)); + + while (!stream.at_end()) { + u8 opcode = 0; + stream >> opcode; + + switch (static_cast(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(); +} + +}; +}; diff --git a/Libraries/LibDebug/Dwarf/Expression.h b/Libraries/LibDebug/Dwarf/Expression.h new file mode 100644 index 0000000000..5f71b68b91 --- /dev/null +++ b/Libraries/LibDebug/Dwarf/Expression.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, Itamar S. + * 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&); + +}; +}; diff --git a/Libraries/LibDebug/Makefile b/Libraries/LibDebug/Makefile index 329450bb51..e6f37a9d1a 100644 --- a/Libraries/LibDebug/Makefile +++ b/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