From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id 20E763858412; Mon, 11 Jul 2022 09:37:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 20E763858412 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/symtab] Fix data race in per_cu->length X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: a4ca6efe0589d0a030920a4686b692208c82a028 X-Git-Newrev: 53a7a7e17c5d21b7b182ddf6bd8bfc092af196f5 Message-Id: <20220711093703.20E763858412@sourceware.org> Date: Mon, 11 Jul 2022 09:37:03 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Jul 2022 09:37:03 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D53a7a7e17c5d= 21b7b182ddf6bd8bfc092af196f5 commit 53a7a7e17c5d21b7b182ddf6bd8bfc092af196f5 Author: Tom de Vries Date: Mon Jul 11 11:36:54 2022 +0200 [gdb/symtab] Fix data race in per_cu->length =20 With gdb build with -fsanitize=3Dthread and test-case gdb.dwarf2/dw4-sig-types.exp and target board cc-with-dwz-m we run into= a data race between: ... Write of size 4 at 0x7b2800002268 by thread T4:^M #0 cutu_reader::cutu_reader(dwarf2_per_cu_data*, dwarf2_per_objfile= *, \ abbrev_table*, dwarf2_cu*, bool, abbrev_cache*) gdb/dwarf2/read.c:6= 236 \ (gdb+0x82f525)^M ... and this read: ... Previous read of size 4 at 0x7b2800002268 by thread T1:^M #0 dwarf2_find_containing_comp_unit gdb/dwarf2/read.c:23444 \ (gdb+0x86e22e)^M ... =20 In other words, between this write: ... this_cu->length =3D cu->header.get_length (); ... and this read: ... && mid_cu->sect_off + mid_cu->length > sect_off)) ... of per_cu->length. =20 Fix this similar to the per_cu->dwarf_version case, by only setting it = if needed, and otherwise verifying that the same value is used. [ Note th= at the same code is already present in the other cutu_reader constructor. ] =20 Move this logic into into a member function set_length to make sure it'= s used consistenly, and make the field private in order to enforce access thro= ugh the member functions, and rename it to m_length. =20 This exposes (running test-case gdb.dwarf2/fission-reread.exp) that in fill_in_sig_entry_from_dwo_entry, the m_length field is overwritten. For now, allow for that exception. =20 While we're at it, make sure that the length is set before read. =20 Tested on x86_64-linux. =20 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D29344 Diff: --- gdb/dwarf2/index-write.c | 2 +- gdb/dwarf2/read.c | 43 ++++++++++++++++++++----------------------- gdb/dwarf2/read.h | 21 ++++++++++++++++++++- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index c3aad8dd999..efd154d41df 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -1214,7 +1214,7 @@ write_gdbindex (dwarf2_per_objfile *per_objfile, sig_type->signature); } else - cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length); + cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length ()); =20 ++this_counter; } diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 40a18796f8d..31000877f42 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -2120,7 +2120,7 @@ create_cu_from_index_list (dwarf2_per_bfd *per_bfd, { dwarf2_per_cu_data_up the_cu =3D per_bfd->allocate_per_cu (); the_cu->sect_off =3D sect_off; - the_cu->length =3D length; + the_cu->set_length (length); the_cu->section =3D section; the_cu->is_dwz =3D is_dwz; return the_cu; @@ -5655,7 +5655,7 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile = *per_objfile, =20 sig_entry->section =3D dwo_entry->section; sig_entry->sect_off =3D dwo_entry->sect_off; - sig_entry->length =3D dwo_entry->length; + sig_entry->set_length (dwo_entry->length, false); sig_entry->reading_dwo_directly =3D 1; sig_entry->per_bfd =3D per_bfd; sig_entry->type_offset_in_tu =3D dwo_entry->type_offset_in_tu; @@ -6233,7 +6233,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_cu, =20 /* LENGTH has not been set yet for type units if we're using .gdb_index. */ - this_cu->length =3D cu->header.get_length (); + this_cu->set_length (cu->header.get_length ()); =20 /* Establish the type offset that can be used to lookup the type. */ sig_type->type_offset_in_section =3D @@ -6249,16 +6249,13 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_= cu, rcuh_kind::COMPILE); =20 gdb_assert (this_cu->sect_off =3D=3D cu->header.sect_off); - if (this_cu->length =3D=3D 0) - this_cu->length =3D cu->header.get_length (); - else - gdb_assert (this_cu->length =3D=3D cu->header.get_length ()); + this_cu->set_length (cu->header.get_length ()); this_cu->set_version (cu->header.version); } } =20 /* Skip dummy compilation units. */ - if (info_ptr >=3D begin_info_ptr + this_cu->length + if (info_ptr >=3D begin_info_ptr + this_cu->length () || peek_abbrev_code (abfd, info_ptr) =3D=3D 0) { dummy_p =3D true; @@ -6412,10 +6409,10 @@ cutu_reader::cutu_reader (dwarf2_per_cu_data *this_= cu, m_new_cu->str_offsets_base =3D parent_cu->str_offsets_base; m_new_cu->addr_base =3D parent_cu->addr_base; } - this_cu->length =3D m_new_cu->header.get_length (); + this_cu->set_length (m_new_cu->header.get_length ()); =20 /* Skip dummy compilation units. */ - if (info_ptr >=3D begin_info_ptr + this_cu->length + if (info_ptr >=3D begin_info_ptr + this_cu->length () || peek_abbrev_code (abfd, info_ptr) =3D=3D 0) { dummy_p =3D true; @@ -7207,7 +7204,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per= _objfile, *slot =3D sig_ptr; } this_cu->sect_off =3D sect_off; - this_cu->length =3D cu_header.get_length (); + this_cu->set_length (cu_header.get_length ()); this_cu->is_dwz =3D is_dwz; this_cu->section =3D section; /* Init this asap, to avoid a data race in the set_version in @@ -7215,7 +7212,7 @@ read_comp_units_from_section (dwarf2_per_objfile *per= _objfile, index case). */ this_cu->set_version (cu_header.version); =20 - info_ptr =3D info_ptr + this_cu->length; + info_ptr =3D info_ptr + this_cu->length (); per_objfile->per_bfd->all_comp_units.push_back (std::move (this_cu)); } } @@ -9904,7 +9901,7 @@ create_dwo_cu_reader (const struct die_reader_specs *= reader, dwo_unit->signature =3D *signature; dwo_unit->section =3D section; dwo_unit->sect_off =3D sect_off; - dwo_unit->length =3D cu->per_cu->length; + dwo_unit->length =3D cu->per_cu->length (); =20 dwarf_read_debug_printf (" offset %s, dwo_id %s", sect_offset_str (sect_off), @@ -9951,7 +9948,7 @@ create_cus_hash_table (dwarf2_per_objfile *per_objfil= e, if (!reader.dummy_p) create_dwo_cu_reader (&reader, reader.info_ptr, reader.comp_unit_die, &dwo_file, &read_unit); - info_ptr +=3D per_cu.length; + info_ptr +=3D per_cu.length (); =20 // If the unit could not be parsed, skip it. if (read_unit.dwo_file =3D=3D NULL) @@ -23459,7 +23456,7 @@ dwarf2_find_containing_comp_unit mid_cu =3D all_comp_units[mid].get (); if (mid_cu->is_dwz > offset_in_dwz || (mid_cu->is_dwz =3D=3D offset_in_dwz - && mid_cu->sect_off + mid_cu->length > sect_off)) + && mid_cu->sect_off + mid_cu->length () > sect_off)) high =3D mid; else low =3D mid + 1; @@ -23495,9 +23492,9 @@ dwarf2_find_containing_comp_unit (sect_offset sect_= off, else { if (low =3D=3D per_bfd->all_comp_units.size () - 1 - && sect_off >=3D this_cu->sect_off + this_cu->length) + && sect_off >=3D this_cu->sect_off + this_cu->length ()) error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off)); - gdb_assert (sect_off < this_cu->sect_off + this_cu->length); + gdb_assert (sect_off < this_cu->sect_off + this_cu->length ()); return this_cu; } } @@ -23519,14 +23516,14 @@ run_test () dwarf2_per_cu_data_up four (new dwarf2_per_cu_data); dwarf2_per_cu_data *four_ptr =3D four.get (); =20 - one->length =3D 5; - two->sect_off =3D sect_offset (one->length); - two->length =3D 7; + one->set_length (5); + two->sect_off =3D sect_offset (one->length ()); + two->set_length (7); =20 - three->length =3D 5; + three->set_length (5); three->is_dwz =3D 1; - four->sect_off =3D sect_offset (three->length); - four->length =3D 7; + four->sect_off =3D sect_offset (three->length ()); + four->set_length (7); four->is_dwz =3D 1; =20 std::vector units; diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index c9afa074ae9..5e0ce5e91a2 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -120,9 +120,10 @@ struct dwarf2_per_cu_data If the DIE refers to a DWO file, this is always of the original die, not the DWO file. */ sect_offset sect_off {}; - unsigned int length =3D 0; =20 private: + unsigned int m_length =3D 0; + /* DWARF standard version this data has been read from (such as 4 or 5).= */ unsigned char m_dwarf_version =3D 0; =20 @@ -288,6 +289,24 @@ public: header for this CU. */ int ref_addr_size () const; =20 + /* Return length of this CU. */ + unsigned int length () const + { + /* Make sure it's set already. */ + gdb_assert (m_length !=3D 0); + return m_length; + } + + void set_length (unsigned int length, bool strict_p =3D true) + { + if (m_length =3D=3D 0) + /* Set if not set already. */ + m_length =3D length; + else if (strict_p) + /* If already set, verify that it's the same value. */ + gdb_assert (m_length =3D=3D length); + } + /* Return DWARF version number of this CU. */ short version () const {