Skip to content

Commit

Permalink
LibDebug: Add support for parsing array types
Browse files Browse the repository at this point in the history
This includes multi-dimensional arrays :O
  • Loading branch information
FalseHonesty authored and awesomekling committed Apr 14, 2021
1 parent acbb119 commit 2d58549
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 28 deletions.
2 changes: 2 additions & 0 deletions Base/home/anon/Source/little/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 :^)
Expand Down
83 changes: 55 additions & 28 deletions Userland/Libraries/LibDebug/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,41 +290,67 @@ OwnPtr<DebugInfo::VariableInfo> DebugInfo::create_variable_info(const Dwarf::DIE
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)
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibDebug/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class DebugInfo {
OwnPtr<VariableInfo> type;
NonnullOwnPtrVector<VariableInfo> members;
VariableInfo* parent { nullptr };
Vector<u32> dimension_sizes;

bool is_enum_type() const { return type && type->type_tag == Dwarf::EntryTag::EnumerationType; }
};
Expand Down Expand Up @@ -142,6 +143,7 @@ class DebugInfo {
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;
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;
String m_source_root;
Expand Down

0 comments on commit 2d58549

Please sign in to comment.