]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/symtab] Handle multiple .debug_info sections
authorTom de Vries <tdevries@suse.de>
Tue, 29 Oct 2024 09:08:04 +0000 (10:08 +0100)
committerTom de Vries <tdevries@suse.de>
Tue, 29 Oct 2024 09:08:04 +0000 (10:08 +0100)
When compiling dw2-multiple-debug-info.c using -gdwarf-5
-fdebug-types-section, we end with two .debug_info sections in the object
file:
...
$ g++ gdb.dwarf2/dw2-multiple-debug-info.c -c -g \
    -gdwarf-5 \
    -fdebug-types-section
$ readelf -WS dw2-multiple-debug-info.o | grep -v RELA | grep .debug_info
  [10] .debug_info  PROGBITS        0 000128 0000cd 00  GC  0   0  8
  [12] .debug_info  PROGBITS        0 0001f8 0000ad 00   C  0   0  8
...

One of them contains the CU for dw2-multiple-debug-info.c, the other contains
the TU for the type of variable a.

When trying to print the type of variable a, we get:
...
$ gdb -q -batch dw2-multiple-debug-info.o -ex "ptype a"
'a' has unknown type; cast it to its declared type
...
because the TU hasn't been read.

Fix this by adding support for reading multiple .debug_info sections, similar
to how that is done for multiple .debug_types sections, getting us instead:
...
$ gdb -q -batch dw2-multiple-debug-info.o -ex "ptype a"
type = class sp1::A {
  ...
}
...

Tested on x86_64-linux.

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

gdb/dwarf2/index-write.c
gdb/dwarf2/read-debug-names.c
gdb/dwarf2/read-gdb-index.c
gdb/dwarf2/read.c
gdb/dwarf2/read.h
gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp [new file with mode: 0644]

index c01e274bd59db1c9565e2217c8dc23797157d3af..1008d19e1692c8774ebb9c4ef987a49fd1fda179 100644 (file)
@@ -1548,6 +1548,9 @@ write_dwarf_index (dwarf2_per_bfd *per_bfd, const char *dir,
   if (table == nullptr)
     error (_("Cannot use an index to create the index"));
 
+  if (per_bfd->infos.size () > 1)
+    error (_("Cannot make an index when the file has multiple .debug_info"
+            " sections"));
   if (per_bfd->types.size () > 1)
     error (_("Cannot make an index when the file has multiple .debug_types sections"));
 
index eebe5a91095e8727b6c5c04871aaf2ca1e4080ab..e6f1fce4eb4bc7057223941cb78b3a8f84232b45 100644 (file)
@@ -690,7 +690,7 @@ check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
                             const mapped_debug_names_reader &map,
                             const mapped_debug_names_reader &dwz_map)
 {
-  if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->info,
+  if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->infos[0],
                                        false /* is_dwz */))
     return false;
 
@@ -742,15 +742,16 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
 
   if (map.tu_count != 0)
     {
-      /* We can only handle a single .debug_types when we have an
-        index.  */
-      if (per_bfd->types.size () > 1)
+      /* We can only handle a single .debug_info and .debug_types when we have
+        an index.  */
+      if (per_bfd->infos.size () > 1
+         || per_bfd->types.size () > 1)
        return false;
 
       dwarf2_section_info *section
        = (per_bfd->types.size () == 1
           ? &per_bfd->types[0]
-          : &per_bfd->info);
+          : &per_bfd->infos[0]);
 
       if (!check_signatured_type_table_from_debug_names (per_objfile,
                                                         map, section))
index 701cdecf392c352c781e6537e8531a77993fc6f4..c0a33a0c9694fae9b69d359819a02ec2d1f917c6 100644 (file)
@@ -497,7 +497,7 @@ create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
   per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
 
   create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
-                                 &per_bfd->info, 0);
+                                 &per_bfd->infos[0], 0);
 
   if (dwz_elements == 0)
     return;
@@ -692,9 +692,10 @@ dwarf2_read_gdb_index
 
   if (types_list_elements)
     {
-      /* We can only handle a single .debug_types when we have an
-        index.  */
-      if (per_bfd->types.size () > 1)
+      /* We can only handle a single .debug_info and .debug_types when we have
+        an index.  */
+      if (per_bfd->infos.size () > 1
+         || per_bfd->types.size () > 1)
        {
          per_bfd->all_units.clear ();
          return 0;
@@ -703,7 +704,7 @@ dwarf2_read_gdb_index
       dwarf2_section_info *section
        = (per_bfd->types.size () == 1
           ? &per_bfd->types[0]
-          : &per_bfd->info);
+          : &per_bfd->infos[0]);
 
       create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
                                                   types_list_elements);
