]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Avoid race when reading dwz file
authorTom Tromey <tom@tromey.com>
Thu, 25 Jan 2024 13:48:22 +0000 (06:48 -0700)
committerTom Tromey <tom@tromey.com>
Fri, 8 Mar 2024 14:15:08 +0000 (07:15 -0700)
PR gdb/31260 points out a race introduced by the background reading
changes.  If a given objfile is re-opened when it is already being
read, dwarf2_initialize_objfile will call dwarf2_read_dwz_file again,
causing the 'dwz_file' to be reset.

This patch fixes the problem by arranging to open the dwz just once:
when the dwarf2_per_bfd object is created.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31260

gdb/dwarf2/dwz.c
gdb/dwarf2/read.c

index 5c855f4c265e52f07d525a436853ba82e0dc05ae..f53a5b64c4a3153e6794dd759fca1c4f1317148f 100644 (file)
@@ -188,6 +188,8 @@ dwarf2_read_dwz_file (dwarf2_per_objfile *per_objfile)
      only be run in the main thread.  */
   gdb_assert (is_main_thread ());
 
+  /* This should only be called once.  */
+  gdb_assert (!per_bfd->dwz_file.has_value ());
   /* Set this early, so that on error it remains NULL.  */
   per_bfd->dwz_file.emplace (nullptr);
 
@@ -281,14 +283,9 @@ dwarf2_read_dwz_file (dwarf2_per_objfile *per_objfile)
 struct dwz_file *
 dwarf2_get_dwz_file (dwarf2_per_bfd *per_bfd, bool require)
 {
-  gdb_assert (!require || per_bfd->dwz_file.has_value ());
-
-  dwz_file *result = nullptr;
-  if (per_bfd->dwz_file.has_value ())
-    {
-      result = per_bfd->dwz_file->get ();
-      if (require && result == nullptr)
-       error (_("could not read '.gnu_debugaltlink' section"));
-    }
+  gdb_assert (per_bfd->dwz_file.has_value ());
+  dwz_file *result = per_bfd->dwz_file->get ();
+  if (require && result == nullptr)
+    error (_("could not read '.gnu_debugaltlink' section"));
   return result;
 }
index 486be7e492148d05adf59a94e9ff2410ba7c0ee9..4afb026b8ce95e59931967e40e1d0f4f08b46dd1 100644 (file)
@@ -1366,6 +1366,7 @@ dwarf2_has_info (struct objfile *objfile,
   if (per_objfile == NULL)
     {
       dwarf2_per_bfd *per_bfd;
+      bool just_created = false;
 
       /* We can share a "dwarf2_per_bfd" with other objfiles if the
         BFD doesn't require relocations.
@@ -1385,6 +1386,7 @@ dwarf2_has_info (struct objfile *objfile,
              per_bfd = new dwarf2_per_bfd (objfile->obfd.get (), names,
                                            can_copy);
              dwarf2_per_bfd_bfd_data_key.set (objfile->obfd.get (), per_bfd);
+             just_created = true;
            }
        }
       else
@@ -1392,9 +1394,25 @@ dwarf2_has_info (struct objfile *objfile,
          /* No sharing possible, create one specifically for this objfile.  */
          per_bfd = new dwarf2_per_bfd (objfile->obfd.get (), names, can_copy);
          dwarf2_per_bfd_objfile_data_key.set (objfile, per_bfd);
+         just_created = true;
        }
 
       per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile, per_bfd);
+
+      if (just_created)
+       {
+         /* Try to fetch any potential dwz file early, while still on
+            the main thread.  Also, be sure to do it just once per
+            BFD, to avoid races.  */
+         try
+           {
+             dwarf2_read_dwz_file (per_objfile);
+           }
+         catch (const gdb_exception_error &err)
+           {
+             warning (_("%s"), err.what ());
+           }
+       }
     }
 
   return (!per_objfile->per_bfd->info.is_virtual
@@ -3202,17 +3220,6 @@ dwarf2_initialize_objfile (struct objfile *objfile,
 
   dwarf_read_debug_printf ("called");
 
-  /* Try to fetch any potential dwz file early, while still on the
-     main thread.  */
-  try
-    {
-      dwarf2_read_dwz_file (per_objfile);
-    }
-  catch (const gdb_exception_error &err)
-    {
-      warning (_("%s"), err.what ());
-    }
-
   /* If we're about to read full symbols, don't bother with the
      indices.  In this case we also don't care if some other debug
      format is making psymtabs, because they are all about to be