From 9bcdbe205b02078f7a6ff01d8769efe4617e60be Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 29 Apr 2021 00:51:54 +0200 Subject: [PATCH] LibDebug: Implement support for AttributeDataForm::ImplicitConst While symbolicating a crash dump for UserspaceEmulator I came across another data form we didn't support. ImplicitConst encodes a LEB128 value in the abbreviation record rather than - like all other values - in the .debug_info section. --- Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp | 6 ++++++ Userland/Libraries/LibDebug/Dwarf/DIE.cpp | 4 ++-- Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp | 8 +++++++- Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h | 2 +- Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h | 1 + Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp | 2 +- 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp b/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp index 8f5c75710b..bbc00fdeb9 100644 --- a/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp @@ -51,6 +51,12 @@ void AbbreviationsMap::populate_map() current_attribute_specification.attribute = static_cast(attribute_value); current_attribute_specification.form = static_cast(form_value); + if (current_attribute_specification.form == AttributeDataForm::ImplicitConst) { + ssize_t data_value; + abbreviation_stream.read_LEB128_signed(data_value); + current_attribute_specification.value = data_value; + } + if (current_attribute_specification.attribute != Attribute::None) { abbrevation_entry.attribute_specifications.append(current_attribute_specification); } diff --git a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp index 2e1150c0a7..a2eef74d94 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DIE.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DIE.cpp @@ -33,7 +33,7 @@ DIE::DIE(const CompilationUnit& unit, u32 offset) // We iterate the attributes data only to calculate this DIE's size for (auto& attribute_spec : abbreviation_info.value().attribute_specifications) { - m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, stream, &m_compilation_unit); + m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit); } } m_size = stream.offset() - m_offset; @@ -48,7 +48,7 @@ Optional DIE::get_attribute(const Attribute& attribute) const VERIFY(abbreviation_info.has_value()); for (const auto& attribute_spec : abbreviation_info.value().attribute_specifications) { - auto value = m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, stream, &m_compilation_unit); + auto value = m_compilation_unit.dwarf_info().get_attribute_value(attribute_spec.form, attribute_spec.value, stream, &m_compilation_unit); if (attribute_spec.attribute == attribute) { return value; } diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp index 85f0c7d9b0..34d7e016e3 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.cpp @@ -49,7 +49,7 @@ void DwarfInfo::populate_compilation_units() } } -AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, +AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, InputMemoryStream& debug_info_stream, const CompilationUnit* unit) const { AttributeValue value; @@ -210,6 +210,12 @@ AttributeValue DwarfInfo::get_attribute_value(AttributeDataForm form, value.data.as_string = reinterpret_cast(strings_data.data() + offset); break; } + case AttributeDataForm::ImplicitConst: { + /* Value is part of the abbreviation record. */ + value.type = AttributeValue::Type::SignedNumber; + value.data.as_i32 = implicit_const_value; + break; + } default: dbgln("Unimplemented AttributeDataForm: {}", (u32)form); VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h index fa7d45383c..d4de6c8319 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h @@ -54,7 +54,7 @@ public: template void for_each_compilation_unit(Callback) const; - AttributeValue get_attribute_value(AttributeDataForm form, + AttributeValue get_attribute_value(AttributeDataForm form, ssize_t implicit_const_value, InputMemoryStream& debug_info_stream, const CompilationUnit* unit = nullptr) const; private: diff --git a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h index 19de2ea809..8a66ca71ea 100644 --- a/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h +++ b/Userland/Libraries/LibDebug/Dwarf/DwarfTypes.h @@ -314,6 +314,7 @@ enum class AttributeDataForm : u8 { struct [[gnu::packed]] AttributeSpecification { Attribute attribute; AttributeDataForm form; + ssize_t value; }; } diff --git a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp index 1c662ba77a..d9f8d14fbc 100644 --- a/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp +++ b/Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp @@ -57,7 +57,7 @@ void LineProgram::parse_path_entries(Function callback, for (size_t i = 0; i < paths_count; i++) { PathEntry entry; for (auto& format_description : format_descriptions) { - auto value = m_dwarf_info.get_attribute_value(format_description.form, m_stream); + auto value = m_dwarf_info.get_attribute_value(format_description.form, 0, m_stream); switch (format_description.type) { case ContentType::Path: entry.path = value.data.as_string;