Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: support w/dw/sw modes
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: support vec2/vec3/vec4 modes
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: support m/dm/sm modes
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: introduce svp64_decode stub
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: setup SVP64 opcodes table
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
opcodes: introduce SVP64 sources
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
opcodes: introduce SVP64 headers
Dmitry Selyutin [Sun, 28 May 2023 22:04:56 +0000 (01:04 +0300)]
ppc/svp64: introduce svp64_assemble stub
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc: share pd_reg definition via libopcodes
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support shadd/shadduw instructions
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support divmod2du instruction
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support maddedu instruction
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support fptrans instructions
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support bmask instruction
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support absd instructions
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support cprop instructions
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support avgadd instructions
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support fishmv instruction
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support fmvis instruction
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc/svp64: support svshape2 instruction
https://libre-soc.org/openpower/sv/
https://libre-soc.org/openpower/sv/remap/#svshape
https://libre-soc.org/openpower/sv/remap/#svshape2
https://libre-soc.org/openpower/isa/simplev/
Dmitry Selyutin [Sun, 28 May 2023 22:04:55 +0000 (01:04 +0300)]
ppc: decouple SFFS and SVP64 extensions
Mihails Strasuns [Tue, 3 Dec 2019 12:13:25 +0000 (13:13 +0100)]
gdb, breakpoint: add breakpoint location debugging logs
Add new commands:
set debug breakpoint on|off
show debug breakpoint
This patch introduces new debugging information that prints
breakpoint location insertion and removal flow.
The debug output looks like:
~~~
(gdb) set debug breakpoint on
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555555129 <+0>: endbr64
0x000055555555512d <+4>: push %rbp
0x000055555555512e <+5>: mov %rsp,%rbp
=> 0x0000555555555131 <+8>: mov $0x0,%eax
0x0000555555555136 <+13>: pop %rbp
0x0000555555555137 <+14>: ret
End of assembler dump.
(gdb) break *0x0000555555555137
Breakpoint 2 at 0x555555555137: file main.c, line 4.
[breakpoint] update_global_location_list: insert_mode = UGLL_MAY_INSERT
(gdb) c
Continuing.
[breakpoint] update_global_location_list: insert_mode = UGLL_INSERT
[breakpoint] insert_bp_location: Breakpoint 2 (0x5565daddb1e0) at address 0x555555555137 in main at main.c:4
[breakpoint] insert_bp_location: Breakpoint -2 (0x5565dab51c10) at address 0x7ffff7fd37b5
[breakpoint] insert_bp_location: Breakpoint -5 (0x5565dab68f30) at address 0x7ffff7fe509e
[breakpoint] insert_bp_location: Breakpoint -7 (0x5565dab694f0) at address 0x7ffff7fe63f4
[breakpoint] remove_breakpoint_1: Breakpoint 2 (0x5565daddb1e0) at address 0x555555555137 in main at main.c:4 due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -2 (0x5565dab51c10) at address 0x7ffff7fd37b5 due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -5 (0x5565dab68f30) at address 0x7ffff7fe509e due to regular remove
[breakpoint] remove_breakpoint_1: Breakpoint -7 (0x5565dab694f0) at address 0x7ffff7fe63f4 due to regular remove
Breakpoint 2, 0x0000555555555137 in main () at main.c:4
4 }
~~~
Co-Authored-By: Christina Schimpe <christina.schimpe@intel.com>
GDB Administrator [Wed, 9 Aug 2023 00:00:37 +0000 (00:00 +0000)]
Automatic date update in version.in
Alan Modra [Mon, 7 Aug 2023 05:10:35 +0000 (14:40 +0930)]
Rename bfd_bread and bfd_bwrite
These were renamed from bfd_read and bfd_write back in 2001 when they
lost an unnecessary parameter. Rename them back, and get rid of a few
casts that are only needed without prototyped functions (K&R C).
Alan Modra [Mon, 7 Aug 2023 05:07:41 +0000 (14:37 +0930)]
Add ld makefile dependencies
* Makefile.am (EXTRA_ld_new_SOURCES): Add pep-dll-aarch64.c
and pep-dll-x86_64.c.
* Makefile.in: Regenerate.
Alan Modra [Sun, 6 Aug 2023 22:58:55 +0000 (08:28 +0930)]
PR30724, cygwin ld performance regression since
014a602b86
According to the reporter of this bug the newlib fseek implementation
is likely slowed down by locking and fflush, only attempting to
optimise seeks when the file is opened read-only. Thus when writing
the output we get a dramatic slowdown due to commit
014a602b86.
PR 30724
* bfd.c (enum bfd_last_io): New.
(struct bfd): Add last_io field.
* bfd-in2.h: Regenerate.
* bfd-io.c (bfd_bread, bfd_bwrite): Force seek if last_io is
opposite direction.
(bfd_seek): Reinstate optimisation for seek to same position.
Tom de Vries [Tue, 8 Aug 2023 22:58:29 +0000 (00:58 +0200)]
[gdb/build] Use move capture in gdb_demangle
Use move capture in gdb_demangle when compiling for c++14 or higher, to save a
std::string copy.
Tested on x86_64-linux.
Reported-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
Sam James [Tue, 8 Aug 2023 01:19:57 +0000 (02:19 +0100)]
ld: Fix retain7a.d XFAIL/notarget entry for hppa
PR 30733
* ld/testsuite/ld-elf/retain7a.d: Fix XFAIL entry for hppa to match
hppa{1.1,2.0}*, like hppa2.0-unknown-linux-gnu which Gentoo uses.
Signed-off-by: Sam James <sam@gentoo.org>
Sam James [Tue, 8 Aug 2023 01:17:57 +0000 (02:17 +0100)]
ld: Fix relocatable.d XFAIL/notarget entry for hppa
PR 30734
* ld/testsuite/ld-elf/relocatable.d: Fix notarget entry for hppa to match
hppa{1.1,2.0}*, like hppa2.0-unknown-linux-gnu which Gentoo uses.
Signed-off-by: Sam James <sam@gentoo.org>
Guinevere Larsen [Tue, 8 Aug 2023 08:47:32 +0000 (10:47 +0200)]
Update my name in maintainers file
Rainer Orth [Tue, 8 Aug 2023 08:13:58 +0000 (10:13 +0200)]
Guard against killing unrelated processes in amd64-disp-step.exp
When testing current gdb trunk on Solaris/amd64, the whole session was
reliably terminated by make check. I could trace this to the following
entry in gdb.arch/amd64-disp-step/gdb.log:
FAIL: gdb.arch/amd64-disp-step.exp: add into rcx: send_signal=on: get
inferior pid
Executing on target: kill -ALRM -1 (timeout = 300)
builtin_spawn -ignore SIGHUP kill -ALRM -1
If $inferior_pid doesn't refer to a single process for some reason, this
kill would terminate either a process group or the whole session.
This patch avoids this by ensuring that the pid arg is positive.
Tested on amd64-pc-solaris2.11 and x86_64-pc-linux-gnu.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
Tom de Vries [Tue, 8 Aug 2023 08:08:04 +0000 (10:08 +0200)]
[gdb/build] Fix build breaker with -std=c++11
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>
Tsukasa OI [Tue, 8 Aug 2023 04:30:41 +0000 (04:30 +0000)]
RISC-V: Update ratified 'Ztso' extension version
Because the 'Ztso' extension is now ratified, it has a version number of 1.0
(not 0.1). This commit updates the number.
bfd/ChangeLog:
* elfxx-riscv.c (riscv_supported_std_z_ext): Update the version
number of the 'Ztso' extension since it's ratified.
GDB Administrator [Tue, 8 Aug 2023 00:00:41 +0000 (00:00 +0000)]
Automatic date update in version.in
Vladimir Mezentsev [Thu, 3 Aug 2023 19:56:54 +0000 (12:56 -0700)]
gprofng: 30700 tmpdir/gp-collect-app_F test fails
gprofng/ChangeLog
2023-08-03 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
PR gprofng/30700
* testsuite/gprofng.display/gp-collect-app_F.exp: Fix -name argument
for sub-experiment filtering.
Jan Beulich [Mon, 7 Aug 2023 09:56:50 +0000 (11:56 +0200)]
RISC-V: move comment describing rules for riscv_opcodes[]
It makes little sense to have this comment meanwhile over a hundred
lines ahead of the array. In fact until spotting the comment, I was
wondering why those pretty important aspects aren't spelled out
anywhere.
Richard Bunt [Mon, 7 Aug 2023 08:12:53 +0000 (09:12 +0100)]
gdb/fortran: Align intrinsic/variable precedence
Fortran allows variables and function to be named after language defined
intrinsics as they are not reserved keywords. For example, the abs maths
intrinsic can be hidden by a user declaring a variable called abs.
The behavior before this patch was to favour the intrinsic, which meant
that any variables named, for example "allocated", could not be
inspected by GDB.
This patch inverts this priority to bring GDB's behaviour closer to the
Fortran language, where the user defined symbol can hide the intrinsic.
Special care was need to prevent any C symbols from overriding either
Fortran intrinsics or user defined variables. This was observed to be
the case when GDB has access to symbols for abs from libm. This was
solved by only allowing symbols not marked with language_fortran to be
overridden.
In total this brings the order of precedence to the following (highest
first):
1. User defined Fortran variable or function.
2. Fortran intrinsic.
3. Symbols from languages other than Fortran.
The sizeof intrinsic is now case insensitive. This is closer to the
Fortran language. I believe this change is safe enough as it increases
the acceptance of the grammar, rather than restricts it. I.e. it should
not break any existing scripts which rely on it. Unless of course they
rely on SIZEOF being rejected.
GDB built with GCC 13.
No test suite regressions detected. Compilers: GCC, ACfL, Intel, Intel
LLVM, NVHPC; Platforms: x86_64, aarch64.
Existing tests in gdb.fortran cover the invocation of intrinsics
including: intrinsics.exp, shape.exp, rank.exp, lbound-ubound.exp.
Approved-By: Tom Tromey <tom@tromey.com>
GDB Administrator [Mon, 7 Aug 2023 00:00:25 +0000 (00:00 +0000)]
Automatic date update in version.in
GDB Administrator [Sun, 6 Aug 2023 00:00:29 +0000 (00:00 +0000)]
Automatic date update in version.in
Tom de Vries [Sat, 5 Aug 2023 15:57:13 +0000 (17:57 +0200)]
[gdb/symtab] Find main language without symtab expansion
When loading an executable using "file a.out", the language is set according
to a.out, which can involve looking up the language of symbol "main", which
will cause the symtab expansion for the containing CU.
Expansion of lto debug info can be slow, so in commit
d3214198119 ("[gdb] Use
partial symbol table to find language for main") a feature was added to avoid
the symtab expansion.
This feature stopped working after commit
7f4307436fd ("Fix "start" for D,
Rust, etc").
[ The commit addresses problems related to command start, which requires finding
the main function:
- for language D, "main" was found instead of "D main", and
- for Rust, the correct function was found, but attributed the wrong name
(not fully qualified). ]
Reimplement the feature by adding
cooked_index_functions::lookup_global_symbol_language.
Tested on x86_64-linux.
PR symtab/30661
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30661
David Carew [Fri, 4 Aug 2023 16:18:06 +0000 (09:18 -0700)]
as: Fix typo in manual
The -D flag should enable "debugging"
GDB Administrator [Sat, 5 Aug 2023 00:00:30 +0000 (00:00 +0000)]
Automatic date update in version.in
Tom Tromey [Fri, 4 Aug 2023 19:57:55 +0000 (13:57 -0600)]
Reindent recursive_dump_type
I noticed that a 'switch' in recursive_dump_type was incorrect
indented. This patch fixes the problem. Tested by rebuilding.
Tom Tromey [Fri, 4 Aug 2023 11:58:35 +0000 (05:58 -0600)]
Consolidate calls to bfd_set_cacheable
I noticed that some spots in gdb call bfd_set_cacheable after opening
a BFD.
The BFD file cache is a bit odd. BFDs that are opened locally are
unconditionally registered with the cache, and their underlying file
descriptor will always be closed when bfd_cache_close_all is called.
However, only "cacheable" BFDs will be eligible for reopening when
needed -- and by default BFD decides that if a file descriptor is
passed in, then it should not be cacheable. If a non-cacheable BFD's
file descriptor is closed, there is no offical way to reopen it.
gdb needs to call bfd_cache_close_all, because some systems cannot
start an executable when it has an open file descriptor referencing
it.
However, gdb also will sometimes passes an open file descriptor to the
various BFD open functions. And, due to lazy DWARF reading, gdb may
also need to reopen these BFDs.
Rather than having all the callers figure out when exactly to set the
cacheable flag, I think it makes sense to consolidate this logic into
the gdb_bfd.c wrapper functions. It is ok to do this because gdb
always passes a filename to these open functions, so reopening should
work ok.
Regression tested on x86-64 Fedora 38.
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
Tom Tromey [Fri, 4 Aug 2023 13:20:13 +0000 (07:20 -0600)]
Remove extra '.' from error message
A local gdb test failed with this error message:
Remote communication error. Target disconnected.: Arg list too long.
The ".:" seemed weird to me. This patch removes the ".".
Reviewed-by: John Baldwin <jhb@FreeBSD.org>
Tom Tromey [Fri, 4 Aug 2023 15:51:54 +0000 (09:51 -0600)]
Fix incorrect class name in free_objfile documentation
The documentation for the Python free_objfile event registry uses the
wrong class name. This patch fixes it. I'm checking this in as
obvious.
Nick Clifton [Fri, 4 Aug 2023 13:19:28 +0000 (14:19 +0100)]
Fix potential infinite loop in bfd_cache_close_all.
PR 15545 * cache.c (bfd_cache_close_all): Extend description to note that all files will be closed, even those that are not cacheable. Add code to prevent a possible infinite loop.
Tom de Vries [Fri, 4 Aug 2023 13:05:57 +0000 (15:05 +0200)]
[gdb/testsuite] Extend gdb.base/index-cache.exp further
Add lookup of a non-existing symbol to test-case gdb.base/index-cache.exp.
This serves as regression test for PR symtab/30718.
PR symtab/30718
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30718
Tom de Vries [Fri, 4 Aug 2023 13:05:57 +0000 (15:05 +0200)]
[gdb/testsuite] Move "maint wait-for-index-cache" ALAP in gdb.base/index-cache.exp
In test-case gdb.base/index-cache.exp proc run_test_with_flags contains:
...
clean_restart ${testfile}
# The tests generally want to check the cache, so make sure it
# has completed its work.
gdb_test_no_output "maintenance wait-for-index-cache"
...
This however hides data races between:
- index-cache writing (due to file $exec), and
- symbol lookups (due to subsequent ptype commands).
Fix this by:
- moving the "maintenance wait-for-index-cache" to proc check_cache_stats, and
- moving all calls to proc check_cache_stats ALAP.
Tested on x86_64-linux.
Tom de Vries [Fri, 4 Aug 2023 13:05:57 +0000 (15:05 +0200)]
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{files_read,is_debug_types}
With gdb build with -fsanitize=thread, and the exec from test-case
gdb.base/index-cache.exp, I run into:
...
$ rm -f ~/.cache/gdb/*; \
gdb -q -batch -iex "set index-cache enabled on" index-cache \
-ex "print foobar"
...
WARNING: ThreadSanitizer: data race (pid=25018)
Write of size 1 at 0x7b200000410d by main thread:
#0 dw2_get_file_names_reader gdb/dwarf2/read.c:2033 (gdb+0x7ab023)
#1 dw2_get_file_names gdb/dwarf2/read.c:2130 (gdb+0x7ab023)
#2 dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>) gdb/dwarf2/read.c:3105 (gdb+0x7ac6e9)
#3 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16812 (gdb+0x7d040f)
#4 objfile::map_symtabs_matching_filename(char const*, char const*, gdb::function_view<bool (symtab*)>) gdb/symfile-debug.c:219 (gdb+0xda5b6e)
#5 iterate_over_symtabs(char const*, gdb::function_view<bool (symtab*)>) gdb/symtab.c:648 (gdb+0xdc441d)
#6 lookup_symtab(char const*) gdb/symtab.c:662 (gdb+0xdc4522)
#7 classify_name gdb/c-exp.y:3083 (gdb+0x61afec)
#8 c_yylex gdb/c-exp.y:3251 (gdb+0x61dd13)
#9 c_yyparse() build/gdb/c-exp.c.tmp:1988 (gdb+0x61f07e)
#10 c_parse(parser_state*) gdb/c-exp.y:3417 (gdb+0x62d864)
#11 language_defn::parser(parser_state*) const gdb/language.c:598 (gdb+0x977245)
#12 parse_exp_in_context gdb/parse.c:414 (gdb+0xb10b1b)
#13 parse_expression(char const*, innermost_block_tracker*, enum_flags<parser_flag>) gdb/parse.c:462 (gdb+0xb1112e)
#14 process_print_command_args gdb/printcmd.c:1321 (gdb+0xb4bf8c)
#15 print_command_1 gdb/printcmd.c:1335 (gdb+0xb4caaa)
#16 print_command gdb/printcmd.c:1468 (gdb+0xb4cdda)
#17 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x65b078)
#18 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x65ed53)
#19 execute_command(char const*, int) gdb/top.c:575 (gdb+0xe3a7ea)
#20 catch_command_errors gdb/main.c:518 (gdb+0xa183fd)
#21 execute_cmdargs gdb/main.c:617 (gdb+0xa185bf)
#22 captured_main_1 gdb/main.c:1289 (gdb+0xa1aad8)
#23 captured_main gdb/main.c:1310 (gdb+0xa1b9da)
#24 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xa1b9da)
#25 main gdb/gdb.c:39 (gdb+0x42506a)
Previous read of size 1 at 0x7b200000410d by thread T2:
#0 write_gdbindex gdb/dwarf2/index-write.c:1214 (gdb+0x75bb30)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1469 (gdb+0x75f803)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x755a36)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:642 (gdb+0x71c96d)
#4 operator() gdb/dwarf2/cooked-index.c:471 (gdb+0x71c96d)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x71c96d)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x72a57c)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x72a5db)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72a5db)
#9 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+0x72a5db)
#10 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+0x72a5db)
#11 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+0x72a5db)
#12 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+0x724954)
#13 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+0x724954)
#14 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+0x72434a)
#15 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+0x72434a)
#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()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x72434a)
#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}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#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}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72532b)
#21 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+0x72532b)
#22 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+0x174570d)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x174570d)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x174570d)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x174570d)
#26 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+0x17480c0)
#27 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+0x17480c0)
#28 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+0x17480c0)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x17480c0)
#30 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+0x17480c0)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:2033 in dw2_get_file_names_reader
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::files_read.
The two bitfields dwarf2_per_cu_data::files_read and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::files_read a packed<bool, 1>.
Tested on x86_64-linux.
PR symtab/30718
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30718
Tom de Vries [Fri, 4 Aug 2023 13:05:57 +0000 (15:05 +0200)]
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{mark,is_debug_types}
With gdb build with -fsanitize=thread, and the exec from test-case
gdb.base/index-cache.exp, I run into:
...
$ rm -f ~/.cache/gdb/*; \
gdb -q -batch -iex "set index-cache enabled on" index-cache \
-ex "print foobar"
...
WARNING: ThreadSanitizer: data race (pid=23970)
Write of size 1 at 0x7b200000410d by main thread:
#0 dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>) gdb/dwarf2/read.c:3077 (gdb+0x7ac54e)
#1 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16812 (gdb+0x7d039f)
#2 objfile::map_symtabs_matching_filename(char const*, char const*, gdb::function_view<bool (symtab*)>) gdb/symfile-debug.c:219 (gdb+0xda5aee)
#3 iterate_over_symtabs(char const*, gdb::function_view<bool (symtab*)>) gdb/symtab.c:648 (gdb+0xdc439d)
#4 lookup_symtab(char const*) gdb/symtab.c:662 (gdb+0xdc44a2)
#5 classify_name gdb/c-exp.y:3083 (gdb+0x61afec)
#6 c_yylex gdb/c-exp.y:3251 (gdb+0x61dd13)
#7 c_yyparse() build/gdb/c-exp.c.tmp:1988 (gdb+0x61f07e)
#8 c_parse(parser_state*) gdb/c-exp.y:3417 (gdb+0x62d864)
#9 language_defn::parser(parser_state*) const gdb/language.c:598 (gdb+0x9771c5)
#10 parse_exp_in_context gdb/parse.c:414 (gdb+0xb10a9b)
#11 parse_expression(char const*, innermost_block_tracker*, enum_flags<parser_flag>) gdb/parse.c:462 (gdb+0xb110ae)
#12 process_print_command_args gdb/printcmd.c:1321 (gdb+0xb4bf0c)
#13 print_command_1 gdb/printcmd.c:1335 (gdb+0xb4ca2a)
#14 print_command gdb/printcmd.c:1468 (gdb+0xb4cd5a)
#15 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x65b078)
#16 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x65ed53)
#17 execute_command(char const*, int) gdb/top.c:575 (gdb+0xe3a76a)
#18 catch_command_errors gdb/main.c:518 (gdb+0xa1837d)
#19 execute_cmdargs gdb/main.c:617 (gdb+0xa1853f)
#20 captured_main_1 gdb/main.c:1289 (gdb+0xa1aa58)
#21 captured_main gdb/main.c:1310 (gdb+0xa1b95a)
#22 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xa1b95a)
#23 main gdb/gdb.c:39 (gdb+0x42506a)
Previous read of size 1 at 0x7b200000410d by thread T1:
#0 write_gdbindex gdb/dwarf2/index-write.c:1214 (gdb+0x75bb30)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1469 (gdb+0x75f803)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x755a36)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:642 (gdb+0x71c96d)
#4 operator() gdb/dwarf2/cooked-index.c:471 (gdb+0x71c96d)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x71c96d)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x72a57c)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x72a5db)
#8 std::__invoke_result<std::function<void ()>&>::type std::__invoke<std::function<void ()>&>(std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:95 (gdb+0x72a5db)
#9 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+0x72a5db)
#10 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+0x72a5db)
#11 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+0x72a5db)
#12 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+0x724954)
#13 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+0x724954)
#14 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+0x72434a)
#15 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+0x72434a)
#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()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x72434a)
#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}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#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}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x72434a)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72532b)
#21 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+0x72532b)
#22 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+0x174568d)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x174568d)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x174568d)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x174568d)
#26 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+0x1748040)
#27 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+0x1748040)
#28 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+0x1748040)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1748040)
#30 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+0x1748040)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:3077 in dw_expand_symtabs_matching_file_matcher(dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>)
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::mark.
The two bitfields dwarf2_per_cu_data::mark and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::mark a packed<unsigned int, 1>.
Tested on x86_64-linux.
PR symtab/30718
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30718
Tom de Vries [Fri, 4 Aug 2023 13:02:43 +0000 (15:02 +0200)]
[gdb/testsuite] Extend gdb.base/index-cache.exp
The test-case gdb.base/index-cache.exp uses only one source file, which
contains main.
While doing "file $exec", in set_initial_language a symbol lookup of "main" is
done, causing the symtab containing main to be expanded.
Handling of main is special, and a future optimization may skip the lookup and
expansion.
Reliably exercise:
- the lookup of main, expanding the symtab containing main, by doing
"ptype main", and
- the lookup of another symbol, expanding a symtab not containing main, by:
- adding another source file containing function foo, and
- doing "ptype foo".
This triggered a segfault with target board native-extended-gdbserver, filed
as PR symtab/30712, but that seems to be fixed by a previous commit in this
series.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30712
Tom de Vries [Fri, 4 Aug 2023 13:02:43 +0000 (15:02 +0200)]
[gdb/symtab] Fix data race on dwarf2_per_cu_data::{m_header_read_in,is_debug_type}
With gdb build with -fsanitize=thread and test-case gdb.base/index-cache.exp
and target board debug-types, 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=9654)
Write of size 1 at 0x7b200000420d by main thread:
#0 dwarf2_per_cu_data::get_header() const gdb/dwarf2/read.c:21513 (gdb+0x8d1eee)
#1 dwarf2_per_cu_data::addr_size() const gdb/dwarf2/read.c:21524 (gdb+0x8d1f4e)
#2 dwarf2_cu::addr_type() const gdb/dwarf2/cu.c:112 (gdb+0x806327)
#3 set_die_type gdb/dwarf2/read.c:21932 (gdb+0x8d3870)
#4 read_base_type gdb/dwarf2/read.c:15448 (gdb+0x8bcacb)
#5 read_type_die_1 gdb/dwarf2/read.c:19832 (gdb+0x8cc0a5)
#6 read_type_die gdb/dwarf2/read.c:19767 (gdb+0x8cbe6d)
#7 lookup_die_type gdb/dwarf2/read.c:19739 (gdb+0x8cbdc7)
#8 die_type gdb/dwarf2/read.c:19593 (gdb+0x8cb68a)
#9 read_subroutine_type gdb/dwarf2/read.c:14648 (gdb+0x8b998e)
#10 read_type_die_1 gdb/dwarf2/read.c:19792 (gdb+0x8cbf2f)
#11 read_type_die gdb/dwarf2/read.c:19767 (gdb+0x8cbe6d)
#12 read_func_scope gdb/dwarf2/read.c:10154 (gdb+0x8a4f36)
#13 process_die gdb/dwarf2/read.c:6667 (gdb+0x898daa)
#14 read_file_scope gdb/dwarf2/read.c:7682 (gdb+0x89bad8)
#15 process_die gdb/dwarf2/read.c:6654 (gdb+0x898ced)
#16 process_full_comp_unit gdb/dwarf2/read.c:6418 (gdb+0x8981de)
#17 process_queue gdb/dwarf2/read.c:5690 (gdb+0x894433)
#18 dw2_do_instantiate_symtab gdb/dwarf2/read.c:1770 (gdb+0x88623a)
#19 dw2_instantiate_symtab gdb/dwarf2/read.c:1792 (gdb+0x886300)
#20 dw2_expand_symtabs_matching_one(dwarf2_per_cu_data*, dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>, gdb::function_view<bool (compunit_symtab*)>) gdb/dwarf2/read.c:3042 (gdb+0x88b1f1)
#21 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16917 (gdb+0x8c228e)
#22 objfile::lookup_symbol(block_enum, char const*, domain_enum) gdb/symfile-debug.c:288 (gdb+0xf39055)
#23 lookup_symbol_via_quick_fns gdb/symtab.c:2385 (gdb+0xf66ab7)
#24 lookup_symbol_in_objfile gdb/symtab.c:2516 (gdb+0xf6711b)
#25 operator() gdb/symtab.c:2562 (gdb+0xf67272)
#26 operator() gdb/../gdbsupport/function-view.h:305 (gdb+0xf776b1)
#27 _FUN gdb/../gdbsupport/function-view.h:299 (gdb+0xf77708)
#28 gdb::function_view<bool (objfile*)>::operator()(objfile*) const gdb/../gdbsupport/function-view.h:289 (gdb+0xc3fc97)
#29 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3455 (gdb+0xecae47)
#30 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad)
#31 lookup_global_or_static_symbol gdb/symtab.c:2559 (gdb+0xf674fb)
#32 lookup_global_symbol(char const*, block const*, domain_enum) gdb/symtab.c:2615 (gdb+0xf67780)
#33 language_defn::lookup_symbol_nonlocal(char const*, block const*, domain_enum) const gdb/symtab.c:2447 (gdb+0xf66d6e)
#34 lookup_symbol_aux gdb/symtab.c:2123 (gdb+0xf65cb3)
#35 lookup_symbol_in_language(char const*, block const*, domain_enum, language, field_of_this_result*) gdb/symtab.c:1931 (gdb+0xf64dab)
#36 set_initial_language() gdb/symfile.c:1708 (gdb+0xf43074)
#37 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf41608)
#38 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf42faf)
#39 file_command gdb/exec.c:554 (gdb+0x94ff29)
#40 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528)
#41 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69)
#42 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff379c)
#43 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94b5bc)
#44 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94bc79)
#45 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x1034efc)
#46 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94ab61)
#47 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11be4ef)
#48 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a960)
#49 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94aa21)
#50 stdin_event_handler gdb/ui.c:155 (gdb+0x10751a0)
#51 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d95bac)
#52 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d962e4)
#53 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d946d0)
#54 start_event_loop gdb/main.c:412 (gdb+0xb5ab52)
#55 captured_command_loop gdb/main.c:476 (gdb+0xb5ad41)
#56 captured_main gdb/main.c:1320 (gdb+0xb5cec1)
#57 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5cf70)
#58 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x7b200000420d by thread T11:
#0 write_gdbindex gdb/dwarf2/index-write.c:1229 (gdb+0x831630)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1484 (gdb+0x832897)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/index-cache.c:173 (gdb+0x82db8d)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*, index_cache_store_context const&) gdb/dwarf2/cooked-index.c:645 (gdb+0x7f1d49)
#4 operator() gdb/dwarf2/cooked-index.c:474 (gdb+0x7f0f31)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f2a13)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#8 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)
#9 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)
#10 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)
#11 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)
#12 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)
#13 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)
#14 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)
#15 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)
#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()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#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}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#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}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#21 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)
#22 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)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dad25a)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dacb7c)
#26 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+0x1dadc2b)
#27 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+0x1dad05c)
#28 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+0x1db038e)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1db0319)
#30 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+0x1db02ce)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:21513 in dwarf2_per_cu_data::get_header() const
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread writing to dwarf2_per_cu_data::m_header_read_in.
The two bitfields dwarf2_per_cu_data::m_header_read_in and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::m_header_read_in a packed<bool, 1>.
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
Tom de Vries [Fri, 4 Aug 2023 13:02:43 +0000 (15:02 +0200)]
[gdb/symtab] Fix race on dwarf2_per_cu_data::{queued,is_debug_type}
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=24296)
Write of size 1 at 0x7b200000420d by main thread:
#0 queue_comp_unit gdb/dwarf2/read.c:5564 (gdb+0x8939ce)
#1 dw2_do_instantiate_symtab gdb/dwarf2/read.c:1754 (gdb+0x885b96)
#2 dw2_instantiate_symtab gdb/dwarf2/read.c:1792 (gdb+0x885d86)
#3 dw2_expand_symtabs_matching_one(dwarf2_per_cu_data*, dwarf2_per_objfile*, gdb::function_view<bool (char const*, bool)>, gdb::function_view<bool (compunit_symtab*)>) gdb/dwarf2/read.c:3042 (gdb+0x88ac77)
#4 cooked_index_functions::expand_symtabs_matching(objfile*, gdb::function_view<bool (char const*, bool)>, lookup_name_info const*, gdb::function_view<bool (char const*)>, gdb::function_view<bool (compunit_symtab*)>, enum_flags<block_search_flag_values>, domain_enum, search_domain) gdb/dwarf2/read.c:16915 (gdb+0x8c1c8a)
#5 objfile::lookup_symbol(block_enum, char const*, domain_enum) gdb/symfile-debug.c:288 (gdb+0xf389a1)
#6 lookup_symbol_via_quick_fns gdb/symtab.c:2385 (gdb+0xf66403)
#7 lookup_symbol_in_objfile gdb/symtab.c:2516 (gdb+0xf66a67)
#8 operator() gdb/symtab.c:2562 (gdb+0xf66bbe)
#9 operator() gdb/../gdbsupport/function-view.h:305 (gdb+0xf76ffd)
#10 _FUN gdb/../gdbsupport/function-view.h:299 (gdb+0xf77054)
#11 gdb::function_view<bool (objfile*)>::operator()(objfile*) const gdb/../gdbsupport/function-view.h:289 (gdb+0xc3f5e3)
#12 svr4_iterate_over_objfiles_in_search_order gdb/solib-svr4.c:3455 (gdb+0xeca793)
#13 gdbarch_iterate_over_objfiles_in_search_order(gdbarch*, gdb::function_view<bool (objfile*)>, objfile*) gdb/gdbarch.c:5041 (gdb+0x537cad)
#14 lookup_global_or_static_symbol gdb/symtab.c:2559 (gdb+0xf66e47)
#15 lookup_global_symbol(char const*, block const*, domain_enum) gdb/symtab.c:2615 (gdb+0xf670cc)
#16 language_defn::lookup_symbol_nonlocal(char const*, block const*, domain_enum) const gdb/symtab.c:2447 (gdb+0xf666ba)
#17 lookup_symbol_aux gdb/symtab.c:2123 (gdb+0xf655ff)
#18 lookup_symbol_in_language(char const*, block const*, domain_enum, language, field_of_this_result*) gdb/symtab.c:1931 (gdb+0xf646f7)
#19 set_initial_language() gdb/symfile.c:1708 (gdb+0xf429c0)
#20 symbol_file_add_main_1 gdb/symfile.c:1212 (gdb+0xf40f54)
#21 symbol_file_command(char const*, int) gdb/symfile.c:1681 (gdb+0xf428fb)
#22 file_command gdb/exec.c:554 (gdb+0x94f875)
#23 do_simple_func gdb/cli/cli-decode.c:95 (gdb+0x6d9528)
#24 cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735 (gdb+0x6e0f69)
#25 execute_command(char const*, int) gdb/top.c:575 (gdb+0xff3166)
#26 command_handler(char const*) gdb/event-top.c:552 (gdb+0x94af08)
#27 command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:788 (gdb+0x94b5c5)
#28 tui_command_line_handler gdb/tui/tui-interp.c:104 (gdb+0x10348c6)
#29 gdb_rl_callback_handler gdb/event-top.c:259 (gdb+0x94a4ad)
#30 rl_callback_read_char readline/readline/callback.c:290 (gdb+0x11bdf87)
#31 gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195 (gdb+0x94a2ac)
#32 gdb_rl_callback_read_char_wrapper gdb/event-top.c:234 (gdb+0x94a36d)
#33 stdin_event_handler gdb/ui.c:155 (gdb+0x1074b6a)
#34 handle_file_event gdbsupport/event-loop.cc:573 (gdb+0x1d9502c)
#35 gdb_wait_for_event gdbsupport/event-loop.cc:694 (gdb+0x1d95764)
#36 gdb_do_one_event(int) gdbsupport/event-loop.cc:264 (gdb+0x1d93b50)
#37 start_event_loop gdb/main.c:412 (gdb+0xb5a49e)
#38 captured_command_loop gdb/main.c:476 (gdb+0xb5a68d)
#39 captured_main gdb/main.c:1320 (gdb+0xb5c80d)
#40 gdb_main(captured_main_args*) gdb/main.c:1339 (gdb+0xb5c8bc)
#41 main gdb/gdb.c:32 (gdb+0x416776)
Previous read of size 1 at 0x7b200000420d by thread T12:
#0 write_gdbindex gdb/dwarf2/index-write.c:1229 (gdb+0x8310c8)
#1 write_dwarf_index(dwarf2_per_bfd*, char const*, char const*, char const*, dw_index_kind) gdb/dwarf2/index-write.c:1484 (gdb+0x83232f)
#2 index_cache::store(dwarf2_per_bfd*, index_cache_store_context*) gdb/dwarf2/index-cache.c:177 (gdb+0x82d62b)
#3 cooked_index::maybe_write_index(dwarf2_per_bfd*) gdb/dwarf2/cooked-index.c:640 (gdb+0x7f1bf7)
#4 operator() gdb/dwarf2/cooked-index.c:470 (gdb+0x7f0f40)
#5 _M_invoke /usr/include/c++/7/bits/std_function.h:316 (gdb+0x7f2909)
#6 std::function<void ()>::operator()() const /usr/include/c++/7/bits/std_function.h:706 (gdb+0x700952)
#7 void std::__invoke_impl<void, std::function<void ()>&>(std::__invoke_other, std::function<void ()>&) /usr/include/c++/7/bits/invoke.h:60 (gdb+0x7381a0)
#8 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)
#9 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)
#10 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)
#11 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)
#12 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)
#13 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)
#14 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)
#15 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)
#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()#1}::operator()() const /usr/include/c++/7/mutex:672 (gdb+0x73300d)
#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}::operator()() const /usr/include/c++/7/mutex:677 (gdb+0x7330b2)
#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}::_FUN() /usr/include/c++/7/mutex:677 (gdb+0x7330f2)
#19 pthread_once <null> (libtsan.so.0+0x4457c)
#20 __gthread_once /usr/include/c++/7/x86_64-suse-linux/bits/gthr-default.h:699 (gdb+0x72f5dd)
#21 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)
#22 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)
#23 std::__future_base::_Task_state<std::function<void ()>, std::allocator<int>, void ()>::_M_run() /usr/include/c++/7/future:1423 (gdb+0x737bef)
#24 std::packaged_task<void ()>::operator()() /usr/include/c++/7/future:1556 (gdb+0x1dac6da)
#25 gdb::thread_pool::thread_function() gdbsupport/thread-pool.cc:242 (gdb+0x1dabffc)
#26 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+0x1dad0ab)
#27 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+0x1dac4dc)
#28 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+0x1daf80e)
#29 std::thread::_Invoker<std::tuple<void (gdb::thread_pool::*)(), gdb::thread_pool*> >::operator()() /usr/include/c++/7/thread:243 (gdb+0x1daf799)
#30 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+0x1daf74e)
#31 <null> <null> (libstdc++.so.6+0xdcac2)
...
SUMMARY: ThreadSanitizer: data race gdb/dwarf2/read.c:5564 in queue_comp_unit
...
The race happens when issuing the "file $exec" command.
The race is between:
- a worker thread writing the index cache, and in the process reading
dwarf2_per_cu_data::is_debug_type, and
- the main thread expanding the CU containing main, and in the process setting
dwarf2_per_cu_data::queued.
The two bitfields dwarf2_per_cu_data::queue and
dwarf2_per_cu_data::is_debug_type share the same bitfield container.
Fix this by making dwarf2_per_cu_data::queued a packed<bool, 1>.
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
Tom de Vries [Fri, 4 Aug 2023 13:02:43 +0000 (15:02 +0200)]
[gdb/symtab] Fix data race on bfd::{cacheable,format}
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
Tom de Vries [Fri, 4 Aug 2023 13:02:43 +0000 (15:02 +0200)]
[gdb/symtab] Fix data race on index_cache::m_enabled
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
Alan Modra [Fri, 4 Aug 2023 08:07:12 +0000 (17:37 +0930)]
ppc: sanity check writing relocs
Check for output buffer overruns.
* elf32-ppc.c (swap_reloc_out, count_and_swap_reloc_out): New
functions. Use throughout file.
* elf64-ppc.c (swap_reloc_out, count_and_swap_reloc_out): Likewise.
Alan Modra [Fri, 4 Aug 2023 05:39:53 +0000 (15:09 +0930)]
PR30697, ppc32 mix of local-dynamic and global-dynamic TLS
This fixes miscounting of dynamic relocations on GOT entries when
a) there are both local-dynamic and global-dynamic tls accesss for a
given symbol, and
b) the symbol is global with non-default visibility, and
c) the __tls_get_addr calls aren't optimised away.
PR 30697
bfd/
* elf32-ppc.c (allocate_dynrelocs): Correct local-dynamic
reloc count.
ld/
* testsuite/ld-powerpc/tls32ldgd.d,
* testsuite/ld-powerpc/tls32ldgd.s: New test.
* testsuite/ld-powerpc/powerpc.exp: Run it.
Bruno Larsen [Fri, 14 Jul 2023 08:06:03 +0000 (10:06 +0200)]
gdb/testsuite: Disable gdb.compile when testing with clang
Attempting to test the gdb.compile with clang as the compiler results in
over 300 unexpected errors, due to a segmentation fault and several
handshake failures. Since the whole feature is designed around a gcc
plugin, and even the gcc testing is shaky at best, this commit restricts
those tests to only running under gcc. If that gets fixed, this commit
can be reverted.
Approved-By: Tom Tromey <tom@tromey.com>
GDB Administrator [Fri, 4 Aug 2023 00:00:29 +0000 (00:00 +0000)]
Automatic date update in version.in
Tom de Vries [Thu, 3 Aug 2023 16:35:23 +0000 (18:35 +0200)]
[gdb/symtab] Remove superfluous handling of Ada main in write_cooked_index
I filed PR29179 about the following FAIL in test-case
gdb.ada/O2_float_param.exp with target board cc-with-gdb-index:
...
(gdb) break increment^M
Function "increment" not defined.^M
Make breakpoint pending on future shared library load? (y or [n]) n^M
(gdb) FAIL: gdb.ada/O2_float_param.exp: scenario=all: gdb_breakpoint: \
set breakpoint at increment
...
The FAIL was a regression since commit
2cf349be0e3 ("Do not put linkage names
into .gdb_index").
Before that commit we had:
...
$ readelf -w foo > READELF
$ grep callee.*increment READELF
[1568] callee__increment: 5 [global, function]
[3115] callee.increment: 5 [global, function]
...
but after only:
...
$ grep callee.*increment READELF
[3115] callee.increment: 5 [global, function]
...
The regression was fixed by commit
67e83a0deef ("Fix regression in
c-linkage-name.exp with gdb index"), which got us again:
...
$ grep callee.*increment READELF
[1568] callee__increment: 5 [global, function]
[3115] callee.increment: 5 [global, function]
...
The commit however did not claim that particular PR. A subsequent commit,
commit
5fea9794325 ("Improve Ada support in .gdb_index") did claim to fix it,
together with commit
dd05fc7071a ("Change .gdb_index de-duplication
implementation").
The commit
5fea9794325 contained the following addition in write_cooked_index:
...
+ if (entry->per_cu->lang () == language_ada)
+ {
+ /* We want to ensure that the Ada main function's name
+ appears verbatim in the index. However, this name will
+ be of the form "_ada_mumble", and will be rewritten by
+ ada_decode. So, recognize it specially here and add it
+ to the index by hand. */
+ if (entry->tag == DW_TAG_subprogram
+ && strcmp (main_for_ada, name) == 0)
+ {
+ /* Leave it alone. */
+ }
+ else
+ {
+ /* In order for the index to work when read back into
+ gdb, it has to use the encoded name, with any
+ suffixes stripped. */
+ std::string encoded = ada_encode (name, false);
+ name = obstack_strdup (&symtab->m_string_obstack,
+ encoded.c_str ());
+ }
+ }
...
The code contains some special handling related to the Ada main function, so
let's look at that one: foo. Before commit
67e83a0deef we have:
...
$ grep foo.*function READELF
[3733] foo: 7 [global, function]
...
and after:
...
$ grep foo.*function READELF
[2738] _ada_foo: 7 [global, function]
[3733] foo: 7 [global, function]
...
so that looks identical to the callee.increment case.
At commit
5fea9794325, we have slightly different index numbers:
...
$ grep foo.*function READELF
[1658] foo: 7 [global, function]
[2738] _ada_foo: 7 [global, function]
...
but otherwise the same result.
If we disable the special handling of the Ada main function like so:
...
- if (entry->tag == DW_TAG_subprogram
+ if (false && entry->tag == DW_TAG_subprogram
...
we still have the exact same result because:
...
(gdb) p main_for_ada
$1 = 0x352e6a0 "_ada_foo"
...
and ada_encode ("_ada_foo", false) == "_ada_foo".
The comment seems to be copied from debug_names::insert, which does indeed use
ada_decode, while the code in write_cooked_index uses ada_encode instead.
Remove the superfluous special handling of Ada main in write_cooked_index.
Tested on x86_64-linux, with target boards unix and cc-with-gdb-index.
Approved-By: Tom Tromey <tom@tromey.com>
Tom Tromey [Thu, 3 Aug 2023 16:25:18 +0000 (10:25 -0600)]
Remove f-string from DAP
One more f-string snuck into the DAP code, in breakpoint.py. Most of
them were removed here:
https://sourceware.org/pipermail/gdb-patches/2023-June/200023.html
but I think this one landed after that patch.
While DAP only supports Python 3.5 and later, f-strings were added in
3.6, so remove this.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30708
Tom Tromey [Tue, 1 Aug 2023 19:57:19 +0000 (13:57 -0600)]
Use frame.name() in FrameDecorator
A co-worker pointed out that gdb's DAP implementation might return an
integer for the name of a stack frame, like:
{"id": 1, "name":
93824992310799, ...}
This can be seen currently in the logs of the bt-nodebug.exp test
case.
What is happening is that FrameDecorator falls back on returning the
PC when the frame's function symbol cannot be found, relying on the
gdb core to look up the minsym and print its name.
This can actually yield the wrong answer sometimes, because it falls
into the get_frame_pc / get_frame_address_in_block problem -- if the
frame is at a call to a noreturn function, the PC in this case might
appear to be in the next function in memory. For more on this, see:
https://sourceware.org/bugzilla/show_bug.cgi?id=8416
and related bugs.
However, there's a different approach we can take: the code here can
simply use Frame.name. This handles the PC problem correctly, and
gets us the information we need.
Andrew Burgess [Wed, 12 Jul 2023 20:56:50 +0000 (21:56 +0100)]
gdb: avoid double stop after failed breakpoint condition check
This commit replaces this earlier commit:
commit
2e411b8c68eb2b035b31d5b00d940d4be1a0928b
Date: Fri Oct 14 14:53:15 2022 +0100
gdb: don't always print breakpoint location after failed condition check
and is a result of feedback received here[1].
The original commit addressed a problem where, if a breakpoint
condition included an inferior function call, and if the inferior
function call failed, then GDB would announce the stop twice. Here's
an example of GDB's output before the above commit that shows the
problem being addressed:
(gdb) break foo if (some_func ())
Breakpoint 1 at 0x40111e: file bpcond.c, line 11.
(gdb) r
Starting program: /tmp/bpcond
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401116 in some_func () at bpcond.c:5
5 return *p;
Error in testing condition for breakpoint 1:
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(some_func) will be abandoned.
When the function is done executing, GDB will silently stop.
Breakpoint 1, 0x0000000000401116 in some_func () at bpcond.c:5
5 return *p;
(gdb)
The original commit addressed this issue in breakpoint.c, by spotting
that the $pc had changed while evaluating the breakpoint condition,
and inferring from this that GDB must have stopped elsewhere.
However, the way in which the original commit suppressed the second
stop announcement was to set bpstat::print to true -- this tells GDB
not to print the frame during the stop announcement, and for the CLI
this is fine, however, it was pointed out that for the MI this still
isn't really enough. Below is an example from an MI session after the
above commit was applied, this shows the problem with the above
commit:
-break-insert -c "cond_fail()" foo
^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040111e",func="foo",file="/tmp/mi-condbreak-fail.c",line="30",thread-groups=["i1"],cond="cond_fail()",times="0",original-location="foo"}
(gdb)
-exec-run
=thread-group-started,id="i1",pid="
2636270"
=thread-created,id="1",group-id="i1"
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7fd3110",to="0x00007ffff7ff2bb4"}]
^running
*running,thread-id="all"
(gdb)
=library-loaded,id="/lib64/libm.so.6",target-name="/lib64/libm.so.6",host-name="/lib64/libm.so.6",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7e59390",to="0x00007ffff7ef4f98"}]
=library-loaded,id="/lib64/libc.so.6",target-name="/lib64/libc.so.6",host-name="/lib64/libc.so.6",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7ca66b0",to="0x00007ffff7df3c5f"}]
~"\nProgram"
~" received signal SIGSEGV, Segmentation fault.\n"
~"0x0000000000401116 in cond_fail () at /tmp/mi-condbreak-fail.c:24\n"
~"24\t return *p;\t\t\t/* Crash here. */\n"
*stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault",frame={addr="0x0000000000401116",func="cond_fail",args=[],file="/tmp/mi-condbreak-fail.c",fullname="/tmp/mi-condbreak-fail.c",line="24",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="9"
&"Error in testing condition for breakpoint 1:\n"
&"The program being debugged was signaled while in a function called from GDB.\n"
&"GDB remains in the frame where the signal was received.\n"
&"To change this behavior use \"set unwindonsignal on\".\n"
&"Evaluation of the expression containing the function\n"
&"(cond_fail) will be abandoned.\n"
&"When the function is done executing, GDB will silently stop.\n"
=breakpoint-modified,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x000000000040111e",func="foo",file="/tmp/mi-condbreak-fail.c",fullname="/tmp/mi-condbreak-fail.c",line="30",thread-groups=["i1"],cond="cond_fail()",times="1",original-location="foo"}
*stopped
(gdb)
Notice that we still see two '*stopped' lines, the first includes the
full frame information, while the second has no frame information,
this is a result of bpstat::print having been set. Ideally, the
second '*stopped' line should not be present.
By setting bpstat::print I was addressing the problem too late, this
flag really only changes how interp::on_normal_stop prints the stop
event, and interp::on_normal_stop is called (indirectly) from the
normal_stop function in infrun.c. A better solution is to avoid
calling normal_stop at all for the stops which should not be reported
to the user, and this is what I do in this commit.
This commit has 3 parts:
1. In breakpoint.c, revert the above commit,
2. In fetch_inferior_event (infrun.c), capture the stop-id before
calling handle_inferior_event. If, after calling
handle_inferior_event, the stop-id has changed, then this indicates
that somewhere within handle_inferior_event, a stop was announced to
the user. If this is the case then GDB should not call normal_stop,
and we should rely on whoever announced the stop to ensure that we
are in a PROMPT_NEEDED state, which means the prompt will be
displayed once fetch_inferior_event returns. And,
3. In infcall.c, do two things:
(a) In run_inferior_call, after making the inferior call, ensure
that either async_disable_stdin or async_enable_stdin is called
to put the prompt state, and stdin handling into the correct
state based on whether the inferior call completed successfully
or not, and
(b) In call_thread_fsm::should_stop, call async_enable_stdin
rather than changing the prompt state directly. This isn't
strictly necessary, but helped me understand this code more.
This async_enable_stdin call is only reached if normal_stop is
not going to be called, and replaces the async_enable_stdin call
that exists in normal_stop. Though we could just adjust the
prompt state if felt (to me) much easier to understand when I
could see this call and the corresponding call in normal_stop.
With these changes in place now, when the inferior call (from the
breakpoint condition) fails, infcall.c leaves the prompt state as
PROMPT_NEEDED, and leaves stdin registered with the event loop.
Back in fetch_inferior_event GDB notices that the stop-id has changed
and so avoids calling normal_stop.
And on return from fetch_inferior_event GDB will display the prompt
and handle input from stdin.
As normal_stop is not called the MI problem is solved, and the test
added in the earlier mentioned commit still passes just fine, so the
CLI has not regressed.
[1] https://inbox.sourceware.org/gdb-patches/
6fd4aa13-6003-2563-5841-
e80d5a55d59e@palves.net/
Tom Tromey [Sun, 30 Jul 2023 16:26:07 +0000 (10:26 -0600)]
Remove PEI_HEADERS define
I noticed a few files double-included libcoff.h, and digging deeper I
found that the PEI_HEADERS define is a sort of external include guard.
This patch adds include guards to the few files in include/coff that
were missing one, and then removes the PEI_HEADERS workaround and the
redundant includes.
I didn't see anything in these files that indicated that
double-inclusion would be useful, so it seems to me that this approach
is ok.
Tested by rebuilding with --enable-targets=all.
2023-08-02 Tom Tromey <tromey@adacore.com>
* pei-x86_64.c (PEI_HEADERS): Do not define.
* pei-loongarch64.c (PEI_HEADERS): Do not define.
* pei-aarch64.c (PEI_HEADERS): Do not define.
* pe-x86_64.c (PEI_HEADERS): Do not define.
* pe-aarch64.c (PEI_HEADERS): Do not define.
* libpei.h (_LIBPEI_H): Add include guard.
* coff-x86_64.c (PEI_HEADERS): Do not check.
* coff-loongarch64.c (PEI_HEADERS): Do not check.
* coff-aarch64.c (PEI_HEADERS): Do not check.
include/ChangeLog
2023-08-02 Tom Tromey <tromey@adacore.com>
* coff/x86_64.h (COFF_X86_64_H): Add include guard.
* coff/loongarch64.h (COFF_LOONGARCH64_H): Add include guard.
* coff/aarch64.h (COFF_AARCH64_H): Add include guard.
Alan Modra [Wed, 2 Aug 2023 01:57:27 +0000 (11:27 +0930)]
readelf sprintf optimisation
This replaces sprintf and strcat calls with stpcpy, and makes use of
sprintf return value rather than using strlen, for get_machine_flags.
decode_NDS32_machine_flags made use of snprintf, which is arguably the
"correct" way to do things if there can be a buffer overflow. In this
case I don't think there can be, the buffer is 1k in size which is at
least 5 times more than needed. What's more, snprintf returns the
count of chars that would be output given no buffer limit, which means
code like
r += snprintf (buf + r, size - r, ...);
r += snprintf (buf + r, size - r, ...);
is just wrong. There needs to be a check on the return value in order
to prevent buf + r being out of bounds for the second snprintf call.
BTW, if you look closely you'll see the return value of the decode
functions is unused. I admit to getting a little carried away with
writing "out = stpcpy (out, ...):" in each of the decode functions and
didn't notice that until get_machine_flags was trimmed down to a much
smaller size. When I did notice, I decided it's not such a bad thing.
* readelf.c (decode_ARC_machine_flags, decode_ARM_machine_flags),
(decode_AVR_machine_flags, decode_NDS32_machine_flags),
(decode_AMDGPU_machine_flags): Use stpcpy and sprintf return
value. Return end of string.
(decode_BLACKFIN_machine_flags, decode_FRV_machine_flags),
(decode_IA64_machine_flags, decode_LOONGARCH_machine_flags),
(decode_M68K_machine_flags, decode_MeP_machine_flags),
(decode_MIPS_machine_flags, decode_MSP430_machine_flags),
(decode_PARISC_machine_flags, decode_RISCV_machine_flags),
(decode_RL78_machine_flags, decode_RX_machine_flags),
(decode_SH_machine_flags, decode_SPARC_machine_flags),
(decode_V800_machine_flags, decode_V850_machine_flags),
(decode_Z80_machine_flags): New functions, split out from..
(get_machine_flags): ..here. Similarly use stpcpy.
Alan Modra [Thu, 3 Aug 2023 03:02:40 +0000 (12:32 +0930)]
binutils sprintf optimisation
Avoid the use of sprintf with a "%s" format string, replacing with
strcpy or stpcpy. Use sprintf return value rather than a later
strlen. Don't use strcat where we can keep track of the end of a
string output buffer.
* dlltool.c (look_for_prog): memcpy prefix and strcpy prog_name.
* dllwrap.c (look_for_prog): Likewise.
* resrc.c (look_for_default): Likewise. Add quotes with memmove
rather than allocating another buffer.
* size.c (size_number): Use sprintf return value.
* stabs.c (parse_stab_argtypes): Likewise.
* windmc.c (write_bin): Likewes, and use stpcpy.
* wrstabs.c: Similarly throughout.
Alan Modra [Thu, 3 Aug 2023 02:56:46 +0000 (12:26 +0930)]
cris: sprintf optimisation
Since I was poking at cris-dis.c to avoid the sanitizer warning,
I figure I might as well make use of stpcpy and sprintf return value
in other places in this file.
* cris-dis.c (format_hex): Use sprintf return value.
(format_reg): Use stpcpy and sprintf return, avoiding strlen.
(format_sup_reg): Likewise.
Alan Modra [Wed, 2 Aug 2023 23:30:05 +0000 (09:00 +0930)]
arm: sanitizer stringop-overflow
In function 'memset',
inlined from 'create_unwind_entry' at /home/alan/src/binutils-gdb/gas/config/tc-arm.c:27881:3:
/usr/include/bits/string_fortified.h:59:10: error: '__builtin_memset' specified size between
2147483652 and
4294967295 exceeds maximum object size
2147483647 [-Werror=stringop-overflow=]
59 | return __builtin___memset_chk (__dest, __ch, __len,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60 | __glibc_objsize0 (__dest));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
* config/tc-arm.c (create_unwind_entry): Return after bad size,
and bad opcode count.
Alan Modra [Wed, 2 Aug 2023 23:26:24 +0000 (08:56 +0930)]
xtensa: sprintf sanitizer null destination pointer
* config/tc-xtensa.c (xtensa_add_config_info): Use auto buffer
rather than malloc. Use sprintf return value.
Alan Modra [Wed, 2 Aug 2023 23:10:12 +0000 (08:40 +0930)]
ld: sprintf sanitizer null destination pointer
* configure.ac (stpcpy): AC_CHECK_DECLS.
* sysdep.h (stpcpy): Add fallback declaraion.
* config.in: Regenerate.
* configure: Regenerate.
* emultempl/pe.em (open_dynamic_archive): Use
stpcpy rather than sprintf plus strlen.
* emultempl/pep.em (open_dynamic_archive): Likewise.
* emultempl/xtensaelf.em (elf_xtensa_before_allocation): Use
auto rather than malloc'd buffer. Use sprintf count.
* ldelf.c (ldelf_search_needed): Use memcpy in place of sprintf.
* pe-dll.c (pe_process_import_defs): Use string already formed
for alias match rather than recreating.
Alan Modra [Wed, 2 Aug 2023 22:53:51 +0000 (08:23 +0930)]
gprof: sprintf sanitizer null destination pointer
* basic_blocks.c (annotate_with_count): Use output of sprintf
rather than strlen.
Alan Modra [Wed, 2 Aug 2023 22:48:13 +0000 (08:18 +0930)]
resrc: sprintf sanitizer null destination pointer
* resrc.c (read_rc_file): Use stpcpy rather than sprintf
followed by strlen. Tidy.
Alan Modra [Wed, 2 Aug 2023 22:45:12 +0000 (08:15 +0930)]
dlltool: sprintf sanitizer null destination pointer
* dlltool.c (gen_lib_file): Avoid bogus sanitizer error.
Alan Modra [Wed, 2 Aug 2023 22:37:54 +0000 (08:07 +0930)]
wrstabs: sprintf sanitizer null destination pointer
gcc-2.12 seems to be ignoring __attribute__((__returns_nonnull__))
on xmalloc.
* wrstabs.c (stab_method_type): Use stpcpy rather than sprintf
or strcat.
Alan Modra [Wed, 2 Aug 2023 22:29:47 +0000 (07:59 +0930)]
cris: sprintf sanitizer null destination pointer
Simplify the sprintf calls, and use sprintf return value. Older code
in binutils avoided using the sprintf return count of chars printed,
because with some older C libraries it wasn't reliable. Nowadays it
should be OK to use (and we already use the return value elsewhere).
sprintf can't return an error status of -1 here.
* cris-dis.c (format_dec): Avoid sanitizer warning. Use sprintf
return value rather than calling strlen.
Alan Modra [Wed, 2 Aug 2023 21:59:58 +0000 (07:29 +0930)]
objdump, nm: sprintf sanitizer null destination pointer
Seen on Ubuntu 23.04 x86_64-linux using gcc-12.2 and gcc-12.3 with
CFLAGS="-m32 -g -O2 -fsanitize=address,undefined".
CC objdump.o
In file included from /usr/include/stdio.h:906,
from /home/alan/src/binutils-gdb/binutils/sysdep.h:24,
from /home/alan/src/binutils-gdb/binutils/objdump.c:51:
In function 'sprintf',
inlined from 'display_utf8' at /home/alan/src/binutils-gdb/binutils/objdump.c:621:14,
inlined from 'sanitize_string.part.0' at /home/alan/src/binutils-gdb/binutils/objdump.c:742:11:
/usr/include/bits/stdio2.h:30:10: error: null destination pointer [-Werror=format-overflow=]
30 | return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31 | __glibc_objsize (__s), __fmt,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 | __va_arg_pack ());
| ~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
The warning is bogus of course. xmalloc is guaranteed to return
non-NULL, but apparently this isn't seen in display_utf6. The same
doesn't happen with -m64, maybe due to inlining differences, I haven't
investigated fully. Easily avoided as we hardly need to use sprintf
for a single char, or a two char string.
* objdump.c (display_utf8): Avoid bogus sprintf sanitizer warning.
Use hex ESC to switch back to default colour.
(sanitize_string): Comment. Bump buffer size by one. Fix overlong
line.
* nm.c (display_utf8, sanitize_string): As above.
Andrew Burgess [Tue, 18 Jul 2023 12:52:20 +0000 (13:52 +0100)]
gdb: fix possible nullptr dereference in a remote_debug_printf call
While working on another patch I triggered a segfault from within the
function remote_target::discard_pending_stop_replies. Turns out this
was caused by a cut&paste error introduced in this commit:
commit
df5ad102009c41ab4dfadbb8cfb8c8b2a02a4f78
Date: Wed Dec 1 09:40:03 2021 -0500
gdb, gdbserver: detach fork child when detaching from fork parent
This commit adds a remote_debug_printf call that was copied from
earlier in the function, however, the new call wasn't updated to use
the appropriate local variable. The local variable that it is using
might be nullptr, in which case we trigger undefined behaviour, and
could crash, which is what I was seeing.
Fixed by updating to use the correct local variable.
Tom de Vries [Thu, 3 Aug 2023 08:48:39 +0000 (09:48 +0100)]
Fix Wlto-type-mismatch in opcodes/ft32-dis.c
Tsukasa OI [Thu, 3 Aug 2023 05:35:53 +0000 (05:35 +0000)]
RISC-V: Add support for 'Zvfh' and 'Zvfhmin'
This commit adds support for recently ratified vector FP16 extensions:
'Zvfh' and 'Zvfhmin'.
This is based on:
<https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#zvfhmin-vector-extension-for-minimal-half-precision-floating-point>
<https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#zvfh-vector-extension-for-half-precision-floating-point>
Despite not having any new instructions, it will be necessary since those
extensions are already implemented in GCC.
Note that however, in this commit, following dependencies are implemented.
1. 'Zvfhmin' -> 'Zve32f'
2. 'Zvfh' -> 'Zvfhmin' (not 'Zvfh' -> 'Zve32f' as in the documentation)
3. 'Zvfh' -> 'Zfhmin'
This is because the instructions and configurations supported by the
'Zvfh' extension is a strict superset of the 'Zvfhmin' extension and
'Zvfh' -> 'Zve32f' dependency is indirectly derived from that fact.
bfd/ChangeLog:
* elfxx-riscv.c (riscv_implicit_subsets): Add implications
related to 'Zvfh' and 'Zvfhmin' extensions.
(riscv_supported_std_z_ext) Add 'Zvfh' and 'Zvfhmin' to the list.
Tsukasa OI [Wed, 2 Aug 2023 23:50:27 +0000 (23:50 +0000)]
RISC-V: Imply 'Zicsr' from 'Zve32x'
Further clarification is made so that 'Zve32x' implies 'Zicsr' (the same
implication is already implemented in LLVM).
See related issue (the author raised) on the vector specification:
<https://github.com/riscv/riscv-v-spec/issues/908>
and its resolution:
<https://github.com/riscv/riscv-v-spec/issues/909>
bfd/ChangeLog:
* elfxx-riscv.c (riscv_implicit_subsets): Add 'Zve32x' -> 'Zicsr'.
GDB Administrator [Thu, 3 Aug 2023 00:00:40 +0000 (00:00 +0000)]
Automatic date update in version.in
Tom de Vries [Wed, 2 Aug 2023 21:17:35 +0000 (23:17 +0200)]
[gdb] Initialize main_thread_id earlier
I wrote a patch using is_main_thread (), and found it returning false in the
main thread due to main_thread_id not being initialized yet.
Initialization currently takes place in _initialize_run_on_main_thread, but
that's too late for earlier uses.
Fix this by initializing, either:
- when entering main, or
- on an earlier first use.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
Tom de Vries [Wed, 2 Aug 2023 21:14:58 +0000 (23:14 +0200)]
[gdb/dap] Disable DAP for python <= 3.5
DAP requires python module typing, which is supported starting python 3.5.
Make this formal by:
- disabling the dap interpreter for python version < 3.5
- returning 0 in allow_dap_tests for python version < 3.5
Approved-By: Tom Tromey <tom@tromey.com>
PR dap/30708
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30708
Tom Tromey [Tue, 1 Aug 2023 14:33:42 +0000 (08:33 -0600)]
Avoid failures in fixed_points.exp with older GCC
Tom de Vries pointed out that my recent change to fixed_points.exp
failed with older versions of GCC. This patch fixes the problem by
skipping the new test in this situation.
Sam James [Wed, 2 Aug 2023 11:06:23 +0000 (12:06 +0100)]
Revert "2.41 Release sources"
This reverts commit
675b9d612cc59446e84e2c6d89b45500cb603a8d.
See https://sourceware.org/pipermail/binutils/2023-August/128761.html.
Nick Clifton [Wed, 2 Aug 2023 08:23:36 +0000 (09:23 +0100)]
2.41 Release sources
Khem Raj [Mon, 31 Jul 2023 22:31:40 +0000 (15:31 -0700)]
gprofng: Fix build with 64bit file offset on 32bit machines
gprofng/ChangeLog
2023-07-31 Khem Raj <raj.khem@gmail.com>
* libcollector/iotrace.c: Define open64, fgetpos64, and fsetpos64
only when __USE_LARGEFILE64 and __USE_FILE_OFFSET64 are not
defined.
GDB Administrator [Wed, 2 Aug 2023 00:00:29 +0000 (00:00 +0000)]
Automatic date update in version.in
Alan Modra [Tue, 1 Aug 2023 22:24:47 +0000 (07:54 +0930)]
Don't declare xmalloc and others in ldmisc.h
* ldmisc.h (xmalloc, xrealloc, xexit, yyerror): Don't declare.
* emultempl/pdp11.em: Include libiberty.h.
* emultempl/ticoff.em: Likewise.
* emultempl/vms.em: Likewise.
* ldctor.c: Likewise.
* ldelfgen.c: Likewise.
* ldgram.y: Likewise.
(yyerror): Prototype and make static.
Alan Modra [Tue, 1 Aug 2023 22:23:26 +0000 (07:53 +0930)]
Don't declare xmalloc or xrealloc in bucomm.h
It's better to include the proper header, which has declarations with
various attributes. Commit
096aefc040 in 1994 introduced this wart.
* bucomm.h (xmalloc, xrealloc): Delete declaration.
* od-macho.c: Include libiberty.h.
* od-xcoff.c: Include libiberty.h.
Alan Modra [Tue, 1 Aug 2023 22:13:50 +0000 (07:43 +0930)]
Regen ld/configure
For commit
3d05c80b5dc4.
Tom Tromey [Thu, 27 Jul 2023 20:27:05 +0000 (14:27 -0600)]
Implement DAP "source" request
This implements the DAP "source" request. I renamed the
"loadedSources" function from "sources" to "loaded_sources" to avoid
any confusion. I also moved the loadedSources test to the new
sources.exp.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30691
Tom Tromey [Thu, 27 Jul 2023 20:21:13 +0000 (14:21 -0600)]
Handle Source in DAP breakpointLocations
This changes the DAP breakpointLocations request to accept a Source
and to decode it properly.
Tom Tromey [Thu, 27 Jul 2023 20:04:31 +0000 (14:04 -0600)]
Introduce sourceReference handling in DAP
This changes the gdb DAP implementation to emit a real
sourceReference, rather than emitting 0. Sources are tracked in some
maps in sources.py, and a new helper function is introduced to compute
the "Source" object that can be sent to the client.
Tom Tromey [Tue, 25 Jul 2023 16:55:14 +0000 (10:55 -0600)]
Don't supply DAP 'path' for non-file shared libraries
The DAP 'module' event may include a 'path' component. I noticed that
this is supplied even when the module in question does not come from a
file.
This patch only emits this field when the objfile corresponds to a
real file.
No test case, because I wasn't sure how to write a portable one.
However, it's clear from gdb.log on Linux:
{"type": "event", "event": "module", "body": {"reason": "new", "module": {"id": "system-supplied DSO at 0x7ffff7fc4000", "name": "system-supplied DSO at 0x7ffff7fc4000"}}, "seq": 21}
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30676
Tom Tromey [Tue, 25 Jul 2023 16:13:52 +0000 (10:13 -0600)]
Implement ValueFormat for DAP
This patch implements ValueFormat for DAP. Currently this only means
supporting "hex".
Note that StackFrameFormat is defined to have many more options, but
none are currently recognized. It isn't entirely clear how these
should be handled. I'll file a new gdb bug for this, and perhaps an
upstream DAP bug as well.
New in v2:
- I realized that the "hover" context was broken, and furthermore
that we only had tests for "hover" failing, not for it succeeding.
This version fixes the oversight and adds a test.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30469
Tom Tromey [Thu, 27 Jul 2023 19:06:38 +0000 (13:06 -0600)]
Respect supportsMemoryReferences in DAP
I noticed that the support for memoryReference in the "variables"
output is gated on the client "supportsMemoryReferences" capability.
This patch implements this and makes some other changes to the DAP
memory reference code:
* Remove the memoryReference special case from _SetResult.
Upstream DAP fixed this oversight in response to
https://github.com/microsoft/debug-adapter-protocol/issues/414
* Don't use the address of a variable as its memoryReference -- only
emit this for pointer types. There's no spec support for the
previous approach.
* Use strip_typedefs to handle typedefs of pointers.
Tom Tromey [Tue, 25 Jul 2023 16:48:13 +0000 (10:48 -0600)]
Add DAP support for C++ exceptions
This adds DAP support for the various C++ exception-catching
operations.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30682
Tom Tromey [Tue, 25 Jul 2023 15:16:35 +0000 (09:16 -0600)]
Implement DAP 'terminated' event
This implements the DAP 'terminated' event. Vladimir Makaev noticed
that VSCode will not report the debug session as over unless this is
sent.
It's not completely clear when exactly this event ought to be sent.
Here I've done it when the inferior exits.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30681