]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/symtab] Fix parent map when handling .debug_info and .debug_types
authorAuthor: Tom Tromey <tom@tromey.com>
Wed, 27 Nov 2024 17:48:43 +0000 (18:48 +0100)
committerTom de Vries <tdevries@suse.de>
Wed, 27 Nov 2024 17:48:43 +0000 (18:48 +0100)
Consider test-case:
...
$ cat test.c
namespace sp1 {
  class A {
    int i;
    const int f1 = 1;
    ...
    const int f29 = 1;
  };
}
sp1::A a;
void _start (void) {}
$ cat test2.c
namespace sp2 {
  class B {
    float f;
    const float f1 = 1;
    ...
    const float f29 = 1;
  };
}
sp2::B b;
...
compiled like this:
...
$ g++ test.c -gdwarf-4 -c -g -fdebug-types-section
$ g++ test2.c -gdwarf-5 -c -g -fdebug-types-section
$ g++ -g test.o test2.o -nostdlib
...

Using:
...
$ gdb -q -batch -iex "maint set worker-threads 0" a.out -ex "maint print objfiles"
...
we get a cooked index entry with incorrect parent:
...
    [29] ((cooked_index_entry *) 0x3c57d1a0)
    name:       B
    canonical:  B
    qualified:  sp1::A::B
    DWARF tag:  DW_TAG_class_type
    flags:      0x0 []
    DIE offset: 0x154
    parent:     ((cooked_index_entry *) 0x3c57d110) [A]
...

The problem is that the parent map assumes that all offsets are in the same
section.

Fix this by using dwarf2_section_info::buffer-relative addresses instead,
which get us instead:
...
    [29] ((cooked_index_entry *) 0x3f0962b0)
    name:       B
    canonical:  B
    qualified:  sp2::B
    DWARF tag:  DW_TAG_class_type
    flags:      0x0 []
    DIE offset: 0x154
    parent:     ((cooked_index_entry *) 0x3f096280) [sp2]
...

Tested on x86_64-linux.

PR symtab/32225
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32225

gdb/dwarf2/parent-map.h
gdb/dwarf2/read.c

index 6cff548a2a71f251332795a3e99262df4bb8c12d..a9ea34ec08c67fb4f2b371aab4505b5a956b5555 100644 (file)
@@ -69,18 +69,15 @@ public:
   parent_map (parent_map &&) = default;
   parent_map &operator= (parent_map &&) = default;
 
-  /* A reasonably opaque type that is used here to combine a section
-     offset and the 'dwz' flag into a single value.  */
+  /* A reasonably opaque type that is used as part of a DIE range.  */
   enum addr_type : CORE_ADDR { };
 
   /* Turn a section offset into a value that can be used in a parent
      map.  */
-  static addr_type form_addr (sect_offset offset, bool is_dwz)
+  static addr_type form_addr (const gdb_byte *info_ptr)
   {
-    CORE_ADDR value = to_underlying (offset);
-    if (is_dwz)
-      value |= ((CORE_ADDR) 1) << (8 * sizeof (CORE_ADDR) - 1);
-    return addr_type (value);
+    static_assert (sizeof (addr_type) >= sizeof (uintptr_t));
+    return (addr_type) (uintptr_t) info_ptr;
   }
 
   /* Add a new entry to this map.  DIEs from START to END, inclusive,
index 3f78b9666203e90320b33148dcb8a5ae69fb56d1..583bd97ad02e22fea52296d46657cd68ab0ba3b9 100644 (file)
@@ -16439,8 +16439,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu_data *scanning_per_cu,
             with a NULL result when when we see a reference to a
             DIE in another CU that we may or may not have
             imported locally.  */
-         parent_map::addr_type addr
-           = parent_map::form_addr (origin_offset, origin_is_dwz);
+         parent_map::addr_type addr = parent_map::form_addr (new_info_ptr);
          if (new_reader->cu != reader->cu || new_info_ptr > watermark_ptr)
            *maybe_defer = addr;
          else
@@ -16579,11 +16578,10 @@ cooked_indexer::recurse (cutu_reader *reader,
       /* Both start and end are inclusive, so use both "+ 1" and "- 1" to
         limit the range to the children of parent_entry.  */
       parent_map::addr_type start
-       = parent_map::form_addr (parent_entry->die_offset + 1,
-                                reader->cu->per_cu->is_dwz);
-      parent_map::addr_type end
-       = parent_map::form_addr (sect_offset (info_ptr - 1 - reader->buffer),
-                                reader->cu->per_cu->is_dwz);
+       = parent_map::form_addr (reader->buffer
+                                + to_underlying (parent_entry->die_offset)
+                                + 1);
+      parent_map::addr_type end = parent_map::form_addr (info_ptr - 1);
       m_die_range_map->add_entry (start, end, parent_entry);
     }