From: Tom de Vries Date: Tue, 8 Oct 2024 10:27:20 +0000 (+0200) Subject: [gdb/symtab] Fix parent of enumerator X-Git-Tag: gdb-16-branchpoint~706 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=42d385542f5f948e68db256b249662683057b288;p=thirdparty%2Fbinutils-gdb.git [gdb/symtab] Fix parent of enumerator As mentioned in commit 489b82720f5 ('[gdb/symtab] Revert "Change handling of DW_TAG_enumeration_type in DWARF scanner"'), when doing "maint print objfiles" in test-case gdb.dwarf2/enum-type.exp, for val1 we get an entry without parent: ... [27] ((cooked_index_entry *) 0x7fbbb4002ef0) name: val1 canonical: val1 qualified: val1 DWARF tag: DW_TAG_enumerator flags: 0x0 [] DIE offset: 0x124 parent: ((cooked_index_entry *) 0) ... This happens here in cooked_indexer::index_dies: ... info_ptr = recurse (reader, info_ptr, is_enum_class ? this_entry : parent_entry, fully); ... when we're passing down a nullptr parent_entry, while the parent of this_entry is deferred. Fix this in cooked_indexer::index_dies by passing down a deffered parent instead, such that we get: ... [27] ((cooked_index_entry *) 0x7ff0e4002ef0)^M name: val1^M canonical: val1^M qualified: ns::val1^M DWARF tag: DW_TAG_enumerator^M flags: 0x0 []^M DIE offset: 0x124^M parent: ((cooked_index_entry *) 0x7ff0e4002f20) [ns]^M ... Tested on x86_64-linux. Approved-By: Tom Tromey --- diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index bf9eeef3820..95e7d6aee31 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -96,6 +96,7 @@ #include "run-on-main-thread.h" #include "dwarf2/parent-map.h" #include "dwarf2/error.h" +#include /* When == 1, print basic high level tracing messages. When > 1, be more verbose. @@ -4530,7 +4531,7 @@ private: bool is_dwz, bool for_scanning); - /* Index DIEs in the READER starting at INFO_PTR. PARENT_ENTRY is + /* Index DIEs in the READER starting at INFO_PTR. PARENT is the entry for the enclosing scope (nullptr at top level). FULLY is true when a full scan must be done -- in some languages, function scopes must be fully explored in order to find nested @@ -4538,7 +4539,8 @@ private: reading stopped. */ const gdb_byte *index_dies (cutu_reader *reader, const gdb_byte *info_ptr, - const cooked_index_entry *parent_entry, + std::variant parent, bool fully); /* Scan the attributes for a given DIE and update the out @@ -4568,7 +4570,8 @@ private: m_die_range_map and then calling index_dies. */ const gdb_byte *recurse (cutu_reader *reader, const gdb_byte *info_ptr, - const cooked_index_entry *parent_entry, + std::variant parent_entry, bool fully); /* The storage object, where the results are kept. */ @@ -16466,10 +16469,16 @@ cooked_indexer::index_imported_unit (cutu_reader *reader, const gdb_byte * cooked_indexer::recurse (cutu_reader *reader, const gdb_byte *info_ptr, - const cooked_index_entry *parent_entry, + std::variant parent, bool fully) { - info_ptr = index_dies (reader, info_ptr, parent_entry, fully); + info_ptr = index_dies (reader, info_ptr, parent, fully); + + if (!std::holds_alternative (parent)) + return info_ptr; + const cooked_index_entry *parent_entry + = std::get (parent); if (parent_entry != nullptr) { @@ -16490,7 +16499,8 @@ cooked_indexer::recurse (cutu_reader *reader, const gdb_byte * cooked_indexer::index_dies (cutu_reader *reader, const gdb_byte *info_ptr, - const cooked_index_entry *parent_entry, + std::variant parent, bool fully) { const gdb_byte *end_ptr = (reader->buffer @@ -16517,15 +16527,20 @@ cooked_indexer::index_dies (cutu_reader *reader, { info_ptr = skip_one_die (reader, info_ptr, abbrev, !fully); if (fully && abbrev->has_children) - info_ptr = index_dies (reader, info_ptr, parent_entry, fully); + info_ptr = index_dies (reader, info_ptr, parent, fully); continue; } const char *name = nullptr; const char *linkage_name = nullptr; parent_map::addr_type defer {}; + if (std::holds_alternative (parent)) + defer = std::get (parent); cooked_index_flag flags = IS_STATIC; sect_offset sibling {}; + const cooked_index_entry *parent_entry = nullptr; + if (std::holds_alternative (parent)) + parent_entry = std::get (parent); const cooked_index_entry *this_parent_entry = parent_entry; bool is_enum_class = false; @@ -16609,9 +16624,21 @@ cooked_indexer::index_dies (cutu_reader *reader, the enum itself as the parent, yielding names like "enum_class::enumerator"; otherwise we inject the names into our own parent scope. */ - info_ptr = recurse (reader, info_ptr, - is_enum_class ? this_entry : parent_entry, - fully); + { + std::variant recurse_parent; + if (is_enum_class) + { + gdb_assert (this_entry != nullptr); + recurse_parent = this_entry; + } + else if (defer != 0) + recurse_parent = defer; + else + recurse_parent = parent_entry; + + info_ptr = recurse (reader, info_ptr, recurse_parent, fully); + } continue; case DW_TAG_module: diff --git a/gdb/testsuite/gdb.dwarf2/enum-type.exp b/gdb/testsuite/gdb.dwarf2/enum-type.exp index b2b3dc6c828..ec12db57c8c 100644 --- a/gdb/testsuite/gdb.dwarf2/enum-type.exp +++ b/gdb/testsuite/gdb.dwarf2/enum-type.exp @@ -114,3 +114,18 @@ gdb_test "ptype enum EU" "type = enum EU {TWO = 2}" \ gdb_test_no_output "set lang c++" gdb_test "ptype enum EU" "type = enum EU : unsigned int {TWO = 2}" \ "ptype EU in C++" + +gdb_test "p ns::val1" \ + " = ns::val1" + +require !readnow +require {string equal [have_index $binfile] ""} + +set re_ws "\[ \t\]" + +gdb_test_lines "maint print objfiles" \ + "val1 has a parent" \ + [multi_line \ + "" \ + "$re_ws+qualified:$re_ws+ns::val1" \ + ".*"]