From patchwork Wed Aug 2 09:53:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 73467 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 331DF3858428 for ; Wed, 2 Aug 2023 09:54:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 331DF3858428 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1690970076; bh=Fjl/rbdYrSM/o6Qz9/EzsH/+yj1dvFBfueQamcLPr8A=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=QE9UfD0Ga4AS5HGibszRzpNOotJwrgEl0ef0vkjtSlO0Iq355C5AWNIIJ2+IQZSIx CuU7eQjqsuHflsF6KNwphdm0AK53Ra77vWetLybtAn7Pt58vhpdANAdVR0jehFWvk3 7Z9ouOFxDUZzKBDl+KF/9ckyxuCSS7Mopir7so8E= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id CB39D3858C5E for ; Wed, 2 Aug 2023 09:53:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CB39D3858C5E Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 083FC1F894 for ; Wed, 2 Aug 2023 09:53:25 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id EA7DA13909 for ; Wed, 2 Aug 2023 09:53:24 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id mKAWOJQnymSscgAAMHmgww (envelope-from ) for ; Wed, 02 Aug 2023 09:53:24 +0000 To: gdb-patches@sourceware.org Subject: [PATCH v2 4/6] [gdb/symtab] Fix data race on bfd_last_cache Date: Wed, 2 Aug 2023 11:53:03 +0200 Message-Id: <20230802095305.3668-5-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230802095305.3668-1-tdevries@suse.de> References: <20230802095305.3668-1-tdevries@suse.de> MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, WEIRD_PORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tom de Vries via Gdb-patches From: Tom de Vries Reply-To: Tom de Vries Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp run using "taskset -c 0", I run into: ... (gdb) file build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache Reading symbols from build/gdb/testsuite/outputs/gdb.base/index-cache/index-cache... ================== WARNING: ThreadSanitizer: data race (pid=5420) Write of size 8 at 0x0000032569e0 by main thread: #0 snip bfd/cache.c:155 (gdb+0x148b709) #1 bfd_cache_delete bfd/cache.c:176 (gdb+0x148b7a8) #2 bfd_cache_close bfd/cache.c:537 (gdb+0x148c406) #3 bfd_cache_close_all bfd/cache.c:561 (gdb+0x148c44a) #4 symbol_file_add_with_addrs gdb/symfile.c:1132 (gdb+0xf412ad) #5 symbol_file_add_from_bfd(gdb::ref_ptr const&, char const*, enum_flags, std::vector >*, enum_flags, objfile*) gdb/symfile.c:1167 (gdb+0xf4141d) #6 symbol_file_add(char const*, enum_flags, std::vector >*, enum_flags) gdb/symfile.c:1180 (gdb+0xf4149d) #7 symbol_file_add_main_1 gdb/symfile.c:1203 (gdb+0xf415a9) #8 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf42f97) #9 file_command gdb/exec.c:554 (gdb+0x94ff11) #10 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528) #11 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69) #12 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff3784) #13 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94b5a4) #14 command_line_handler(std::unique_ptr >&&) gdb/event-top.c:788 (gdb+0x94bc61) #15 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x1034ee4) #16 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94ab49) #17 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11be4d7) #18 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a948) #19 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94aa09) #20 stdin_event_handler gdb/ui.c:155 (gdb+0x1075188) #21 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d95b94) #22 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d962cc) #23 gdb_do_one_event(int) gdbsupport/event-loop.cc:217 (gdb+0x1d94573) #24 start_event_loop gdb/main.c:412 (gdb+0xb5ab3a) #25 captured_command_loop gdb/main.c:476 (gdb+0xb5ad29) #26 captured_main gdb/main.c:1320 (gdb+0xb5cea9) #27 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5cf58) #28 main gdb/gdb.c:32 (gdb+0x416776) Previous read of size 8 at 0x0000032569e0 by thread T12: #0 cache_bseek bfd/cache.c:289 (gdb+0x148bbf7) #1 bfd_seek bfd/bfdio.c:459 (gdb+0x148a554) #2 _bfd_generic_get_section_contents bfd/libbfd.c:1069 (gdb+0x14980c7) #3 bfd_get_section_contents bfd/section.c:1606 (gdb+0x149d59f) #4 section_table_xfer_memory_partial(unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*, std::vector > const&, gdb::function_view) gdb/exec.c:840 (gdb+0x951171) #5 exec_target::xfer_partial(target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) gdb/exec.c:894 (gdb+0x951372) #6 raw_memory_xfer_partial(target_ops*, unsigned char*, unsigned char const*, unsigned long, long, unsigned long*) gdb/target.c:1476 (gdb+0xfade7a) #7 memory_xfer_partial_1 gdb/target.c:1607 (gdb+0xfae39a) #8 memory_xfer_partial gdb/target.c:1636 (gdb+0xfae46c) #9 target_xfer_partial(target_ops*, target_object, char const*, unsigned char*, unsigned char const*, unsigned long, unsigned long, unsigned long*) gdb/target.c:1693 (gdb+0xfae7f4) #10 target_read_partial gdb/target.c:1947 (gdb+0xfaf3e4) #11 target_read(target_ops*, target_object, char const*, unsigned char*, unsigned long, long) gdb/target.c:1986 (gdb+0xfaf54a) #12 target_read_memory(unsigned long, unsigned char*, long) gdb/target.c:1782 (gdb+0xfaecc6) #13 gdb_bfd_scan_elf_dyntag(int, bfd*, unsigned long*, unsigned long*) gdb/solib.c:1638 (gdb+0xed98cf) #14 elf_locate_base gdb/solib-svr4.c:743 (gdb+0xec32e5) #15 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3430 (gdb+0xecad23) #16 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad) #17 find_main_name gdb/symtab.c:6270 (gdb+0xf74b6b) #18 main_name() gdb/symtab.c:6299 (gdb+0xf74bf9) #19 write_cooked_index gdb/dwarf2/index-write.c:1131 (gdb+0x831044) #20 write_gdbindex gdb/dwarf2/index-write.c:1256 (gdb+0x83189b) #21 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1484 (gdb+0x83287f) #22 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x82db35) #23 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:642 (gdb+0x7f1d31) #24 operator() gdb/dwarf2/cooked-index.c:471 (gdb+0x7f0f31) #25 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f29fb) #26 std::function::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952) #27 void std::__invoke_impl&>(std::__invoke_other, std::function&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0) #28 std::__invoke_result&>::type std::__invoke&>(std::function&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91) #29 std::__future_base::_Task_state, std::allocator, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59) #30 std::__future_base::_Task_setter, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state, std::allocator, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660) #31 std::_Function_handler (), std::__future_base::_Task_setter, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state, std::allocator, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c) #32 std::function ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623) #33 std::__future_base::_State_baseV2::_M_do_set(std::function ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf) #34 void std::__invoke_impl ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f) #35 std::__invoke_result ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>::type std::__invoke ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5) #36 std::call_once ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d) #37 std::call_once ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2) #38 std::call_once ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2) #39 pthread_once (libtsan.so.0+0x4457c) #40 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd) #41 void std::call_once ()>*, bool*), std::__future_base::_State_baseV2*, std::function ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224) #42 std::__future_base::_State_baseV2::_M_set_result(std::function ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852) #43 std::__future_base::_Task_state, std::allocator, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef) #44 std::packaged_task::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dad242) #45 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dacb64) #46 void std::__invoke_impl(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dadc13) #47 std::__invoke_result::type std::__invoke(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dad044) #48 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1db0376) #49 std::thread::_Invoker >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1db0301) #50 std::thread::_State_impl > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1db02b6) #51 (libstdc++.so.6+0xdcac2) Location is global 'bfd_last_cache' of size 8 at 0x0000032569e0 (gdb+0x0000032569e0) ... SUMMARY: ThreadSanitizer: data race bfd/cache.c:155 in snip ... The race happens when issuing the "file $exec" command. The race is between: - a worker thread calling main_name (), and in the process reading bfd_last_cache, and - the main thread writing to bfd_last_cache. Fix this by calling main_name () from the main thread. Tested on x86_64-linux. PR symtab/30392 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392 --- gdb/dwarf2/cooked-index.c | 7 +++++++ gdb/dwarf2/read.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c index b5718ae5529..9f647cfd4a2 100644 --- a/gdb/dwarf2/cooked-index.c +++ b/gdb/dwarf2/cooked-index.c @@ -462,6 +462,13 @@ cooked_index::start_writing_index (dwarf2_per_bfd *per_bfd) { struct index_cache_store_context ctx (global_index_cache, per_bfd); + if (global_index_cache.enabled ()) + { + /* Make sure find_main_name is called in the main thread rather than a + worker thread, to avoid data races on bfd. */ + main_name (); + } + /* This must be set after all the finalization tasks have been started, because it may call 'wait'. */ m_write_future diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 61730f6481c..c37bacad3b1 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -5175,10 +5175,6 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile) cooked_index *vec = new cooked_index (std::move (indexes)); per_bfd->index_table.reset (vec); - /* Cannot start writing the index entry until after the - 'index_table' member has been set. */ - vec->start_writing_index (per_bfd); - const cooked_index_entry *main_entry = vec->get_main (); if (main_entry != nullptr) { @@ -5193,6 +5189,10 @@ dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile) set_objfile_main_name (objfile, full_name, lang); } + /* Cannot start writing the index entry until after the + 'index_table' member has been set. */ + vec->start_writing_index (per_bfd); + dwarf_read_debug_printf ("Done building psymtabs of %s", objfile_name (objfile)); }