]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[gdb/symtab] Fix data race in get_die_type_at_offset
authorTom de Vries <tdevries@suse.de>
Fri, 15 Jul 2022 15:10:20 +0000 (17:10 +0200)
committerTom de Vries <tdevries@suse.de>
Thu, 21 Jul 2022 13:06:40 +0000 (15:06 +0200)
Data race between:
...
==================
WARNING: ThreadSanitizer: data race (pid=28142)
  Read of size 4 at 0x7b1c0004b978 by thread T2:
    #0 htab_find_with_hash libiberty/hashtab.c:591 (gdb+0x1c5a254)
    #1 htab_find libiberty/hashtab.c:621 (gdb+0x1c5a44d)
    #2 get_die_type_at_offset gdb/dwarf2/read.c:23877 (gdb+0x872004)
    #3 get_die_type gdb/dwarf2/read.c:23890 (gdb+0x8720d0)
    #4 read_type_die gdb/dwarf2/read.c:21460 (gdb+0x8698e4)
    #5 process_die gdb/dwarf2/read.c:8674 (gdb+0x839f6e)
    #6 read_file_scope gdb/dwarf2/read.c:9610 (gdb+0x83ca5d)
    #7 process_die gdb/dwarf2/read.c:8614 (gdb+0x839e1f)
    #8 process_full_comp_unit gdb/dwarf2/read.c:8383 (gdb+0x83945e)
    #9 process_queue_item gdb/dwarf2/read.c:7592 (gdb+0x83597d)
...
and:
...
  Previous write of size 4 at 0x7b1c0004b978 by thread T1:
    #0 htab_find_with_hash libiberty/hashtab.c:591 (gdb+0x1c5a26e)
    #1 htab_find libiberty/hashtab.c:621 (gdb+0x1c5a44d)
    #2 get_die_type_at_offset gdb/dwarf2/read.c:23877 (gdb+0x872004)
    #3 get_die_type gdb/dwarf2/read.c:23890 (gdb+0x8720d0)
    #4 process_structure_scope gdb/dwarf2/read.c:14845 (gdb+0x851c12)
    #5 process_die gdb/dwarf2/read.c:8643 (gdb+0x839f24)
    #6 read_file_scope gdb/dwarf2/read.c:9610 (gdb+0x83ca5d)
    #7 process_die gdb/dwarf2/read.c:8614 (gdb+0x839e1f)
    #8 process_full_comp_unit gdb/dwarf2/read.c:8383 (gdb+0x83945e)
    #9 process_queue_item gdb/dwarf2/read.c:7592 (gdb+0x83597d)
...

Fix by using lock, also in set_die_type.

gdb/dwarf2/read.c

index 895bb3938e274726dd9ee7dfff2c99c1bc000fa5..11ba01c6b01a89ddf2b3d931f22fa58bfa8f0250 100644 (file)
@@ -23773,6 +23773,10 @@ per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
          && ofs_lhs->sect_off == ofs_rhs->sect_off);
 }
 
+#if CXX_STD_THREAD
+  static std::mutex die_type_hash_lock;
+#endif
+
 /* Set the type associated with DIE to TYPE.  Save it in CU's hash
    table if necessary.  For convenience, return TYPE.
 
@@ -23853,25 +23857,30 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
        type->add_dyn_prop (DYN_PROP_DATA_LOCATION, prop);
     }
 
-  if (per_objfile->die_type_hash == NULL)
-    per_objfile->die_type_hash
-      = htab_up (htab_create_alloc (127,
-                                   per_cu_offset_and_type_hash,
-                                   per_cu_offset_and_type_eq,
-                                   NULL, xcalloc, xfree));
-
-  ofs.per_cu = cu->per_cu;
-  ofs.sect_off = die->sect_off;
-  ofs.type = type;
-  slot = (struct dwarf2_per_cu_offset_and_type **)
-    htab_find_slot (per_objfile->die_type_hash.get (), &ofs, INSERT);
-  if (*slot)
-    complaint (_("A problem internal to GDB: DIE %s has type already set"),
-              sect_offset_str (die->sect_off));
-  *slot = XOBNEW (objfile->objfile_obstack (),
-                 struct dwarf2_per_cu_offset_and_type);
-  **slot = ofs;
-  return type;
+  {
+#if CXX_STD_THREAD
+    std::lock_guard<std::mutex> guard (die_type_hash_lock);
+#endif
+    if (per_objfile->die_type_hash == NULL)
+      per_objfile->die_type_hash
+       = htab_up (htab_create_alloc (127,
+                                     per_cu_offset_and_type_hash,
+                                     per_cu_offset_and_type_eq,
+                                     NULL, xcalloc, xfree));
+
+    ofs.per_cu = cu->per_cu;
+    ofs.sect_off = die->sect_off;
+    ofs.type = type;
+    slot = (struct dwarf2_per_cu_offset_and_type **)
+      htab_find_slot (per_objfile->die_type_hash.get (), &ofs, INSERT);
+    if (*slot)
+      complaint (_("A problem internal to GDB: DIE %s has type already set"),
+                sect_offset_str (die->sect_off));
+    *slot = XOBNEW (objfile->objfile_obstack (),
+                   struct dwarf2_per_cu_offset_and_type);
+    **slot = ofs;
+    return type;
+  }
 }
 
 /* Look up the type for the die at SECT_OFF in PER_CU in die_type_hash,
@@ -23882,6 +23891,10 @@ get_die_type_at_offset (sect_offset sect_off,
                        dwarf2_per_cu_data *per_cu,
                        dwarf2_per_objfile *per_objfile)
 {
+#if CXX_STD_THREAD
+  std::lock_guard<std::mutex> guard (die_type_hash_lock);
+#endif
+
   struct dwarf2_per_cu_offset_and_type *slot, ofs;
 
   if (per_objfile->die_type_hash == NULL)