From 2d58549296531819332e106d86dc92dfbf017ea5 Mon Sep 17 00:00:00 2001 From: FalseHonesty Date: Tue, 13 Apr 2021 22:08:24 -0400 Subject: [PATCH] LibDebug: Add support for parsing array types This includes multi-dimensional arrays :O --- Base/home/anon/Source/little/main.cpp | 2 + Userland/Libraries/LibDebug/DebugInfo.cpp | 95 +++++++++++++++-------- Userland/Libraries/LibDebug/DebugInfo.h | 2 + 3 files changed, 65 insertions(+), 34 deletions(-) diff --git a/Base/home/anon/Source/little/main.cpp b/Base/home/anon/Source/little/main.cpp index 9ee63e2f4c..42816ee22c 100644 --- a/Base/home/anon/Source/little/main.cpp +++ b/Base/home/anon/Source/little/main.cpp @@ -23,6 +23,8 @@ int main(int, char**) MyStruct my_struct; my_struct.status = !my_struct.status; 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; for (int i = 0; i < 3; ++i) { // This is a comment :^) diff --git a/Userland/Libraries/LibDebug/DebugInfo.cpp b/Userland/Libraries/LibDebug/DebugInfo.cpp index 5b1c77aa81..f49f799796 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.cpp +++ b/Userland/Libraries/LibDebug/DebugInfo.cpp @@ -290,43 +290,69 @@ OwnPtr DebugInfo::create_variable_info(const Dwarf::DIE variable_info->location_data.address += address_offset; } - if (type_die.has_value()) { - OwnPtr 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); - } - - type_die.value().for_each_child([&](const Dwarf::DIE& member) { - if (member.is_null()) - 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); - - 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); - - member_variable->parent = variable_info.ptr(); - variable_info->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_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 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; + } + + if (!is_variable_tag_supported(member.tag())) + return; + + auto member_variable = create_variable_info(member, regs, parent_variable->location_data.address); + VERIFY(member_variable); + + 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 = parent_variable; + parent_variable->members.append(member_variable.release_nonnull()); + } + }); + + 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(); + } +} + bool DebugInfo::is_variable_tag_supported(const Dwarf::EntryTag& tag) { return tag == Dwarf::EntryTag::Variable @@ -334,7 +360,8 @@ bool DebugInfo::is_variable_tag_supported(const Dwarf::EntryTag& tag) || tag == Dwarf::EntryTag::FormalParameter || tag == Dwarf::EntryTag::EnumerationType || 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 diff --git a/Userland/Libraries/LibDebug/DebugInfo.h b/Userland/Libraries/LibDebug/DebugInfo.h index a70e96c5f4..14ba0c1712 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.h +++ b/Userland/Libraries/LibDebug/DebugInfo.h @@ -94,6 +94,7 @@ public: OwnPtr type; NonnullOwnPtrVector members; VariableInfo* parent { nullptr }; + Vector dimension_sizes; 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); OwnPtr 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); + void add_type_info_to_variable(const Dwarf::DIE& type_die, const PtraceRegisters& regs, DebugInfo::VariableInfo* parent_variable) const; NonnullOwnPtr m_elf; String m_source_root;