aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2/cooked-index.c
AgeCommit message (Collapse)AuthorFilesLines
2023-09-15Rename split_style::DOTTom Tromey1-1/+1
This renames split_style::DOT, to avoid name clashes when building gdb with an old version of Bison (2.3, the version available on macOS). In particular the error looks like: ./split-name.h:34:3: error: expected identifier DOT, ^ m2-exp.c:163:13: note: expanded from macro 'DOT' Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30286
2023-08-28Use sect_offset_str in cooked_index::dumpTom Tromey1-2/+1
Mark Wielaard pointed out that cooked_index::dump uses PRIx64, and Andreas Schwab pointed out that gdb already has sect_offset_str. This patch applies both these observations.
2023-08-10[gdb/symtab] Dump qualified name of cooked_index_entryTom de Vries1-0/+3
When doing "maint print objfiles" for the exec of test-case gdb.dwarf2/pr13961.exp, we get: ... [25] ((cooked_index_entry *) 0x37b25d0) name: foo canonical: foo DWARF tag: DW_TAG_class_type flags: 0x0 [] DIE offset: 0x2a parent: ((cooked_index_entry *) 0) [26] ((cooked_index_entry *) 0x37b2630) name: foo canonical: foo DWARF tag: DW_TAG_class_type flags: 0x0 [] DIE offset: 0x25 parent: ((cooked_index_entry *) 0x37b25d0) [foo] ... By following the parent links in the text, we can conclude that the qualified name of DIE 0x25 is foo::foo (which is incorrect, that's PR symtab/30739). But it's not evident, and also hard to verify in a test-case. Add dumping of the qualified name, such that we have: ... [25] ((cooked_index_entry *) 0x333b5d0) name: foo canonical: foo qualified: foo DWARF tag: DW_TAG_class_type flags: 0x0 [] DIE offset: 0x2a parent: ((cooked_index_entry *) 0) [26] ((cooked_index_entry *) 0x333b630) name: foo canonical: foo qualified: foo::foo DWARF tag: DW_TAG_class_type flags: 0x0 [] DIE offset: 0x25 parent: ((cooked_index_entry *) 0x333b5d0) [foo] ... Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com>
2023-08-08[gdb/build] Fix build breaker with -std=c++11Tom de Vries1-1/+6
When building with -std=c++11 I run into: ... gdb/dwarf2/cooked-index.c: In member function \ ‘void cooked_index::start_writing_index(dwarf2_per_bfd*)’: gdb/dwarf2/cooked-index.c:469:10: error: lambda capture initializers only \ available with -std=c++14 or -std=gnu++14 [-Werror] ctx = std::move (ctx)] () ^~~ ... Fix this by capturing a copy instead when using -std=c++11: ... = gdb::thread_pool::g_thread_pool->post_task ([this, per_bfd, ctx] () ... Tested by building with and without -stdc=++11 on x86_64-linux. Reported-By: Tom Tromey <tom@tromey.com> Reviewed-by: John Baldwin <jhb@FreeBSD.org>
2023-08-04[gdb/symtab] Fix data race on bfd::{cacheable,format}Tom de Vries1-1/+1
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp 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=12261) Write of size 4 at 0x7b4400097d08 by main thread: #0 bfd_open_file bfd/cache.c:584 (gdb+0x148bb92) #1 bfd_cache_lookup_worker bfd/cache.c:261 (gdb+0x148b12a) #2 cache_bseek bfd/cache.c:289 (gdb+0x148b324) #3 bfd_seek bfd/bfdio.c:459 (gdb+0x1489c31) #4 _bfd_generic_get_section_contents bfd/libbfd.c:1069 (gdb+0x14977a4) #5 bfd_get_section_contents bfd/section.c:1606 (gdb+0x149cc7c) #6 gdb_bfd_scan_elf_dyntag(int, bfd*, unsigned long*, unsigned long*) gdb/solib.c:1601 (gdb+0xed8eca) #7 elf_locate_base gdb/solib-svr4.c:705 (gdb+0xec28ac) #8 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3430 (gdb+0xeca55d) #9 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad) #10 find_main_name gdb/symtab.c:6270 (gdb+0xf743a5) #11 main_language() gdb/symtab.c:6313 (gdb+0xf74499) #12 set_initial_language() gdb/symfile.c:1700 (gdb+0xf4285c) #13 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf40e2a) #14 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf427d1) #15 file_command gdb/exec.c:554 (gdb+0x94f74b) #16 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528) #17 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69) #18 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff303c) #19 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94adde) #20 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b49b) #21 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x103479c) #22 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a383) #23 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bde5d) #24 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a182) #25 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a243) #26 stdin_event_handler gdb/ui.c:155 (gdb+0x1074a40) #27 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d94f02) #28 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d9563a) #29 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93a26) #30 start_event_loop gdb/main.c:412 (gdb+0xb5a374) #31 captured_command_loop gdb/main.c:476 (gdb+0xb5a563) #32 captured_main gdb/main.c:1320 (gdb+0xb5c6e3) #33 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c792) #34 main gdb/gdb.c:32 (gdb+0x416776) Previous read of size 1 at 0x7b4400097d08 by thread T12: #0 bfd_check_format_matches bfd/format.c:323 (gdb+0x1492db4) #1 bfd_check_format bfd/format.c:94 (gdb+0x1492104) #2 build_id_bfd_get(bfd*) gdb/build-id.c:42 (gdb+0x6648f7) #3 index_cache::store(dwarf2_per_bfd*, index_cache_store_context*) gdb/dwarf2/index-cache.c:110 (gdb+0x82d205) #4 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:640 (gdb+0x7f1bf1) #5 operator() gdb/dwarf2/cooked-index.c:470 (gdb+0x7f0f40) #6 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f28f7) #7 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952) #8 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0) #9 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91) #10 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59) #11 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660) #12 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c) #13 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623) #14 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf) #15 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f) #16 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5) #17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d) #18 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2) #19 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2) #20 pthread_once <null> (libtsan.so.0+0x4457c) #21 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd) #22 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224) #23 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852) #24 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef) #25 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac5b0) #26 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabed2) #27 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dacf81) #28 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dac3b2) #29 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1daf6e4) #30 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf66f) #31 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1daf624) #32 <null> <null> (libstdc++.so.6+0xdcac2) ... SUMMARY: ThreadSanitizer: data race bfd/cache.c:584 in bfd_open_file ... The race happens when issuing the "file $exec" command. The race is between: - a worker thread getting the build id while writing the index cache, and in the process reading bfd::format, and - the main thread calling find_main_name, and in the process setting bfd::cacheable. The two bitfields bfd::cacheable and bfd::format share the same bitfield container. Fix this by capturing the build id in the main thread, and using the captured value in the worker thread. Likewise for the dwz build id, which likely suffers from the same issue. While we're at it, also move the creation of the cache directory to the index_cache_store_context constructor, to: - make sure there's no race between subsequent file commands, and - issue any related warning or error messages during the file command. Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com> PR symtab/30392 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
2023-08-04[gdb/symtab] Fix data race on index_cache::m_enabledTom de Vries1-4/+8
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp 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... (gdb) show index-cache enabled The index cache is off. (gdb) PASS: gdb.base/index-cache.exp: test_basic_stuff: index-cache is disabled by default set index-cache enabled on ================== WARNING: ThreadSanitizer: data race (pid=32248) Write of size 1 at 0x00000321f540 by main thread: #0 index_cache::enable() gdb/dwarf2/index-cache.c:76 (gdb+0x82cfdd) #1 set_index_cache_enabled_command gdb/dwarf2/index-cache.c:270 (gdb+0x82d9af) #2 bool setting::set<bool>(bool const&) gdb/command.h:353 (gdb+0x6fe5f2) #3 do_set_command(char const*, int, cmd_list_element*) gdb/cli/cli-setshow.c:414 (gdb+0x6fcd21) #4 execute_command(char const*, int) gdb/top.c:567 (gdb+0xff2e64) #5 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94acc0) #6 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b37d) #7 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x103467e) #8 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a265) #9 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bdd3f) #10 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a064) #11 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a125) #12 stdin_event_handler gdb/ui.c:155 (gdb+0x1074922) #13 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d94de4) #14 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d9551c) #15 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93908) #16 start_event_loop gdb/main.c:412 (gdb+0xb5a256) #17 captured_command_loop gdb/main.c:476 (gdb+0xb5a445) #18 captured_main gdb/main.c:1320 (gdb+0xb5c5c5) #19 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c674) #20 main gdb/gdb.c:32 (gdb+0x416776) Previous read of size 1 at 0x00000321f540 by thread T12: #0 index_cache::enabled() const gdb/dwarf2/index-cache.h:48 (gdb+0x82e1a6) #1 index_cache::store(dwarf2_per_bfd*) gdb/dwarf2/index-cache.c:94 (gdb+0x82d0bc) #2 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:638 (gdb+0x7f1b97) #3 operator() gdb/dwarf2/cooked-index.c:468 (gdb+0x7f0f24) #4 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f285b) #5 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952) #6 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0) #7 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x737e91) #8 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}::operator()() const /usr/include/c++/7/future:1421 (gdb+0x737b59) #9 std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void>::operator()() const /usr/include/c++/7/future:1362 (gdb+0x738660) #10 std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run()::{lambda()#1}, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/7/bits/std_function.h:302 (gdb+0x73825c) #11 std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x733623) #12 std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/include/c++/7/future:561 (gdb+0x732bdf) #13 void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x734c4f) #14 std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x733bc5) #15 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d) #16 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2) #17 std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::{lambda()#2}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2) #18 pthread_once <null> (libtsan.so.0+0x4457c) #19 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd) #20 void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/7/mutex:684 (gdb+0x733224) #21 std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/include/c++/7/future:401 (gdb+0x732852) #22 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef) #23 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac492) #24 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabdb4) #25 void std::__invoke_impl<void, void (gdb::thread_pool::*)(), gdb::thread_pool*>(std::__invoke_memfun_deref, void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:73 (gdb+0x1dace63) #26 std::__invoke_result<void (gdb::thread_pool::*)(), gdb::thread_pool*>::type std::__invoke<void (gdb::thread_pool::*)(), gdb::thread_pool*>(void (gdb::thread_pool::*&&)(), gdb::thread_pool*&&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x1dac294) #27 decltype (__invoke((_S_declval<0ul>)(), (_S_declval<1ul>)())) std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/7/thread:234 (gdb+0x1daf5c6) #28 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf551) #29 std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> > >::_M_run() /usr/include/c++/7/thread:186 (gdb+0x1daf506) #30 <null> <null> (libstdc++.so.6+0xdcac2) Location is global 'global_index_cache' of size 48 at 0x00000321f520 (gdb+0x00000321f540) ... SUMMARY: ThreadSanitizer: data race gdb/dwarf2/index-cache.c:76 in index_cache::enable() ... The race happens when issuing a "file $exec" command followed by a "set index-cache enabled on" command. The race is between: - a worker thread reading index_cache::m_enabled to determine whether an index-cache entry for $exec needs to be written (due to command "file $exec"), and - the main thread setting index_cache::m_enabled (due to command "set index-cache enabled on"). Fix this by capturing the value of index_cache::m_enabled in the main thread, and using the captured value in the worker thread. Tested on x86_64-linux. PR symtab/30392 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
2023-04-29gdb: Fix building with latest libc++Manoj Gupta1-1/+1
Latest libc++[1] causes transitive include to <locale> when <mutex> or <thread> header is included. This causes gdb to not build[2] since <locale> defines isupper/islower etc. functions that are explicitly macroed-out in safe-ctype.h to prevent their use. Use the suggestion from libc++ to include <locale> internally when building in C++ mode to avoid build errors. Use safe-gdb-ctype.h as the include instead of "safe-ctype.h" to keep this isolated to gdb since rest of binutils does not seem to use much C++. [1]: https://reviews.llvm.org/D144331 [2]: https://issuetracker.google.com/issues/277967395
2023-03-31Fix race in background index-cache writingTom Tromey1-9/+15
Tom de Vries pointed out a bug in the index-cache background writer -- sometimes it will fail. He also noted that it fails when the number of worker threads is set to zero. These turn out to be the same problem -- the cache can't be written to until the per-BFD's "index_table" member is set. This patch avoids the race by rearranging the code slightly, to ensure the cache cannot possibly be written before the member is set. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30261
2023-03-27Populate seen_names hash in cooked_index_shard::do_finalizeTom Tromey1-0/+1
Hannes pointed out that cooked_index_shard::do_finalize never populates the seen_names hash table. This patch adds the necessary store. This reduces memory use a little for "gdb gdb": (before) Space used: 28909568 (+0 for this command) (after) Space used: 28884992 (+0 for this command) What this means, btw, is that in gdb there are not many symbols that are both mentioned in many CUs and that also require name canonicalization. It's possible this would differ in other programs.
2023-03-07Fix selfcheck regression due to new maint commandTom Tromey1-2/+2
Simon points out that the new maint command, intended to fix a regression, also introduces a new regression in "maint selftest". This patch fixes the error. I did a full regression test on x86-64 Fedora 36.
2023-03-07Ensure index cache entry written in testTom Tromey1-0/+15
Now that index cache files are written in the background, one test in index-cache.exp is racy -- it assumes that the cache file will have been written during startup. This patch fixes the problem by introducing a new maintenance command to wait for all pending writes to the index cache. Approved-By: Simon Marchi <simon.marchi@efficios.com> Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2023-02-24Write the DWARF index in the backgroundTom Tromey1-1/+67
The new DWARF cooked indexer interacts poorly with the DWARF index cache. In particular, the cache will require gdb to wait for the cooked index to be finalized. As this happens in the foreground, it means that users with this setting enabled will see a slowdown. This patch changes gdb to write the cache entry a worker thread. (As usual, in the absence of threads, this work is simply done immediately in the main thread.) Some care is taken to ensure that this can't crash, and that gdb will not exit before the task is complete. To avoid use-after-free problems, the DWARF per-BFD object explicitly waits for the index cache task to complete. To avoid gdb exiting early, an exit observer is used to wait for all such pending tasks. In normal use, neither of these waits will be very visible. For users using "-batch" to pre-generate the index, though, it would be. However I don't think there is much to be done about this, as it was the status quo ante.
2023-02-18Fix "start" for D, Rust, etcTom Tromey1-17/+33
The new DWARF indexer broke "start" for some languages. For D, it is broken because, while the code in cooked_index_shard::add specifically excludes Ada, it fails to exclude D. This means that the C "main" will be detected as "main" here -- whereas what is intended is for the code in find_main_name to use d_main_name to find the name. The Rust compiler, on the other hand, uses DW_AT_main_subprogram. However, the code in dwarf2_build_psymtabs_hard fails to create a fully-qualified name, so the name always ends up as plain "main". For D and Ada, a very simple approach suffices: remove the check against "main" from cooked_index_shard::add. This also has the benefit of slightly speeding up DWARF indexing. I assume this approach will work for Pascal and Modula-2 as well, but I don't have a way to test those at present. For Rust, though, this is not sufficient. And, computing the fully-qualified name in dwarf2_build_psymtabs_hard will crash, because cooked_index_entry::full_name uses the canonical name -- and that is not computed until after canonicalization. However, we don't want to wait for canonicalization to be done before computing the main name. That would remove any benefit from doing canonicalization is the background. This patch solves this dilemma by noticing that languages using DW_AT_main_subprogram are, currently, disjoint from languages requiring canonicalization. Because of this, we can add a parameter to full_name to let us avoid crashes, slowdowns, and races here. This is kind of tricky and ugly, so I've tried to comment it sufficiently. While doing this, I had to change gdb.dwarf2/main-subprogram.exp. A different possibility here would be to ignore the canonicalization needs of C in this situation, because those only affect certain types. However, I chose this approach because the test case is artificial anyhow. A long time ago, in an earlier threading attempt, I changed the global current_language to be a function (hidden behind a macro) to let us attempt lazily computing the current language. Perhaps this approach could still be made to work. However, that also seemed rather tricky, more so than this patch. Reviewed-By: Andrew Burgess <aburgess@redhat.com> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30116
2023-02-09Let user C-c when waiting for DWARF index finalizationTom Tromey1-0/+16
In PR gdb/29854, Simon pointed out that it would be good to be able to use C-c when the DWARF cooked index is waiting for finalization. The idea here is to be able to interrupt a command like "break" -- not to stop the finalization process itself, which runs in a worker thread. This patch implements this idea, by changing the index wait functions to, by default, allow a quit. Polling is done, because there doesn't seem to be a better way to interrupt a wait on a std::future. For v2, I realized that the thread compatibility code in thread-pool.h also needed an update. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29854
2023-01-31gdb/dwarf: rename cooked_index_vector to cooked_indexSimon Marchi1-7/+7
See previous patch's commit message for rationale. Change-Id: I6b8cdc045dffccc1c01ed690ff258af09f6ff076 Approved-By: Tom Tromey <tom@tromey.com>
2023-01-31gdb/dwarf: rename cooked_index to cooked_index_shardSimon Marchi1-11/+11
I propose to rename cooked_index_vector and cooked_index such that the "main" object, that is the entry point to the index, is called cooked_index. The fact that the cooked index is implemented as a vector of smaller indexes is an implementation detail. This patch renames cooked_index to cooked_index_shard. The following patch renames cooked_index_vector to cooked_index. Change-Id: Id650f97dcb23c48f8409fa0974cd093ca0b75177 Approved-By: Tom Tromey <tom@tromey.com>
2023-01-30gdb: fix dwarf2/cooked-index.c compilation on 32-bit systemsSimon Marchi1-1/+1
The i386 builder shows: ../../binutils-gdb/gdb/dwarf2/cooked-index.c: In member function ‘void cooked_index_vector::dump(gdbarch*) const’: ../../binutils-gdb/gdb/dwarf2/cooked-index.c:492:40: error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘std::__underlying_type_impl<sect_offset, true>::type’ {aka ‘long long unsigned int’} [-Werror=format=] 492 | gdb_printf (" DIE offset: 0x%lx\n", | ~~^ | | | long unsigned int | %llx 493 | to_underlying (entry->die_offset)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | std::__underlying_type_impl<sect_offset, true>::type {aka long long unsigned int} The die_offset's underlying type is uint64, so use PRIx64 in the format string. Change-Id: Ibdde4c624ed1bb50eced9a514a4e37aec70a1323
2023-01-30gdb/dwarf: dump cooked index contents in cooked_index_functions::dumpSimon Marchi1-0/+93
As I am investigating a crash I see with the cooked index, I thought it would be useful to have a way to dump the index contents. For those not too familiar with it (that includes me), it can help get a feel of what it contains and how it is structured. The cooked_index_functions::dump function is called as part of the "maintenance print objfiles" command. I tried to make the output well structured and indented to help readability, as this prints a lot of text. The dump function first dumps all cooked index entries, like this: [25] ((cooked_index_entry *) 0x621000121220) name: __ioinit canonical: __ioinit DWARF tag: DW_TAG_variable flags: 0x2 [IS_STATIC] DIE offset: 0x21a4 parent: ((cooked_index_entry *) 0x6210000f9610) [std] Then the information about the main symbol: main: ((cooked_index_entry *) 0x621000123b40) [main] And finally the address map contents: [1] ((addrmap *) 0x6210000f7910) [0x0] ((dwarf2_per_cu_data *) 0) [0x118a] ((dwarf2_per_cu_data *) 0x60c000007f00) [0x1cc7] ((dwarf2_per_cu_data *) 0) [0x1cc8] ((dwarf2_per_cu_data *) 0x60c000007f00) [0x1cdf] ((dwarf2_per_cu_data *) 0) [0x1ce0] ((dwarf2_per_cu_data *) 0x60c000007f00) The display of address maps above could probably be improved, to show it more as ranges, but I think this is a reasonable start. Note that this patch depends on Pedro Alves' patch "enum_flags to_string" [1]. If my patch is to be merged before Pedro's series, I will cherry-pick this patch from his series and merge it before mine. [1] https://inbox.sourceware.org/gdb-patches/20221212203101.1034916-8-pedro@palves.net/ Change-Id: Ida13e479fd4c8d21102ddd732241778bc3b6904a
2023-01-30Fix comparator bug in cooked indexTom Tromey1-79/+88
Simon pointed out that the cooked index template-matching patch introduced a failure in libstdc++ debug mode. In particular, the new code violates the assumption of std::lower_bound and std::upper_bound that the range is sorted with respect to the comparison. When I first debugged this, I thought the problem was unfixable as-is and that a second layer of filtering would have to be done. However, on irc, Simon pointed out that it could perhaps be solved if the comparison function were assured that one operand always came from the index, with the other always being the search string. This patch implements this idea. First, a new mode is introduced: a sorting mode for cooked_index_entry::compare. In this mode, strings are compared case-insensitively, but we're careful to always sort '<' before any other printable character. This way, two names like "func" and "func<param>" will be sorted next to each other -- i.e., "func1" will not be seen between them. This is important when searching. Second, the compare function is changed to work in a strcmp-like way. This makes it easier to test and (IMO) understand. Third, the compare function is modified so that in non-sorting modes, the index entry is always the first argument. This allows consistency in compares. I regression tested this in libstdc++ debug mode on x86-64 Fedora 36. It fixes the crash that Simon saw. This is v2. I believe it addresses the review comments, except for the 'enum class' change, as I mentioned in email on the list. Approved-By: Simon Marchi <simon.marchi@efficios.com>
2023-01-30Make addrmap const-correct in cooked indexTom Tromey1-3/+3
After the cooked index is created, the addrmaps should be const. Change-Id: I8234520ab346ced40a8dd6e478ba21fc438c2ba2
2023-01-27More const-correctness in cooked indexerTom Tromey1-4/+4
I noticed that iterating over the index yields non-const cooked_index_entry objects. However, after finalization, they should not be modified. This patch enforces this by adding const where needed. v2 makes the find, all_entries, and wait methods const as well.
2023-01-17Fix parameter-less template regression in new DWARF readerTom Tromey1-16/+127
PR c++/29896 points out a regression in the new DWARF reader. It does not properly handle a case like "break fn", where "fn" is a template function. This happens because the new index uses strncasecmp to compare. However, to make this work correctly, we need a custom function that ignores template parameters. This patch adds a custom comparison function and fixes the bug. A new test case is included. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29896
2023-01-17Move hash_entry and eq_entry into cooked_index::do_finalizeTom Tromey1-20/+14
I was briefly confused by the hash_entry and eq_entry functions in the cooked index. They are only needed in a single method, and that method already has a couple of local lambdas for a different hash table. So, it seemed cleaner to move these there as well.
2023-01-01Update copyright year range in header of all files managed by GDBJoel Brobecker1-1/+1
This commit is the result of running the gdb/copyright.py script, which automated the update of the copyright year range for all source files managed by the GDB project to be updated to include year 2023.
2022-12-01Add name canonicalization for CTom Tromey1-2/+6
PR symtab/29105 shows a number of situations where symbol lookup can result in the expansion of too many CUs. What happens is that lookup_signed_typename will try to look up a type like "signed int". In cooked_index_functions::expand_symtabs_matching, when looping over languages, the C++ case will canonicalize this type name to be "int" instead. Then this method will proceed to expand every CU that has an entry for "int" -- i.e., nearly all of them. A crucial component of this is that the caller, objfile::lookup_symbol, does not do this canonicalization, so when it tries to find the symbol for "signed int", it fails -- causing the loop to continue. This patch fixes the problem by introducing name canonicalization for C. The idea here is that, by making C and C++ agree on the canonical name when a symbol name can have multiple spellings, we avoid the bad behavior in objfile::lookup_symbol (and any other such code -- I don't know if there is any). Unlike C++, C only has a few situations where canonicalization is needed. And, in particular, due to the lack of overloading (thus avoiding any issues in linespec) and due to the way c-exp.y works, I think that no canonicalization is needed during symbol lookup -- only during symtab construction. This explains why lookup_name_info is not touched. The stabs reader is modified on a "best effort" basis. The DWARF reader needed one small tweak in dwarf2_name to avoid a regression in dw2-unusual-field-names.exp. I think this is adequately explained by the comment, but basically this is a scenario that should not occur in real code, only the gdb test suite. lookup_signed_typename is simplified. It used to search for two different type names, but now gdb can search just for the canonical form. gdb.dwarf2/enum-type.exp needed a small tweak, because the canonicalizer turns "unsigned integer" into "unsigned int integer". It seems better here to use the correct C type name. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29105 Tested-by: Simon Marchi <simark@simark.ca> Reviewed-by: Andrew Burgess <aburgess@redhat.com>
2022-12-01Refactor cooked_index::do_finalizeTom Tromey1-26/+23
This refactors cooked_index::do_finalize, reordering an 'if' to make it a little less redundant. This change makes a subsequent patch easier to read. Reviewed-by: Andrew Burgess <aburgess@redhat.com>
2022-07-04[gdb/symtab] Add get/set functions for per_cu->lang/unit_typeTom de Vries1-5/+5
The dwarf2_per_cu_data fields lang and unit_type both have a dont-know initial value (respectively language_unknown and (dwarf_unit_type)0), which allows us to add certain checks, f.i. checking that that a field is not read before written. Add get/set member functions for the two fields as a convenient location to add such checks, make the fields private to enforce using the member functions, and add the m_ prefix. Tested on x86_64-linux.
2022-05-26Finalize each cooked index separatelyTom Tromey1-131/+136
After DWARF has been scanned, the cooked index code does a "finalization" step in a worker thread. This step combines all the index entries into a single master list, canonicalizes C++ names, and splits Ada names to synthesize package names. While this step is run in the background, gdb will wait for the results in some situations, and it turns out that this step can be slow. This is PR symtab/29105. This can be sped up by parallelizing, at a small memory cost. Now each index is finalized on its own, in a worker thread. The cost comes from name canonicalization: if a given non-canonical name is referred to by multiple indices, there will be N canonical copies (one per index) rather than just one. This requires changing the users of the index to iterate over multiple results. However, this is easily done by introducing a new "chained range" class. When run on gdb itself, the memory cost seems rather low -- on my current machine, "maint space 1" reports no change due to the patch. For performance testing, using "maint time 1" and "file" will not show correct results. That approach measures "time to next prompt", but because the patch only affects background work, this shouldn't (and doesn't) change. Instead, a simple way to make gdb wait for the results is to set a breakpoint. Before: $ /bin/time -f%e ~/gdb/install/bin/gdb -nx -q -batch \ -ex 'break main' /tmp/gdb Breakpoint 1 at 0x43ec30: file ../../binutils-gdb/gdb/gdb.c, line 28. 2.00 After: $ /bin/time -f%e ./gdb/gdb -nx -q -batch \ -ex 'break main' /tmp/gdb Breakpoint 1 at 0x43ec30: file ../../binutils-gdb/gdb/gdb.c, line 28. 0.65 Regression tested on x86-64 Fedora 34. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29105
2022-04-20Micro-optimize cooked_index_entry::full_nameTom Tromey1-6/+5
I noticed that cooked_index_entry::full_name can return the canonical string when there is no parent entry. Regression tested on x86-64 Fedora 34.
2022-04-12gdb: fix "passing NULL to memcpy" UBsan error in dwarf2/cooked-index.cSimon Marchi1-4/+2
Reading a simple file compiled with : $ gcc -DONE=1 -gdwarf-4 -g3 test.c $ gcc --version gcc (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0 I get: Reading symbols from /tmp/cwd/a.out... /home/smarchi/src/binutils-gdb/gdb/dwarf2/cooked-index.c:332:11: runtime error: null pointer passed as argument 2, which is declared to never be null It looks like even if the size is 0 (the size of the `entries` vector is 0), we shouldn't be passing a NULL pointer to memcpy. And `entries.data ()` returns NULL. Fix that by using std::vector::insert to insert the items of entries into m_entries. I haven't checked, but it should essentially compile down to a memcpy, since the vector elements are trivially copyiable. Change-Id: I75f1c901e9b522e42e89eb5936e2c70d68eb21e5
2022-04-12"Finalize" the DWARF index in the backgroundTom Tromey1-2/+8
After scanning the CUs, the DWARF indexer merges all the data into a single vector, canonicalizing C++ names as it proceeds. While not necessarily single-threaded, this process is currently done in just one thread, to keep memory costs lower. However, this work is all done without reference to any data outside of the indexes. This patch improves the apparent performance of GDB by moving it to the background. All uses of the index are then made to wait for this process to complete. In our ongoing example, this reduces the scanning time on gdb itself to 0.173937 (wall). Recall that before this patch, the time was 0.668923; and psymbol reader does this in 1.598869. That is, at the end of this series, we see about a 10x speedup.
2022-04-12Parallelize DWARF indexingTom Tromey1-37/+105
This parallelizes the new DWARF indexer. The indexer's storage was designed so that each storage object and each indexer is fully independent. This setup makes it simple to scan different CUs independently. This patch creates a new cooked index storage object per thread, and then scans a subset of all the CUs in each such thread, using gdb's existing thread pool. In the ongoing "gdb gdb" example, this patch reduces the wall time down to 0.668923, from 0.903534. (Note that the 0.903534 is the time for the new index -- that is, when the "enable the new index" patch is rebased to before this one. However, in the final series, that patch appears toward the end. Hopefully this isn't too confusing.)
2022-04-12Introduce the new DWARF index classTom Tromey1-0/+270
This patch introduces the new DWARF index class. It is called "cooked" to contrast against a "raw" index, which is mapped from disk without extra effort. Nothing constructs a cooked index yet. The essential idea here is that index entries are created via the "add" method; then when all the entries have been read, they are "finalize"d -- name canonicalization is performed and the entries are added to a sorted vector. Entries use the DWARF name (DW_AT_name) or linkage name, not the full name as is done for partial symbols. These two facets -- the short name and the deferred canonicalization -- help improve the performance of this approach. This will become clear in later patches, when parallelization is added. Some special code is needed for Ada, because GNAT only emits mangled ("encoded", in the Ada lingo) names, and so we reconstruct the hierarchical structure after the fact. This is also done in the finalization phase. One other aspect worth noting is that the way the "main" function is found is different in the new code. Currently gdb will notice DW_AT_main_subprogram, but won't recognize "main" during reading -- this is done later, via explicit symbol lookup. This is done differently in the new code so that finalization can be done in the background without then requiring a synchronization to look up the symbol.