Make m_addr_size, m_offset_size, and m_ref_addr_size use std::atomic.
Multiple indexer threads may set these values concurrently, which
currently causes a TSan failure:
WARNING: ThreadSanitizer: data race (pid=
1535364)
Write of size 1 at 0xfffed1813515 by thread T1:
#0 dwarf2_per_cu::set_addr_size(unsigned char) /home/vries/gdb/src/gdb/dwarf2/read.h:291 (gdb+0x98af68) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#1 cutu_reader::cutu_reader(dwarf2_per_cu&, dwarf2_per_objfile&, abbrev_table const*, dwarf2_cu*, bool, language, abbrev_table_cache const*) /home/vries/gdb/src/gdb/dwarf2/read.c:3114 (gdb+0x9472b4) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#2 std::__detail::_MakeUniq<cutu_reader>::__single_object std::make_unique<cutu_reader, dwarf2_per_cu&, dwarf2_per_objfile&, decltype(nullptr), decltype(nullptr), bool, language, abbrev_table_cache const*>(dwarf2_per_cu&, dwarf2_per_objfile&, decltype(nullptr)&&, decltype(nullptr)&&, bool&&, language&&, abbrev_table_cache const*&&) /usr/include/c++/15/bits/unique_ptr.h:1084 (gdb+0x891f98) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#3 cooked_indexer::ensure_cu_exists(cutu_reader*, section_and_offset const&, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:118 (gdb+0x88e1e8) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#4 cooked_indexer::scan_attributes(dwarf2_per_cu*, cutu_reader*, unsigned char const*, unsigned char const*, abbrev_info const*, char const**, char const**, enum_flags<cooked_index_flag_enum>*, sect_offset*, cooked_index_entry const**, parent_map::addr_type*, bool*, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:316 (gdb+0x88ed1c) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#5 cooked_indexer::index_dies(cutu_reader*, unsigned char const*, std::variant<cooked_index_entry const*, parent_map::addr_type>, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:539 (gdb+0x88fa50) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#6 cooked_indexer::make_index(cutu_reader*) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:718 (gdb+0x890430) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
...
Previous write of size 1 at 0xfffed1813515 by thread T4:
#0 dwarf2_per_cu::set_addr_size(unsigned char) /home/vries/gdb/src/gdb/dwarf2/read.h:291 (gdb+0x98af68) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#1 cutu_reader::cutu_reader(dwarf2_per_cu&, dwarf2_per_objfile&, abbrev_table const*, dwarf2_cu*, bool, language, abbrev_table_cache const*) /home/vries/gdb/src/gdb/dwarf2/read.c:3114 (gdb+0x9472b4) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#2 std::__detail::_MakeUniq<cutu_reader>::__single_object std::make_unique<cutu_reader, dwarf2_per_cu&, dwarf2_per_objfile&, decltype(nullptr), decltype(nullptr), bool, language, abbrev_table_cache const*>(dwarf2_per_cu&, dwarf2_per_objfile&, decltype(nullptr)&&, decltype(nullptr)&&, bool&&, language&&, abbrev_table_cache const*&&) /usr/include/c++/15/bits/unique_ptr.h:1084 (gdb+0x891f98) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#3 cooked_indexer::ensure_cu_exists(cutu_reader*, section_and_offset const&, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:118 (gdb+0x88e1e8) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#4 cooked_indexer::index_imported_unit(cutu_reader*, unsigned char const*, abbrev_info const*) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:431 (gdb+0x88f454) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#5 cooked_indexer::index_dies(cutu_reader*, unsigned char const*, std::variant<cooked_index_entry const*, parent_map::addr_type>, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:498 (gdb+0x88f770) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#6 cooked_indexer::index_imported_unit(cutu_reader*, unsigned char const*, abbrev_info const*) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:434 (gdb+0x88f4ac) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#7 cooked_indexer::index_dies(cutu_reader*, unsigned char const*, std::variant<cooked_index_entry const*, parent_map::addr_type>, bool) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:498 (gdb+0x88f770) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
#8 cooked_indexer::make_index(cutu_reader*) /home/vries/gdb/src/gdb/dwarf2/cooked-indexer.c:718 (gdb+0x890430) (BuildId:
cce1d3c72972f5759cd1746e1a001e90d7498301)
...
It's fine for multiple threads to try to set these values concurrently.
The only condition is that either the previous value was 0 (unset) or
equals the new value being set.
Change-Id: Ib13218707cefdf33a51b3246ba5773a7800463b9
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33775
Reviewed-By: Tom de Vries <tdevries@suse.de>
private:
/* Sizes for an address, an offset, and a section offset. These fields are
set by cutu_reader when the unit is read. */
- std::uint8_t m_addr_size = 0;
- std::uint8_t m_offset_size = 0;
- std::uint8_t m_ref_addr_size = 0;
+ std::atomic<std::uint8_t> m_addr_size = 0;
+ std::atomic<std::uint8_t> m_offset_size = 0;
+ std::atomic<std::uint8_t> m_ref_addr_size = 0;
public:
/* Our index in the unshared "symtabs" vector. */
/* Set the address size given in the compilation unit header for
this CU. */
void set_addr_size (std::uint8_t addr_size)
- { m_addr_size = addr_size; }
+ {
+ std::uint8_t old = m_addr_size.exchange (addr_size);
+ gdb_assert (old == 0 || old == addr_size);
+ }
/* Return the offset size given in the compilation unit header for
this CU. */
/* Set the offset size given in the compilation unit header for
this CU. */
void set_offset_size (std::uint8_t offset_size)
- { m_offset_size = offset_size; }
+ {
+ std::uint8_t old = m_offset_size.exchange (offset_size);
+ gdb_assert (old == 0 || old == offset_size);
+ }
/* Return the DW_FORM_ref_addr size given in the compilation unit
header for this CU. */
return m_ref_addr_size;
}
- /* Return the DW_FORM_ref_addr size given in the compilation unit
+ /* Set the DW_FORM_ref_addr size given in the compilation unit
header for this CU. */
void set_ref_addr_size (std::uint8_t ref_addr_size)
- { m_ref_addr_size = ref_addr_size; }
+ {
+ std::uint8_t old = m_ref_addr_size.exchange (ref_addr_size);
+ gdb_assert (old == 0 || old == ref_addr_size);
+ }
/* Return length of this CU. */
unsigned int length () const