Jelajahi Sumber

LibDebug: Add support for parsing array types

This includes multi-dimensional arrays :O
FalseHonesty 4 tahun lalu
induk
melakukan
2d58549296

+ 2 - 0
Base/home/anon/Source/little/main.cpp

@@ -23,6 +23,8 @@ int main(int, char**)
     MyStruct my_struct;
     MyStruct my_struct;
     my_struct.status = !my_struct.status;
     my_struct.status = !my_struct.status;
     printf("my_struct.x is %d\n", my_struct.x);
     printf("my_struct.x is %d\n", my_struct.x);
+    int arr[6] = { -1, 2, 20, 5, 5 };
+    int other_arr[1][2] = { { 0, 2 } };
     Container container;
     Container container;
     for (int i = 0; i < 3; ++i) {
     for (int i = 0; i < 3; ++i) {
         // This is a comment :^)
         // This is a comment :^)

+ 55 - 28
Userland/Libraries/LibDebug/DebugInfo.cpp

@@ -290,41 +290,67 @@ OwnPtr<DebugInfo::VariableInfo> DebugInfo::create_variable_info(const Dwarf::DIE
         variable_info->location_data.address += address_offset;
         variable_info->location_data.address += address_offset;
     }
     }
 
 
-    if (type_die.has_value()) {
-        OwnPtr<VariableInfo> type_info;
-        if (type_die.value().tag() == Dwarf::EntryTag::EnumerationType || type_die.value().tag() == Dwarf::EntryTag::StructureType) {
-            type_info = create_variable_info(type_die.value(), regs);
+    if (type_die.has_value())
+        add_type_info_to_variable(type_die.value(), regs, variable_info);
+
+    return variable_info;
+}
+
+void DebugInfo::add_type_info_to_variable(const Dwarf::DIE& type_die, const PtraceRegisters& regs, DebugInfo::VariableInfo* parent_variable) const
+{
+    OwnPtr<VariableInfo> type_info;
+    auto is_array_type = type_die.tag() == Dwarf::EntryTag::ArrayType;
+
+    if (type_die.tag() == Dwarf::EntryTag::EnumerationType
+        || type_die.tag() == Dwarf::EntryTag::StructureType
+        || is_array_type) {
+        type_info = create_variable_info(type_die, regs);
+    }
+
+    type_die.for_each_child([&](const Dwarf::DIE& member) {
+        if (member.is_null())
+            return;
+
+        if (is_array_type && member.tag() == Dwarf::EntryTag::SubRangeType) {
+            auto upper_bound = member.get_attribute(Dwarf::Attribute::UpperBound);
+            VERIFY(upper_bound.has_value());
+            auto size = upper_bound.value().data.as_u32 + 1;
+            type_info->dimension_sizes.append(size);
+            return;
         }
         }
 
 
-        type_die.value().for_each_child([&](const Dwarf::DIE& member) {
-            if (member.is_null())
-                return;
-            if (!is_variable_tag_supported(member.tag()))
-                return;
+        if (!is_variable_tag_supported(member.tag()))
+            return;
 
 
-            auto member_variable = create_variable_info(member, regs, variable_info->location_data.address);
-            VERIFY(member_variable);
+        auto member_variable = create_variable_info(member, regs, parent_variable->location_data.address);
+        VERIFY(member_variable);
 
 
-            if (type_die.value().tag() == Dwarf::EntryTag::EnumerationType) {
-                member_variable->parent = type_info.ptr();
-                type_info->members.append(member_variable.release_nonnull());
-            } else {
-                if (variable_info->location_type == DebugInfo::VariableInfo::LocationType::None)
-                    return;
-                VERIFY(variable_info->location_type == DebugInfo::VariableInfo::LocationType::Address);
+        if (type_die.tag() == Dwarf::EntryTag::EnumerationType) {
+            member_variable->parent = type_info.ptr();
+            type_info->members.append(member_variable.release_nonnull());
+        } else {
+            if (parent_variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
+                return;
 
 
-                member_variable->parent = variable_info.ptr();
-                variable_info->members.append(member_variable.release_nonnull());
-            }
-        });
+            member_variable->parent = parent_variable;
+            parent_variable->members.append(member_variable.release_nonnull());
+        }
+    });
 
 
-        if (type_info) {
-            variable_info->type = move(type_info);
-            variable_info->type->type_tag = type_die.value().tag();
+    if (type_info) {
+        if (is_array_type) {
+            StringBuilder array_type_name;
+            array_type_name.append(type_info->type_name);
+            for (auto array_size : type_info->dimension_sizes) {
+                array_type_name.append("[");
+                array_type_name.append(String::formatted("{:d}", array_size));
+                array_type_name.append("]");
+            }
+            parent_variable->type_name = array_type_name.to_string();
         }
         }
+        parent_variable->type = move(type_info);
+        parent_variable->type->type_tag = type_die.tag();
     }
     }
-
-    return variable_info;
 }
 }
 
 
 bool DebugInfo::is_variable_tag_supported(const Dwarf::EntryTag& tag)
 bool DebugInfo::is_variable_tag_supported(const Dwarf::EntryTag& tag)
@@ -334,7 +360,8 @@ bool DebugInfo::is_variable_tag_supported(const Dwarf::EntryTag& tag)
         || tag == Dwarf::EntryTag::FormalParameter
         || tag == Dwarf::EntryTag::FormalParameter
         || tag == Dwarf::EntryTag::EnumerationType
         || tag == Dwarf::EntryTag::EnumerationType
         || tag == Dwarf::EntryTag::Enumerator
         || tag == Dwarf::EntryTag::Enumerator
-        || tag == Dwarf::EntryTag::StructureType;
+        || tag == Dwarf::EntryTag::StructureType
+        || tag == Dwarf::EntryTag::ArrayType;
 }
 }
 
 
 String DebugInfo::name_of_containing_function(u32 address) const
 String DebugInfo::name_of_containing_function(u32 address) const

+ 2 - 0
Userland/Libraries/LibDebug/DebugInfo.h

@@ -94,6 +94,7 @@ public:
         OwnPtr<VariableInfo> type;
         OwnPtr<VariableInfo> type;
         NonnullOwnPtrVector<VariableInfo> members;
         NonnullOwnPtrVector<VariableInfo> members;
         VariableInfo* parent { nullptr };
         VariableInfo* parent { nullptr };
+        Vector<u32> dimension_sizes;
 
 
         bool is_enum_type() const { return type && type->type_tag == Dwarf::EntryTag::EnumerationType; }
         bool is_enum_type() const { return type && type->type_tag == Dwarf::EntryTag::EnumerationType; }
     };
     };
@@ -142,6 +143,7 @@ private:
     void parse_scopes_impl(const Dwarf::DIE& die);
     void parse_scopes_impl(const Dwarf::DIE& die);
     OwnPtr<VariableInfo> create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&, u32 address_offset = 0) const;
     OwnPtr<VariableInfo> create_variable_info(const Dwarf::DIE& variable_die, const PtraceRegisters&, u32 address_offset = 0) const;
     static bool is_variable_tag_supported(const Dwarf::EntryTag& tag);
     static bool is_variable_tag_supported(const Dwarf::EntryTag& tag);
+    void add_type_info_to_variable(const Dwarf::DIE& type_die, const PtraceRegisters& regs, DebugInfo::VariableInfo* parent_variable) const;
 
 
     NonnullOwnPtr<const ELF::Image> m_elf;
     NonnullOwnPtr<const ELF::Image> m_elf;
     String m_source_root;
     String m_source_root;