瀏覽代碼

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.
Gunnar Beutner 4 年之前
父節點
當前提交
9bcdbe205b

+ 6 - 0
Userland/Libraries/LibDebug/Dwarf/AbbreviationsMap.cpp

@@ -51,6 +51,12 @@ void AbbreviationsMap::populate_map()
             current_attribute_specification.attribute = static_cast<Attribute>(attribute_value);
             current_attribute_specification.form = static_cast<AttributeDataForm>(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);
             }

+ 2 - 2
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<AttributeValue> 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;
         }

+ 7 - 1
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<const char*>(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();

+ 1 - 1
Userland/Libraries/LibDebug/Dwarf/DwarfInfo.h

@@ -54,7 +54,7 @@ public:
     template<typename Callback>
     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:

+ 1 - 0
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;
 };
 
 }

+ 1 - 1
Userland/Libraries/LibDebug/Dwarf/LineProgram.cpp

@@ -57,7 +57,7 @@ void LineProgram::parse_path_entries(Function<void(PathEntry& entry)> 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;