aboutsummaryrefslogtreecommitdiff
path: root/gdb/defs.h
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2022-07-12 12:20:13 +0200
committerTom de Vries <tdevries@suse.de>2022-07-12 12:20:13 +0200
commitac3972d81f1065a156daa0da97320262845c2469 (patch)
treeefc63f78e6509e7bad69598161f5c0432d51a341 /gdb/defs.h
parent68c0faca76a9b179af1a098946d6020091f43e06 (diff)
downloadgdb-ac3972d81f1065a156daa0da97320262845c2469.zip
gdb-ac3972d81f1065a156daa0da97320262845c2469.tar.gz
gdb-ac3972d81f1065a156daa0da97320262845c2469.tar.bz2
Fix -fsanitize=thread for per_cu fields
When building gdb with -fsanitize=thread and gcc 12, and running test-case gdb.dwarf2/dwz.exp, we run into a data race between: ... Read of size 1 at 0x7b200000300d by thread T2:^M #0 cutu_reader::cutu_reader(dwarf2_per_cu_data*, dwarf2_per_objfile*, \ abbrev_table*, dwarf2_cu*, bool, abbrev_cache*) gdb/dwarf2/read.c:6164 \ (gdb+0x82ec95)^M ... and: ... Previous write of size 1 at 0x7b200000300d by main thread:^M #0 prepare_one_comp_unit gdb/dwarf2/read.c:23588 (gdb+0x86f973)^M ... In other words, between: ... if (this_cu->reading_dwo_directly) ... and: ... cu->per_cu->lang = pretend_language; ... Likewise, we run into a data race between: ... Write of size 1 at 0x7b200000300e by thread T4: #0 process_psymtab_comp_unit gdb/dwarf2/read.c:6789 (gdb+0x830720) ... and: ... Previous read of size 1 at 0x7b200000300e by main thread: #0 cutu_reader::cutu_reader(dwarf2_per_cu_data*, dwarf2_per_objfile*, \ abbrev_table*, dwarf2_cu*, bool, abbrev_cache*) gdb/dwarf2/read.c:6164 \ (gdb+0x82edab) ... In other words, between: ... this_cu->unit_type = DW_UT_partial; ... and: ... if (this_cu->reading_dwo_directly) ... Likewise for the write to addresses_seen in cooked_indexer::check_bounds and a read from is_dwz in dwarf2_find_containing_comp_unit for test-case gdb.dwarf2/dw2-dir-file-name.exp and target board cc-with-dwz-m. The problem is that the written fields are part of the same memory location as the read fields, so executing a read and write in different threads is undefined behavour. Making the written fields separate memory locations, using the new struct packed template fixes this. The set of fields has been established experimentally to be the minimal set to get rid of this type of -fsanitize=thread errors, but more fields might require the same treatment. Looking at the properties of the lang field, unlike dwarf_version it's not available in the unit header, so it will be set the first time during the parallel cooked index reading. The same holds for unit_type, and likewise for addresses_seen. dwarf2_per_cu_data::addresses_seen is moved so that the bitfields that currently follow it can be merged in the same memory location as the bitfields that currently precede it, for better packing. Tested on x86_64-linux. Co-Authored-By: Pedro Alves <pedro@palves.net> Change-Id: Ifa94f0a2cebfae5e8f6ddc73265f05e7fd9e1532
Diffstat (limited to 'gdb/defs.h')
-rw-r--r--gdb/defs.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/gdb/defs.h b/gdb/defs.h
index 99bfdd5..19f379d 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -232,6 +232,9 @@ enum language
#define LANGUAGE_BITS 5
gdb_static_assert (nr_languages <= (1 << LANGUAGE_BITS));
+/* The number of bytes needed to represent all languages. */
+#define LANGUAGE_BYTES ((LANGUAGE_BITS + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT)
+
enum precision_type
{
single_precision,