index 6ac6f7c6a390915a7e11c774fd72629dadbed1f0..2a29b8448452cdae8e07a7555da29dd4a292e660 100644 (file)
@@ -1392,8 +1392,11 @@ dwarf2_has_info (struct objfile *objfile,
       per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile, per_bfd);
     }
 
-  const bool has_info = (!per_objfile->per_bfd->info.is_virtual
-                        && per_objfile->per_bfd->info.s.section != nullptr
+  /* Virtual sections are created from DWP files.  It's not clear those
+     can occur here, so perhaps the is_virtual checks here are dead code.  */
+  const bool has_info = (!per_objfile->per_bfd->infos.empty ()
+                        && !per_objfile->per_bfd->infos[0].is_virtual
+                        && per_objfile->per_bfd->infos[0].s.section != nullptr
                         && !per_objfile->per_bfd->abbrev.is_virtual
                         && per_objfile->per_bfd->abbrev.s.section != nullptr);
 
@@ -1436,8 +1439,11 @@ dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp,
     }
   else if (names.info.matches (sectp->name))
     {
-      this->info.s.section = sectp;
-      this->info.size = bfd_section_size (sectp);
+      struct dwarf2_section_info info_section;
+      memset (&info_section, 0, sizeof (info_section));
+      info_section.s.section = sectp;
+      info_section.size = bfd_section_size (sectp);
+      this->infos.push_back (info_section);
     }
   else if (names.abbrev.matches (sectp->name))
     {
@@ -1585,7 +1591,9 @@ dwarf2_get_section_info (struct objfile *objfile,
 void
 dwarf2_per_bfd::map_info_sections (struct objfile *objfile)
 {
-  info.read (objfile);
+  for (auto &section : infos)
+    section.read (objfile);
+
   abbrev.read (objfile);
   line.read (objfile);
   str.read (objfile);
@@ -5134,9 +5142,10 @@ create_all_units (dwarf2_per_objfile *per_objfile)
   htab_up types_htab;
   gdb_assert (per_objfile->per_bfd->all_units.empty ());
 
-  read_comp_units_from_section (per_objfile, &per_objfile->per_bfd->info,
-                               &per_objfile->per_bfd->abbrev, 0,
-                               types_htab, rcuh_kind::COMPILE);
+  for (dwarf2_section_info &section : per_objfile->per_bfd->infos)
+    read_comp_units_from_section (per_objfile, &section,
+                                 &per_objfile->per_bfd->abbrev, 0,
+                                 types_htab, rcuh_kind::COMPILE);
   for (dwarf2_section_info &section : per_objfile->per_bfd->types)
     read_comp_units_from_section (per_objfile, &section,
                                  &per_objfile->per_bfd->abbrev, 0,
index 728f2b552244b758c59101d91dffaf58659a3b78..66374834a17020698a5f229d3d19390ff635e54a 100644 (file)
@@ -468,7 +468,7 @@ public:
      the objfile obstack.  */
   auto_obstack obstack;
 
-  dwarf2_section_info info {};
+  std::vector<dwarf2_section_info> infos;
   dwarf2_section_info abbrev {};
   dwarf2_section_info line {};
   dwarf2_section_info loc {};
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.c b/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.c
new file mode 100644 (file)
index 0000000..5370a43
--- /dev/null
@@ -0,0 +1,40 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+namespace sp1 {
+  class A {
+    int i;
+    const int c1 = 1;
+    const int c2 = 2;
+    const int c3 = 3;
+    const int c4 = 4;
+    const int c5 = 5;
+    const int c6 = 6;
+    const int c7 = 7;
+    const int c8 = 8;
+    const int c9 = 9;
+    const int c10 = 10;
+  };
+}
+
+sp1::A a;
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp b/gdb/testsuite/gdb.dwarf2/dw2-multiple-debug-info.exp
new file mode 100644 (file)
index 0000000..957f41f
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright 2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+require dwarf2_support
+
+standard_testfile .c
+
+set opts {}
+lappend opts debug
+lappend opts dwarf5
+lappend opts c++
+lappend opts additional_flags=-fdebug-types-section
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" "$binfile" object \
+         $opts] != "" } {
+    return -1
+}
+
+clean_restart $binfile
+
+gdb_test "ptype a" "type = class sp1::A .*"