Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breakpoint suspend set doesn't seem to work #4

Open
simark opened this issue Jun 6, 2016 · 0 comments
Open

Breakpoint suspend set doesn't seem to work #4

simark opened this issue Jun 6, 2016 · 0 comments

Comments

@simark
Copy link
Contributor

simark commented Jun 6, 2016

I don't know if I am not using it right, or if it's buggy, but here is how it goes. I use the following test case:

#include <stdio.h>
#include <pthread.h>

static pthread_barrier_t barrier;

void *t1_func(void *arg) {
    int i;

    pthread_barrier_wait (&barrier);

    for (i = 0; i < 100; i++) {
        sleep (1);
    }

    return NULL;
}

void *t2_func(void *arg) {
    int i;

    pthread_barrier_wait (&barrier);

    for (i = 0; i < 100; i++) {
        sleep (1);
    }

    return NULL;
}

void all_threads_started (void)
{
}

int main(int argc, char **argv) {
    pthread_t t1, t2;

    pthread_barrier_init (&barrier, NULL, 3);

    pthread_create(&t1, NULL, t1_func, NULL);
    pthread_create(&t2, NULL, t2_func, NULL);

    pthread_barrier_wait (&barrier);

    all_threads_started ();

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    return 0;
}

I start gdb with:

$ ./gdb -nx threads -ex "b all_threads_started" -ex  r

Once there, I want to set a breakpoint in the thread 1's (t1.2) code that will only interrupt thread 2 (t1.3).

(gdb) itfocus tt1.2 break -suspend tt1.3 threads.c:12
Breakpoint 2 at 0x40076c: file threads.c, line 12.
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007cf in all_threads_started at threads.c:32
    trigger only in: at1.1
    suspend all of: at*.*
    breakpoint already hit 1 time
2       breakpoint     keep y   0x000000000040076c in t1_func at threads.c:12
    trigger only in: tt1.2
    suspend all of: tt1.3

So far this looks good, breakpoint 2 will only get triggered by thread 1.2 and will only suspend thread 1.3. I continue:

(gdb) c
Continuing.
[Switching to Thread 0x7ffff77f6700 (LWP 31988)]

Breakpoint 2, t1_func (arg=0x0) at threads.c:12
12          sleep (1);
(gdb) i th
  Id   Target Id         Frame 
  1.1  Thread 0x7ffff7fc5740 (LWP 31984) "threads" (running)
* 1.2  Thread 0x7ffff77f6700 (LWP 31988) "threads" t1_func (arg=0x0) at threads.c:12
  1.3  Thread 0x7ffff6ff5700 (LWP 31989) "threads" 0x00007ffff78b7dfd in nanosleep ()
   from /lib/x86_64-linux-gnu/libc.so.6

Thread 1.3 is interrupted somewhere in its sleep, which is expected, but thread 1.2 was stopped as well, which is unexpected.

If I try in non-stop instead:

$ ./gdb -nx threads -ex "set non-stop on" -ex "b all_threads_started" -ex  r

depending on whether I stop the threads before inserting the breakpoints, I get two different results:

(gdb) i th
  Id   Target Id         Frame 
* 1.1  Thread 0x7ffff7fc5740 (LWP 32591) "threads" all_threads_started () at threads.c:32
  1.2  Thread 0x7ffff77f6700 (LWP 32595) "threads" (running)
  1.3  Thread 0x7ffff6ff5700 (LWP 32596) "threads" (running)
(gdb) itfocus tt1.2 break -suspend tt1.3 threads.c:12
Breakpoint 2 at 0x40076c: file threads.c, line 12.
(gdb) 
Breakpoint 2, t1_func (arg=0x0) at threads.c:12
12          sleep (1);
i th
  Id   Target Id         Frame 
* 1.1  Thread 0x7ffff7fc5740 (LWP 32591) "threads" all_threads_started () at threads.c:32
  1.2  Thread 0x7ffff77f6700 (LWP 32595) "threads" t1_func (arg=0x0) at threads.c:12
  1.3  Thread 0x7ffff6ff5700 (LWP 32596) "threads" (running)

t1.2 was stopped, whereas we would have expected thread 1.3 to stop. Thread 1.1 is still stopped, which is fine because I haven't told it to resume.

And:

(gdb) interrupt -a
(gdb) 
[Thread 0x7ffff77f6700 (LWP 401)] #2 stopped.
0x00007ffff78b7dfd in nanosleep () from /lib/x86_64-linux-gnu/libc.so.6

[Thread 0x7ffff6ff5700 (LWP 402)] #3 stopped.
0x00007ffff78b7dfd in nanosleep () from /lib/x86_64-linux-gnu/libc.so.6
i th
  Id   Target Id         Frame 
* 1.1  Thread 0x7ffff7fc5740 (LWP 397) "threads" all_threads_started () at threads.c:32
  1.2  Thread 0x7ffff77f6700 (LWP 401) "threads" 0x00007ffff78b7dfd in nanosleep ()
   from /lib/x86_64-linux-gnu/libc.so.6
  1.3  Thread 0x7ffff6ff5700 (LWP 402) "threads" 0x00007ffff78b7dfd in nanosleep ()
   from /lib/x86_64-linux-gnu/libc.so.6
(gdb) itfocus tt1.2 break -suspend tt1.3 threads.c:12
Breakpoint 2 at 0x40076c: file threads.c, line 12.
(gdb) c -a &
Continuing.

We would expect a stop of thread 1.3, but nothing stops. The info breakpoint still shows the correct information:

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007cf in all_threads_started at threads.c:32
    trigger only in: at1.1
    suspend all of: 
    breakpoint already hit 1 time
2       breakpoint     keep y   0x000000000040076c in t1_func at threads.c:12
    trigger only in: tt1.2
    suspend all of: tt1.3
palves pushed a commit that referenced this issue Jun 21, 2016
As reported in PR 19998, after type ctrl-c, GDB hang there and does
not send interrupt.  It causes a fail in gdb.base/interrupt.exp.
All targets support remote fileio should be affected.

When we type ctrc-c, SIGINT is handled by remote_fileio_sig_set,
as shown below,

 #0  remote_fileio_sig_set (sigint_func=0x4495d0 <remote_fileio_ctrl_c_signal_handler(int)>) at /home/yao/SourceCode/gnu/gdb/git/gdb/remote-fileio.c:325
 #1  0x00000000004495de in remote_fileio_ctrl_c_signal_handler (signo=<optimised out>) at /home/yao/SourceCode/gnu/gdb/git/gdb/remote-fileio.c:349
 #2  <signal handler called>
 #3  0x00007ffff647ed83 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81
 #4  0x00000000005530ce in interruptible_select (n=10, readfds=readfds@entry=0x7fffffffd730, writefds=writefds@entry=0x0, exceptfds=exceptfds@entry=0x0,
    timeout=timeout@entry=0x0) at /home/yao/SourceCode/gnu/gdb/git/gdb/event-top.c:1017
 #5  0x000000000061ab20 in stdio_file_read (file=<optimised out>, buf=0x12d02e0 "\n\022-\001", length_buf=16383)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/ui-file.c:577
 #6  0x000000000044a4dc in remote_fileio_func_read (buf=0x12c0360 "") at /home/yao/SourceCode/gnu/gdb/git/gdb/remote-fileio.c:583
 #7  0x0000000000449598 in do_remote_fileio_request (uiout=<optimised out>, buf_arg=buf_arg@entry=0x12c0340)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/remote-fileio.c:1179

we don't set quit_serial_event,

  do
    {
      res = gdb_select (n, readfds, writefds, exceptfds, timeout);
    }
  while (res == -1 && errno == EINTR);

  if (res == 1 && FD_ISSET (fd, readfds))
    {
      errno = EINTR;
      return -1;
    }
  return res;

we can't go out of the loop above, and that is why GDB can't send
interrupt.

Recently, we stop throwing exception from SIGINT handler
(remote_fileio_ctrl_c_signal_handler)
https://sourceware.org/ml/gdb-patches/2016-03/msg00372.html, which
is correct, because gdb_select is interruptible.  However, in the
same patch series, we add interruptible_select later as a wrapper
to gdb_select, https://sourceware.org/ml/gdb-patches/2016-03/msg00375.html
and it is not interruptible (because of the loop in it) unless
select/poll-able file descriptors are marked.

This fix in this patch is to call quit_serial_event_set, so that we can
go out of the loop above, return -1 and set errno to EINTR.

2016-06-01  Yao Qi  <[email protected]>

	PR remote/19998
	* remote-fileio.c (remote_fileio_ctrl_c_signal_handler): Call
	quit_serial_event_set.
palves pushed a commit that referenced this issue Jun 21, 2016
This patch adds some sanity check that reinsert breakpoints must be
there when doing step-over on software single step target.  The check
triggers an assert when running forking-threads-plus-breakpoint.exp
on arm-linux target,

 gdb/gdbserver/linux-low.c:4714: A problem internal to GDBserver has been detected.^M
 int finish_step_over(lwp_info*): Assertion `has_reinsert_breakpoints ()' failed.

the error happens when GDBserver has already resumed a thread of
process A for step-over (and wait for it hitting reinsert breakpoint),
but receives detach request for process B from GDB, which is shown in
the backtrace below,

 (gdb) bt
 #2  0x000228aa in finish_step_over (lwp=0x12bbd98) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4703
 #3  0x00025a50 in finish_step_over (lwp=0x12bbd98) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4749
 #4  complete_ongoing_step_over () at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4760
 #5  linux_detach (pid=25228) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:1503
 #6  0x00012bae in process_serial_event () at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/server.c:3974
 #7  handle_serial_event (err=<optimized out>, client_data=<optimized out>) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/server.c:4347
 #8  0x00016d68 in handle_file_event (event_file_desc=<optimized out>) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/event-loop.c:429
 #9  0x000173ea in process_event () at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/event-loop.c:184
 #10 start_event_loop () at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/event-loop.c:547
 #11 0x0000aa2c in captured_main (argv=<optimized out>, argc=<optimized out>) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/server.c:3719
 #12 main (argc=<optimized out>, argv=<optimized out>) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/server.c:3804

the sanity check tries to find the reinsert breakpoint from process B,
but nothing is found.  It is wrong, we need to search in process A,
since we started step-over of a thread of process A.

 (gdb) p lwp->thread->entry.id
 $3 = {pid = 25120, lwp = 25131, tid = 0}
 (gdb) p current_thread->entry.id
 $4 = {pid = 25228, lwp = 25228, tid = 0}

This patch switched current_thread to the thread we are doing step-over
in finish_step_over.

gdb/gdbserver:

2016-06-17  Yao Qi  <[email protected]>

	* linux-low.c (maybe_hw_step): New function.
	(linux_resume_one_lwp_throw): Call maybe_hw_step.
	(finish_step_over): Switch current_thread to lwp temporarily,
	and assert has_reinsert_breakpoints returns true.
	(proceed_one_lwp): Call maybe_hw_step.
	* mem-break.c (has_reinsert_breakpoints): New function.
	* mem-break.h (has_reinsert_breakpoints): Declare.
palves pushed a commit that referenced this issue Aug 25, 2016
When I run process-dies-while-detaching.exp with GDBserver, I see many
warnings printed by GDBserver,

ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26183: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process
ptrace(regsets_fetch_inferior_registers) PID=26184: No such process

regsets_fetch_inferior_registers is called when GDBserver resumes each
lwp.

 #2  0x0000000000428260 in regsets_fetch_inferior_registers (regsets_info=0x4690d0 <aarch64_regsets_info>, regcache=0x31832020)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:5412
 #3  0x00000000004070e8 in get_thread_regcache (thread=0x31832940, fetch=fetch@entry=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/regcache.c:58
 #4  0x0000000000429c40 in linux_resume_one_lwp_throw (info=<optimized out>, signal=0, step=0, lwp=0x31832830)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4463
 #5  linux_resume_one_lwp (lwp=0x31832830, step=<optimized out>, signal=<optimized out>, info=<optimized out>)
    at /home/yao/SourceCode/gnu/gdb/git/gdb/gdbserver/linux-low.c:4573

The is the case that threads are disappeared when GDB/GDBserver resumes
them.  We check errno for ESRCH, and don't print error messages, like
what we are doing in regsets_store_inferior_registers.

gdb/gdbserver:

2016-08-04  Yao Qi  <[email protected]>

	* linux-low.c (regsets_fetch_inferior_registers): Check
	errno is ESRCH or not.
palves added a commit that referenced this issue Aug 25, 2016
… out value

With something like:

  struct A { int bitfield:4; } var;

If 'var' ends up wholly-optimized out, printing 'var.bitfield' crashes
gdb here:

 (top-gdb) bt
 #0  0x000000000058b89f in extract_unsigned_integer (addr=0x2 <error: Cannot access memory at address 0x2>, len=2, byte_order=BFD_ENDIAN_LITTLE)
     at /home/pedro/gdb/mygit/src/gdb/findvar.c:109
 #1  0x00000000005a187a in unpack_bits_as_long (field_type=0x16cff70, valaddr=0x0, bitpos=16, bitsize=12) at /home/pedro/gdb/mygit/src/gdb/value.c:3347
 #2  0x00000000005a1b9d in unpack_value_bitfield (dest_val=0x1b5d9d0, bitpos=16, bitsize=12, valaddr=0x0, embedded_offset=0, val=0x1b5d8d0)
     at /home/pedro/gdb/mygit/src/gdb/value.c:3441
 #3  0x00000000005a2a5f in value_fetch_lazy (val=0x1b5d9d0) at /home/pedro/gdb/mygit/src/gdb/value.c:3958
 #4  0x00000000005a10a7 in value_primitive_field (arg1=0x1b5d8d0, offset=0, fieldno=0, arg_type=0x16d04c0) at /home/pedro/gdb/mygit/src/gdb/value.c:3161
 #5  0x00000000005b01e5 in do_search_struct_field (name=0x1727c60 "bitfield", arg1=0x1b5d8d0, offset=0, type=0x16d04c0, looking_for_baseclass=0, result_ptr=0x7fffffffcaf8,
 [...]

unpack_value_bitfield is already optimized-out/unavailable -aware:

   (...) VALADDR points to the contents of VAL.  If the VAL's contents
   required to extract the bitfield from are unavailable/optimized
   out, DEST_VAL is correspondingly marked unavailable/optimized out.

however, it is not considering the case of the value having no
contents buffer at all, as can happen through
allocate_optimized_out_value.

gdb/ChangeLog:
2016-08-09  Pedro Alves  <[email protected]>

	* value.c (unpack_value_bitfield): Skip unpacking if the parent
	has no contents buffer to begin with.

gdb/testsuite/ChangeLog:
2016-08-09  Pedro Alves  <[email protected]>

	* gdb.dwarf2/bitfield-parent-optimized-out.exp: New file.
palves pushed a commit that referenced this issue Aug 25, 2016
If I build gdb with -fsanitize=address and run tests, I get error,

malformed linespec error: unexpected colon^M
(gdb) PASS: gdb.linespec/ls-errs.exp: lang=C: break     :
break   :=================================================================^M
==3266==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000051451 at pc 0x2b5797a972a8 bp 0x7fffd8e0f3c0 sp 0x7fffd8e0f398^M
READ of size 2 at 0x602000051451 thread T0
    #0 0x2b5797a972a7 in __interceptor_strlen (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x322a7)^M
    #1 0x7bd004 in compare_filenames_for_search(char const*, char const*) /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:316^M
    #2 0x7bd310 in iterate_over_some_symtabs(char const*, char const*, int (*)(symtab*, void*), void*, compunit_symtab*, compunit_symtab*) /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:411^M
    #3 0x7bd775 in iterate_over_symtabs(char const*, int (*)(symtab*, void*), void*) /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:481^M
    #4 0x7bda15 in lookup_symtab(char const*) /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:527^M
    #5 0x7d5e2a in make_file_symbol_completion_list_1 /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:5635^M
    #6 0x7d61e1 in make_file_symbol_completion_list(char const*, char const*, char const*) /home/yao/SourceCode/gnu/gdb/git/gdb/symtab.c:5684^M
    #7 0x88dc06 in linespec_location_completer /home/yao/SourceCode/gnu/gdb/git/gdb/completer.c:288
....
0x602000051451 is located 0 bytes to the right of 1-byte region [0x602000051450,0x602000051451)^M
mallocated by thread T0 here:
    #0 0x2b5797ab97ef in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x547ef)^M
    #1 0xbbfb8d in xmalloc /home/yao/SourceCode/gnu/gdb/git/gdb/common/common-utils.c:43^M
    #2 0x88dabd in linespec_location_completer /home/yao/SourceCode/gnu/gdb/git/gdb/completer.c:273^M
    #3 0x88e5ef in location_completer(cmd_list_element*, char const*, char const*) /home/yao/SourceCode/gnu/gdb/git/gdb/completer.c:531^M
    #4 0x8902e7 in complete_line_internal /home/yao/SourceCode/gnu/gdb/git/gdb/completer.c:964^

The code in question is here

       file_to_match = (char *) xmalloc (colon - text + 1);
       strncpy (file_to_match, text, colon - text + 1);

it is likely that file_to_match is not null-terminated.  The patch is
to strncpy 'colon - text' bytes and explicitly set '\0'.

gdb:

2016-08-19  Yao Qi  <[email protected]>

	* completer.c (linespec_location_completer): Make file_to_match
	null-terminated.
palves added a commit that referenced this issue Aug 25, 2016
This patch fixes a problem that problem triggers if you start an
inferior, e.g., with the "start" command, in a UI created with the
new-ui command, and then run a foreground execution command in the
main UI.  Once the program stops for the latter command, typing in the
main UI no longer echoes back to the user.

The problem revolves around this:

- gdb_has_a_terminal computes its result lazily, on first call.

  that is what saves gdb's initial main UI terminal state (the UI
  associated with stdin):

          our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);

  This is the state that target_terminal_ours() restores.

- In this scenario, the gdb_has_a_terminal function happens to be
  first ever called from within the target_terminal_init call in
  startup_inferior:

      (top-gdb) bt
      #0  gdb_has_a_terminal () at src/gdb/inflow.c:157
      #1  0x000000000079db22 in child_terminal_init_with_pgrp () at src/gdb/inflow.c:217
       [...]
      #4  0x000000000065bacb in target_terminal_init () at src/gdb/target.c:456
      #5  0x00000000004676d2 in startup_inferior () at src/gdb/fork-child.c:531
       [...]
      #7  0x000000000046b168 in linux_nat_create_inferior () at src/gdb/linux-nat.c:1112
       [...]
      #9  0x00000000005f20c9 in start_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:657

If the command to start the inferior is issued on the main UI, then
readline will have deprepped the terminal when we reach the above, and
the problem doesn't appear.

If however the command is issued on a non-main UI, then when we reach
that gdb_has_a_terminal call, the main UI's terminal state is still
set to whatever readline has sets it to in rl_prep_terminal, which
happens to have echo disabled.  Later, when the following synchronous
execution command finishes, we'll call target_terminal_ours to restore
gdb's the main UI's terminal settings, and that restores the terminal
state with echo disabled...

Conceptually, the fix is to move the gdb_has_a_terminal call earlier,
to someplace during GDB initialization, before readline/ncurses have
had a chance to change terminal settings.  Turns out that
"set_initial_gdb_ttystate" is exactly such a place.

I say conceptually, because the fix actually inlines the
gdb_has_a_terminal part that saves the terminal state in
set_initial_gdb_ttystate and then simplifies gdb_has_a_terminal, since
there's no point in making gdb_has_a_terminal do lazy computation.

gdb/ChangeLog:
2016-08-23  Pedro Alves  <[email protected]>

	PR gdb/20494
	* inflow.c (our_terminal_info, initial_gdb_ttystate): Update
	comments.
	(enum gdb_has_a_terminal_flag_enum, gdb_has_a_terminal_flag):
	Delete.
	(set_initial_gdb_ttystate): Record our_terminal_info here too,
	instead of ...
	(gdb_has_a_terminal): ... here.  Reimplement in terms of
	initial_gdb_ttystate.  Make static.
	* terminal.h (gdb_has_a_terminal): Delete declaration.
	(set_initial_gdb_ttystate): Add comment.
	* top.c (show_interactive_mode): Use input_interactive_p instead
	of gdb_has_a_terminal.

gdb/testsuite/ChangeLog:
2016-08-23  Pedro Alves  <[email protected]>

	PR gdb/20494
	* gdb.base/new-ui-echo.c: New file.
	* gdb.base/new-ui-echo.exp: New file.
palves added a commit that referenced this issue Oct 10, 2016
Even though this was supposedly in the gdb 7.2 timeframe, the testcase
in PR11094 crashes current GDB with a segfault:

  Program received signal SIGSEGV, Segmentation fault.
  0x00000000005ee894 in event_location_to_string (location=0x0) at
  src/gdb/location.c:412
  412       if (EL_STRING (location) == NULL)
  (top-gdb) bt
  #0  0x00000000005ee894 in event_location_to_string (location=0x0) at
  src/gdb/location.c:412
  #1  0x000000000057411a in print_breakpoint_location (b=0x18288e0, loc=0x0) at
  src/gdb/breakpoint.c:6201
  #2  0x000000000057483f in print_one_breakpoint_location (b=0x18288e0,
  loc=0x182cf10, loc_number=0, last_loc=0x7fffffffd258, allflag=1)
      at src/gdb/breakpoint.c:6473
  #3  0x00000000005751e1 in print_one_breakpoint (b=0x18288e0,
  last_loc=0x7fffffffd258, allflag=1) at
  src/gdb/breakpoint.c:6707
  #4  0x000000000057589c in breakpoint_1 (args=0x0, allflag=1, filter=0x0) at
  src/gdb/breakpoint.c:6947
  #5  0x0000000000575aa8 in maintenance_info_breakpoints (args=0x0, from_tty=0)
  at src/gdb/breakpoint.c:7026
  [...]

This is GDB trying to print the location spec of the JIT event
breakpoint, but that's an internal breakpoint without one.

If I add a NULL check, then we see that the JIT breakpoint is now
pending (because its location has shlib_disabled set):

  (gdb) maint info breakpoints
  Num     Type           Disp Enb Address            What
  [...]
  -8      jit events     keep y   <PENDING>           inf 1
  [...]

But that's incorrect.  GDB should have managed to recreate the JIT
breakpoint's location for the second run.  So the problem is
elsewhere.

The problem is that if the JIT loads at the same address on the second
run, we never recreate the JIT breakpoint, because we hit this early
return:

  static int
  jit_breakpoint_re_set_internal (struct gdbarch *gdbarch,
				  struct jit_program_space_data *ps_data)
  {
    [...]
    if (ps_data->cached_code_address == addr)
      return 0;

    [...]
      delete_breakpoint (ps_data->jit_breakpoint);
    [...]
    ps_data->jit_breakpoint = create_jit_event_breakpoint (gdbarch, addr);

Fix this by deleting the breakpoint and discarding the cached code
address when the objfile where the previous JIT breakpoint was found
is deleted/unloaded in the first place.

The test that was originally added for PR11094 doesn't trip on this
because:

  #1 - It doesn't test the case of the JIT descriptor's address _not_
       changing between reruns.

  #2 - And then it doesn't do "maint info breakpoints", or really
       anything with the JIT at all.

  #3 - and even then, to trigger the problem the JIT descriptor needs
       to be in a separate library, while the current test puts it in
       the main program.

The patch extends the test to cover all combinations of these
scenarios.

gdb/ChangeLog:
2016-10-06  Pedro Alves  <[email protected]>

	* jit.c (free_objfile_data): Delete the JIT breakpoint and clear
	the cached code address.

gdb/testsuite/ChangeLog:
2016-10-06  Pedro Alves  <[email protected]>

	* gdb.base/jit-simple-dl.c: New file.
	* gdb.base/jit-simple-jit.c: New file, factored out from ...
	* gdb.base/jit-simple.c: ... this.
	* gdb.base/jit-simple.exp (jit_run): Delete.
	(build_jit): New proc.
	(jit_test_reread): Recompile either the main program or the shared
	library, depending on what is being tested.  Skip changing address
	if caller wants to.  Compare before/after addresses.  If testing
	standalone, explicitly load the binary.  Test "maint info
	breakpoints".
	(top level): Add "standalone vs shared lib" and "change address"
	vs "same address" axes.
palves added a commit that referenced this issue Nov 7, 2016
Currently GDB never sends more than one action per vCont packet, when
connected in non-stop mode.  A follow up patch will change that, and
it exposed a gdbserver problem with the vCont handling.

For example, this in non-stop mode:

  => vCont;s:p1.1;c
  <= OK

Should be equivalent to:

  => vCont;s:p1.1
  <= OK
  => vCont;c
  <= OK

But gdbserver currently doesn't handle this.  In the latter case,
"vCont;c" makes gdbserver clobber the previous step request.  This
patch fixes that.

Note the server side must ignore resume actions for the thread that
has a pending %Stopped notification (and any other threads with events
pending), until GDB acks the notification with vStopped.  Otherwise,
e.g., the following case is mishandled:

 #1 => g  (or any other packet)
 #2 <= [registers]
 #3 <= %Stopped T05 thread:p1.2
 #4 => vCont s:p1.1;c
 #5 <= OK

Above, the server must not resume thread p1.2 when it processes the
vCont.  GDB can't know that p1.2 stopped until it acks the %Stopped
notification.  (Otherwise it wouldn't send a default "c" action.)

(The vCont documentation already specifies this.)

Finally, special care must also be given to handling fork/vfork
events.  A (v)fork event actually tells us that two processes stopped
-- the parent and the child.  Until we follow the fork, we must not
resume the child.  Therefore, if we have a pending fork follow, we
must not send a global wildcard resume action (vCont;c).  We can still
send process-wide wildcards though.

(The comments above will be added as code comments to gdb in a follow
up patch.)

gdb/gdbserver/ChangeLog:
2016-10-26  Pedro Alves  <[email protected]>

	* linux-low.c (handle_extended_wait): Link parent/child fork
	threads.
	(linux_wait_1): Unlink them.
	(linux_set_resume_request): Ignore resume requests for
	already-resumed and unhandled fork child threads.
	* linux-low.h (struct lwp_info) <fork_relative>: New field.
	* server.c (in_queued_stop_replies_ptid, in_queued_stop_replies):
	New functions.
	(handle_v_requests) <vCont>: Don't call require_running.
	* server.h (in_queued_stop_replies): New declaration.
palves pushed a commit that referenced this issue Nov 7, 2016
Most of the time, the trace should be in one piece.  This case is handled fine
by GDB.  In some cases, however, there may be gaps in the trace.  They result
from trace decode errors or from overflows.

A gap in the trace means we lost an unknown amount of trace.  Gaps can be very
small, such as a few instructions in the same function, or they can be rather
big.  We may, for example, lose a few function calls or returns.  The trace may
continue in a different function and we likely don't know how we got there.

Even though we can't say how the program executed across a gap, higher levels
may not be impacted too much by it.  Let's assume we have functions a-e and a
trace that looks roughly like this:

  a
   \
    b                    b
     \                  /
      c   <gap>        c
                      /
                 d   d
                  \ /
                   e

Even though we can't say for sure, it is likely that b and c are the same
function instance before and after the gap.  This patch is trying to connect
the c and b function segments across the gap.

This will add a to the back trace of b on the right hand side.  The changes are
reflected in GDB's internal representation of the trace and will improve:

  - the output of "record function-call-history /c"
  - the output of "backtrace" in replay mode
  - source stepping in replay mode
    will be improved indirectly via the improved back trace

I don't have an automated test for this patch; decode errors will be fixed and
overflows occur sporadically and are quite rare.  I tested it by hacking GDB to
provoke a decode error and on the expected gap in the gdb.btrace/dlopen.exp
test.

The issue is that we can't predict where we will be able to re-sync in case of
errors.  For the expected decode error in gdb.btrace/dlopen.exp, for example, we
may be able to re-sync somewhere in dlclose, in test, in main, or not at all.

Here's one example run of gdb.btrace/dlopen.exp with and without this patch.

    (gdb) info record
    Active record target: record-btrace
    Recording format: Intel Processor Trace.
    Buffer size: 16kB.
    warning: Non-contiguous trace at instruction 66608 (offset = 0xa83, pc = 0xb7fdcc31).
    warning: Non-contiguous trace at instruction 66652 (offset = 0xa9b, pc = 0xb7fdcc31).
    warning: Non-contiguous trace at instruction 66770 (offset = 0xacb, pc = 0xb7fdcc31).
    warning: Non-contiguous trace at instruction 66966 (offset = 0xb60, pc = 0xb7ff5ee4).
    warning: Non-contiguous trace at instruction 66994 (offset = 0xb74, pc = 0xb7ff5f24).
    warning: Non-contiguous trace at instruction 67334 (offset = 0xbac, pc = 0xb7ff5e6d).
    warning: Non-contiguous trace at instruction 69022 (offset = 0xc04, pc = 0xb7ff60b3).
    warning: Non-contiguous trace at instruction 69116 (offset = 0xc1c, pc = 0xb7ff60b3).
    warning: Non-contiguous trace at instruction 69504 (offset = 0xc74, pc = 0xb7ff605d).
    warning: Non-contiguous trace at instruction 83648 (offset = 0xecc, pc = 0xb7ff6134).
    warning: Decode error (-13) at instruction 83876 (offset = 0xf48, pc = 0xb7fd6380): no memory mapped at this address.
    warning: Non-contiguous trace at instruction 83876 (offset = 0x11b7, pc = 0xb7ff1c70).
    Recorded 83948 instructions in 912 functions (12 gaps) for thread 1 (process 12996).
    (gdb) record instruction-history 83876, +2
    83876   => 0xb7fec46f <call_init.part.0+95>:    call   *%eax
    [decode error (-13): no memory mapped at this address]
    [disabled]
    83877      0xb7ff1c70 <_dl_close_worker.part.0+1584>:   nop

Without the patch, the trace is disconnected and the backtrace is short:

    (gdb) record goto 83876
    #0  0xb7fec46f in call_init.part () from /lib/ld-linux.so.2
    (gdb) backtrace
    #0  0xb7fec46f in call_init.part () from /lib/ld-linux.so.2
    #1  0xb7fec5d0 in _dl_init () from /lib/ld-linux.so.2
    #2  0xb7ff0fe3 in dl_open_worker () from /lib/ld-linux.so.2
    Backtrace stopped: not enough registers or memory available to unwind further
    (gdb) record goto 83877
    #0  0xb7ff1c70 in _dl_close_worker.part.0 () from /lib/ld-linux.so.2
    (gdb) backtrace
    #0  0xb7ff1c70 in _dl_close_worker.part.0 () from /lib/ld-linux.so.2
    #1  0xb7ff287a in _dl_close () from /lib/ld-linux.so.2
    #2  0xb7fc3d5d in dlclose_doit () from /lib/libdl.so.2
    #3  0xb7fec354 in _dl_catch_error () from /lib/ld-linux.so.2
    #4  0xb7fc43dd in _dlerror_run () from /lib/libdl.so.2
    #5  0xb7fc3d98 in dlclose () from /lib/libdl.so.2
    #6  0x0804860a in test ()
    #7  0x08048628 in main ()

With the patch, GDB is able to connect the trace pieces and we get a full
backtrace.

    (gdb) record goto 83876
    #0  0xb7fec46f in call_init.part () from /lib/ld-linux.so.2
    (gdb) backtrace
    #0  0xb7fec46f in call_init.part () from /lib/ld-linux.so.2
    #1  0xb7fec5d0 in _dl_init () from /lib/ld-linux.so.2
    #2  0xb7ff0fe3 in dl_open_worker () from /lib/ld-linux.so.2
    #3  0xb7fec354 in _dl_catch_error () from /lib/ld-linux.so.2
    #4  0xb7ff02e2 in _dl_open () from /lib/ld-linux.so.2
    #5  0xb7fc3c65 in dlopen_doit () from /lib/libdl.so.2
    #6  0xb7fec354 in _dl_catch_error () from /lib/ld-linux.so.2
    #7  0xb7fc43dd in _dlerror_run () from /lib/libdl.so.2
    #8  0xb7fc3d0e in dlopen@@GLIBC_2.1 () from /lib/libdl.so.2
    #9  0xb7ff28ee in _dl_runtime_resolve () from /lib/ld-linux.so.2
    #10 0x0804841c in ?? ()
    #11 0x08048470 in dlopen@plt ()
    #12 0x080485a3 in test ()
    #13 0x08048628 in main ()
    (gdb) record goto 83877
    #0  0xb7ff1c70 in _dl_close_worker.part.0 () from /lib/ld-linux.so.2
    (gdb) backtrace
    #0  0xb7ff1c70 in _dl_close_worker.part.0 () from /lib/ld-linux.so.2
    #1  0xb7ff287a in _dl_close () from /lib/ld-linux.so.2
    #2  0xb7fc3d5d in dlclose_doit () from /lib/libdl.so.2
    #3  0xb7fec354 in _dl_catch_error () from /lib/ld-linux.so.2
    #4  0xb7fc43dd in _dlerror_run () from /lib/libdl.so.2
    #5  0xb7fc3d98 in dlclose () from /lib/libdl.so.2
    #6  0x0804860a in test ()
    #7  0x08048628 in main ()

It worked nicely in this case but it may, of course, also lead to weird
connections; it is a heuristic, after all.

It works best when the gap is small and the trace pieces are long.

gdb/
	* btrace.c (bfun_s): New typedef.
	(ftrace_update_caller): Print caller in debug dump.
	(ftrace_get_caller, ftrace_match_backtrace, ftrace_fixup_level)
	(ftrace_compute_global_level_offset, ftrace_connect_bfun)
	(ftrace_connect_backtrace, ftrace_bridge_gap, btrace_bridge_gaps): New.
	(btrace_compute_ftrace_bts): Pass vector of gaps.  Collect gaps.
	(btrace_compute_ftrace_pt): Likewise.
	(btrace_compute_ftrace): Split into this, ...
	(btrace_compute_ftrace_1): ... this, and ...
	(btrace_finalize_ftrace): ... this.  Call btrace_bridge_gaps.
palves pushed a commit that referenced this issue Dec 2, 2016
… frame

This patch ensures that the frame id for the current frame is stashed
before that of the previous frame (to the current frame).

First, it should be noted that the frame id for the current frame is
not stashed by get_current_frame().  The current frame's frame id is
lazily computed and stashed via calls to get_frame_id().  However,
it's possible for get_prev_frame() to be called without first stashing
the current frame.

The frame stash is used not only to speed up frame lookups, but
also to detect cycles.  When attempting to compute the frame id
for a "previous" frame (in get_prev_frame_if_no_cycle), a cycle
is detected if the computed frame id is already in the stash.

If it should happen that a previous frame id is stashed which should
represent a cycle for the current frame, then an assertion failure
will trigger should get_frame_id() be later called to determine
the frame id for the current frame.

As of late 2016, with the "Tweak meaning of VALUE_FRAME_ID" patch in
place, this actually occurs when running the
gdb.dwarf2/dw2-dup-frame.exp test.  While attempting to generate a
backtrace, the python frame filter code is invoked, leading to
frame_info_to_frame_object() (in python/py-frame.c) being called.
That function will potentially call get_prev_frame() before
get_frame_id() is called.  The call to get_prev_frame() can eventually
end up in get_prev_frame_if_no_cycle() which, in turn, calls
compute_frame_id(), after which the frame id is stashed for the
previous frame.

If the frame id for the current frame is stashed, the cycle detection
code (which relies on the frame stash) in get_prev_frame_if_no_cycle()
will be triggered for a cycle starting with the current frame.  If the
current frame's id is not stashed, the cycle detecting code can't
operate as designed.  Instead, when get_frame_id() is called on the
current frame at some later point, the current frame's id will found
to be already in the stash, triggering an assertion failure.

Below is an in depth examination of the failure which lead to this change.
I've shortened pathnames for brevity and readability.

Here's the portion of the log file showing the failure/internal error:

(gdb) break stop_frame
Breakpoint 1 at 0x40059a: file dw2-dup-frame.c, line 22.
(gdb) run
Starting program: testsuite/outputs/gdb.dwarf2/dw2-dup-frame/dw2-dup-frame

Breakpoint 1, stop_frame () at dw2-dup-frame.c:22
22	}
(gdb) bt
gdb/frame.c:544: internal-error: frame_id get_frame_id(frame_info*): Assertion `stashed' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n)
FAIL: gdb.dwarf2/dw2-dup-frame.exp: backtrace from stop_frame (GDB internal error)

Here's a partial backtrace from the internal error, showing the frames
which I think are relevant, plus several extra to provide context:

    #0  internal_error (
	file=0x932b98 "gdb/frame.c", line=544,
	fmt=0x932b20 "%s: Assertion `%s' failed.")
	at gdb/common/errors.c:54
    #1  0x000000000072207e in get_frame_id (fi=0xe5a760)
	at gdb/frame.c:544
    #2  0x00000000004eb50d in frame_info_to_frame_object (frame=0xe5a760)
	at gdb/python/py-frame.c:390
    #3  0x00000000004ef5be in bootstrap_python_frame_filters (frame=0xe5a760,
	frame_low=0, frame_high=-1)
	at gdb/python/py-framefilter.c:1453
    #4  0x00000000004ef7a9 in gdbpy_apply_frame_filter (
	extlang=0x8857e0 <extension_language_python>, frame=0xe5a760, flags=7,
	args_type=CLI_SCALAR_VALUES, out=0xf6def0, frame_low=0, frame_high=-1)
	at gdb/python/py-framefilter.c:1548
    #5  0x00000000005f2c5a in apply_ext_lang_frame_filter (frame=0xe5a760,
	flags=7, args_type=CLI_SCALAR_VALUES, out=0xf6def0, frame_low=0,
	frame_high=-1)
	at gdb/extension.c:572
    #6  0x00000000005ea896 in backtrace_command_1 (count_exp=0x0, show_locals=0,
	no_filters=0, from_tty=1)
	at gdb/stack.c:1834

Examination of the code in frame_info_to_frame_object(), which is in
python/py-frame.c, is key to understanding this problem:

      if (get_prev_frame (frame) == NULL
	  && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON
	  && get_next_frame (frame) != NULL)
	{
	  frame_obj->frame_id = get_frame_id (get_next_frame (frame));
	  frame_obj->frame_id_is_next = 1;
	}
      else
	{
	  frame_obj->frame_id = get_frame_id (frame);
	  frame_obj->frame_id_is_next = 0;
	}

I will first note that the frame id for frame has not been computed yet.  (This
was verified by placing a breakpoint on compute_frame_id().)

The call to get_prev_frame() causes the the frame id to (eventually) be
computed for the previous frame.  Here's a backtrace showing how we
get there:

    #0  compute_frame_id (fi=0x10e2810)
	at gdb/frame.c:496
    #1  0x0000000000724a67 in get_prev_frame_if_no_cycle (this_frame=0xe5a760)
	at gdb/frame.c:1871
    #2  0x0000000000725136 in get_prev_frame_always_1 (this_frame=0xe5a760)
	at gdb/frame.c:2045
    #3  0x000000000072516b in get_prev_frame_always (this_frame=0xe5a760)
	at gdb/frame.c:2061
    #4  0x000000000072570f in get_prev_frame (this_frame=0xe5a760)
	at gdb/frame.c:2303
    #5  0x00000000004eb471 in frame_info_to_frame_object (frame=0xe5a760)
	at gdb/python/py-frame.c:381

For this particular case, we end up in the else clause of the code above
which calls get_frame_id (frame).  It's at this point that the frame id
for frame is computed.  Again, here's a backtrace:

    #0  compute_frame_id (fi=0xe5a760)
	at gdb/frame.c:496
    #1  0x000000000072203d in get_frame_id (fi=0xe5a760)
	at gdb/frame.c:539
    #2  0x00000000004eb50d in frame_info_to_frame_object (frame=0xe5a760)
	at gdb/python/py-frame.c:390

The test in question, dw2-dup-frame.exp, deliberately creates a broken
(cyclic) stack.  So, in this instance, the frame id for the prev
`frame' will be the same as that for `frame'.  But that particular
frame id ended up in the stash during the previous frame operation.
When, just a few lines later, we compute the frame id for `frame', the
id in question is already in the stash, thus triggering the assertion
failure.

I considered two other solutions to solving this problem:

We could prevent get_prev_frame() from being called before
get_frame_id() in frame_info_to_frame_object().  (See above for the
snippet of code where this happens.) A call to get_frame_id (frame)
could be placed ahead of that code snippet above.  I have tested this
approach and, while it does work, I can't be certain that
get_prev_frame() isn't called ahead of stashing the current frame
somewhere else in GDB, but in a less obvious way.

Another approach is to stash the current frame's id by calling
get_frame_id() in get_current_frame().  This approach is conceptually
simpler, but when importing a python unwinder, has the unwelcome side
effect of causing the unwinder to be called during import.

A cleaner looking fix would be to place this code after code
corresponding to the "Don't compute the frame id of the current frame
yet..." comment in get_prev_frame_if_no_cycle().  Sadly, this does not
work though; by the time we get to this point, the frame state for the
prev frame has been modified just enough to cause an internal error to
occur when attempting to compute the (current) frame id for inline
frames.  (The unexpected failure count increases by roughly 130
failures.)  Therefore, I decided to place it as early as possible
in get_prev_frame().

gdb/ChangeLog:

	* frame.c (get_prev_frame): Stash frame id for current frame
	prior to computing frame id for previous frame.
palves added a commit that referenced this issue Jan 3, 2017
…binations

This adds a test that exposes several problems fixed by earlier
patches:

#1 - Buffer overrun when host/target formats match, but sizes don't.
     https://sourceware.org/ml/gdb-patches/2016-03/msg00125.html

#2 - Missing handling for FR-V FR300.
     https://sourceware.org/ml/gdb-patches/2016-03/msg00117.html

#3 - BFD architectures with spaces in their names (v850).
     https://sourceware.org/ml/binutils/2016-03/msg00108.html

#4 - The OS ABI names with spaces issue.
     https://sourceware.org/ml/gdb-patches/2016-03/msg00116.html

#5 - Bogus HP/PA long double format.
     https://sourceware.org/ml/gdb-patches/2016-03/msg00122.html

#6 - Cris big endian internal error.
     https://sourceware.org/ml/gdb-patches/2016-03/msg00126.html

#7 - Several PowerPC bfd archs/machines not handled by gdb.
     https://sourceware.org/bugzilla/show_bug.cgi?id=19797

And hopefully helps catch others in the future.

This started out as a test that simply did,

 gdb -ex "print 1.0L"

to exercise #1 above.

Then to cover both 32-bit target / 64-bit host and the converse, I
thought of having the testcase print the floats twice, once with the
architecture set to "i386" and then to "i386:x86-64".  This way it
wouldn't matter whether gdb was built as 32-bit or a 64-bit program.

Then I thought that other archs might have similar host/target
floatformat conversion issues as well.  Instead of hardcoding some
architectures in the test file, I thought we could just iterate over
all bfd architectures and OS ABIs supported by the gdb build being
tested.  This is what then exposed all the other problems listed
above...

With an --enable-targets=all, this exercises over 14 thousand
combinations.  If left in a single test file, it all consistenly runs
in under a minute on my machine (An Intel i7-4810MQ @ 2.8 MHZ running
Fedora 23).  Split in 8 chunks, as in this commit, it runs in around
25 seconds, with make -j8.

To avoid flooding the gdb.sum file, it avoids calling "pass" on each
tested combination/iteration.  I'm explicitly not implementing that by
passing an empty message to gdb_test / gdb_test_multiple, because I
still want a FAIL to be logged in gdb.sum.  So instead this puts the
internal passes in the gdb.log file, only, prefixed "IPASS:", for
internal pass.  TBC, if some iteration fails, it'll still show up as
FAIL in gdb.sum.  If this is an approach that takes on, I can see us
extending the common bits to support it for all testcases.

gdb/testsuite/ChangeLog:
2016-12-09  Pedro Alves  <[email protected]>

	* gdb.base/all-architectures-0.exp: New file.
	* gdb.base/all-architectures-1.exp: New file.
	* gdb.base/all-architectures-2.exp: New file.
	* gdb.base/all-architectures-3.exp: New file.
	* gdb.base/all-architectures-4.exp: New file.
	* gdb.base/all-architectures-5.exp: New file.
	* gdb.base/all-architectures-6.exp: New file.
	* gdb.base/all-architectures-7.exp: New file.
	* gdb.base/all-architectures.exp.in: New file.
palves pushed a commit that referenced this issue Jan 3, 2017
I build GDB for all targets enabled.  When I "set architecture rl78",
GDB crashes,

(gdb) set architecture rl78

Program received signal SIGSEGV, Segmentation fault.
append_flags_type_flag (type=0x20cc0e0, bitpos=bitpos@entry=0, name=name@entry=0x11dba3f "CY") at ../../binutils-gdb/gdb/gdbtypes.c:4926
4926				   name);
(gdb) bt 10
 #0  append_flags_type_flag (type=0x20cc0e0, bitpos=bitpos@entry=0, name=name@entry=0x11dba3f "CY") at ../../binutils-gdb/gdb/gdbtypes.c:4926
 #1  0x00000000004aaca8 in rl78_gdbarch_init (info=..., arches=<optimized out>) at ../../binutils-gdb/gdb/rl78-tdep.c:1410
 #2  0x00000000006b05a4 in gdbarch_find_by_info (info=...) at ../../binutils-gdb/gdb/gdbarch.c:5269
 #3  0x000000000060eee4 in gdbarch_update_p (info=...) at ../../binutils-gdb/gdb/arch-utils.c:557
 #4  0x000000000060f8a8 in set_architecture (ignore_args=<optimized out>, from_tty=1, c=<optimized out>) at ../../binutils-gdb/gdb/arch-utils.c:531
 #5  0x0000000000593d0b in do_set_command (arg=<optimized out>, arg@entry=0x20be851 "rl78", from_tty=from_tty@entry=1, c=c@entry=0x20b1540)
    at ../../binutils-gdb/gdb/cli/cli-setshow.c:455
 #6  0x00000000007665c3 in execute_command (p=<optimized out>, p@entry=0x20be840 "set architecture rl78", from_tty=1) at ../../binutils-gdb/gdb/top.c:666
 #7  0x00000000006935f4 in command_handler (command=0x20be840 "set architecture rl78") at ../../binutils-gdb/gdb/event-top.c:577
 #8  0x00000000006938d8 in command_line_handler (rl=<optimized out>) at ../../binutils-gdb/gdb/event-top.c:767
 #9  0x0000000000692c2c in gdb_rl_callback_handler (rl=0x20be890 "") at ../../binutils-gdb/gdb/event-top.c:200

The cause is that we want to access some builtin types in gdbarch init, but
it is not initialized yet.  I fix it by creating the type when it is to be
used.  We've already done this in sparc, sparc64 and m68k.

gdb:

2016-12-09  Yao Qi  <[email protected]>

	PR tdep/20953
	* rl78-tdep.c (rl78_psw_type): New function.
	(rl78_register_type): Call rl78_psw_type.
	(rl78_gdbarch_init): Move code to rl78_psw_type.

gdb/testsuite:

2016-12-09  Yao Qi  <[email protected]>

	* gdb.base/all-architectures.exp.in: Remove kfail for rl78.
palves pushed a commit that referenced this issue Jan 3, 2017
I build GDB with all targets enabled, and "set architecture rx",
GDB crashes,

(gdb) set architecture rx

Program received signal SIGSEGV, Segmentation fault.
append_flags_type_flag (type=0x20cc360, bitpos=bitpos@entry=0, name=name@entry=0xd27529 "C") at ../../binutils-gdb/gdb/gdbtypes.c:4926
4926				   name);
(gdb) bt 10
 #0  append_flags_type_flag (type=0x20cc360, bitpos=bitpos@entry=0, name=name@entry=0xd27529 "C") at ../../binutils-gdb/gdb/gdbtypes.c:4926
 #1  0x00000000004ce725 in rx_gdbarch_init (info=..., arches=<optimized out>) at ../../binutils-gdb/gdb/rx-tdep.c:1051
 #2  0x00000000006b05a4 in gdbarch_find_by_info (info=...) at ../../binutils-gdb/gdb/gdbarch.c:5269
 #3  0x000000000060eee4 in gdbarch_update_p (info=...) at ../../binutils-gdb/gdb/arch-utils.c:557
 #4  0x000000000060f8a8 in set_architecture (ignore_args=<optimized out>, from_tty=1, c=<optimized out>) at ../../binutils-gdb/gdb/arch-utils.c:531
 #5  0x0000000000593d0b in do_set_command (arg=<optimized out>, arg@entry=0x20bee81 "rx ", from_tty=from_tty@entry=1, c=c@entry=0x20b1540)
    at ../../binutils-gdb/gdb/cli/cli-setshow.c:455
 #6  0x00000000007665c3 in execute_command (p=<optimized out>, p@entry=0x20bee70 "set architecture rx ", from_tty=1) at ../../binutils-gdb/gdb/top.c:666
 #7  0x00000000006935f4 in command_handler (command=0x20bee70 "set architecture rx ") at ../../binutils-gdb/gdb/event-top.c:577
 #8  0x00000000006938d8 in command_line_handler (rl=<optimized out>) at ../../binutils-gdb/gdb/event-top.c:767
 #9  0x0000000000692c2c in gdb_rl_callback_handler (rl=0x20be7f0 "") at ../../binutils-gdb/gdb/event-top.c:200

The cause is that we want to access some builtin types in gdbarch init, but
it is not initialized yet.  I fix it by creating the type when it is to be
used.  We've already done this in sparc, sparc64 and m68k.

gdb:

2016-12-09  Yao Qi  <[email protected]>

	PR tdep/20954
	* rx-tdep.c (rx_psw_type): New function.
	(rx_fpsw_type): New function.
	(rx_register_type): Call rx_psw_type and rx_fpsw_type.
	(rx_gdbarch_init): Move code to rx_psw_type and
	rx_fpsw_type.

gdb/testsuite:

2016-12-09  Yao Qi  <[email protected]>

	* gdb.base/all-architectures.exp.in: Remove kfail for "rx".
palves added a commit that referenced this issue Jan 3, 2017
Nowadays, GDB propagates C++ exceptions across readline using
setjmp/longjmp 8952576 ("Propagate GDB/C++ exceptions across
readline using sj/lj-based TRY/CATCH") because DWARF-based unwinding
can't cross C functions compiled without -fexceptions (see details
from the commit above).

Unfortunately, toolchains that use SjLj-based C++ exceptions got
broken with that fix, because _Unwind_SjLj_Unregister, which is put at
the exit of a function, is not executed due to the longjmp added by
that commit.

 (gdb) [New Thread 2936.0xb80]
 kill

 Thread 1 received signal SIGSEGV, Segmentation fault.
 0x03ff662b in ?? ()
 top?bt 15
 #0  0x03ff662b in ?? ()
 #1  0x00526b92 in stdin_event_handler (error=0, client_data=0x172ed8)
    at ../../binutils-gdb/gdb/event-top.c:555
 #2  0x00525a94 in handle_file_event (ready_mask=<optimized out>,
    file_ptr=0x3ff5cb8) at ../../binutils-gdb/gdb/event-loop.c:733
 #3  gdb_wait_for_event (block=block@entry=1)
    at ../../binutils-gdb/gdb/event-loop.c:884
 #4  0x00525bfb in gdb_do_one_event ()
    at ../../binutils-gdb/gdb/event-loop.c:347
 #5  0x00525ce5 in start_event_loop ()
    at ../../binutils-gdb/gdb/event-loop.c:371
 #6  0x0051fada in captured_command_loop (data=0x0)
    at ../../binutils-gdb/gdb/main.c:324
 #7  0x0051cf5d in catch_errors (
    func=func@entry=0x51fab0 <captured_command_loop(void*)>,
    func_args=func_args@entry=0x0,
    errstring=errstring@entry=0x7922bf <VEC_interp_factory_p_quick_push(VEC_inte rp_factory_p*, interp_factory*, char const*, unsigned int)::__PRETTY_FUNCTION__+351> "", mask=mask@entry=RETURN_MASK_ALL)
    at ../../binutils-gdb/gdb/exceptions.c:236
 #8  0x00520f0c in captured_main (data=0x328feb4)
    at ../../binutils-gdb/gdb/main.c:1149
 #9  gdb_main (args=args@entry=0x328feb4) at ../../binutils-gdb/gdb/main.c:1159
 #10 0x0071e400 in main (argc=1, argv=0x171220)
    at ../../binutils-gdb/gdb/gdb.c:32

Fix this by making the functions involved in setjmp/longjmp as
noexcept, so that the compiler knows it doesn't need to emit the
_Unwind_SjLj_Register / _Unwind_SjLj_Unregister calls for C++
exceptions.

Tested on x86_64 Fedora 23 with:
 - GCC 5.3.1 w/ DWARF-based exceptions.
 - GCC 7 built with --enable-sjlj-exceptions.

gdb/ChangeLog:
2016-12-20  Pedro Alves  <[email protected]>
	    Yao Qi  <[email protected]>

	PR gdb/20977
	* event-top.c (gdb_rl_callback_read_char_wrapper_noexcept): New
	noexcept function, factored out from ...
	(gdb_rl_callback_read_char_wrapper): ... this.
	(gdb_rl_callback_handler): Mark noexcept.
palves pushed a commit that referenced this issue Jan 24, 2017
New in v2:

 - Define PyMem_RawMalloc as PyMem_Malloc for Python < 3.4 and use
   PyMem_RawMalloc in the code.

Since Python 3.4, the callback installed in PyOS_ReadlineFunctionPointer
should return a value allocated with PyMem_RawMalloc instead of
PyMem_Malloc.  The reason is that PyMem_Malloc must be called with the
Python Global Interpreter Lock (GIL) held, which is not the case in the
context where this function is called.  PyMem_RawMalloc was introduced
for cases like this.

In Python 3.6, it looks like they added an assert to verify that
PyMem_Malloc was not called without the GIL.  The consequence is that
typing anything in the python-interactive mode of gdb crashes the
process.  The same behavior was observed with the official package on
Arch Linux as well as with a manual Python build on Ubuntu 14.04.

This is what is shown with a debug build of Python 3.6 (the error with a
non-debug build is far less clear):

  (gdb) pi
  >>> print(1)
  Fatal Python error: Python memory allocator called without holding the GIL

  Current thread 0x00007f1459af8780 (most recent call first):
  [1]    21326 abort      ./gdb

and the backtrace:

  #0  0x00007ffff618bc37 in raise () from /lib/x86_64-linux-gnu/libc.so.6
  #1  0x00007ffff618f028 in abort () from /lib/x86_64-linux-gnu/libc.so.6
  #2  0x00007ffff6b104d6 in Py_FatalError (msg=msg@entry=0x7ffff6ba15b8 "Python memory allocator called without holding the GIL") at Python/pylifecycle.c:1457
  #3  0x00007ffff6a37a68 in _PyMem_DebugCheckGIL () at Objects/obmalloc.c:1972
  #4  0x00007ffff6a3804e in _PyMem_DebugFree (ctx=0x7ffff6e65290 <_PyMem_Debug+48>, ptr=0x24f8830) at Objects/obmalloc.c:1994
  #5  0x00007ffff6a38e1d in PyMem_Free (ptr=<optimized out>) at Objects/obmalloc.c:442
  #6  0x00007ffff6b866c6 in _PyFaulthandler_Fini () at ./Modules/faulthandler.c:1369
  #7  0x00007ffff6b104bd in Py_FatalError (msg=msg@entry=0x7ffff6ba15b8 "Python memory allocator called without holding the GIL") at Python/pylifecycle.c:1431
  #8  0x00007ffff6a37a68 in _PyMem_DebugCheckGIL () at Objects/obmalloc.c:1972
  #9  0x00007ffff6a37aa3 in _PyMem_DebugMalloc (ctx=0x7ffff6e65290 <_PyMem_Debug+48>, nbytes=5) at Objects/obmalloc.c:1980
  #10 0x00007ffff6a38d91 in PyMem_Malloc (size=<optimized out>) at Objects/obmalloc.c:418
  #11 0x000000000064dbe2 in gdbpy_readline_wrapper (sys_stdin=0x7ffff6514640 <_IO_2_1_stdin_>, sys_stdout=0x7ffff6514400 <_IO_2_1_stdout_>, prompt=0x7ffff4d4f7d0 ">>> ")
    at /home/emaisin/src/binutils-gdb/gdb/python/py-gdb-readline.c:75

The documentation is very clear about it [1] and it was also mentioned
in the "What's New In Python 3.4" page [2].

[1] https://docs.python.org/3/c-api/veryhigh.html#c.PyOS_ReadlineFunctionPointer
[2] https://docs.python.org/3/whatsnew/3.4.html#changes-in-the-c-api

gdb/ChangeLog:

	* python/python-internal.h (PyMem_RawMalloc): Define for
	Python < 3.4.
	* python/py-gdb-readline.c (gdbpy_readline_wrapper): Use
	PyMem_RawMalloc instead of PyMem_Malloc.
palves pushed a commit that referenced this issue Jan 24, 2017
When the gdbpy_ref objects get destroyed, they call Py_DECREF to
decrement the reference counter of the python object they hold a
reference to.  Any time we call into the Python API, we should be
holding the GIL.  The gdbpy_enter object does that for us in an
RAII-fashion.

However, if gdbpy_enter is declared after a gdbpy_ref object in a
function, gdbpy_enter's destructor will be called (and the GIL will be
released) before gdbpy_ref's destructor is called.  Therefore, we will
end up calling Py_DECREF without holding the GIL.

This became obvious with Python 3.6, where memory management functions
have asserts to make sure that the GIL is held.  This was exposed by
tests py-as-string.exp, py-function.exp and py-xmethods.  For example:

  (gdb) p $_as_string(enum_valid)
  Fatal Python error: Python memory allocator called without holding the GIL

  Current thread 0x00007f7f7b21c780 (most recent call first):
  [1]    18678 abort (core dumped)  ./gdb -nx testsuite/outputs/gdb.python/py-as-string/py-as-string

  #0  0x00007ffff618bc37 in raise () from /lib/x86_64-linux-gnu/libc.so.6
  #1  0x00007ffff618f028 in abort () from /lib/x86_64-linux-gnu/libc.so.6
  #2  0x00007ffff6b104d6 in Py_FatalError (msg=msg@entry=0x7ffff6ba15b8 "Python memory allocator called without holding the GIL") at Python/pylifecycle.c:1457
  #3  0x00007ffff6a37a68 in _PyMem_DebugCheckGIL () at Objects/obmalloc.c:1972
  #4  0x00007ffff6a3804e in _PyMem_DebugFree (ctx=0x7ffff6e65290 <_PyMem_Debug+48>, ptr=0x24f8830) at Objects/obmalloc.c:1994
  #5  0x00007ffff6a38e1d in PyMem_Free (ptr=<optimized out>) at Objects/obmalloc.c:442
  #6  0x00007ffff6b866c6 in _PyFaulthandler_Fini () at ./Modules/faulthandler.c:1369
  #7  0x00007ffff6b104bd in Py_FatalError (msg=msg@entry=0x7ffff6ba15b8 "Python memory allocator called without holding the GIL") at Python/pylifecycle.c:1431
  #8  0x00007ffff6a37a68 in _PyMem_DebugCheckGIL () at Objects/obmalloc.c:1972
  #9  0x00007ffff6a3804e in _PyMem_DebugFree (ctx=0x7ffff6e652c0 <_PyMem_Debug+96>, ptr=0x7ffff46b6040) at Objects/obmalloc.c:1994
  #10 0x00007ffff6a38f55 in PyObject_Free (ptr=<optimized out>) at Objects/obmalloc.c:503
  #11 0x00007ffff6a5f27e in unicode_dealloc (unicode=unicode@entry=0x7ffff46b6040) at Objects/unicodeobject.c:1794
  #12 0x00007ffff6a352a9 in _Py_Dealloc (op=0x7ffff46b6040) at Objects/object.c:1786
  #13 0x000000000063f28b in gdb_Py_DECREF (op=0x7ffff46b6040) at /home/emaisin/src/binutils-gdb/gdb/python/python-internal.h:192
  #14 0x000000000063fa33 in gdbpy_ref_policy::decref (ptr=0x7ffff46b6040) at /home/emaisin/src/binutils-gdb/gdb/python/py-ref.h:35
  #15 0x000000000063fa77 in gdb::ref_ptr<_object, gdbpy_ref_policy>::~ref_ptr (this=0x7fffffffcdf0, __in_chrg=<optimized out>) at /home/emaisin/src/binutils-gdb/gdb/common/gdb_ref_ptr.h:91
  #16 0x000000000064d8b8 in fnpy_call (gdbarch=0x2b50010, language=0x115d2c0 <c_language_defn>, cookie=0x7ffff46b7468, argc=1, argv=0x7fffffffcf48)
    at /home/emaisin/src/binutils-gdb/gdb/python/py-function.c:145

The fix is to place the gdbpy_enter first in the function.  I also
cleaned up the comments a bit and removed the unnecessary initialization
of the value variable.

gdb/ChangeLog:

	* python/py-function.c (fnpy_call): Reorder declarations to have
	the gdbpy_enter object declared first.
	* python/py-xmethods.c (gdbpy_get_xmethod_arg_types): Likewise.
palves added a commit that referenced this issue Feb 9, 2017
This commit fixes a "-gdb-set logging redirect on" crash by not
handling "logging redirect on" on the fly.

Previous discussion here:
 https://sourceware.org/ml/gdb-patches/2017-01/msg00467.html

Code for handling "logging redirect on" on the fly was added here:
 https://sourceware.org/ml/gdb-patches/2010-08/msg00202.html

Meanwhile, MI gained support for logging, but flipping redirect "on"
on the fly was not considered.  The result is that this sequence of
commands crashes GDB:

 -gdb-set logging on
 -gdb-set logging redirect on

 Program received signal SIGSEGV, Segmentation fault.
 0x00000000008dd7bc in gdb_flush (file=0x2a097f0) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/ui-file.c:95
 194       file->to_flush (file);
 (top-gdb) bt
 #0  0x00000000008dd7bc in gdb_flush(ui_file*) (file=0x2a097f0) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/ui-file.c:95
 #1  0x00000000007b5f34 in gdb_wait_for_event(int) (block=0) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/event-loop.c:752
 #2  0x00000000007b52b6 in gdb_do_one_event() () at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/event-loop.c:322
 #3  0x00000000007b5362 in start_event_loop() () at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/event-loop.c:371
 #4  0x000000000082704a in captured_command_loop(void*) (data=0x0) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/main.c:325
 #5  0x00000000007b8d7c in catch_errors(int (*)(void*), void*, char*, return_mask) (func=0x827008 <captured_command_loop(void*)>, func_args=0x0, errstring=0x11dee51 "", mask=RETURN_MASK_ALL) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/exceptions.c:236
 #6  0x000000000082839b in captured_main(void*) (data=0x7fffffffd820) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/main.c:1148
 During symbol reading, cannot get low and high bounds for subprogram DIE at 24065.
 #7  0x00000000008283c4 in gdb_main(captured_main_args*) (args=0x7fffffffd820) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/main.c:1158
 #8  0x0000000000412d4d in main(int, char**) (argc=4, argv=0x7fffffffd928) at /home/pedro/gdb/mygit/cxx-convertion/src/gdb/gdb.c:32

The handling of redirect on the fly is not really a use case we need
to handle, IMO.  Its inconsistent (other "set logging foo" commands
aren't handled on the fly), and complicates the code significantly.
Instead of complicating it further for MI, go back to the original
idea of warning, only:

  https://sourceware.org/ml/gdb-patches/2010-08/msg00083.html

New test included.

gdb/ChangeLog:
2017-02-02  Pedro Alves  <[email protected]>

	* cli/cli-logging.c (maybe_warn_already_logging): New factored out
	from ...
	(set_logging_overwrite): ... here.
	(logging_no_redirect_file): Delete.
	(set_logging_redirect): Don't handle redirection on the fly.
	Instead warn that "logging off" / "logging on" is necessary.
	(pop_output_files): Delete references to logging_no_redirect_file.
	(show_logging_command): Always speak in terms of what will happen
	once logging is reenabled.

gdb/testsuite/ChangeLog:
2017-02-02  Pedro Alves  <[email protected]>

	* gdb.mi/mi-logging.exp: Add "redirect while already logging"
	tests.
palves pushed a commit that referenced this issue Feb 14, 2017
This is a follow-up to

  https://sourceware.org/ml/gdb-patches/2017-02/msg00261.html

This patch restricts queries to the main UI, which allows to avoid two
different problems.

The first one is that GDB is issuing queries on secondary MI channels
for which a TTY is allocated.  The second one is that GDB is not able to
handle queries on two (CLI) UIs simultaneously.  Restricting queries to
the main UI allows to bypass these two problems.

More details on how/why these two problems happen:

1. Queries on secondary MI UI

  The current criterion to decide if we should query the user is whether
  the input stream is a TTY.  The original way to start GDB in MI mode
  from a front-end was to create a subprocess with pipes to its
  stdin/stdout.  In this case, the input was considered non-interactive
  and queries were auto-answered.  Now that front-ends can create the MI
  channel as a separate UI connected to a dedicated TTY, GDB now
  considers this input stream as interactive and sends queries to it.
  By restricting queries to the main UI, we make sure we never query on
  the secondary MI UI.

2. Simultaneous queries

  As Pedro stated it, when you have two queries on two different CLI UIs
  at the same time, you end up with the following pseudo stack:

  #0 gdb_readline_wrapper
  #1 defaulted_query                 // for UI #2
  #2 handle_command
  #3 execute_command ("handle SIGTRAP" ....
  #4 stdin_event_handler             // input on UI #2
  #5 gdb_do_one_event
  #7 gdb_readline_wrapper
  #8 defaulted_query                 // for UI #1
  #9 handle_command
  #10 execute_command ("handle SIGINT" ....
  #11 stdin_event_handler            // input on UI #1
  #12 gdb_do_one_event
  #13 gdb_readline_wrapper

  trying to answer the query on UI #1 will therefore answer for UI #2.

  By restricting the queries to the main UI, we ensure that there will
  never be more than one pending query, since you can't have two queries
  on a UI at the same time.

I added a snippet to gdb.base/new-ui.exp to verify that we get a query
on the main UI, but that we don't on the secondary one (or, more
precisely, that it gets auto-answered).

gdb/ChangeLog:

	* utils.c (defaulted_query): Don't query on secondary UIs.

gdb/testsuite/ChangeLog:

	* gdb.base/new-ui.exp (do_test): Test queries behavior on main
	and extra UIs.
palves pushed a commit that referenced this issue Feb 24, 2017
In commit 2f408ec (Use ui_file_as_string throughout more), we start to
new varobj_item,

> -  vitem = XNEW (struct varobj_item);
> +  vitem = new varobj_item ();

but we still use xfree.  This causes some ASAN errors,

-var-update container^M
=================================================================^M
^[[1m^[[31m==20660==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new vs free) on 0x602000090c10^M
^[[1m^[[0m    #0 0x2baa77d03631 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x54631)^M
    #1 0x80e0c8 in xfree(void*) /home/yao/SourceCode/gnu/gdb/git/gdb/common/common-utils.c:100^M
    #2 0xc13670 in varobj_clear_saved_item /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:727^M
    #3 0xc13957 in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:752^M
    #4 0xc1841c in varobj_update(varobj**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:1699^M
    #5 0x5a2bf7 in varobj_update_one /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:712^M
    #6 0x5a2a41 in mi_cmd_var_update(char*, char**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:695^
........
^M
^[[1m^[[32m0x602000090c10 is located 0 bytes inside of 16-byte region [0x602000090c10,0x602000090c20)^M
^[[1m^[[0m^[[1m^[[35mallocated by thread T0 here:^[[1m^[[0m^M
    #0 0x2baa77d0415f in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.1+0x5515f)^M
    #1 0x63613e in py_varobj_iter_next /home/yao/SourceCode/gnu/gdb/git/gdb/python/py-varobj.c:112^M
    #2 0xc13b89 in update_dynamic_varobj_children /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:776^M
    #3 0xc1841c in varobj_update(varobj**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/varobj.c:1699^M
    #4 0x5a2bf7 in varobj_update_one /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:712^M
    #5 0x5a2a41 in mi_cmd_var_update(char*, char**, int) /home/yao/SourceCode/gnu/gdb/git/gdb/mi/mi-cmd-var.c:695^M

gdb:

2017-02-23  Yao Qi  <[email protected]>

	* varobj.c (varobj_clear_saved_item): Use delete instead of
	xfree.
	(update_dynamic_varobj_children): Likewise.
palves pushed a commit that referenced this issue Feb 24, 2017
ASAN reports an error,

-var-create container @ c^M
=================================================================^M
^[[1m^[[31m==21639==ERROR: AddressSanitizer: alloc-dealloc-mismatch (malloc vs operator delete) on 0x6030000805c0^M
^[[1m^[[0m    #0 0x7f2449b01b2a in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99b2a)^M
    #1 0xbb601d in update_dynamic_varobj_children ../../binutils-gdb/gdb/varobj.c:794^M
    #2 0xbb6556 in varobj_get_num_children(varobj*) ../../binutils-gdb/gdb/varobj.c:854^M
    #3 0x580cb4 in print_varobj ../../binutils-gdb/gdb/mi/mi-cmd-var.c:61^M
    #4 0x58138b in mi_cmd_var_create(char*, char**, int) ../../binutils-gdb/gdb/mi/mi-cmd-var.c:145^M
    #5 0x5967ce in mi_cmd_execute ../../binutils-gdb/gdb/mi/mi-main.c:2301^M
    #6 0x594b05 in captured_mi_execute_command ../../binutils-gdb/gdb/mi/mi-main.c:2001
....
^M
^[[1m^[[32m0x6030000805c0 is located 0 bytes inside of 32-byte region [0x6030000805c0,0x6030000805e0)^M
^[[1m^[[0m^[[1m^[[35mallocated by thread T0 here:^[[1m^[[0m^M
    #0 0x7f2449b00602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)^M
    #1 0x7d1596 in xmalloc ../../binutils-gdb/gdb/common/common-utils.c:43^M
    #2 0x604176 in py_varobj_iter_new ../../binutils-gdb/gdb/python/py-varobj.c:159^M
    #3 0x6042da in py_varobj_get_iterator(varobj*, _object*) ../../binutils-gdb/gdb/python/py-varobj.c:198^M
    #4 0xbb5806 in varobj_get_iterator ../../binutils-gdb/gdb/varobj.c:720^M
    #5 0xbb5b9b in update_dynamic_varobj_children ../../binutils-gdb/gdb/varobj.c:758^M

gdb:

2017-02-23  Yao Qi  <[email protected]>

	* varobj-iter.h (varobj_iter_delete): Call xfree instead of
	delete.
palves pushed a commit that referenced this issue Mar 7, 2017
ASAN reports the following error,

(gdb) PASS: gdb.fortran/vla-ptr-info.exp: continue to breakpoint: pvla-associated
print &pvla^M
=================================================================^M
^[[1m^[[31m==14331==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000ea569f at pc 0x0000008eb546 bp 0x7ffde0c1dc70 sp 0x7ffde0c1dc60^M
^[[1m^[[0m^[[1m^[[34mREAD of size 1 at 0x000000ea569f thread T0^[[1m^[[0m^M
    #0 0x8eb545 in f_print_type(type*, char const*, ui_file*, int, int, type_print_options const*) ../../binutils-gdb/gdb/f-typeprint.c:89^M
    #1 0xb611e2 in type_print(type*, char const*, ui_file*, int) ../../binutils-gdb/gdb/typeprint.c:365^M
    #2 0x7b3471 in c_value_print(value*, ui_file*, value_print_options const*) ../../binutils-gdb/gdb/c-valprint.c:650^M
    #3 0xb99517 in value_print(value*, ui_file*, value_print_options const*) ../../binutils-gdb/gdb/valprint.c:1233^M
    #4 0xa42be8 in print_formatted ../../binutils-gdb/gdb/printcmd.c:321^M
    #5 0xa46ac9 in print_value(value*, format_data const*) ../../binutils-gdb/gdb/printcmd.c:1233^M
    #6 0xa46d82 in print_command_1 ../../binutils-gdb/gdb/printcmd.c:1261^M
    #7 0xa46e3e in print_command ../../binutils-gdb/gdb/printcmd.c:1267

on this line of code

      demangled_args = varstring[strlen (varstring) - 1] == ')';

because varstring is an empty string and strlen () is 0, so "strlen () - 1"
is definitely out of the bound of "varstring",

(gdb) bt 10
    at /home/yao/SourceCode/gnu/gdb/git/gdb/f-typeprint.c:56
    at /home/yao/SourceCode/gnu/gdb/git/gdb/typeprint.c:365
    at /home/yao/SourceCode/gnu/gdb/git/gdb/c-valprint.c:650
    at /home/yao/SourceCode/gnu/gdb/git/gdb/valprint.c:1236

This patch adds a pre-check that varstring is empty or not.

gdb:

2017-02-27  Yao Qi  <[email protected]>

	* f-typeprint.c (f_print_type): Check "varstring" is empty first.
palves added a commit that referenced this issue Apr 4, 2017
Commit d7e7473 ("Eliminate make_cleanup_ui_file_delete / make
ui_file a class hierarchy") introduced a problem when using "layout
regs", that leads gdb to crash when issuing:

./gdb ./a.out -ex 'layout regs' -ex start

From the backtrace, it's caused by this 'delete' on tui_restore_gdbout():

 (gdb) bt
 #0  0x00007ffff6b962b2 in free () from /lib64/libc.so.6
 #1  0x000000000059fa47 in tui_restore_gdbout (ui=0x22997b0) at ../../gdb/tui/tui-regs.c:714
 #2  0x0000000000619996 in do_my_cleanups (pmy_chain=pmy_chain@entry=0x1e08320 <cleanup_chain>, old_chain=old_chain@entry=0x235b4b0) at ../../gdb/common/cleanups.c:154
 #3  0x0000000000619b1d in do_cleanups (old_chain=old_chain@entry=0x235b4b0) at ../../gdb/common/cleanups.c:176
 #4  0x000000000059fb0d in tui_register_format (frame=frame@entry=0x22564e0, regnum=regnum@entry=0) at ../../gdb/tui/tui-regs.c:747
 #5  0x000000000059ffeb in tui_get_register (data=0x2434d18, changedp=0x0, regnum=0, frame=0x22564e0) at ../../gdb/tui/tui-regs.c:768
 #6  tui_show_register_group (refresh_values_only=<optimized out>, frame=0x22564e0, group=0x1e09250 <general_group>) at ../../gdb/tui/tui-regs.c:287
 #7  tui_show_registers (group=0x1e09250 <general_group>) at ../../gdb/tui/tui-regs.c:156
 #8  0x00000000005a07cf in tui_check_register_values (frame=frame@entry=0x22564e0) at ../../gdb/tui/tui-regs.c:496
 #9  0x00000000005a3e65 in tui_check_data_values (frame=frame@entry=0x22564e0) at ../../gdb/tui/tui-windata.c:232
 #10 0x000000000059cf65 in tui_refresh_frame_and_register_information (registers_too_p=1) at ../../gdb/tui/tui-hooks.c:156
 #11 0x00000000006d5c05 in generic_observer_notify (args=0x7fffffffdbe0, subject=<optimized out>) at ../../gdb/observer.c:167
 #12 observer_notify_normal_stop (bs=<optimized out>, print_frame=print_frame@entry=1) at ./observer.inc:61
 #13 0x00000000006a6409 in normal_stop () at ../../gdb/infrun.c:8364
 #14 0x00000000006af8f5 in fetch_inferior_event (client_data=<optimized out>) at ../../gdb/infrun.c:3990
 #15 0x000000000066f0fd in gdb_wait_for_event (block=block@entry=0) at ../../gdb/event-loop.c:859
 #16 0x000000000066f237 in gdb_do_one_event () at ../../gdb/event-loop.c:322
 #17 0x000000000066f386 in gdb_do_one_event () at ../../gdb/event-loop.c:353
 #18 0x00000000007411bc in wait_sync_command_done () at ../../gdb/top.c:570
 #19 0x0000000000741426 in maybe_wait_sync_command_done (was_sync=0) at ../../gdb/top.c:587
 #20 execute_command (p=<optimized out>, p@entry=0x7fffffffe43a "start", from_tty=from_tty@entry=1) at ../../gdb/top.c:676
 #21 0x00000000006c2048 in catch_command_errors (command=0x741200 <execute_command(char*, int)>, arg=0x7fffffffe43a "start", from_tty=1) at ../../gdb/main.c:376
 #22 0x00000000006c2b60 in captured_main_1 (context=0x7fffffffde70) at ../../gdb/main.c:1119
 #23 captured_main (data=0x7fffffffde70) at ../../gdb/main.c:1140
 #24 gdb_main (args=args@entry=0x7fffffffdf90) at ../../gdb/main.c:1158
 #25 0x0000000000408cf5 in main (argc=<optimized out>, argv=<optimized out>) at ../../gdb/gdb.c:32
 (gdb) f 1
 #1  0x000000000059fa47 in tui_restore_gdbout (ui=0x22997b0) at ../../gdb/tui/tui-regs.c:714
 714	  delete gdb_stdout;

The problem is simply that the commit mentioned above made the ui_file
that gdb_stdout is temporarily set to be a stack-allocated
string_file, while before it used to be a heap-allocated ui_file.  The
fix is simply to remove the now-incorrect delete.

New test included, which exercises enabling all TUI layouts, with and
without execution.  (This particular crash only triggers with
execution.)

gdb/ChangeLog:
2017-03-07  Pedro Alves  <[email protected]>

	* tui/tui-regs.c (tui_restore_gdbout): Don't delete gdb_stdout.

gdb/testsuite/ChangeLog:
2017-03-07  Pedro Alves  <[email protected]>

	* gdb.base/tui-layout.c: New file.
	* gdb.base/tui-layout.exp: New file.
palves pushed a commit that referenced this issue May 8, 2017
I build GDB with asan, and run test case hook-stop.exp, and threadapply.exp,
I got the following asan error,

=================================================================^M
^[[1m^[[31m==2291==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000999c4 at pc 0x000000826022 bp 0x7ffd28a8ff70 sp 0x7ffd28a8ff60^M
^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000999c4 thread T0^[[1m^[[0m^M
    #0 0x826021 in release_stop_context_cleanup ../../binutils-gdb/gdb/infrun.c:8203^M
    #1 0x72798a in do_my_cleanups ../../binutils-gdb/gdb/common/cleanups.c:154^M
    #2 0x727a32 in do_cleanups(cleanup*) ../../binutils-gdb/gdb/common/cleanups.c:176^M
    #3 0x826895 in normal_stop() ../../binutils-gdb/gdb/infrun.c:8381^M
    #4 0x815208 in fetch_inferior_event(void*) ../../binutils-gdb/gdb/infrun.c:4011^M
    #5 0x868aca in inferior_event_handler(inferior_event_type, void*) ../../binutils-gdb/gdb/inf-loop.c:44^M
....
^[[1m^[[32m0x6160000999c4 is located 68 bytes inside of 568-byte region [0x616000099980,0x616000099bb8)^M
^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
    #0 0x7fb0bc1312ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
    #1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
    #2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
    #3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M
    #4 0x805494 in kill_command ../../binutils-gdb/gdb/infcmd.c:2595^M
....

Detaching from program: /home/yao.qi/SourceCode/gnu/build-with-asan/gdb/testsuite/outputs/gdb.threads/threadapply/threadapply, process 2399^M
=================================================================^M
^[[1m^[[31m==2387==ERROR: AddressSanitizer: heap-use-after-free on address 0x6160000a98c0 at pc 0x00000083fd28 bp 0x7ffd401c3110 sp 0x7ffd401c3100^M
^[[1m^[[0m^[[1m^[[34mREAD of size 4 at 0x6160000a98c0 thread T0^[[1m^[[0m^M
    #0 0x83fd27 in thread_alive ../../binutils-gdb/gdb/thread.c:741^M
    #1 0x844277 in thread_apply_all_command ../../binutils-gdb/gdb/thread.c:1804^M
....
^M
^[[1m^[[32m0x6160000a98c0 is located 64 bytes inside of 568-byte region [0x6160000a9880,0x6160000a9ab8)^M
^[[1m^[[0m^[[1m^[[35mfreed by thread T0 here:^[[1m^[[0m^M
    #0 0x7f59a7e322ca in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x982ca)^M
    #1 0xb8c62f in xfree(void*) ../../binutils-gdb/gdb/common/common-utils.c:100^M
    #2 0x83df67 in free_thread ../../binutils-gdb/gdb/thread.c:207^M
    #3 0x83dfd2 in init_thread_list() ../../binutils-gdb/gdb/thread.c:223^M

This patch fixes the issue by deleting thread_info object if it is
deletable, otherwise, mark it as exited (by set_thread_exited).
Function set_thread_exited is shared from delete_thread_1.  This patch
also moves field "refcount" to private and methods incref and
decref.  Additionally, we stop using "ptid_t" in
"struct current_thread_cleanup" to reference threads, instead we use
"thread_info" directly.  Due to this change, we don't need
restore_current_thread_ptid_changed anymore.

gdb:

2017-04-10  Yao Qi  <[email protected]>

	PR gdb/19942
	* gdbthread.h (thread_info::deletable): New method.
	(thread_info::incref): New method.
	(thread_info::decref): New method.
	(thread_info::refcount): Move it to private.
	* infrun.c (save_stop_context): Call inc_refcount.
	(release_stop_context_cleanup): Likewise.
	* thread.c (set_thread_exited): New function.
	(init_thread_list): Delete "tp" only it is deletable, otherwise
	call set_thread_exited.
	(delete_thread_1): Call set_thread_exited.
	(current_thread_cleanup) <inferior_pid>: Remove.
	<thread>: New field.
	(restore_current_thread_ptid_changed): Removed.
	(do_restore_current_thread_cleanup): Adjust.
	(restore_current_thread_cleanup_dtor): Don't call
	find_thread_ptid.
	(set_thread_refcount): Use dec_refcount.
	(make_cleanup_restore_current_thread): Adjust.
	(thread_apply_all_command): Call inc_refcount.
	(_initialize_thread): Don't call
	observer_attach_thread_ptid_changed.
palves pushed a commit that referenced this issue May 8, 2017
Change

  if (PIC)
    {
      #1
    }
  else
    {
      #2
      if (VxWorks)
        {
          #3
        }
    }
  #4
  if (VxWorks && !PIC)
    {
      #5
    }

to

  #4
  if (PIC)
    {
      #1
    }
  else
    {
      #2
      if (VxWorks)
        {
          #3
          #5
        }
    }

	* elf32-i386.c (elf_i386_finish_dynamic_sections): Simplify
	VxWorks for non-PIC.
palves pushed a commit that referenced this issue Jun 14, 2017
This patch adds one unit test for gdbarch methods register_to_value and
value_to_register.  The test pass different combinations of {regnu, type}
to gdbarch_register_to_value and gdbarch_value_to_register.  In order
to do the test, add a new function create_new_frame to create a fake
frame.  It can be improved after we converted frame_info to class.

In order to isolate regcache (from target_ops operations on writing
registers, like target_store_registers), the sub-class of regcache in the
test override raw_write.  Also, in order to get the right regcache from
get_thread_arch_aspace_regcache, the sub-class of regcache inserts itself
to current_regcache.

Suppose I incorrectly modified the size of buffer as below,

@@ -1228,7 +1228,7 @@ ia64_register_to_value (struct frame_info *frame, int regnum,
                        int *optimizedp, int *unavailablep)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  gdb_byte in[MAX_REGISTER_SIZE];
+  gdb_byte in[1];

   /* Convert to TYPE.  */
   if (!get_frame_register_bytes (frame, regnum, 0,

build GDB with "-fsanitize=address" and run unittest.exp, asan can detect
such error

==2302==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff98193870 at pc 0xbd55ea bp 0x7fff981935a0 sp 0x7fff98193598
WRITE of size 16 at 0x7fff98193870 thread T0
    #0 0xbd55e9 in frame_register_unwind(frame_info*, int, int*, int*, lval_type*, unsigned long*, int*, unsigned char*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1119
    #1 0xbd58c8 in frame_register(frame_info*, int, int*, int*, lval_type*, unsigned long*, int*, unsigned char*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1147
    #2 0xbd6e25 in get_frame_register_bytes(frame_info*, int, unsigned long, int, unsigned char*, int*, int*) /home/yao/SourceCode/gnu/gdb/git/gdb/frame.c:1427
    #3 0x70080a in ia64_register_to_value /home/yao/SourceCode/gnu/gdb/git/gdb/ia64-tdep.c:1236
    #4 0xbf570e in gdbarch_register_to_value(gdbarch*, frame_info*, int, type*, unsigned char*, int*, int*) /home/yao/SourceCode/gnu/gdb/git/gdb/gdbarch.c:2619
    #5 0xc05975 in register_to_value_test /home/yao/SourceCode/gnu/gdb/git/gdb/gdbarch-selftests.c:131

Or, even if GDB is not built with asan, GDB just crashes.

*** stack smashing detected ***: ./gdb terminated
Aborted (core dumped)

gdb:

2017-05-24  Yao Qi  <[email protected]>

	* Makefile.in (SFILES): Add gdbarch-selftests.c.
	(COMMON_OBS): Add gdbarch-selftests.o.
	* frame.c [GDB_SELF_TESTS] (create_new_frame): New function.
	* frame.h [GDB_SELF_TESTS] (create_new_frame): Declare.
	* gdbarch-selftests.c: New file.
	* regcache.h (regcache) <~regcache>: Mark it virtual if
	GDB_SELF_TEST.
	<raw_write>: Likewise.
palves added a commit that referenced this issue Jul 5, 2017
In some cases we've been replacing heap-allocated gdb_byte buffers
managed with xmalloc/make_cleanup(xfree) with gdb::vector<gdb_byte>.
That usually pessimizes the code a little bit because std::vector
value-initializes elements (which for gdb_byte means
zero-initialization), while if you're creating a temporary buffer,
you're most certaintly going to fill it in with some data.  An
alternative is to use

  unique_ptr<gdb_byte[]> buf (new gdb_byte[size]);

but it looks like that's not very popular.

Recently, a use of obstacks in dwarf2read.c was replaced with
std::vector<gdb_byte> and that as well introduced a pessimization for
always memsetting the buffer when it's garanteed that the zeros will
be overwritten immediately.  (see dwarf2read.c change in this patch to
find it.)

So here's a different take at addressing this issue "by design":

#1 - Introduce default_init_allocator<T>

I.e., a custom allocator that does default construction using default
initialization, meaning, no more zero initialization.  That's the
default_init_allocation<T> class added in this patch.

See "Notes" at
<http://en.cppreference.com/w/cpp/container/vector/resize>.

#2 - Introduce def_vector<T>

I.e., a convenience typedef, because typing the allocator is annoying:

  using def_vector<T> = std::vector<T, gdb::default_init_allocator<T>>;

#3 - Introduce byte_vector

Because gdb_byte vectors will be the common thing, add a convenience
"byte_vector" typedef:

  using byte_vector = def_vector<gdb_byte>;

which is really the same as:

  std::vector<gdb_byte, gdb::default_init_allocator<gdb_byte>>;

The intent then is to make "gdb::byte_vector" be the go-to for dynamic
byte buffers.  So the less friction, the better.

#4 - Adjust current code to use it.

To set the example going forward.  Replace std::vector uses and also
unique_ptr<byte[]> uses.

One nice thing is that with this allocator, for changes like these:

  -std::unique_ptr<byte[]> buf (new gdb_byte[some_size]);
  +gdb::byte_vector buf (some_size);
   fill_with_data (buf.data (), buf.size ());

the generated code is the same as before.  I.e., the compiler
de-structures the vector and gets rid of the unused "reserved vs size"
related fields.

The other nice thing is that it's easier to write
  gdb::byte_vector buf (size);
than
  std::unique_ptr<gdb_byte[]> buf (new gdb_byte[size]);
or even (C++14):
  auto buf = std::make_unique<gdb_byte[]> (size); // zero-initializes...

#5 - Suggest s/std::vector<gdb_byte>/gdb::byte_vector/ going forward.

Note that this commit actually fixes a couple of bugs where the current
code is incorrectly using "std::vector::reserve(new_size)" and then
accessing the vector's internal buffer beyond the vector's size: see
dwarf2loc.c and charset.c.  That's undefined behavior and may trigger
debug mode assertion failures.  With default_init_allocator,
"resize()" behaves like "reserve()" performance wise, in that it
leaves new elements with unspecified values, but, it does that safely
without triggering undefined behavior when you access those values.

gdb/ChangeLog:
2017-06-14  Pedro Alves  <[email protected]>

	* ada-lang.c: Include "common/byte-vector.h".
	(ada_value_primitive_packed_val): Use gdb::byte_vector.
	* charset.c (wchar_iterator::iterate): Resize the vector instead
	of reserving it.
	* common/byte-vector.h: Include "common/def-vector.h".
	(wchar_iterator::m_out): Now a gdb::def_vector<gdb_wchar_t>.
	* cli/cli-dump.c: Include "common/byte-vector.h".
	(dump_memory_to_file, restore_binary_file): Use gdb::byte_vector.
	* common/byte-vector.h: New file.
	* common/def-vector.h: New file.
	* common/default-init-alloc.h: New file.
	* dwarf2loc.c: Include "common/byte-vector.h".
	(rw_pieced_value): Use gdb::byte_vector, and resize the vector
	instead of reserving it.
	* dwarf2read.c: Include "common/byte-vector.h".
	(data_buf::m_vec): Now a gdb::byte_vector.
	* gdb_regex.c: Include "common/def-vector.h".
	(compiled_regex::compiled_regex): Use gdb::def_vector<char>.
	* mi/mi-main.c: Include "common/byte-vector.h".
	(mi_cmd_data_read_memory): Use gdb::byte_vector.
	* printcmd.c: Include "common/byte-vector.h".
	(print_scalar_formatted): Use gdb::byte_vector.
	* valprint.c: Include "common/byte-vector.h".
	(maybe_negate_by_bytes, print_decimal_chars): Use
	gdb::byte_vector.
palves added a commit that referenced this issue Aug 31, 2017
Ref: https://sourceware.org/ml/gdb-patches/2017-07/msg00162.html

Debugging x86-64 GNU/Linux programs currently crashes GDB in
tdesc_use_registers during gdbarch initialization:

  Program received signal SIGSEGV, Segmentation fault.
  0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728
  728       if (*slot == HTAB_EMPTY_ENTRY)
  (top-gdb) p slot
  $1 = (void **) 0x0
  (top-gdb) bt
  #0  0x0000000001093eaf in htab_remove_elt_with_hash (htab=0x2ef9fa0, element=0x26af960, hash=557151073) at src/libiberty/hashtab.c:728
  #1  0x0000000001093e79 in htab_remove_elt (htab=0x2ef9fa0, element=0x26af960) at src/libiberty/hashtab.c:714
  #2  0x00000000009121b0 in tdesc_use_registers (gdbarch=0x3001240, target_desc=0x2659cb0, early_data=0x2881cb0)
      at src/gdb/target-descriptions.c:1328
  #3  0x000000000047c93e in i386_gdbarch_init (info=..., arches=0x0) at src/gdb/i386-tdep.c:8634
  #4  0x0000000000818d5f in gdbarch_find_by_info (info=...) at src/gdb/gdbarch.c:5394
  #5  0x00000000007198a8 in set_gdbarch_from_file (abfd=0x2f48250) at src/gdb/arch-utils.c:618
  #6  0x00000000007f21cb in exec_file_attach (filename=0x7fffffffddb0 "/home/pedro/gdb/tests/threads", from_tty=1) at src/gdb/exec.c:380
  #7  0x0000000000865c18 in catch_command_errors_const (command=0x7f1d83 <exec_file_attach(char const*, int)>, arg=0x7fffffffddb0 "/home/pedro/gdb/tests/threads",
      from_tty=1) at src/gdb/main.c:403
  #8  0x00000000008669cf in captured_main_1 (context=0x7fffffffd860) at src/gdb/main.c:1035
  #9  0x0000000000866de2 in captured_main (data=0x7fffffffd860) at src/gdb/main.c:1142
  #10 0x0000000000866e24 in gdb_main (args=0x7fffffffd860) at src/gdb/main.c:1160
  #11 0x000000000041312d in main (argc=3, argv=0x7fffffffd968) at src/gdb/gdb.c:32

The direct cause of the crash is that we tried to remove an element
from the hash which supposedly exists, but does not.  (htab_remove_elt
shouldn't really crash in this case, but that's secondary.)

The real problem is that early_data passed to tdesc_use_registers
includes regs from a target description that is not the target_desc,
which violates its assumptions.  The registers in question are the
fs_base/gs_base registers, added by amd64_init_abi:

      tdesc_numbered_register (feature, tdesc_data_segments,
		       AMD64_FSBASE_REGNUM, "fs_base");
      tdesc_numbered_register (feature, tdesc_data_segments,
		       AMD64_GSBASE_REGNUM, "gs_base");

and that happens because amd64_linux_init_abi uses amd64_init_abi as
helper, but they don't coordinate on which fallback tdesc to use.

amd64_init_abi does:

  if (! tdesc_has_registers (tdesc))
    tdesc = tdesc_amd64;

and then adds the fs_base/gs_base registers of the "tdesc_amd64" tdesc
to the tdesc_arch_data.

After amd64_init_abi returns, amd64_linux_init_abi does:

  if (! tdesc_has_registers (tdesc))
    tdesc = tdesc_amd64_linux;
  tdep->tdesc = tdesc;

and we end up tdesc_amd64_linux installed in tdep->tdesc.

The fix is to make sure that amd64_linux_init_abi and amd64_init_abi
agree on default tdesc, by adding a "default tdesc" parameter to
amd64_init_abi, instead of having amd64_init_abi hardcode a default.
With this, amd64_init_abi creates the fs_base/gs_base registers using
the tdesc_amd64_linux tdesc.

Tested on x86-64 GNU/Linux, -m64.  I don't have an x32 setup handy.

Thanks to John Baldwin, Yao Qi and Simon Marchi for the investigation.

gdb/ChangeLog:
2017-07-13  Pedro Alves  <[email protected]>

	* amd64-darwin-tdep.c (x86_darwin_init_abi_64): Pass tdesc_amd64
	as default tdesc.
	* amd64-dicos-tdep.c (amd64_dicos_init_abi):
	* amd64-fbsd-tdep.c (amd64fbsd_init_abi):
	* amd64-linux-tdep.c (amd64_linux_init_abi): Pass
	tdesc_amd64_linux as default tdesc.  Get final tdesc from the
	tdep.
	(amd64_x32_linux_init_abi): Pass tdesc_x32_linux as default tdesc.
	Get final tdesc from the tdep.
	* amd64-nbsd-tdep.c (amd64nbsd_init_abi): Pass tdesc_amd64 as
	default tdesc.
	* amd64-obsd-tdep.c (amd64obsd_init_abi): Likewise.
	* amd64-sol2-tdep.c (amd64_sol2_init_abi): Likewise.
	* amd64-tdep.c (amd64_init_abi): Add 'default_tdesc' parameter.
	Use it as default tdesc.
	(amd64_x32_init_abi): Add 'default_tdesc' parameter, and pass it
	down to amd_init_abi.  No longer handle fallback tdesc here.
	* amd64-tdep.h (tdesc_x32): Declare.
	(amd64_init_abi, amd64_x32_init_abi): Add 'default_tdesc'
	parameter.
	* amd64-windows-tdep.c (amd64_windows_init_abi): Pass tdesc_amd64
	as default tdesc.
palves pushed a commit that referenced this issue Aug 31, 2017
PR 21555 is caused by the exception during the prologue analysis when re-set
a breakpoint.

(gdb) bt
 #0  memory_error_message (err=TARGET_XFER_E_IO, gdbarch=0x153db50, memaddr=93824992233232) at ../../binutils-gdb/gdb/corefile.c:192
 #1  0x00000000005718ed in memory_error (err=TARGET_XFER_E_IO, memaddr=memaddr@entry=93824992233232) at ../../binutils-gdb/gdb/corefile.c:220
 #2  0x00000000005719d6 in read_memory_object (object=object@entry=TARGET_OBJECT_CODE_MEMORY, memaddr=93824992233232, memaddr@entry=1, myaddr=myaddr@entry=0x7fffffffd0a0 "P\333S\001", len=len@entry=1) at ../../binutils-gdb/gdb/corefile.c:259
 #3  0x0000000000571c6e in read_code (len=1, myaddr=0x7fffffffd0a0 "P\333S\001", memaddr=<optimized out>) at ../../binutils-gdb/gdb/corefile.c:287
 #4  read_code_unsigned_integer (memaddr=memaddr@entry=93824992233232, len=len@entry=1, byte_order=byte_order@entry=BFD_ENDIAN_LITTLE)                          at ../../binutils-gdb/gdb/corefile.c:362
 #5  0x000000000041d4a0 in amd64_analyze_prologue (gdbarch=gdbarch@entry=0x153db50, pc=pc@entry=93824992233232, current_pc=current_pc@entry=18446744073709551615, cache=cache@entry=0x7fffffffd1e0) at ../../binutils-gdb/gdb/amd64-tdep.c:2310
 #6  0x000000000041e404 in amd64_skip_prologue (gdbarch=0x153db50, start_pc=93824992233232) at ../../binutils-gdb/gdb/amd64-tdep.c:2459
 #7  0x000000000067bfb0 in skip_prologue_sal (sal=sal@entry=0x7fffffffd4e0) at ../../binutils-gdb/gdb/symtab.c:3628
 #8  0x000000000067c4d8 in find_function_start_sal (sym=sym@entry=0x1549960, funfirstline=1) at ../../binutils-gdb/gdb/symtab.c:3501
 #9  0x000000000060999d in symbol_to_sal (result=result@entry=0x7fffffffd5f0, funfirstline=<optimized out>, sym=sym@entry=0x1549960) at ../../binutils-gdb/gdb/linespec.c:3860
....
 #16 0x000000000054b733 in location_to_sals (b=b@entry=0x15792d0, location=0x157c230, search_pspace=search_pspace@entry=0x1148120, found=found@entry=0x7fffffffdc64) at ../../binutils-gdb/gdb/breakpoint.c:14211
 #17 0x000000000054c1f5 in breakpoint_re_set_default (b=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14301
 #18 0x00000000005412a9 in breakpoint_re_set_one (bint=bint@entry=0x15792d0) at ../../binutils-gdb/gdb/breakpoint.c:14412

This problem can be fixed by

 - either each prologue analyzer doesn't throw exception,
 - or catch the exception thrown from gdbarch_skip_prologue,

I choose the latter because the former needs to fix *every* prologue
analyzer to not throw exception.

This error can be reproduced by changing reread.exp.  The test reread.exp
has already test that breakpoint can be reset correctly after the
executable is re-read.  This patch extends this test by compiling test c
file with and without -fPIE.

(gdb) run ^M
The program being debugged has been started already.^M
Start it from the beginning? (y or n) y^M
x86_64/gdb/testsuite/outputs/gdb.base/reread/reread' has changed; re-reading symbols.
Error in re-setting breakpoint 1: Cannot access memory at address 0x555555554790^M
Error in re-setting breakpoint 2: Cannot access memory at address 0x555555554790^M
Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/testsuite/outputs/gdb.base/reread/reread ^M
This is foo^M
[Inferior 1 (process 27720) exited normally]^M
(gdb) FAIL: gdb.base/reread.exp: opts= "-fPIE" "ldflags=-pie" : run to foo() second time (the program exited)

This patch doesn't re-indent the code, to keep the patch simple.

gdb:

2017-07-25  Yao Qi  <[email protected]>

	PR gdb/21555
	* arch-utils.c (gdbarch_skip_prologue_noexcept): New function.
	* arch-utils.h (gdbarch_skip_prologue_noexcept): Declare.
	* infrun.c: Include arch-utils.h
	(handle_step_into_function): Call gdbarch_skip_prologue_noexcept.
	(handle_step_into_function_backward): Likewise.
	* symtab.c (skip_prologue_sal): Likewise.

gdb/testsuite:

2017-07-25  Yao Qi  <[email protected]>

	PR gdb/21555
	* gdb.base/reread.exp: Wrap the whole test with two kinds of
	compilation flags, with -fPIE and without -fPIE.
palves added a commit that referenced this issue Oct 6, 2017
…ior yet

A following patch will change the default target_thread_architecture
method, like this:

   struct gdbarch *
   default_thread_architecture (struct target_ops *ops, ptid_t ptid)
   {
  -  return target_gdbarch ();
  +  inferior *inf = find_inferior_ptid (ptid);
  +  gdb_assert (inf != NULL);
  +  return inf->gdbarch;
   }

This is because target_gdbarch is really just
current_inferior()->gdbarch, and it's wrong to return that
architecture when the inferior of the passed in PTID is NOT the
current inferior -- the inferior for PTID may be running a different
architecture.  E.g., a mix of 64-bit and 32-bit inferiors in the same
debug session.

Doing that change above however exposes a problem in "maint print
registers", caught be the testsuite:

 -PASS: gdb.base/maint.exp: maint print registers
 +FAIL: gdb.base/maint.exp: maint print registers (GDB internal error)
...
  gdb/inferior.c:309: internal-error: inferior* find_inferior_pid(int): Assertion `pid != 0' failed.
  A problem internal to GDB has been detected,

The call stack looks like this:

  #0  0x000000000068b707 in internal_error(char const*, int, char const*, ...) (file=0xa9b958 "gdb/inferior.c", line=309, fmt=0xa9b8e0 "%s: Assertion `%s' failed.") at gdb/common/errors.c:54
  #1  0x00000000006e1c40 in find_inferior_pid(int) (pid=0) at gdb/inferior.c:309
  #2  0x00000000006e1c8d in find_inferior_ptid(ptid_t) (ptid=...) at gdb/inferior.c:323
  #3  0x00000000007c18dc in default_thread_architecture(target_ops*, ptid_t) (ops=0xf86d60 <dummy_target>, ptid=...)
      at gdb/target.c:3134
  #4  0x00000000007b5414 in delegate_thread_architecture(target_ops*, ptid_t) (self=0xf86d60 <dummy_target>, arg1=...)
      at gdb/target-delegates.c:2527
  #5  0x00000000007647b3 in get_thread_regcache(ptid_t) (ptid=...) at gdb/regcache.c:466
  #6  0x00000000007647ff in get_current_regcache() () at gdb/regcache.c:475
  #7  0x0000000000767495 in regcache_print(char const*, regcache_dump_what) (args=0x0, what_to_dump=regcache_dump_none)
      at gdb/regcache.c:1599
  #8  0x0000000000767550 in maintenance_print_registers(char const*, int) (args=0x0, from_tty=1)
      at gdb/regcache.c:1613

I.e., the test does "maint print registers" while the inferior is not
running yet.  This is expected to work, and there's already a hack in
get_thread_arch_regcache to make it work.

Instead of pilling on hacks in the internal of regcache and
target_ops, this commit moves the null_ptid special casing to where it
belongs -- higher up in the call chain in the implementation of "maint
print registers" & co directly.

gdb/ChangeLog:
2017-10-04  Pedro Alves  <[email protected]>

	* regcache.c (get_thread_arch_regcache): Remove null_ptid special
	case.
	(regcache_print): Handle !target_has_registers here instead.
palves pushed a commit that referenced this issue Nov 16, 2017
M68HC11_LAST_HARD_REG is 8, but m68hc11 register number is started from 0,
so there are 9 raw registers, but M68HC11_NUM_REGS is 8 by mistake.

My following unit test can find this issue (GDB is built with asan)

=================================================================
==15555==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000113150 at pc 0x51393f bp 0x7fffcec36f60 sp 0x7fffcec36f58
WRITE of size 2 at 0x602000113150 thread T0
    #0 0x51393e in m68hc11_pseudo_register_read gdb/m68hc11-tdep.c:320
    #1 0xc4b620 in gdbarch_pseudo_register_read(gdbarch*, regcache*, int, unsigned char*) gdb/gdbarch.c:1974
    #2 0xddad88 in regcache::cooked_read(int, unsigned char*) gdb/regcache.c:710
    #3 0xddff2b in cooked_read_test gdb/regcache.c:1850
    #4 0xdf8cfb in selftests::gdbarch_selftest::operator()() const gdb/selftest-arch.c:73

gdb:

2017-11-15  Yao Qi  <[email protected]>

	* m68hc11-tdep.c (M68HC11_NUM_REGS): Change it to
	M68HC11_LAST_HARD_REG + 1.
palves pushed a commit that referenced this issue Apr 30, 2021
…PR gdb/27147)

PR 27147 shows that on sparc64, GDB is unable to properly unwind:

Expected result (from GDB 9.2):

    #0  0x0000000000108de4 in puts ()
    #1  0x0000000000100950 in hello () at gdb-test.c:4
    #2  0x0000000000100968 in main () at gdb-test.c:8

Actual result (from GDB latest git):

    #0  0x0000000000108de4 in puts ()
    #1  0x0000000000100950 in hello () at gdb-test.c:4
    Backtrace stopped: previous frame inner to this frame (corrupt stack?)

The first failing commit is 5b6d1e4 ("Multi-target support").  The cause
of the change in behavior is due to (thanks for Andrew Burgess for finding
this):

 - inferior_ptid is no longer set on entry of target_ops::wait, whereas
   it was set to something valid previously
 - deep down in linux_nat_target::wait (see stack trace below), we fetch
   the registers of the event thread
 - on sparc64, fetching registers involves reading memory (in
   sparc_supply_rwindow, see stack trace below)
 - reading memory (target_ops::xfer_partial) relies on inferior_ptid
   being set to the thread from which we want to read memory

This is where things go wrong:

    #0  linux_nat_target::xfer_partial (this=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, annex=0x0, readbuf=0x7feffe3b000 "", writebuf=0x0, offset=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:3697
    #1  0x00000100007f5b10 in raw_memory_xfer_partial (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, readbuf=0x7feffe3b000 "", writebuf=0x0, memaddr=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/target.c:912
    #2  0x00000100007f60e8 in memory_xfer_partial_1 (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, readbuf=0x7feffe3b000 "", writebuf=0x0, memaddr=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/target.c:1043
    #3  0x00000100007f61b4 in memory_xfer_partial (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, readbuf=0x7feffe3b000 "", writebuf=0x0, memaddr=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/target.c:1072
    #4  0x00000100007f6538 in target_xfer_partial (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, annex=0x0, readbuf=0x7feffe3b000 "", writebuf=0x0, offset=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/target.c:1129
    #5  0x00000100007f7094 in target_read_partial (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, annex=0x0, buf=0x7feffe3b000 "", offset=8791798050744, len=8, xfered_len=0x7feffe3ae88) at /home/simark/src/binutils-gdb/gdb/target.c:1375
    #6  0x00000100007f721c in target_read (ops=0x10000fa2c40 <the_sparc64_linux_nat_target>, object=TARGET_OBJECT_MEMORY, annex=0x0, buf=0x7feffe3b000 "", offset=8791798050744, len=8) at /home/simark/src/binutils-gdb/gdb/target.c:1415
    #7  0x00000100007f69d4 in target_read_memory (memaddr=8791798050744, myaddr=0x7feffe3b000 "", len=8) at /home/simark/src/binutils-gdb/gdb/target.c:1218
    #8  0x0000010000758520 in sparc_supply_rwindow (regcache=0x10000fea4f0, sp=8791798050736, regnum=-1) at /home/simark/src/binutils-gdb/gdb/sparc-tdep.c:1960
    #9  0x000001000076208c in sparc64_supply_gregset (gregmap=0x10000be3190 <sparc64_linux_ptrace_gregmap>, regcache=0x10000fea4f0, regnum=-1, gregs=0x7feffe3b230) at /home/simark/src/binutils-gdb/gdb/sparc64-tdep.c:1974
    #10 0x0000010000751b64 in sparc_fetch_inferior_registers (regcache=0x10000fea4f0, regnum=80) at /home/simark/src/binutils-gdb/gdb/sparc-nat.c:170
    #11 0x0000010000759d68 in sparc64_linux_nat_target::fetch_registers (this=0x10000fa2c40 <the_sparc64_linux_nat_target>, regcache=0x10000fea4f0, regnum=80) at /home/simark/src/binutils-gdb/gdb/sparc64-linux-nat.c:38
    #12 0x00000100008146ec in target_fetch_registers (regcache=0x10000fea4f0, regno=80) at /home/simark/src/binutils-gdb/gdb/target.c:3287
    #13 0x00000100006a8c5c in regcache::raw_update (this=0x10000fea4f0, regnum=80) at /home/simark/src/binutils-gdb/gdb/regcache.c:584
    #14 0x00000100006a8d94 in readable_regcache::raw_read (this=0x10000fea4f0, regnum=80, buf=0x7feffe3b7c0 "") at /home/simark/src/binutils-gdb/gdb/regcache.c:598
    #15 0x00000100006a93b8 in readable_regcache::cooked_read (this=0x10000fea4f0, regnum=80, buf=0x7feffe3b7c0 "") at /home/simark/src/binutils-gdb/gdb/regcache.c:690
    #16 0x00000100006b288c in readable_regcache::cooked_read<unsigned long, void> (this=0x10000fea4f0, regnum=80, val=0x7feffe3b948) at /home/simark/src/binutils-gdb/gdb/regcache.c:777
    #17 0x00000100006a9b44 in regcache_cooked_read_unsigned (regcache=0x10000fea4f0, regnum=80, val=0x7feffe3b948) at /home/simark/src/binutils-gdb/gdb/regcache.c:791
    #18 0x00000100006abf3c in regcache_read_pc (regcache=0x10000fea4f0) at /home/simark/src/binutils-gdb/gdb/regcache.c:1295
    #19 0x0000010000507920 in save_stop_reason (lp=0x10000fc5b10) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:2612
    #20 0x00000100005095a4 in linux_nat_filter_event (lwpid=520983, status=1407) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:3050
    #21 0x0000010000509f9c in linux_nat_wait_1 (ptid=..., ourstatus=0x7feffe3c8f0, target_options=...) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:3194
    #22 0x000001000050b1d0 in linux_nat_target::wait (this=0x10000fa2c40 <the_sparc64_linux_nat_target>, ptid=..., ourstatus=0x7feffe3c8f0, target_options=...) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:3432
    #23 0x00000100007f8ac0 in target_wait (ptid=..., status=0x7feffe3c8f0, options=...) at /home/simark/src/binutils-gdb/gdb/target.c:2000
    #24 0x00000100004ac17c in do_target_wait_1 (inf=0x1000116d280, ptid=..., status=0x7feffe3c8f0, options=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:3464
    #25 0x00000100004ac3b8 in operator() (__closure=0x7feffe3c678, inf=0x1000116d280) at /home/simark/src/binutils-gdb/gdb/infrun.c:3527
    #26 0x00000100004ac7cc in do_target_wait (wait_ptid=..., ecs=0x7feffe3c8c8, options=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:3540
    #27 0x00000100004ad8c4 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:3880
    #28 0x0000010000485568 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
    #29 0x000001000050d394 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
    #30 0x0000010000ab5c8c in handle_file_event (file_ptr=0x10001207270, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
    #31 0x0000010000ab6334 in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
    #32 0x0000010000ab487c in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
    #33 0x0000010000542668 in start_event_loop () at /home/simark/src/binutils-gdb/gdb/main.c:348
    #34 0x000001000054287c in captured_command_loop () at /home/simark/src/binutils-gdb/gdb/main.c:408
    #35 0x0000010000544e84 in captured_main (data=0x7feffe3d188) at /home/simark/src/binutils-gdb/gdb/main.c:1242
    #36 0x0000010000544f2c in gdb_main (args=0x7feffe3d188) at /home/simark/src/binutils-gdb/gdb/main.c:1257
    #37 0x00000100000c1f14 in main (argc=4, argv=0x7feffe3d548) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

There is a target_read_memory call in sparc_supply_rwindow, whose return
value is not checked.  That call fails, because inferior_ptid does not
contain a valid ptid, and uninitialized buffer contents is used.
Ultimately it results in a corrupt stop_pc.

target_ops::fetch_registers can be (and should remain, in my opinion)
independent of inferior_ptid, because the ptid of the thread from which
to fetch registers can be obtained from the regcache.  In other words,
implementations of target_ops::fetch_registers should not rely on
inferior_ptid having a sensible value on entry.

The sparc64_linux_nat_target::fetch_registers case is special, because it calls
a target method that is dependent on the inferior_ptid value
(target_read_inferior, and ultimately target_ops::xfer_partial).  So I would
say it's the responsibility of sparc64_linux_nat_target::fetch_registers to set
up inferior_ptid correctly prior to calling target_read_inferior.

This patch makes sparc64_linux_nat_target::fetch_registers (and
store_registers, since it works the same) temporarily set inferior_ptid.  If we
ever make target_ops::xfer_partial independent of inferior_ptid, setting
inferior_ptid won't be necessary, we'll simply pass down the ptid as a
parameter in some way.

I chose to set/restore inferior_ptid in sparc_fetch_inferior_registers, because
I am not convinced that doing so in an inner location (in sparc_supply_rwindow
for instance) would always be correct.  We have access to the ptid in
sparc_supply_rwindow (from the regcache), so we _could_ set inferior_ptid
there.  However, I don't want to just set inferior_ptid, as that would make it
not desync'ed with `current_thread ()` and `current_inferior ()`.  It's
preferable to use switch_to_thread instead, as that switches all the global
"current" stuff in a coherent way.  But doing so requires a `thread_info *`,
and getting a `thread_info *` from a ptid requires a `process_stratum_target
*`.  We could use `current_inferior()->process_target()` in
sparc_supply_rwindow for this (using target_read_memory uses the current
inferior's target stack anyway).  However, sparc_supply_rwindow is also used in
the context of BSD uthreads, where a thread stratum target defines threads.  I
presume the ptid in the regcache would be the ptid of the uthread, defined by
the thread stratum target (bsd_uthread_target).  Using
`current_inferior()->process_target()` would look up a ptid defined by the
thread stratum target using the process stratum target.  I don't think it would
give good results.  So I prefer playing it safe and looking up the thread
earlier, in sparc_fetch_inferior_registers.

I added some assertions (in sparc_supply_rwindow and others) to verify
that the regcache's ptid matches inferior_ptid.  That verifies that the
caller has properly set the correct global context.  This would have
caught (though a failed assertion) the current problem.

gdb/ChangeLog:

	PR gdb/27147
	* sparc-nat.h (sparc_fetch_inferior_registers): Add
	process_stratum_target parameter,
	sparc_store_inferior_registers): update callers.
	* sparc-nat.c (sparc_fetch_inferior_registers,
	sparc_store_inferior_registers): Add process_stratum_target
	parameter.  Switch current thread before calling
	sparc_supply_gregset / sparc_collect_rwindow.
	(sparc_store_inferior_registers): Likewise.
	* sparc-obsd-tdep.c (sparc32obsd_supply_uthread): Add assertion.
	(sparc32obsd_collect_uthread): Likewise.
	* sparc-tdep.c (sparc_supply_rwindow, sparc_collect_rwindow):
	Add assertion.
	* sparc64-obsd-tdep.c (sparc64obsd_collect_uthread,
	sparc64obsd_supply_uthread): Add assertion.

Change-Id: I16c658cd70896cea604516714f7e2428fbaf4301
palves added a commit that referenced this issue Apr 30, 2021
When testing with "maint set target-non-stop on",
gdb.server/bkpt-other-inferior.exp sometimes fails like so:

 (gdb) inferior 2
 [Switching to inferior 2 [process 368191] (<noexec>)]
 [Switching to thread 2.1 (Thread 368191.368191)]
 [remote] Sending packet: $m7ffff7fd0100,1#5b
 [remote] Packet received: 48
 [remote] Sending packet: $m7ffff7fd0100,1#5b
 [remote] Packet received: 48
 [remote] Sending packet: $m7ffff7fd0100,9#63
 [remote] Packet received: 4889e7e8e80c000049
 #0  0x00007ffff7fd0100 in ?? ()
 (gdb) PASS: gdb.server/bkpt-other-inferior.exp: inf 2: switch to inferior
 break -q main
 Breakpoint 2 at 0x1138: file /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.server/server.c, line 21.
 (gdb) PASS: gdb.server/bkpt-other-inferior.exp: inf 2: set breakpoint
 delete breakpoints
 Delete all breakpoints? (y or n) y
 (gdb) [remote] wait: enter
 [remote] wait: exit
 FAIL: gdb.server/bkpt-other-inferior.exp: inf 2: delete all breakpoints in delete_breakpoints (timeout)
 ERROR: breakpoints not deleted
 Remote debugging from host ::1, port 55876
 monitor exit

The problem is here:

 (gdb) [remote] wait: enter

The testcase isn't expecting any output after the prompt.

Why is that "[remote] wait" output?  What happens is that "delete
breakpoints" queries the user, and `query` disables/reenables target
async, which results in the remote target's async event handler ending
up marked:

 (top-gdb) bt
 #0  mark_async_event_handler (async_handler_ptr=0x556bffffffff) at ../../src/gdb/async-event.c:295
 #1  0x0000556bf71b711f in infrun_async (enable=1) at ../../src/gdb/infrun.c:119
 #2  0x0000556bf7471387 in target_async (enable=1) at ../../src/gdb/target.c:3684
 #3  0x0000556bf748a0bd in gdb_readline_wrapper_cleanup::~gdb_readline_wrapper_cleanup (this=0x7ffe3cf30eb0, __in_chrg=<optimized out>) at ../../src/gdb/top.c:1074
 #4  0x0000556bf74874e2 in gdb_readline_wrapper (prompt=0x556bfa17da60 "Delete all breakpoints? (y or n) ") at ../../src/gdb/top.c:1096
 #5  0x0000556bf75111c5 in defaulted_query(const char *, char, typedef __va_list_tag __va_list_tag *) (ctlstr=0x556bf7717f34 "Delete all breakpoints? ", defchar=0 '\000', args=0x7ffe3cf31020) at ../../src/gdb/utils.c:893
 #6  0x0000556bf751166f in query (ctlstr=0x556bf7717f34 "Delete all breakpoints? ") at ../../src/gdb/utils.c:985
 #7  0x0000556bf6f11404 in delete_command (arg=0x0, from_tty=1) at ../../src/gdb/breakpoint.c:13500
 ...

... which then later results in a target_wait call:

 (top-gdb) bt
 #0  remote_target::wait_ns (this=0x7ffe3cf30f80, ptid=..., status=0xde530314f0802800, options=...) at ../../src/gdb/remote.c:7937
 #1  0x0000556bf7369dcb in remote_target::wait (this=0x556bfa0b2180, ptid=..., status=0x7ffe3cf31568, options=...) at ../../src/gdb/remote.c:8173
 #2  0x0000556bf745e527 in target_wait (ptid=..., status=0x7ffe3cf31568, options=...) at ../../src/gdb/target.c:2000
 #3  0x0000556bf71be686 in do_target_wait_1 (inf=0x556bfa1573d0, ptid=..., status=0x7ffe3cf31568, options=...) at ../../src/gdb/infrun.c:3463
 #4  0x0000556bf71be88b in <lambda(inferior*)>::operator()(inferior *) const (__closure=0x7ffe3cf31320, inf=0x556bfa1573d0) at ../../src/gdb/infrun.c:3526
 #5  0x0000556bf71bebcd in do_target_wait (wait_ptid=..., ecs=0x7ffe3cf31540, options=...) at ../../src/gdb/infrun.c:3539
 #6  0x0000556bf71bf97b in fetch_inferior_event () at ../../src/gdb/infrun.c:3879
 #7  0x0000556bf71a27f8 in inferior_event_handler (event_type=INF_REG_EVENT) at ../../src/gdb/inf-loop.c:42
 #8  0x0000556bf71cc8b7 in infrun_async_inferior_event_handler (data=0x0) at ../../src/gdb/infrun.c:9220
 #9  0x0000556bf6ecb80f in check_async_event_handlers () at ../../src/gdb/async-event.c:327
 #10 0x0000556bf76b011a in gdb_do_one_event () at ../../src/gdbsupport/event-loop.cc:216
 ...

... which returns TARGET_WAITKIND_IGNORE.

Fix this by only enabling remote output around setting the breakpoint.

gdb/testsuite/ChangeLog:

	* gdb.server/bkpt-other-inferior.exp: Only enable remote output
	around setting the breakpoint.

Change-Id: I2fd152fd9c46b1c5e7fa678cc4d4054dac0b2bd4
palves added a commit that referenced this issue May 25, 2021
$ make check RUNTESTFLAGS="--target_board=native-extended-gdbserver" TESTS="gdb.base/signest.exp"
make[1]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
Nothing to be done for all...
make check-single
make[2]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
rootme=`pwd`; export rootme; srcdir=/home/pedro/gdb/mygit/src/gdb/testsuite ; export srcdir ; EXPECT=`if [ "${READ1}" != "" ] ; then echo ${rootme}/expect-read1; elif [ -f ${rootme}/../../expect/expect ] ; then echo ${rootme}/../../expect/expect ; else echo expect ; fi` ; export EXPECT ; EXEEXT= ; export EXEEXT ;    LD_LIBRARY_PATH=$rootme/../../expect:$rootme/../../libstdc++:$rootme/../../tk/unix:$rootme/../../tcl/unix:$rootme/../../bfd:$rootme/../../opcodes:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; if [ -f ${rootme}/../../expect/expect ] ; then TCL_LIBRARY=${srcdir}/../../tcl/library ; export TCL_LIBRARY ; fi ; runtest --status --target_board=native-extended-gdbserver gdb.base/signest.exp
Using /home/pedro/gdb/mygit/src/gdb/testsuite/lib/gdb.exp as tool init file.
NOTE: Dejagnu's default_target_compile is missing support for Go, using local override
NOTE: Dejagnu's default_target_compile is missing support for Rust, using local override
Test run by pedro on Wed May 19 00:00:39 2021
Native configuration is x86_64-pc-linux-gnu

                === gdb tests ===

Schedule of variations:
    native-extended-gdbserver

Running target native-extended-gdbserver
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/native-extended-gdbserver.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/gdbserver-base.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
configuring for gdbserver local testing (extended-remote)
Using /home/pedro/gdb/mygit/src/gdb/testsuite/config/extended-gdbserver.exp as tool-and-target-specific interface file.
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/signest.exp ...
ERROR: GDB process no longer exists

                === gdb Summary ===

# of expected passes            4
# of unresolved testcases       1

Infinite recursion:

 (top-gdb) bt 20
 #0  0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #1  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #2  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #3  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #4  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #5  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #6  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #7  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #8  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #9  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #11 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #14 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #17 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 (More stack frames follow...)

 (top-gdb) bt -30
 #157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157055 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157058 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:970
 #157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2625
 #157062 0x0000561d6a1bf63e in get_frame_address_in_block (this_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2655
 #157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1010
 #157064 0x0000561d6a0cb928 in dwarf2_frame_this_id (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8, this_id=0x561d6b19faf0) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1227
 #157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:588
 #157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:636
 #157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:650
 #157068 0x0000561d6a26ecd0 in insert_hp_step_resume_breakpoint_at_frame (return_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/infrun.c:7809
 #157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:6428
 #157070 0x0000561d6a269d81 in handle_inferior_event (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:5741
 #157071 0x0000561d6a265bd0 in fetch_inferior_event () at /home/pedro/gdb/mygit/src/gdb/infrun.c:4120
 #157072 0x0000561d6a244c24 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/mygit/src/gdb/inf-loop.c:41
 #157073 0x0000561d6a435cc4 in remote_async_serial_handler (scb=0x561d6b4a8990, context=0x561d6b4a4c48) at /home/pedro/gdb/mygit/src/gdb/remote.c:14403
 #157074 0x0000561d6a460bc5 in run_async_handler_and_reschedule (scb=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:138
 #157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:189
 #157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:575
 #157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:701
 #157078 0x0000561d6a7694ee in gdb_do_one_event () at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:237
 #157079 0x0000561d6a2df16b in start_event_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:421
 #157080 0x0000561d6a2df2b6 in captured_command_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:481
 #157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1353
 #157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1370
 #157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc67022d68) at /home/pedro/gdb/mygit/src/gdb/gdb.c:33

The annota1.exp change is necessary because we'd get a regression
otherwise:

  @@ -238,8 +238,6 @@ Continuing.

   ▒▒breakpoints-invalid

  -▒▒frames-invalid
  -
   ▒▒breakpoint 3

   Breakpoint 3,
  @@ -276,7 +274,7 @@ printf.c
   ▒▒pre-prompt
   (gdb)
   ▒▒prompt
  -PASS: gdb.base/annota1.exp: continue to printf
  +FAIL: gdb.base/annota1.exp: continue to printf

... before this patch avoids flushing the frame cache.  We still need
to match frames-invalid because against gdbserver + "maint set target
non-stop on", some other code path flushes the frame cache resulting
in the annotation being emitted anyway.
palves added a commit that referenced this issue May 26, 2021
$ make check RUNTESTFLAGS="--target_board=native-extended-gdbserver" TESTS="gdb.base/signest.exp"
make[1]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
Nothing to be done for all...
make check-single
make[2]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
rootme=`pwd`; export rootme; srcdir=/home/pedro/gdb/mygit/src/gdb/testsuite ; export srcdir ; EXPECT=`if [ "${READ1}" != "" ] ; then echo ${rootme}/expect-read1; elif [ -f ${rootme}/../../expect/expect ] ; then echo ${rootme}/../../expect/expect ; else echo expect ; fi` ; export EXPECT ; EXEEXT= ; export EXEEXT ;    LD_LIBRARY_PATH=$rootme/../../expect:$rootme/../../libstdc++:$rootme/../../tk/unix:$rootme/../../tcl/unix:$rootme/../../bfd:$rootme/../../opcodes:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; if [ -f ${rootme}/../../expect/expect ] ; then TCL_LIBRARY=${srcdir}/../../tcl/library ; export TCL_LIBRARY ; fi ; runtest --status --target_board=native-extended-gdbserver gdb.base/signest.exp
Using /home/pedro/gdb/mygit/src/gdb/testsuite/lib/gdb.exp as tool init file.
NOTE: Dejagnu's default_target_compile is missing support for Go, using local override
NOTE: Dejagnu's default_target_compile is missing support for Rust, using local override
Test run by pedro on Wed May 19 00:00:39 2021
Native configuration is x86_64-pc-linux-gnu

                === gdb tests ===

Schedule of variations:
    native-extended-gdbserver

Running target native-extended-gdbserver
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/native-extended-gdbserver.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/gdbserver-base.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
configuring for gdbserver local testing (extended-remote)
Using /home/pedro/gdb/mygit/src/gdb/testsuite/config/extended-gdbserver.exp as tool-and-target-specific interface file.
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/signest.exp ...
ERROR: GDB process no longer exists

                === gdb Summary ===

# of expected passes            4
# of unresolved testcases       1

Infinite recursion:

 (top-gdb) bt 20
 #0  0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #1  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #2  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #3  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #4  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #5  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #6  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #7  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #8  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #9  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #11 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #14 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #17 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 (More stack frames follow...)

 (top-gdb) bt -30
 #157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157055 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157058 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:970
 #157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2625
 #157062 0x0000561d6a1bf63e in get_frame_address_in_block (this_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2655
 #157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1010
 #157064 0x0000561d6a0cb928 in dwarf2_frame_this_id (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8, this_id=0x561d6b19faf0) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1227
 #157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:588
 #157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:636
 #157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:650
 #157068 0x0000561d6a26ecd0 in insert_hp_step_resume_breakpoint_at_frame (return_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/infrun.c:7809
 #157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:6428
 #157070 0x0000561d6a269d81 in handle_inferior_event (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:5741
 #157071 0x0000561d6a265bd0 in fetch_inferior_event () at /home/pedro/gdb/mygit/src/gdb/infrun.c:4120
 #157072 0x0000561d6a244c24 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/mygit/src/gdb/inf-loop.c:41
 #157073 0x0000561d6a435cc4 in remote_async_serial_handler (scb=0x561d6b4a8990, context=0x561d6b4a4c48) at /home/pedro/gdb/mygit/src/gdb/remote.c:14403
 #157074 0x0000561d6a460bc5 in run_async_handler_and_reschedule (scb=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:138
 #157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:189
 #157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:575
 #157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:701
 #157078 0x0000561d6a7694ee in gdb_do_one_event () at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:237
 #157079 0x0000561d6a2df16b in start_event_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:421
 #157080 0x0000561d6a2df2b6 in captured_command_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:481
 #157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1353
 #157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1370
 #157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc67022d68) at /home/pedro/gdb/mygit/src/gdb/gdb.c:33

The annota1.exp change is necessary because we'd get a regression
otherwise:

  @@ -238,8 +238,6 @@ Continuing.

   ▒▒breakpoints-invalid

  -▒▒frames-invalid
  -
   ▒▒breakpoint 3

   Breakpoint 3,
  @@ -276,7 +274,7 @@ printf.c
   ▒▒pre-prompt
   (gdb)
   ▒▒prompt
  -PASS: gdb.base/annota1.exp: continue to printf
  +FAIL: gdb.base/annota1.exp: continue to printf

... before this patch avoids flushing the frame cache.  We still need
to match frames-invalid because against gdbserver + "maint set target
non-stop on", some other code path flushes the frame cache resulting
in the annotation being emitted anyway.
palves added a commit that referenced this issue May 31, 2021
$ make check RUNTESTFLAGS="--target_board=native-extended-gdbserver" TESTS="gdb.base/signest.exp"
make[1]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
Nothing to be done for all...
make check-single
make[2]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
rootme=`pwd`; export rootme; srcdir=/home/pedro/gdb/mygit/src/gdb/testsuite ; export srcdir ; EXPECT=`if [ "${READ1}" != "" ] ; then echo ${rootme}/expect-read1; elif [ -f ${rootme}/../../expect/expect ] ; then echo ${rootme}/../../expect/expect ; else echo expect ; fi` ; export EXPECT ; EXEEXT= ; export EXEEXT ;    LD_LIBRARY_PATH=$rootme/../../expect:$rootme/../../libstdc++:$rootme/../../tk/unix:$rootme/../../tcl/unix:$rootme/../../bfd:$rootme/../../opcodes:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; if [ -f ${rootme}/../../expect/expect ] ; then TCL_LIBRARY=${srcdir}/../../tcl/library ; export TCL_LIBRARY ; fi ; runtest --status --target_board=native-extended-gdbserver gdb.base/signest.exp
Using /home/pedro/gdb/mygit/src/gdb/testsuite/lib/gdb.exp as tool init file.
NOTE: Dejagnu's default_target_compile is missing support for Go, using local override
NOTE: Dejagnu's default_target_compile is missing support for Rust, using local override
Test run by pedro on Wed May 19 00:00:39 2021
Native configuration is x86_64-pc-linux-gnu

                === gdb tests ===

Schedule of variations:
    native-extended-gdbserver

Running target native-extended-gdbserver
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/native-extended-gdbserver.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/gdbserver-base.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
configuring for gdbserver local testing (extended-remote)
Using /home/pedro/gdb/mygit/src/gdb/testsuite/config/extended-gdbserver.exp as tool-and-target-specific interface file.
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/signest.exp ...
ERROR: GDB process no longer exists

                === gdb Summary ===

# of expected passes            4
# of unresolved testcases       1

Infinite recursion:

 (top-gdb) bt 20
 #0  0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #1  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #2  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #3  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #4  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #5  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #6  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #7  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #8  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #9  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #11 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #14 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #17 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 (More stack frames follow...)

 (top-gdb) bt -30
 #157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157055 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157058 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:970
 #157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2625
 #157062 0x0000561d6a1bf63e in get_frame_address_in_block (this_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2655
 #157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1010
 #157064 0x0000561d6a0cb928 in dwarf2_frame_this_id (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8, this_id=0x561d6b19faf0) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1227
 #157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:588
 #157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:636
 #157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:650
 #157068 0x0000561d6a26ecd0 in insert_hp_step_resume_breakpoint_at_frame (return_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/infrun.c:7809
 #157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:6428
 #157070 0x0000561d6a269d81 in handle_inferior_event (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:5741
 #157071 0x0000561d6a265bd0 in fetch_inferior_event () at /home/pedro/gdb/mygit/src/gdb/infrun.c:4120
 #157072 0x0000561d6a244c24 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/mygit/src/gdb/inf-loop.c:41
 #157073 0x0000561d6a435cc4 in remote_async_serial_handler (scb=0x561d6b4a8990, context=0x561d6b4a4c48) at /home/pedro/gdb/mygit/src/gdb/remote.c:14403
 #157074 0x0000561d6a460bc5 in run_async_handler_and_reschedule (scb=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:138
 #157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:189
 #157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:575
 #157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:701
 #157078 0x0000561d6a7694ee in gdb_do_one_event () at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:237
 #157079 0x0000561d6a2df16b in start_event_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:421
 #157080 0x0000561d6a2df2b6 in captured_command_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:481
 #157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1353
 #157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1370
 #157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc67022d68) at /home/pedro/gdb/mygit/src/gdb/gdb.c:33

The annota1.exp change is necessary because we'd get a regression
otherwise:

  @@ -238,8 +238,6 @@ Continuing.

   ▒▒breakpoints-invalid

  -▒▒frames-invalid
  -
   ▒▒breakpoint 3

   Breakpoint 3,
  @@ -276,7 +274,7 @@ printf.c
   ▒▒pre-prompt
   (gdb)
   ▒▒prompt
  -PASS: gdb.base/annota1.exp: continue to printf
  +FAIL: gdb.base/annota1.exp: continue to printf

... before this patch avoids flushing the frame cache.  We still need
to match frames-invalid because against gdbserver + "maint set target
non-stop on", some other code path flushes the frame cache resulting
in the annotation being emitted anyway.
palves added a commit that referenced this issue Jun 1, 2021
$ make check RUNTESTFLAGS="--target_board=native-extended-gdbserver" TESTS="gdb.base/signest.exp"
make[1]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
Nothing to be done for all...
make check-single
make[2]: Entering directory '/home/pedro/gdb/mygit/build/gdb/testsuite'
rootme=`pwd`; export rootme; srcdir=/home/pedro/gdb/mygit/src/gdb/testsuite ; export srcdir ; EXPECT=`if [ "${READ1}" != "" ] ; then echo ${rootme}/expect-read1; elif [ -f ${rootme}/../../expect/expect ] ; then echo ${rootme}/../../expect/expect ; else echo expect ; fi` ; export EXPECT ; EXEEXT= ; export EXEEXT ;    LD_LIBRARY_PATH=$rootme/../../expect:$rootme/../../libstdc++:$rootme/../../tk/unix:$rootme/../../tcl/unix:$rootme/../../bfd:$rootme/../../opcodes:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; if [ -f ${rootme}/../../expect/expect ] ; then TCL_LIBRARY=${srcdir}/../../tcl/library ; export TCL_LIBRARY ; fi ; runtest --status --target_board=native-extended-gdbserver gdb.base/signest.exp
Using /home/pedro/gdb/mygit/src/gdb/testsuite/lib/gdb.exp as tool init file.
NOTE: Dejagnu's default_target_compile is missing support for Go, using local override
NOTE: Dejagnu's default_target_compile is missing support for Rust, using local override
Test run by pedro on Wed May 19 00:00:39 2021
Native configuration is x86_64-pc-linux-gnu

                === gdb tests ===

Schedule of variations:
    native-extended-gdbserver

Running target native-extended-gdbserver
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/native-extended-gdbserver.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/gdbserver-base.exp as board description file for target.
Using /home/pedro/gdb/mygit/src/gdb/testsuite/boards/../boards/local-board.exp as board description file for target.
configuring for gdbserver local testing (extended-remote)
Using /home/pedro/gdb/mygit/src/gdb/testsuite/config/extended-gdbserver.exp as tool-and-target-specific interface file.
Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/signest.exp ...
ERROR: GDB process no longer exists

                === gdb Summary ===

# of expected passes            4
# of unresolved testcases       1

Infinite recursion:

 (top-gdb) bt 20
 #0  0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #1  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #2  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #3  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #4  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #5  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #6  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #7  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #8  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #9  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #11 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #14 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #17 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 (More stack frames follow...)

 (top-gdb) bt -30
 #157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157055 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157058 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:970
 #157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2625
 #157062 0x0000561d6a1bf63e in get_frame_address_in_block (this_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2655
 #157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1010
 #157064 0x0000561d6a0cb928 in dwarf2_frame_this_id (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8, this_id=0x561d6b19faf0) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1227
 #157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:588
 #157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:636
 #157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:650
 #157068 0x0000561d6a26ecd0 in insert_hp_step_resume_breakpoint_at_frame (return_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/infrun.c:7809
 #157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:6428
 #157070 0x0000561d6a269d81 in handle_inferior_event (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:5741
 #157071 0x0000561d6a265bd0 in fetch_inferior_event () at /home/pedro/gdb/mygit/src/gdb/infrun.c:4120
 #157072 0x0000561d6a244c24 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/mygit/src/gdb/inf-loop.c:41
 #157073 0x0000561d6a435cc4 in remote_async_serial_handler (scb=0x561d6b4a8990, context=0x561d6b4a4c48) at /home/pedro/gdb/mygit/src/gdb/remote.c:14403
 #157074 0x0000561d6a460bc5 in run_async_handler_and_reschedule (scb=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:138
 #157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:189
 #157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:575
 #157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:701
 #157078 0x0000561d6a7694ee in gdb_do_one_event () at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:237
 #157079 0x0000561d6a2df16b in start_event_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:421
 #157080 0x0000561d6a2df2b6 in captured_command_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:481
 #157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1353
 #157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1370
 #157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc67022d68) at /home/pedro/gdb/mygit/src/gdb/gdb.c:33

The annota1.exp change is necessary because we'd get a regression
otherwise:

  @@ -238,8 +238,6 @@ Continuing.

   ▒▒breakpoints-invalid

  -▒▒frames-invalid
  -
   ▒▒breakpoint 3

   Breakpoint 3,
  @@ -276,7 +274,7 @@ printf.c
   ▒▒pre-prompt
   (gdb)
   ▒▒prompt
  -PASS: gdb.base/annota1.exp: continue to printf
  +FAIL: gdb.base/annota1.exp: continue to printf

... before this patch avoids flushing the frame cache.  We still need
to match frames-invalid because against gdbserver + "maint set target
non-stop on", some other code path flushes the frame cache resulting
in the annotation being emitted anyway.
palves added a commit that referenced this issue Jun 2, 2021
A following patch adds a exists_non_stop_target call in the
target_terminal routines, and that surprisingly caused a weird
regression / GDB crash:

 $ make check RUNTESTFLAGS="--target_board=native-extended-gdbserver" TESTS="gdb.base/signest.exp"
 ...
 configuring for gdbserver local testing (extended-remote)
 Using /home/pedro/gdb/mygit/src/gdb/testsuite/config/extended-gdbserver.exp as tool-and-target-specific interface file.
 Running /home/pedro/gdb/mygit/src/gdb/testsuite/gdb.base/signest.exp ...
 ERROR: GDB process no longer exists

Debugging the core, we see infinite recursion:

 (top-gdb) bt 20
 #0  0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #1  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #2  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #3  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #4  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #5  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #6  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #7  0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #8  0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #9  0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #11 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #14 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #17 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 (More stack frames follow...)

 (top-gdb) bt -30
 #157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157055 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2939
 #157058 0x0000561d6a1b989f in frame_unwind_find_by_frame (this_frame=0x561d6b19f9c0, this_cache=0x561d6b19f9d8) at /home/pedro/gdb/mygit/src/gdb/frame-unwind.c:174
 #157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:2950
 #157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at /home/pedro/gdb/mygit/src/gdb/frame.c:970
 #157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2625
 #157062 0x0000561d6a1bf63e in get_frame_address_in_block (this_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:2655
 #157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1010
 #157064 0x0000561d6a0cb928 in dwarf2_frame_this_id (this_frame=0x561d6b19fa90, this_cache=0x561d6b19faa8, this_id=0x561d6b19faf0) at /home/pedro/gdb/mygit/src/gdb/dwarf2/frame.c:1227
 #157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:588
 #157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:636
 #157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/frame.c:650
 #157068 0x0000561d6a26ecd0 in insert_hp_step_resume_breakpoint_at_frame (return_frame=0x561d6b19fa90) at /home/pedro/gdb/mygit/src/gdb/infrun.c:7809
 #157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:6428
 #157070 0x0000561d6a269d81 in handle_inferior_event (ecs=0x7ffc67022830) at /home/pedro/gdb/mygit/src/gdb/infrun.c:5741
 #157071 0x0000561d6a265bd0 in fetch_inferior_event () at /home/pedro/gdb/mygit/src/gdb/infrun.c:4120
 #157072 0x0000561d6a244c24 in inferior_event_handler (event_type=INF_REG_EVENT) at /home/pedro/gdb/mygit/src/gdb/inf-loop.c:41
 #157073 0x0000561d6a435cc4 in remote_async_serial_handler (scb=0x561d6b4a8990, context=0x561d6b4a4c48) at /home/pedro/gdb/mygit/src/gdb/remote.c:14403
 #157074 0x0000561d6a460bc5 in run_async_handler_and_reschedule (scb=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:138
 #157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at /home/pedro/gdb/mygit/src/gdb/ser-base.c:189
 #157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:575
 #157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:701
 #157078 0x0000561d6a7694ee in gdb_do_one_event () at /home/pedro/gdb/mygit/src/gdbsupport/event-loop.cc:237
 #157079 0x0000561d6a2df16b in start_event_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:421
 #157080 0x0000561d6a2df2b6 in captured_command_loop () at /home/pedro/gdb/mygit/src/gdb/main.c:481
 #157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1353
 #157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at /home/pedro/gdb/mygit/src/gdb/main.c:1370
 #157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc67022d68) at /home/pedro/gdb/mygit/src/gdb/gdb.c:33

This was caused by exists_non_stop_target flushing the frame cache via
scoped_restore_current_thread/switch_to_thread, while we're in the
middle of unwinding.

Fix this by making exists_non_stop_target only switch the inferior,
like done in target_pass_ctrlc.

The annota1.exp change is necessary because we'd get a regression
otherwise:

  @@ -238,8 +238,6 @@ Continuing.

   ▒▒breakpoints-invalid

  -▒▒frames-invalid
  -
   ▒▒breakpoint 3

   Breakpoint 3,
  @@ -276,7 +274,7 @@ printf.c
   ▒▒pre-prompt
   (gdb)
   ▒▒prompt
  -PASS: gdb.base/annota1.exp: continue to printf
  +FAIL: gdb.base/annota1.exp: continue to printf

... because this patch avoids flushing the frame cache that lead to
that missing frames-invalid.  We still need to match frames-invalid
because against gdbserver + "maint set target non-stop on", some other
code path flushes the frame cache resulting in the annotation being
emitted anyway.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <[email protected]>

	* target.c (exists_non_stop_target): Use
	scoped_restore_current_inferior and set_current_inferior instead
	of scoped_restore_current_thread / switch_to_inferior_no_thread.
palves pushed a commit that referenced this issue Jun 17, 2021
When loading the debug info package
libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug from openSUSE Leap 15.2, we
run into a dwarf error:
...
$ gdb -q -batch libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug
Dwarf Error: Cannot not find DIE at 0x18a936e7 \
  [from module libLLVM.so.10-10.0.1-lp152.30.4.x86_64.debug]
...
The DIE @ 0x18a936e7 does in fact exist, and is part of a CU @ 0x18a23e52.
No error message is printed when using -readnow.

What happens is the following:
- a dwarf2_per_cu_data P is created for the CU.
- a dwarf2_cu A is created for the same CU.
- another dwarf2_cu B is created for the same CU.
- the dwarf2_cu B is set in per_objfile->m_dwarf2_cus, such that
  per_objfile->get_cu (P) returns B.
- P->load_all_dies is set to 1.
- all dies are read into the A->partial_dies htab
- dwarf2_cu A is destroyed.
- we try to find the partial_die for the DIE @ 0x18a936e7 in B->partial_dies.
  We can't find it, but do not try to load all dies, because P->load_all_dies
  is already set to 1.
- an error message is generated.

The question is why we're creating dwarf2_cu A and B for the same CU.

The dwarf2_cu A is created here:
...
 (gdb) bt
 #0  dwarf2_cu::dwarf2_cu (this=0x79a9660, per_cu=0x23c0b30,
     per_objfile=0x1ad01b0) at dwarf2/cu.c:38
 #1  0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffd040,
     this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0,
     existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487
 #2  0x0000000000676eb3 in process_psymtab_comp_unit (this_cu=0x23c0b30,
      per_objfile=0x1ad01b0, want_partial_unit=false,
      pretend_language=language_minimal) at dwarf2/read.c:7028
...

And the dwarf2_cu B is created here:
...
 (gdb) bt
 #0  dwarf2_cu::dwarf2_cu (this=0x885e8c0, per_cu=0x23c0b30,
     per_objfile=0x1ad01b0) at dwarf2/cu.c:38
 #1  0x0000000000675799 in cutu_reader::cutu_reader (this=0x7fffffffcc50,
     this_cu=0x23c0b30, per_objfile=0x1ad01b0, abbrev_table=0x0,
     existing_cu=0x0, skip_partial=false) at dwarf2/read.c:6487
 #2  0x0000000000678118 in load_partial_comp_unit (this_cu=0x23c0b30,
     per_objfile=0x1ad01b0, existing_cu=0x0) at dwarf2/read.c:7436
 #3  0x000000000069721d in find_partial_die (sect_off=(unknown: 0x18a55054),
     offset_in_dwz=0, cu=0x0) at dwarf2/read.c:19391
 #4  0x000000000069755b in partial_die_info::fixup (this=0x9096900,
     cu=0xa6a85f0) at dwarf2/read.c:19512
 #5  0x0000000000697586 in partial_die_info::fixup (this=0x8629bb0,
     cu=0xa6a85f0) at dwarf2/read.c:19516
 #6  0x00000000006787b1 in scan_partial_symbols (first_die=0x8629b40,
     lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660)
     at dwarf2/read.c:7563
 #7  0x0000000000678878 in scan_partial_symbols (first_die=0x796ebf0,
     lowpc=0x7fffffffcf58, highpc=0x7fffffffcf50, set_addrmap=0, cu=0x79a9660)
     at dwarf2/read.c:7580
 #8  0x0000000000676b82 in process_psymtab_comp_unit_reader
     (reader=0x7fffffffd040, info_ptr=0x7fffc1b3f29b, comp_unit_die=0x6ea90f0,
     pretend_language=language_minimal) at dwarf2/read.c:6954
 #9  0x0000000000676ffd in process_psymtab_comp_unit (this_cu=0x23c0b30,
     per_objfile=0x1ad01b0, want_partial_unit=false,
     pretend_language=language_minimal) at dwarf2/read.c:7057
...

So in frame #9, a cutu_reader is created with dwarf2_cu A.  Then a fixup takes
us to the following CU @ 0x18aa33d6, in frame #5.  And a similar fixup in
frame #4 takes us back to CU @ 0x18a23e52.  At that point, there's no
information available that we're already trying to read that CU, and we end up
creating another cutu_reader with dwarf2_cu B.

It seems that there are two related problems:
- creating two dwarf2_cu's is not optimal
- the unoptimal case is not handled correctly

This patch addresses the last problem, by moving the load_all_dies flag from
dwarf2_per_cu_data to dwarf2_cu, such that it is paired with the partial_dies
field, which ensures that the two can be kept in sync.

Tested on x86_64-linux.

gdb/ChangeLog:

2021-05-27  Tom de Vries  <[email protected]>

	PR symtab/27898
	* dwarf2/cu.c (dwarf2_cu::dwarf2_cu): Add load_all_dies init.
	* dwarf2/cu.h (dwarf2_cu): Add load_all_dies field.
	* dwarf2/read.c (load_partial_dies, find_partial_die): Update.
	* dwarf2/read.h (dwarf2_per_cu_data::dwarf2_per_cu_data): Remove
	load_all_dies init.
	(dwarf2_per_cu_data): Remove load_all_dies field.
palves pushed a commit that referenced this issue Jun 17, 2021
… when attaching / handling a fork child

When trying to attach to a pthread process on a Linux system with glibc 2.33,
we get:

    $ ./gdb -q -nx --data-directory=data-directory -p 1472010
    Attaching to process 1472010
    [New LWP 1472013]
    [New LWP 1472014]
    [New LWP 1472015]
    Error while reading shared library symbols for /usr/lib/libpthread.so.0:
    Cannot find user-level thread for LWP 1472015: generic error
    0x00007ffff6d3637f in poll () from /usr/lib/libc.so.6
    (gdb)

When attaching to a process (or handling a fork child, an operation very
similar to attaching), GDB reads the shared library list from the
process.  For each shared library (if "set auto-solib-add" is on), it
reads its symbols and calls the "new_objfile" observable.

The libthread-db code monitors this observable, and if it sees an
objfile named somewhat like "libpthread.so" go by, it tries to load
libthread_db.so in the GDB process itself.  libthread_db knows how to
navigate libpthread's data structures to get information about the
existing threads.

To locate these data structures, libthread_db calls ps_pglobal_lookup
(implemented in proc-service.c), passing in a symbol name and expecting
an address in return.

Before glibc 2.33, libthread_db always asked for symbols found in
libpthread.  There was no ordering problem: since we were always trying
to load libthread_db in reaction to processing libpthread (and reading
in its symbols) and libthread_db only asked symbols from libpthread, the
requested symbols could always be found.  Starting with glibc 2.33,
libthread_db now asks for a symbol name that can be found in
/lib/ld-linux-x86-64.so.2 (_rtld_global).  And the ordering in which GDB
reads the shared libraries from the inferior when attaching is
unfortunate, in that libpthread is processed before ld-linux.  So when
loading libthread_db in reaction to processing libpthread, and
libthread_db requests the symbol that is from ld-linux, GDB is not yet
able to supply it.

That problematic symbol lookup happens in the thread_from_lwp function,
when we call td_ta_map_lwp2thr_p, and an exception is thrown at this
point:

    #0  0x00007ffff6681012 in __cxxabiv1::__cxa_throw (obj=0x60e000006100, tinfo=0x555560033b50 <typeinfo for gdb_exception_error>, dest=0x55555d9404bc <gdb_exception_error::~gdb_exception_error()>) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:78
    #1  0x000055555e5d3734 in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR, error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:200
    #2  0x000055555e5d37d4 in throw_verror (error=GENERIC_ERROR, fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", ap=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdbsupport/common-exceptions.cc:208
    #3  0x000055555e0b0ed2 in verror (string=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s", args=0x7fffffffaae0) at /home/simark/src/binutils-gdb/gdb/utils.c:171
    #4  0x000055555e5e898a in error (fmt=0x55555f0c5360 "Cannot find user-level thread for LWP %ld: %s") at /home/simark/src/binutils-gdb/gdbsupport/errors.cc:43
    #5  0x000055555d06b4bc in thread_from_lwp (stopped=0x617000035d80, ptid=...) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:418
    #6  0x000055555d07040d in try_thread_db_load_1 (info=0x60c000011140) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:912
    #7  0x000055555d071103 in try_thread_db_load (library=0x55555f0c62a0 "libthread_db.so.1", check_auto_load_safe=false) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1014
    #8  0x000055555d072168 in try_thread_db_load_from_sdir () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1091
    #9  0x000055555d072d1c in thread_db_load_search () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1146
    #10 0x000055555d07365c in thread_db_load () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1203
    #11 0x000055555d07373e in check_for_thread_db () at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1246
    #12 0x000055555d0738ab in thread_db_new_objfile (objfile=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/linux-thread-db.c:1275
    #13 0x000055555bd10740 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:60
    #14 0x000055555bd02096 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x616000068d88: 0x55555d073745 <thread_db_new_objfile(objfile*)>) at /usr/include/c++/10.2.0/bits/invoke.h:153
    #15 0x000055555bce0392 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffb4a0: 0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:291
    #16 0x000055555d3595c0 in std::function<void (objfile*)>::operator()(objfile*) const (this=0x616000068d88, __args#0=0x61300000c0c0) at /usr/include/c++/10.2.0/bits/std_function.h:622
    #17 0x000055555d356b7f in gdb::observers::observable<objfile*>::notify (this=0x555566727020 <gdb::observers::new_objfile>, args#0=0x61300000c0c0) at /home/simark/src/binutils-gdb/gdb/../gdbsupport/observable.h:106
    #18 0x000055555da3f228 in symbol_file_add_with_addrs (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=..., addrs=0x7fffffffbc10, flags=..., parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1131
    #19 0x000055555da3f763 in symbol_file_add_from_bfd (abfd=0x61200001ccc0, name=0x6190000d9090 "/usr/lib/libpthread.so.0", add_flags=<error reading variable: Cannot access memory at address 0xffffffffffffffb0>, addrs=0x7fffffffbc10, flags=<error reading variable: Cannot access memory at address 0xffffffffffffffc0>, parent=0x0) at /home/simark/src/binutils-gdb/gdb/symfile.c:1167
    #20 0x000055555d95f9fa in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:681
    #21 0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
    #22 0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
    #23 0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
    #24 0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
    #25 0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
    #26 0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
    #27 0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
    #28 0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
    #29 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
    #30 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
    #31 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
    #32 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
    #33 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
    #34 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
    #35 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
    #36 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
    #37 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
    #38 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
    #39 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
    #40 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
    #41 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
    #42 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
    #43 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
    #44 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

The exception is caught here:

    #0  __cxxabiv1::__cxa_begin_catch (exc_obj_in=0x60e0000060e0) at /build/gcc/src/gcc/libstdc++-v3/libsupc++/eh_catch.cc:84
    #1  0x000055555d95fded in solib_read_symbols (so=0x6190000d8e80, flags=...) at /home/simark/src/binutils-gdb/gdb/solib.c:689
    #2  0x000055555d96233d in solib_add (pattern=0x0, from_tty=0, readsyms=1) at /home/simark/src/binutils-gdb/gdb/solib.c:987
    #3  0x000055555d93646e in enable_break (info=0x608000008f20, from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:2238
    #4  0x000055555d93cfc0 in svr4_solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib-svr4.c:3049
    #5  0x000055555d96610d in solib_create_inferior_hook (from_tty=0) at /home/simark/src/binutils-gdb/gdb/solib.c:1195
    #6  0x000055555cdee318 in post_create_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:318
    #7  0x000055555ce00e6e in setup_inferior (from_tty=0) at /home/simark/src/binutils-gdb/gdb/infcmd.c:2439
    #8  0x000055555ce59c34 in handle_one (event=...) at /home/simark/src/binutils-gdb/gdb/infrun.c:4887
    #9  0x000055555ce5cd00 in stop_all_threads () at /home/simark/src/binutils-gdb/gdb/infrun.c:5064
    #10 0x000055555ce7f0da in stop_waiting (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:8006
    #11 0x000055555ce67f5c in handle_signal_stop (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:6062
    #12 0x000055555ce63653 in handle_inferior_event (ecs=0x7fffffffd170) at /home/simark/src/binutils-gdb/gdb/infrun.c:5727
    #13 0x000055555ce4f297 in fetch_inferior_event () at /home/simark/src/binutils-gdb/gdb/infrun.c:4105
    #14 0x000055555cdbe3bf in inferior_event_handler (event_type=INF_REG_EVENT) at /home/simark/src/binutils-gdb/gdb/inf-loop.c:42
    #15 0x000055555d018047 in handle_target_event (error=0, client_data=0x0) at /home/simark/src/binutils-gdb/gdb/linux-nat.c:4060
    #16 0x000055555e5ea77e in handle_file_event (file_ptr=0x60600008b1c0, ready_mask=1) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:575
    #17 0x000055555e5eb09c in gdb_wait_for_event (block=0) at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:701
    #18 0x000055555e5e8d19 in gdb_do_one_event () at /home/simark/src/binutils-gdb/gdbsupport/event-loop.cc:212
    #19 0x000055555dd6e0d4 in wait_sync_command_done () at /home/simark/src/binutils-gdb/gdb/top.c:528
    #20 0x000055555dd6e372 in maybe_wait_sync_command_done (was_sync=0) at /home/simark/src/binutils-gdb/gdb/top.c:545
    #21 0x000055555d0ec7c8 in catch_command_errors (command=0x55555ce01bb8 <attach_command(char const*, int)>, arg=0x7fffffffe28d "1472010", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:452
    #22 0x000055555d0f03ad in captured_main_1 (context=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1149
    #23 0x000055555d0f1239 in captured_main (data=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1232
    #24 0x000055555d0f1315 in gdb_main (args=0x7fffffffdd10) at /home/simark/src/binutils-gdb/gdb/main.c:1257
    #25 0x000055555bb70cf9 in main (argc=7, argv=0x7fffffffde88) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

Catching the exception at this point means that the thread_db_info
object for this inferior will be left in place, despite the failure to
load libthread_db.  This means that there won't be further attempts at
loading libthread_db, because thread_db_load will think that
libthread_db is already loaded for this inferior and will always exit
early.  To fix this, add a try/catch around calling try_thread_db_load_1
in try_thread_db_load, such that if some exception is thrown while
trying to load libthread_db, we reset / delete the thread_db_info for
that inferior.  That alone makes attach work fine again, because
check_for_thread_db is called again in the thread_db_inferior_created
observer (that happens after we learned about all shared libraries and
their symbols), and libthread_db is successfully loaded then.

When attaching, I think that the inferior_created observer is a good
place to try to load libthread_db: it is called once everything has
stabilized, when we learned about all shared libraries.

The only problem then is that when we first try (and fail) to load
libthread_db, in reaction to learning about libpthread, we show this
warning:

    warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.

This is misleading, because we do succeed in loading it later.  So when
attaching, I think we shouldn't try to load libthread_db in reaction to
the new_objfile events, we should wait until we have learned about all
shared libraries (using the inferior_created observable).  To do so, add
an `in_initial_library_scan` flag to struct inferior.  This flag is used
to postpone loading libthread_db if we are attaching or handling a fork
child.

When debugging remotely with GDBserver, the same problem happens, except
that the qSymbol mechanism (allowing the remote side to ask GDB for
symbols values) is involved.  The fix there is the same idea, we make
GDB wait until all shared libraries and their symbols are known before
sending out a qSymbol packet.  This way, we never present the remote
side a state where libpthread.so's symbols are known but ld-linux's
symbols aren't.

gdb/ChangeLog:

	* inferior.h (class inferior) <in_initial_library_scan>: New.
	* infcmd.c (post_create_inferior): Set in_initial_library_scan.
	* infrun.c (follow_fork_inferior): Likewise.
	* linux-thread-db.c (try_thread_db_load): Catch exception thrown
	by try_thread_db_load_1
	(thread_db_load): Return early if in_initial_library_scan is
	set.
	* remote.c (remote_new_objfile): Return early if
	in_initial_library_scan is set.

Change-Id: I7a279836cfbb2b362b4fde11b196b4aab82f5efb
palves pushed a commit that referenced this issue Jul 2, 2021
When loading a mach-o (macOS) executable and trying to set a breakpoint,
a GDB built with ASan or -D_GLIBCXX_DEBUG will crash with an
out-of-bound vector access.  This can be reproduced on Linux using the
repro files in bug 28017 [1]:

    $ ./gdb -nx --data-directory=data-directory -q repro/test -ex "b main" -batch
    /usr/include/c++/11.1.0/debug/vector:445:
    In function:
        std::__debug::vector<_Tp, _Allocator>::const_reference
        std::__debug::vector<_Tp,
        _Allocator>::operator[](std::__debug::vector<_Tp,
        _Allocator>::size_type) const [with _Tp = long unsigned int; _Allocator
        = std::allocator<long unsigned int>; std::__debug::vector<_Tp,
        _Allocator>::const_reference = const long unsigned int&;
        std::__debug::vector<_Tp, _Allocator>::size_type = long unsigned int]

    Error: attempt to subscript container with out-of-bounds index 13, but
    container only holds 13 elements.

    Objects involved in the operation:
        sequence "this" @ 0x0x61300000a590 {
          type = std::__debug::vector<unsigned long, std::allocator<unsigned long> >;
        }

The out-of-bound access happens here:

    #0  0x00007ffff6405d22 in raise () from /usr/lib/libc.so.6
    #1  0x00007ffff63ef862 in abort () from /usr/lib/libc.so.6
    #2  0x00007ffff664e21e in __gnu_debug::_Error_formatter::_M_error() const [clone .cold] from /usr/lib/libstdc++.so.6
    #3  0x000055555699e5ff in std::__debug::vector<unsigned long, std::allocator<unsigned long> >::operator[] (this=0x61300000a590, __n=13) at /usr/include/c++/11.1.0/debug/vector:445
    #4  0x0000555556a58c17 in objfile::section_offset (this=0x61300000a4c0, section=0x55555bbe4ac0 <_bfd_std_section>) at /home/simark/src/binutils-gdb/gdb/objfiles.h:644
    #5  0x0000555556a58cac in obj_section::offset (this=0x62100016d2a8) at /home/simark/src/binutils-gdb/gdb/objfiles.h:838
    #6  0x0000555556a58cfa in obj_section::addr (this=0x62100016d2a8) at /home/simark/src/binutils-gdb/gdb/objfiles.h:850
    #7  0x000055555779f5f7 in sort_cmp (sect1=0x62100016d2a8, sect2=0x62100016d170) at /home/simark/src/binutils-gdb/gdb/objfiles.c:902
    #8  0x00005555577aae35 in __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(obj_section const*, obj_section const*)>::operator()<obj_section**, obj_section**> (this=0x7fffffffa9e0, __it1=0x60c000015970, __it2=0x60c000015940) at /usr/include/c++/11.1.0/bits/predefined_ops.h:158
    #9  0x00005555577aa2b8 in std::__insertion_sort<obj_section**, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(obj_section const*, obj_section const*)> > (__first=0x60c000015940, __last=0x60c0000159c0, __comp=...) at /usr/include/c++/11.1.0/bits/stl_algo.h:1826
    #10 0x00005555577a8e26 in std::__final_insertion_sort<obj_section**, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(obj_section const*, obj_section const*)> > (__first=0x60c000015940, __last=0x60c0000159c0, __comp=...) at /usr/include/c++/11.1.0/bits/stl_algo.h:1871
    #11 0x00005555577a723c in std::__sort<obj_section**, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(obj_section const*, obj_section const*)> > (__first=0x60c000015940, __last=0x60c0000159c0, __comp=...) at /usr/include/c++/11.1.0/bits/stl_algo.h:1957
    #12 0x00005555577a50f4 in std::sort<obj_section**, bool (*)(obj_section const*, obj_section const*)> (__first=0x60c000015940, __last=0x60c0000159c0, __comp=0x55555779f4e7 <sort_cmp(obj_section const*, obj_section const*)>) at /usr/include/c++/11.1.0/bits/stl_algo.h:4875
    #13 0x00005555577a147e in update_section_map (pspace=0x61200001d2c0, pmap=0x6030000d40b0, pmap_size=0x6030000d40b8) at /home/simark/src/binutils-gdb/gdb/objfiles.c:1165
    #14 0x00005555577a19a0 in find_pc_section (pc=0x100003fa0) at /home/simark/src/binutils-gdb/gdb/objfiles.c:1212
    #15 0x00005555576dd39e in lookup_minimal_symbol_by_pc_section (pc_in=0x100003fa0, section=0x0, prefer=lookup_msym_prefer::TEXT, previous=0x0) at /home/simark/src/binutils-gdb/gdb/minsyms.c:750
    #16 0x00005555576de552 in lookup_minimal_symbol_by_pc (pc=0x100003fa0) at /home/simark/src/binutils-gdb/gdb/minsyms.c:986
    #17 0x0000555557d44b54 in find_pc_sect_line (pc=0x100003fa0, section=0x62100016d170, notcurrent=0) at /home/simark/src/binutils-gdb/gdb/symtab.c:3163
    #18 0x0000555557d489fa in find_function_start_sal_1 (func_addr=0x100003fa0, section=0x62100016d170, funfirstline=true) at /home/simark/src/binutils-gdb/gdb/symtab.c:3650
    #19 0x0000555557d49015 in find_function_start_sal (sym=0x621000191670, funfirstline=true) at /home/simark/src/binutils-gdb/gdb/symtab.c:3706
    #20 0x0000555557485283 in symbol_to_sal (result=0x7fffffffbb30, funfirstline=1, sym=0x621000191670) at /home/simark/src/binutils-gdb/gdb/linespec.c:4460
    #21 0x00005555574728c2 in convert_linespec_to_sals (state=0x7fffffffc390, ls=0x7fffffffc3e0) at /home/simark/src/binutils-gdb/gdb/linespec.c:2335
    #22 0x0000555557475a8e in parse_linespec (parser=0x7fffffffc360, arg=0x60200007a550 "main", match_type=symbol_name_match_type::WILD) at /home/simark/src/binutils-gdb/gdb/linespec.c:2716
    #23 0x0000555557479027 in event_location_to_sals (parser=0x7fffffffc360, location=0x606000097be0) at /home/simark/src/binutils-gdb/gdb/linespec.c:3173
    #24 0x00005555574798f7 in decode_line_full (location=0x606000097be0, flags=1, search_pspace=0x0, default_symtab=0x0, default_line=0, canonical=0x7fffffffcca0, select_mode=0x0, filter=0x0) at /home/simark/src/binutils-gdb/gdb/linespec.c:3253
    #25 0x0000555556b4949f in parse_breakpoint_sals (location=0x606000097be0, canonical=0x7fffffffcca0) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:9134
    #26 0x0000555556b6ce95 in create_sals_from_location_default (location=0x606000097be0, canonical=0x7fffffffcca0, type_wanted=bp_breakpoint) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:13819
    #27 0x0000555556b645a6 in bkpt_create_sals_from_location (location=0x606000097be0, canonical=0x7fffffffcca0, type_wanted=bp_breakpoint) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:12631
    #28 0x0000555556b4badf in create_breakpoint (gdbarch=0x621000152d10, location=0x606000097be0, cond_string=0x0, thread=0, extra_string=0x0, force_condition=false, parse_extra=1, tempflag=0, type_wanted=bp_breakpoint, ignore_count=0, pending_break_support=AUTO_BOOLEAN_AUTO, ops=0x55555bd728a0 <bkpt_breakpoint_ops>, from_tty=0, enabled=1, internal=0, flags=0) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:9410
    #29 0x0000555556b4d3b1 in break_command_1 (arg=0x7fffffffe291 "", flag=0, from_tty=0) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:9590
    #30 0x0000555556b4dc1b in break_command (arg=0x7fffffffe28d "main", from_tty=0) at /home/simark/src/binutils-gdb/gdb/breakpoint.c:9660
    #31 0x0000555556d24ca9 in do_const_cfunc (c=0x61100003a240, args=0x7fffffffe28d "main", from_tty=0) at /home/simark/src/binutils-gdb/gdb/cli/cli-decode.c:102
    #32 0x0000555556d2fcd3 in cmd_func (cmd=0x61100003a240, args=0x7fffffffe28d "main", from_tty=0) at /home/simark/src/binutils-gdb/gdb/cli/cli-decode.c:2160
    #33 0x0000555557e84e93 in execute_command (p=0x7fffffffe290 "n", from_tty=0) at /home/simark/src/binutils-gdb/gdb/top.c:674
    #34 0x00005555575a9933 in catch_command_errors (command=0x555557e84043 <execute_command(char const*, int)>, arg=0x7fffffffe28b "b main", from_tty=0, do_bp_actions=true) at /home/simark/src/binutils-gdb/gdb/main.c:523
    #35 0x00005555575a9fdb in execute_cmdargs (cmdarg_vec=0x7fffffffd910, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffd5b0) at /home/simark/src/binutils-gdb/gdb/main.c:618
    #36 0x00005555575ad48a in captured_main_1 (context=0x7fffffffdd00) at /home/simark/src/binutils-gdb/gdb/main.c:1322
    #37 0x00005555575ada9c in captured_main (data=0x7fffffffdd00) at /home/simark/src/binutils-gdb/gdb/main.c:1343
    #38 0x00005555575adb31 in gdb_main (args=0x7fffffffdd00) at /home/simark/src/binutils-gdb/gdb/main.c:1368
    #39 0x000055555681e179 in main (argc=8, argv=0x7fffffffde78) at /home/simark/src/binutils-gdb/gdb/gdb.c:32

The section being dealt with at that moment is the special *COM*
section:

    (top-gdb) p section.name
    $1 = 0x55555a1bbe60 "*COM*"
    (top-gdb) p section
    $2 = (bfd_section *) 0x55555bbe4ac0 <_bfd_std_section>

I'm not too sure what this section is for, but this is one of four
special BFD sections that GDB puts after the regular sections in the
objfile::sections and objfile::section_offsets lists.  You can check
gdb_bfd_section_index to see how they are handled.
gdb_bfd_count_sections returns "+ 4" to account for those sections.

The problem is that macho_symfile_offsets uses bfd_count_sections
instead of gdb_bfd_count_sections when allocating the
objfile::section_offsets vector.  The vector will therefore contain,
say, 13 elements instead of 17.  When trying to access the section
offset of the *COM* section, the first after the regular sections, we
access section_offsets[13], which is out of bounds.

Fix that by using gdb_bfd_count_sections instead of bfd_count_sections.
I'm fairly confident that this is correct, as this is what
default_symfile_offsets does.

With this patch, the command shown above terminates normally:

    $ ./gdb -nx --data-directory=data-directory -q repro/test -ex "b main" -batch
    Breakpoint 1 at 0x100003fad: file test.c, line 2.

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=28017

gdb/ChangeLog:

	PR gdb/28017
	* machoread.c (macho_symfile_offsets): Use
	gdb_bfd_count_sections to allocate objfile::section_offsets.

Change-Id: Ic3a56f46f7232e9f24581f8255fc1ab981935450
palves added a commit that referenced this issue Jul 2, 2021
Running the gdb.threads/interrupt-while-step-over.exp testcase added
later in the series against gdbserver, after the
TARGET_WAITKIND_NO_RESUMED fix from the following patch would run into
an infinite loop in stop_all_threads.  I added a hacky gdb_assert to
catch the loop, and it looked like this:

   [infrun] stop_all_threads:   Thread 3492141.3492141 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492716 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492717 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492718 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492719 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492720 executing, need stop
   [remote] stop: enter
     [remote] remote_stop_ns: Enqueueing phony stop reply for thread pending vCont-resume (3492141, 3492720, 0)
   [remote] stop: exit
   [infrun] stop_all_threads:   Thread 3492141.3492721 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492722 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492723 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492724 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492725 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492726 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492727 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492728 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492729 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492730 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492731 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492732 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492733 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492734 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492735 not executing
   [remote] wait: enter
   [remote] wait: exit
   [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) =
   [infrun] print_target_wait_results:   -1.0.0 [process -1],
   [infrun] print_target_wait_results:   status->kind = no-resumed
   [infrun] infrun_async: enable=0
   [infrun] handle_one: status->kind = no-resumed process -1
   [remote] Sending packet: $qXfer:threads:read::0,1000#92
   [remote] Packet received: l<threads>\n<thread id="p35492d.35492d" core="16" name="interrupt-while" handle="40d7d8f7ff7f0000"/>\n<thread id="p35492d.354b6c" core="12" name="interrupt-while" handle="00c7d8f7ff7f0000"/>\n<thread id="p35492d.354b6d" core="5" name="interrupt-while" handle="00b758f7ff7f0000"/>\n<thread id="p35492d.354b6e" core="19" name="interrupt-while" handle="00a7d8f6ff7f0000"/>\n<thread id="p35492d.354b6f" core="15" name="interrupt-while" handle="009758f6ff7f0000"/>\n<thread id="p35492d.354b70" core="6" name="interrupt-whil [1370 bytes omitted]
   [infrun] stop_all_threads:   Thread 3492141.3492141 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492716 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492717 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492718 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492719 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492720 executing, already stopping
   [infrun] stop_all_threads:   Thread 3492141.3492721 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492722 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492723 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492724 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492725 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492726 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492727 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492728 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492729 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492730 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492731 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492732 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492733 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492734 not executing
   [infrun] stop_all_threads:   Thread 3492141.3492735 not executing
 ../../src/gdb/infrun.c:5066: internal-error: void stop_all_threads(): Assertion `0' failed.
 A problem internal to GDB has been detected,
 further debugging may prove unreliable.
 Quit this debugging session? (y or n)

What happened above was that gdbserver had sent a
TARGET_WAITKIND_NO_RESUMED stop reply (N) to GDB already, and that
event was still in transit, held in remote.c's stop reply queue, not
yet seen by infrun.  In stop_all_threads, GDB told remote.c to stop
thread 3492141.3492720.  That thread had a pending vCont resume, so
remote.c queued a phony stop.  This event is queued _after_ the
TARGET_WAITKIND_NO_RESUMED stop reply that was already there.
stop_all_threads calls wait_one to collect one event and gets back
that TARGET_WAITKIND_NO_RESUMED.  Seeing TARGET_WAITKIND_NO_RESUMED,
wait_one disables target_async for that target to stop listing to
events from that target.  No other unresumed target has async active,
so wait_one returns TARGET_WAITKIND_NO_RESUMED.  stop_all_threads
still hasn't seen the stop for 3492141.3492720, so we go for another
iteration.  But since the target is not async, wait_one returns
TARGET_WAITKIND_NO_RESUMED without calling target_wait.  The queued
event for 3492141.3492720 remains pending forever, and
stop_all_threads keeps iterating forever.

The comment in the patch describes a different scenario that does not
involve the phony stop:

	/* wait_one waits for events until it sees a
	TARGET_WAITKIND_NO_RESUMED.  When it sees one, it disables
	target_async for the target and no longer waits for events from
	that target.  TARGET_WAITKIND_NO_RESUMED can be delayed though,
	consider:

     #1 - threads 2-5 are stopped, thread 1 is running

     #2 - target reports breakpoint hit for thread 1, event
	  is queued.

     #3 - target reports no-resumed left, event is queued

     #4 - user resumes all threads

     #5 - gdb decides to stop all threads, stops threads 1-5

     #6 - wait_one returns the queued breakpoint hit for
	  thread 1

     #7 - wait_one returns the queued no-resumed event,
	  wait_one stops waiting for events from target.

     #8 - we still haven't seen the stops for threads 2-5, so
	  we do another pass.

     #9 - if the target is not async wait_one doesn't wait on
	  the target, so it won't see the stops.

     #a - we'd loop forever with WAITS_NEEDED > 0.

Fix this by explicitly enabling target async on each iteration, before
starting the wait_one loop.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <[email protected]>

	PR gdb/27338
	* infrun.c (reenable_target_async): New.
	(stop_all_threads): Enable/re-enable async on targets that can
	async before waiting for stops.

Change-Id: Ie3ffb0df89635585a6631aa842689cecc989e33f
palves pushed a commit that referenced this issue Jul 18, 2021
When loading a file using the file command on macOS, we get:

    $ ./gdb -nx --data-directory=data-directory -q -ex "file ./test"
    Reading symbols from ./test...
    Reading symbols from /Users/smarchi/build/binutils-gdb/gdb/test.dSYM/Contents/Resources/DWARF/test...
    /Users/smarchi/src/binutils-gdb/gdb/thread.c:72: internal-error: struct thread_info *inferior_thread(): Assertion `current_thread_ != nullptr' failed.
    A problem internal to GDB has been detected,
    further debugging may prove unreliable.
    Quit this debugging session? (y or n)

The backtrace is:

    * frame #0: 0x0000000101fcb826 gdb`internal_error(file="/Users/smarchi/src/binutils-gdb/gdb/thread.c", line=72, fmt="%s: Assertion `%s' failed.") at errors.cc:52:3
      frame #1: 0x00000001018a2584 gdb`inferior_thread() at thread.c:72:3
      frame #2: 0x0000000101469c09 gdb`get_current_regcache() at regcache.c:421:31
      frame #3: 0x00000001015f9812 gdb`darwin_solib_get_all_image_info_addr_at_init(info=0x0000603000006d00) at solib-darwin.c:464:34
      frame #4: 0x00000001015f7a04 gdb`darwin_solib_create_inferior_hook(from_tty=1) at solib-darwin.c:515:5
      frame #5: 0x000000010161205e gdb`solib_create_inferior_hook(from_tty=1) at solib.c:1200:3
      frame #6: 0x00000001016d8f76 gdb`symbol_file_command(args="./test", from_tty=1) at symfile.c:1650:7
      frame #7: 0x0000000100abab17 gdb`file_command(arg="./test", from_tty=1) at exec.c:555:3
      frame #8: 0x00000001004dc799 gdb`do_const_cfunc(c=0x000061100000c340, args="./test", from_tty=1) at cli-decode.c:102:3
      frame #9: 0x00000001004ea042 gdb`cmd_func(cmd=0x000061100000c340, args="./test", from_tty=1) at cli-decode.c:2160:7
      frame #10: 0x00000001018d4f59 gdb`execute_command(p="t", from_tty=1) at top.c:674:2
      frame #11: 0x0000000100eee430 gdb`catch_command_errors(command=(gdb`execute_command(char const*, int) at top.c:561), arg="file ./test", from_tty=1, do_bp_actions=true)(char const*, int), char const*, int, bool) at main.c:523:7
      frame #12: 0x0000000100eee902 gdb`execute_cmdargs(cmdarg_vec=0x00007ffeefbfeba0 size=1, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x00007ffeefbfec20) at main.c:618:9
      frame #13: 0x0000000100eed3a4 gdb`captured_main_1(context=0x00007ffeefbff780) at main.c:1322:3
      frame #14: 0x0000000100ee810d gdb`captured_main(data=0x00007ffeefbff780) at main.c:1343:3
      frame #15: 0x0000000100ee8025 gdb`gdb_main(args=0x00007ffeefbff780) at main.c:1368:7
      frame #16: 0x00000001000044f1 gdb`main(argc=6, argv=0x00007ffeefbff8a0) at gdb.c:32:10
      frame #17: 0x00007fff20558f5d libdyld.dylib`start + 1

The solib_create_inferior_hook call in symbol_file_command was added by
commit ea142fb ("Fix breakpoints on file reloads for PIE
binaries").  It causes solib_create_inferior_hook to be called while
the inferior is not running, which darwin_solib_create_inferior_hook
does not expect.  darwin_solib_get_all_image_info_addr_at_init, in
particular, assumes that there is a current thread, as it tries to get
the current thread's regcache.

Fix it by adding a target_has_execution check and returning early.  Note
that there is a similar check in svr4_solib_create_inferior_hook.

gdb/ChangeLog:

	* solib-darwin.c (darwin_solib_create_inferior_hook): Return
	early if no execution.

Change-Id: Ia11dd983a1e29786e5ce663d0fcaa6846dc611bb
palves added a commit that referenced this issue Jul 18, 2021
Commit 408f668 ("detach in all-stop
with threads running") regressed "detach" with "target remote":

 (gdb) detach
 Detaching from program: target:/any/program, process 3671843
 Detaching from process 3671843
 Ending remote debugging.
 [Inferior 1 (process 3671843) detached]
 In main
 terminate called after throwing an instance of 'gdb_exception_error'
 Aborted (core dumped)

Here's the exception above being thrown:

 (top-gdb) bt
 #0  throw_error (error=TARGET_CLOSE_ERROR, fmt=0x555556035588 "Remote connection closed") at src/gdbsupport/common-exceptions.cc:222
 #1  0x0000555555bbaa46 in remote_target::readchar (this=0x555556a11040, timeout=10000) at src/gdb/remote.c:9440
 #2  0x0000555555bbb9e5 in remote_target::getpkt_or_notif_sane_1 (this=0x555556a11040, buf=0x555556a11058, forever=0, expecting_notif=0, is_notif=0x0) at src/gdb/remote.c:9928
 #3  0x0000555555bbbda9 in remote_target::getpkt_sane (this=0x555556a11040, buf=0x555556a11058, forever=0) at src/gdb/remote.c:10030
 #4  0x0000555555bc0e75 in remote_target::remote_hostio_send_command (this=0x555556a11040, command_bytes=13, which_packet=14, remote_errno=0x7fffffffcfd0, attachment=0x0, attachment_len=0x0) at src/gdb/remote.c:12137
 #5  0x0000555555bc1b6c in remote_target::remote_hostio_close (this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12455
 #6  0x0000555555bc1bb4 in remote_target::fileio_close (During symbol reading: .debug_line address at offset 0x64f417 is 0 [in module build/gdb/gdb]
 this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12462
 #7  0x0000555555c9274c in target_fileio_close (fd=3, target_errno=0x7fffffffcfd0) at src/gdb/target.c:3365
 #8  0x000055555595a19d in gdb_bfd_iovec_fileio_close (abfd=0x555556b9f8a0, stream=0x555556b11530) at src/gdb/gdb_bfd.c:439
 #9  0x0000555555e09e3f in opncls_bclose (abfd=0x555556b9f8a0) at src/bfd/opncls.c:599
 #10 0x0000555555e0a2c7 in bfd_close_all_done (abfd=0x555556b9f8a0) at src/bfd/opncls.c:847
 #11 0x0000555555e0a27a in bfd_close (abfd=0x555556b9f8a0) at src/bfd/opncls.c:814
 #12 0x000055555595a9d3 in gdb_bfd_close_or_warn (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:626
 #13 0x000055555595ad29 in gdb_bfd_unref (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:715
 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573
 #15 0x0000555555ae955a in std::_Sp_counted_ptr<objfile*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:377
 #16 0x000055555572b7c8 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:155
 #17 0x00005555557263c3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x555556bf0588, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:730
 #18 0x0000555555ae745e in std::__shared_ptr<objfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:1169
 #19 0x0000555555ae747e in std::shared_ptr<objfile>::~shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr.h:103
 #20 0x0000555555b1c1dc in __gnu_cxx::new_allocator<std::_List_node<std::shared_ptr<objfile> > >::destroy<std::shared_ptr<objfile> > (this=0x5555564cdd60, __p=0x555556bf0580) at /usr/include/c++/9/ext/new_allocator.h:153
 #21 0x0000555555b1bb1d in std::allocator_traits<std::allocator<std::_List_node<std::shared_ptr<objfile> > > >::destroy<std::shared_ptr<objfile> > (__a=..., __p=0x555556bf0580) at /usr/include/c++/9/bits/alloc_traits.h:497
 #22 0x0000555555b1b73e in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/stl_list.h:1921
 #23 0x0000555555b1afeb in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/list.tcc:158
 #24 0x0000555555b19576 in program_space::remove_objfile (this=0x5555564cdd20, objfile=0x555556515540) at src/gdb/progspace.c:210
 #25 0x0000555555ae4502 in objfile::unlink (this=0x555556515540) at src/gdb/objfiles.c:487
 #26 0x0000555555ae5a12 in objfile_purge_solibs () at src/gdb/objfiles.c:875
 #27 0x0000555555c09686 in no_shared_libraries (ignored=0x0, from_tty=1) at src/gdb/solib.c:1236
 #28 0x00005555559e3f5f in detach_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:2769

So frame #28 already detached the remote process, and then we're
purging the shared libraries.  GDB had opened remote shared libraries
via the target: sysroot, so it tries closing them.  GDBserver is
tearing down already, so remote communication breaks down and we close
the remote target and throw TARGET_CLOSE_ERROR.

Note frame #14:

 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573

That's a dtor, thus noexcept.  That's the reason for the
std::terminate.

Stepping back a bit, why do we still have open remote files if we've
managed to detach already, and, we're debugging with "target remote"?
The reason is that commit 408f668
makes detach_command hold a reference to the target, so the remote
target won't be finally closed until frame #28 returns.  It's closing
the target that invalidates target file I/O handles.

This commit fixes the issue by not relying on target_close to
invalidate the target file I/O handles, instead invalidate them
immediately in remote_unpush_target.  So when GDB purges the solibs,
and we end up in target_fileio_close (frame #7 above), there's nothing
to do, and we don't try to talk with the remote target anymore.

The regression isn't seen when testing with
--target_board=native-gdbserver, because that does "set sysroot" to
disable the "target:" sysroot, for test run speed reasons.  So this
commit adds a testcase that explicitly tests detach with "set sysroot
target:".

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <[email protected]>

	PR gdb/28080
	* remote.c (remote_unpush_target): Invalidate file I/O target
	handles.
	* target.c (fileio_handles_invalidate_target): Make extern.
	* target.h (fileio_handles_invalidate_target): Declare.

gdb/testsuite/ChangeLog:
yyyy-mm-dd  Pedro Alves  <[email protected]>

	PR gdb/28080
	* gdb.base/detach-sysroot-target.exp: New.
	* gdb.base/detach-sysroot-target.c: New.

Reported-By: Jonah Graham <[email protected]>

Change-Id: I851234910172f42a1b30e731161376c344d2727d
palves added a commit that referenced this issue Jul 18, 2021
…080)

Before PR gdb/28080 was fixed by the previous patch, GDB was crashing
like this:

 (gdb) detach
 Detaching from program: target:/any/program, process 3671843
 Detaching from process 3671843
 Ending remote debugging.
 [Inferior 1 (process 3671843) detached]
 In main
 terminate called after throwing an instance of 'gdb_exception_error'
 Aborted (core dumped)

Here's the exception above being thrown:

 (top-gdb) bt
 #0  throw_error (error=TARGET_CLOSE_ERROR, fmt=0x555556035588 "Remote connection closed") at src/gdbsupport/common-exceptions.cc:222
 #1  0x0000555555bbaa46 in remote_target::readchar (this=0x555556a11040, timeout=10000) at src/gdb/remote.c:9440
 #2  0x0000555555bbb9e5 in remote_target::getpkt_or_notif_sane_1 (this=0x555556a11040, buf=0x555556a11058, forever=0, expecting_notif=0, is_notif=0x0) at src/gdb/remote.c:9928
 #3  0x0000555555bbbda9 in remote_target::getpkt_sane (this=0x555556a11040, buf=0x555556a11058, forever=0) at src/gdb/remote.c:10030
 #4  0x0000555555bc0e75 in remote_target::remote_hostio_send_command (this=0x555556a11040, command_bytes=13, which_packet=14, remote_errno=0x7fffffffcfd0, attachment=0x0, attachment_len=0x0) at src/gdb/remote.c:12137
 #5  0x0000555555bc1b6c in remote_target::remote_hostio_close (this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12455
 #6  0x0000555555bc1bb4 in remote_target::fileio_close (During symbol reading: .debug_line address at offset 0x64f417 is 0 [in module build/gdb/gdb]
 this=0x555556a11040, fd=8, remote_errno=0x7fffffffcfd0) at src/gdb/remote.c:12462
 #7  0x0000555555c9274c in target_fileio_close (fd=3, target_errno=0x7fffffffcfd0) at src/gdb/target.c:3365
 #8  0x000055555595a19d in gdb_bfd_iovec_fileio_close (abfd=0x555556b9f8a0, stream=0x555556b11530) at src/gdb/gdb_bfd.c:439
 #9  0x0000555555e09e3f in opncls_bclose (abfd=0x555556b9f8a0) at src/bfd/opncls.c:599
 #10 0x0000555555e0a2c7 in bfd_close_all_done (abfd=0x555556b9f8a0) at src/bfd/opncls.c:847
 #11 0x0000555555e0a27a in bfd_close (abfd=0x555556b9f8a0) at src/bfd/opncls.c:814
 #12 0x000055555595a9d3 in gdb_bfd_close_or_warn (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:626
 #13 0x000055555595ad29 in gdb_bfd_unref (abfd=0x555556b9f8a0) at src/gdb/gdb_bfd.c:715
 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573
 #15 0x0000555555ae955a in std::_Sp_counted_ptr<objfile*, (__gnu_cxx::_Lock_policy)2>::_M_dispose (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:377
 #16 0x000055555572b7c8 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x555556c20db0) at /usr/include/c++/9/bits/shared_ptr_base.h:155
 #17 0x00005555557263c3 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x555556bf0588, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:730
 #18 0x0000555555ae745e in std::__shared_ptr<objfile, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr_base.h:1169
 #19 0x0000555555ae747e in std::shared_ptr<objfile>::~shared_ptr (this=0x555556bf0580, __in_chrg=<optimized out>) at /usr/include/c++/9/bits/shared_ptr.h:103
 #20 0x0000555555b1c1dc in __gnu_cxx::new_allocator<std::_List_node<std::shared_ptr<objfile> > >::destroy<std::shared_ptr<objfile> > (this=0x5555564cdd60, __p=0x555556bf0580) at /usr/include/c++/9/ext/new_allocator.h:153
 #21 0x0000555555b1bb1d in std::allocator_traits<std::allocator<std::_List_node<std::shared_ptr<objfile> > > >::destroy<std::shared_ptr<objfile> > (__a=..., __p=0x555556bf0580) at /usr/include/c++/9/bits/alloc_traits.h:497
 #22 0x0000555555b1b73e in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::_M_erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/stl_list.h:1921
 #23 0x0000555555b1afeb in std::__cxx11::list<std::shared_ptr<objfile>, std::allocator<std::shared_ptr<objfile> > >::erase (this=0x5555564cdd60, __position=std::shared_ptr<objfile> (expired, weak count 1) = {get() = 0x555556515540}) at /usr/include/c++/9/bits/list.tcc:158
 #24 0x0000555555b19576 in program_space::remove_objfile (this=0x5555564cdd20, objfile=0x555556515540) at src/gdb/progspace.c:210
 #25 0x0000555555ae4502 in objfile::unlink (this=0x555556515540) at src/gdb/objfiles.c:487
 #26 0x0000555555ae5a12 in objfile_purge_solibs () at src/gdb/objfiles.c:875
 #27 0x0000555555c09686 in no_shared_libraries (ignored=0x0, from_tty=1) at src/gdb/solib.c:1236
 #28 0x00005555559e3f5f in detach_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:2769

Note frame #14:

 #14 0x0000555555ae4730 in objfile::~objfile (this=0x555556515540, __in_chrg=<optimized out>) at src/gdb/objfiles.c:573

That's a dtor, thus noexcept.  That's the reason for the
std::terminate.

The previous patch fixed things such that the exception above isn't
thrown anymore.  However, it's possible that e.g., the remote
connection drops just while a user types "nosharedlibrary", or some
other reason that leads to objfile::~objfile, and then we end up the
same std::terminate problem.

Also notice that frames #9-#11 are BFD frames:

 #9  0x0000555555e09e3f in opncls_bclose (abfd=0x555556bc27e0) at src/bfd/opncls.c:599
 #10 0x0000555555e0a2c7 in bfd_close_all_done (abfd=0x555556bc27e0) at src/bfd/opncls.c:847
 #11 0x0000555555e0a27a in bfd_close (abfd=0x555556bc27e0) at src/bfd/opncls.c:814

BFD is written in C and thus throwing exceptions over such frames may
either not clean up properly, or, may abort if bfd is not compiled
with -fasynchronous-unwind-tables (x86-64 defaults that on, but not
all GCC ports do).

Thus frame #8 seems like a good place to swallow exceptions.  More so
since in this spot we already ignore target_fileio_close return
errors.  That's what this commit does.  Without the previous fix, we'd
see:

 (gdb) detach
 Detaching from program: target:/any/program, process 2197701
 Ending remote debugging.
 [Inferior 1 (process 2197701) detached]
 warning: cannot close "target:/lib64/ld-linux-x86-64.so.2": Remote connection closed

Note it prints a warning, which would still be a regression compared
to GDB 10, if it weren't for the previous fix.

gdb/ChangeLog:
yyyy-mm-dd  Pedro Alves  <[email protected]>

	PR gdb/28080
	* gdb_bfd.c (gdb_bfd_close_warning): New.
	(gdb_bfd_iovec_fileio_close): Wrap target_fileio_close in
	try/catch and print warning on exception.
	(gdb_bfd_close_or_warn): Use gdb_bfd_close_warning.

Change-Id: Ic7a26ddba0a4444e3377b0e7c1c89934a84545d7
palves added a commit that referenced this issue Jun 7, 2023
After running a number of programs under gdb and detaching them, I
typed run in gdb, and got a hang, here:

 (top-gdb) bt
 #0  sharing_input_terminal (pid=4672) at /home/pedro/rocm/gdb/src/gdb/mingw-hdep.c:388
 #1  0x00007ff71a2d8678 in sharing_input_terminal (inf=0x23bf23dafb0) at /home/pedro/rocm/gdb/src/gdb/inflow.c:269
 #2  0x00007ff71a2d887b in child_terminal_save_inferior (self=0x23bf23de060) at /home/pedro/rocm/gdb/src/gdb/inflow.c:423
 #3  0x00007ff71a2c80c0 in inf_child_target::terminal_save_inferior (this=0x23bf23de060) at /home/pedro/rocm/gdb/src/gdb/inf-child.c:111
 #4  0x00007ff71a429c0f in target_terminal_is_ours_kind (desired_state=target_terminal_state::is_ours_for_output) at /home/pedro/rocm/gdb/src/gdb/target.c:1037
 #5  0x00007ff71a429e02 in target_terminal::ours_for_output () at /home/pedro/rocm/gdb/src/gdb/target.c:1094
 #6  0x00007ff71a2ccc8e in post_create_inferior (from_tty=0) at /home/pedro/rocm/gdb/src/gdb/infcmd.c:245
 #7  0x00007ff71a2cd431 in run_command_1 (args=0x0, from_tty=0, run_how=RUN_NORMAL) at /home/pedro/rocm/gdb/src/gdb/infcmd.c:502
 #8  0x00007ff71a2cd58b in run_command (args=0x0, from_tty=0) at /home/pedro/rocm/gdb/src/gdb/infcmd.c:527

The problem is that the loop around GetConsoleProcessList looped
forever, because there were exactly 10 processes to return.
GetConsoleProcessList's documentation says:

  If the buffer is too small to hold all the valid process identifiers,
  the return value is the required number of array elements. The
  function will have stored no identifiers in the buffer. In this
  situation, use the return value to allocate a buffer that is large
  enough to store the entire list and call the function again.

In this case, the buffer wasn't too small, it was exactly the right
size, so we should have broken out of the loop.  We didn't due to a
"<" check that should have been "<=".  That is fixed by this patch.

Change-Id: I14e4909f2ac2fa83d0d9b6e64418b5831ac4e4e3
palves pushed a commit that referenced this issue Jun 7, 2023
In some cases GDB will fail when attempting to complete a command that
involves a rust symbol, the failure can manifest as a crash.

The problem is caused by the completion_match_for_lcd object being
left containing invalid data during calls to cp_symbol_name_matches_1.

The first question to address is why we are calling a C++ support
function when handling a rust symbol.  That's due to GDB's auto
language detection for msymbols, in some cases GDB can't tell if a
symbol is a rust symbol, or a C++ symbol.

The test application contains symbols for functions which are
statically linked in from various rust support libraries.  There's no
DWARF for these symbols, so all GDB has is the msymbols built from the
ELF symbol table.

Here's the problematic symbol that leads to our crash:

    mangled: _ZN4core3str21_$LT$impl$u20$str$GT$5parse17h5111d2d6a50d22bdE
  demangled: core::str::<impl str>::parse

As an msymbol this is initially created with language auto, then GDB
eventually calls symbol_find_demangled_name, which loops over all
languages calling language_defn::sniff_from_mangled_name, the first
language that can demangle the symbol gets assigned as the language
for that symbol.

Unfortunately, there's overlap in the mangled symbol names,
some (legacy) rust symbols can be demangled as both rust and C++, see
cplus_demangle in libiberty/cplus-dem.c where this is mentioned.

And so, because we check the C++ language before we check for rust,
then the msymbol is (incorrectly) given the C++ language.

Now it's true that is some cases we might be able to figure out that a
demangled symbol is not actually a valid C++ symbol, for example, in
our case, the construct '::<impl str>::' is not, I believe, valid in a
C++ symbol, we could look for ':<' and '>:' and refuse to accept this
as a C++ symbol.

However, I'm not sure it is always possible to tell that a demangled
symbol is rust or C++, so, I think, we have to accept that some times
we will get this language detection wrong.

If we accept that we can't fix the symbol language detection 100% of
the time, then we should make sure that GDB doesn't crash when it gets
the language wrong, that is what this commit addresses.

In our test case the user tries to complete a symbol name like this:

  (gdb) complete break pars

This results in GDB trying to find all symbols that match 'pars',
eventually we consider our problematic symbol, and we end up with a
call stack that looks like this:

  #0  0x0000000000f3c6bd in strncmp_iw_with_mode
  #1  0x0000000000706d8d in cp_symbol_name_matches_1
  #2  0x0000000000706fa4 in cp_symbol_name_matches
  #3  0x0000000000df3c45 in compare_symbol_name
  #4  0x0000000000df3c91 in completion_list_add_name
  #5  0x0000000000df3f1d in completion_list_add_msymbol
  #6  0x0000000000df4c94 in default_collect_symbol_completion_matches_break_on
  #7  0x0000000000658c08 in language_defn::collect_symbol_completion_matches
  #8  0x0000000000df54c9 in collect_symbol_completion_matches
  #9  0x00000000009d98fb in linespec_complete_function
  #10 0x00000000009d99f0 in complete_linespec_component
  #11 0x00000000009da200 in linespec_complete
  #12 0x00000000006e4132 in complete_address_and_linespec_locations
  #13 0x00000000006e4ac3 in location_completer

In cp_symbol_name_matches_1 we enter a loop, this loop repeatedly
tries to match the demangled problematic symbol name against the user
supplied text ('pars').  Each time around the loop another component
of the symbol name is stripped off, thus, we check 'pars' against
these options:

  core::str::<impl str>::parse
  str::<impl str>::parse
  <impl str>::parse
  parse

As soon as we get a match the cp_symbol_name_matches_1 exits its loop
and returns.  In our case, when we're looking for 'pars', the match
occurs on the last iteration of the loop, when we are comparing to
'parse'.

Now the problem here is that cp_symbol_name_matches_1 uses the
strncmp_iw_with_mode, and inside strncmp_iw_with_mode we allow for
skipping over template parameters.  This allows GDB to match the
symbol name 'foo<int>(int,int)' if the user supplies 'foo(int,'.
Inside strncmp_iw_with_mode GDB will record any template arguments
that it has skipped over inside the completion_match_for_lcd object
that is passed in as an argument.

And so, when GDB tries to match against '<impl str>::parse', the first
thing it sees is '<impl str>', GDB assumes this is a template argument
and records this as a skipped region within the
completion_match_for_lcd object.  After '<impl str>' GDB sees a ':'
character, which doesn't match with the 'pars' the user supplied, so
strncmp_iw_with_mode returns a value indicating a non-match.  GDB then
removes the '<impl str>' component from the symbol name and tries
again, this time comparing to 'parse', which does match.

Having found a match, then in cp_symbol_name_matches_1 we record the
match string, and the full symbol name within the
completion_match_result object, and return.

The problem here is that the skipped region, the '<impl str>' that we
recorded in the penultimate loop iteration was never discarded, its
still there in our returned result.

If we look at what the pointers held in the completion_match_result
that cp_symbol_name_matches_1 returns, this is what we see:

  core::str::<impl str>::parse
  |          \________/  |
  |               |      '--- completion match string
  |               '---skip range
  '--- full symbol name

When GDB calls completion_match_for_lcd::finish, GDB tries to create a
string using the completion match string (parse), but excluding the
skip range, as the stored skip range is before the start of the
completion match string, then GDB tries to do some weird string
creation, which will cause GDB to crash.

The reason we don't often see this problem in C++ is that for C++
symbols there is always some non-template text before the template
argument.  This non-template text means GDB is likely to either match
the symbol, or reject the symbol without storing a skip range.

However, notice, I did say, we don't often see this problem.  Once I
understood the issue, I was able to reproduce the crash using a pure
C++ example:

  template<typename S>
  struct foo
  {
    template<typename T>
    foo (int p1, T a)
    {
      s = 0;
    }

    S s;
  };

  int
  main ()
  {
    foo<int> obj (2.3, 0);
    return 0;
  }

Then in GDB:

  (gdb) complete break foo(int

The problem here is that the C++ symbol for the constructor looks like
this:

  foo<int>::foo<double>(int, double)

When GDB enters cp_symbol_name_matches_1 the symbols it examines are:

  foo<int>::foo<double>(int, double)
  foo<double>(int, double)

The first iteration of the loop will match the 'foo', then add the
'<int>' template argument will be added as a skip range.  When GDB
find the ':' after the '<int>' the first iteration of the loop fails
to match, GDB removes the 'foo<int>::' component, and starts the
second iteration of the loop.

Again, GDB matches the 'foo', and now adds '<double>' as a skip
region.  After that the '(int' successfully matches, and so the second
iteration of the loop succeeds, but, once again we left the '<int>' in
place as a skip region, even though this occurs before the start of
our match string, and this will cause GDB to crash.

This problem was reported to the mailing list, and a solution
discussed in this thread:

  https://sourceware.org/pipermail/gdb-patches/2023-January/195166.html

The solution proposed here is similar to one proposed by the original
bug reported, but implemented in a different location within GDB.
Instead of placing the fix in strncmp_iw_with_mode, I place the fix in
cp_symbol_name_matches_1.  I believe this is a better location as it
is this function that implements the loop, and it is this loop, which
repeatedly calls strncmp_iw_with_mode, that should be resetting the
result object state (I believe).

What I have done is add an assert to strncmp_iw_with_mode that the
incoming result object is empty.

I've also added some other asserts in related code, in
completion_match_for_lcd::mark_ignored_range, I make some basic
assertions about the incoming range pointers, and in
completion_match_for_lcd::finish I also make some assertions about how
the skip ranges relate to the match pointer.

There's two new tests.  The original rust example that was used in the
initial bug report, and a C++ test.  The rust example depends on which
symbols are pulled in from the rust libraries, so it is possible that,
at some future date, the problematic symbol will disappear from this
test program.  The C++ test should be more reliable, as this only
depends on symbols from within the C++ source code.

Since I originally posted this patch to the mailing list, the
following patch has been merged:

  commit 6e7eef7
  Date:   Sun Mar 19 09:13:10 2023 -0600

      Use rust_demangle to fix a crash

This solves the problem of a rust symbol ending up in the C++ specific
code by changing the order languages are sorted.  However, this new
commit doesn't address the issue in the C++ code which was fixed with
this commit.

Given that the C++ issue is real, and has a reproducer, I'm still
going to merge this fix.  I've left the discussion of rust in this
commit message as I originally wrote it, but it should be read within
the context of GDB prior to commit 6e7eef7.

Co-Authored-By:  Zheng Zhan <[email protected]>
palves pushed a commit that referenced this issue Jun 7, 2023
Commit 7a8de0c ("Remove ALL_BREAKPOINTS_SAFE") introduced a
use-after-free in the breakpoints iterations (see below for full ASan
report).  This makes gdb.base/stale-infcall.exp fail when GDB is build
with ASan.

check_longjmp_breakpoint_for_call_dummy iterates on all breakpoints,
possibly deleting the current breakpoint as well as related breakpoints.
The problem arises when a breakpoint in the B->related_breakpoint chain
is also B->next.  In that case, deleting that related breakpoint frees
the breakpoint that all_breakpoints_safe has saved.

The old code worked around that by manually changing B_TMP, which was
the next breakpoint saved by the "safe iterator":

	while (b->related_breakpoint != b)
	  {
	    if (b_tmp == b->related_breakpoint)
	      b_tmp = b->related_breakpoint->next;
	    delete_breakpoint (b->related_breakpoint);
	  }

(Note that this seemed to assume that b->related_breakpoint->next was
the same as b->next->next, not sure this is guaranteed.)

The new code kept the B_TMP variable, but it's not useful in that
context.  We can't go change the next breakpoint as saved by the safe
iterator, like we did before.  I suggest fixing that by saving the
breakpoints to delete in a map and deleting them all at the end.

Here's the full ASan report:

    (gdb) PASS: gdb.base/stale-infcall.exp: continue to breakpoint: break-run1
    print infcall ()
    =================================================================
    ==47472==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000034980 at pc 0x563f7012c7bc bp 0x7ffdf3804d70 sp 0x7ffdf3804d60
    READ of size 8 at 0x611000034980 thread T0
        #0 0x563f7012c7bb in next_iterator<breakpoint>::operator++() /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/next-iterator.h:66
        #1 0x563f702ce8c0 in basic_safe_iterator<next_iterator<breakpoint> >::operator++() /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/safe-iterator.h:84
        #2 0x563f7021522a in check_longjmp_breakpoint_for_call_dummy(thread_info*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7611
        #3 0x563f714567b1 in process_event_stop_test /home/smarchi/src/binutils-gdb/gdb/infrun.c:6881
        #4 0x563f71454e07 in handle_signal_stop /home/smarchi/src/binutils-gdb/gdb/infrun.c:6769
        #5 0x563f7144b680 in handle_inferior_event /home/smarchi/src/binutils-gdb/gdb/infrun.c:6023
        #6 0x563f71436165 in fetch_inferior_event() /home/smarchi/src/binutils-gdb/gdb/infrun.c:4387
        #7 0x563f7136ff51 in inferior_event_handler(inferior_event_type) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:42
        #8 0x563f7168038d in handle_target_event /home/smarchi/src/binutils-gdb/gdb/linux-nat.c:4219
        #9 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #10 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #11 0x563f72fcaf2b in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:217
        #12 0x563f7262b9bb in wait_sync_command_done() /home/smarchi/src/binutils-gdb/gdb/top.c:426
        #13 0x563f7137a7c3 in run_inferior_call /home/smarchi/src/binutils-gdb/gdb/infcall.c:650
        #14 0x563f71381295 in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1332
        #15 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #16 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #17 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #18 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #19 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #20 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #21 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #22 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #23 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #24 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #25 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #26 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #27 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #28 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543
        #29 0x563f7101014b in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /home/smarchi/src/binutils-gdb/gdb/event-top.c:779
        #30 0x563f72777942 in tui_command_line_handler /home/smarchi/src/binutils-gdb/gdb/tui/tui-interp.c:104
        #31 0x563f7100d059 in gdb_rl_callback_handler /home/smarchi/src/binutils-gdb/gdb/event-top.c:250
        #32 0x7f5a80418246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)
        #33 0x563f7100ca06 in gdb_rl_callback_read_char_wrapper_noexcept /home/smarchi/src/binutils-gdb/gdb/event-top.c:192
        #34 0x563f7100cc5e in gdb_rl_callback_read_char_wrapper /home/smarchi/src/binutils-gdb/gdb/event-top.c:225
        #35 0x563f728c70db in stdin_event_handler /home/smarchi/src/binutils-gdb/gdb/ui.c:155
        #36 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #37 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #38 0x563f72fcb15c in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:264
        #39 0x563f7177ec1c in start_event_loop /home/smarchi/src/binutils-gdb/gdb/main.c:412
        #40 0x563f7177f12e in captured_command_loop /home/smarchi/src/binutils-gdb/gdb/main.c:476
        #41 0x563f717846e4 in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1320
        #42 0x563f71784821 in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1339
        #43 0x563f6fcedfbd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32
        #44 0x7f5a7e43984f  (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
        #45 0x7f5a7e439909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
        #46 0x563f6fcedd84 in _start (/home/smarchi/build/binutils-gdb/gdb/gdb+0xafb0d84) (BuildId: 50bd32e6e9d5e84543e9897b8faca34858ca3995)

    0x611000034980 is located 0 bytes inside of 208-byte region [0x611000034980,0x611000034a50)
    freed by thread T0 here:
        #0 0x7f5a7fce312a in operator delete(void*, unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164
        #1 0x563f702bd1fa in momentary_breakpoint::~momentary_breakpoint() /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:304
        #2 0x563f702771c5 in delete_breakpoint(breakpoint*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:12404
        #3 0x563f702150a7 in check_longjmp_breakpoint_for_call_dummy(thread_info*) /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7673
        #4 0x563f714567b1 in process_event_stop_test /home/smarchi/src/binutils-gdb/gdb/infrun.c:6881
        #5 0x563f71454e07 in handle_signal_stop /home/smarchi/src/binutils-gdb/gdb/infrun.c:6769
        #6 0x563f7144b680 in handle_inferior_event /home/smarchi/src/binutils-gdb/gdb/infrun.c:6023
        #7 0x563f71436165 in fetch_inferior_event() /home/smarchi/src/binutils-gdb/gdb/infrun.c:4387
        #8 0x563f7136ff51 in inferior_event_handler(inferior_event_type) /home/smarchi/src/binutils-gdb/gdb/inf-loop.c:42
        #9 0x563f7168038d in handle_target_event /home/smarchi/src/binutils-gdb/gdb/linux-nat.c:4219
        #10 0x563f72fccb6d in handle_file_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:573
        #11 0x563f72fcd503 in gdb_wait_for_event /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:694
        #12 0x563f72fcaf2b in gdb_do_one_event(int) /home/smarchi/src/binutils-gdb/gdbsupport/event-loop.cc:217
        #13 0x563f7262b9bb in wait_sync_command_done() /home/smarchi/src/binutils-gdb/gdb/top.c:426
        #14 0x563f7137a7c3 in run_inferior_call /home/smarchi/src/binutils-gdb/gdb/infcall.c:650
        #15 0x563f71381295 in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1332
        #16 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #17 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #18 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #19 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #20 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #21 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #22 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #23 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #24 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #25 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #26 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #27 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #28 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #29 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543

    previously allocated by thread T0 here:
        #0 0x7f5a7fce2012 in operator new(unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:95
        #1 0x563f7029a9a3 in new_momentary_breakpoint<program_space*&, frame_id&, int&> /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:8129
        #2 0x563f702212f6 in momentary_breakpoint_from_master /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:8169
        #3 0x563f70212db1 in set_longjmp_breakpoint_for_call_dummy() /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:7582
        #4 0x563f713804db in call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*) /home/smarchi/src/binutils-gdb/gdb/infcall.c:1260
        #5 0x563f7137c0e2 in call_function_by_hand(value*, type*, gdb::array_view<value*>) /home/smarchi/src/binutils-gdb/gdb/infcall.c:780
        #6 0x563f70fe5960 in evaluate_subexp_do_call(expression*, noside, value*, gdb::array_view<value*>, char const*, type*) /home/smarchi/src/binutils-gdb/gdb/eval.c:649
        #7 0x563f70fe6617 in expr::operation::evaluate_funcall(type*, expression*, noside, char const*, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:677
        #8 0x563f6fd19668 in expr::operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/expression.h:136
        #9 0x563f70fe6bba in expr::var_value_operation::evaluate_funcall(type*, expression*, noside, std::__debug::vector<std::unique_ptr<expr::operation, std::default_delete<expr::operation> >, std::allocator<std::unique_ptr<expr::operation, std::default_delete<expr::operation> > > > const&) /home/smarchi/src/binutils-gdb/gdb/eval.c:689
        #10 0x563f704b71dc in expr::funcall_operation::evaluate(type*, expression*, noside) /home/smarchi/src/binutils-gdb/gdb/expop.h:2219
        #11 0x563f70fe0f02 in expression::evaluate(type*, noside) /home/smarchi/src/binutils-gdb/gdb/eval.c:110
        #12 0x563f71b1373e in process_print_command_args /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1319
        #13 0x563f71b1391b in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1332
        #14 0x563f71b147ec in print_command /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1465
        #15 0x563f706029b8 in do_simple_func /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:95
        #16 0x563f7061972a in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2735
        #17 0x563f7262d0ef in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:572
        #18 0x563f7100ed9c in command_handler(char const*) /home/smarchi/src/binutils-gdb/gdb/event-top.c:543
        #19 0x563f7101014b in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /home/smarchi/src/binutils-gdb/gdb/event-top.c:779
        #20 0x563f72777942 in tui_command_line_handler /home/smarchi/src/binutils-gdb/gdb/tui/tui-interp.c:104
        #21 0x563f7100d059 in gdb_rl_callback_handler /home/smarchi/src/binutils-gdb/gdb/event-top.c:250
        #22 0x7f5a80418246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)

Change-Id: Id00c17ab677f847fbf4efdf0f4038373668d3d88
Approved-By: Tom Tromey <[email protected]>
palves pushed a commit that referenced this issue Jun 7, 2023
Commit b5661ff ("gdb: fix possible use-after-free when
executing commands") attempted to fix possible use-after-free
in case command redefines itself.

Commit 37e5833 ("gdb: fix command lookup in execute_command ()")
updated the previous fix to handle subcommands as well by using the
original command string to lookup the command again after its execution.

This fixed the test in gdb.base/define.exp but it turned out that it
does not work (at least) for "target remote" and "target extended-remote".

The problem is that the command buffer P passed to execute_command ()
gets overwritten in dont_repeat () while executing "target remote"
command itself:

	#0  dont_repeat () at top.c:822
	#1  0x000055555730982a in target_preopen (from_tty=1) at target.c:2483
	#2  0x000055555711e911 in remote_target::open_1 (name=0x55555881c7fe ":1234", from_tty=1, extended_p=0)
	    at remote.c:5946
	#3  0x000055555711d577 in remote_target::open (name=0x55555881c7fe ":1234", from_tty=1) at remote.c:5272
	#4  0x00005555573062f2 in open_target (args=0x55555881c7fe ":1234", from_tty=1, command=0x5555589d0490)
	    at target.c:853
	#5  0x0000555556ad22fa in cmd_func (cmd=0x5555589d0490, args=0x55555881c7fe ":1234", from_tty=1)
	    at cli/cli-decode.c:2737
	#6  0x00005555573487fd in execute_command (p=0x55555881c802 "4", from_tty=1) at top.c:688

Therefore the second call to lookup_cmd () at line 697 fails to find
command because the original command string is gone.

This commit addresses this particular problem by creating a *copy* of
original command string for the sole purpose of using it after command
execution to lookup the command again. It may not be the most efficient
way but it's safer given that command buffer is shared and overwritten
in hard-to-foresee situations.

Tested on x86_64-linux.

PR 30249
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30249

Approved-By: Tom Tromey <[email protected]>
palves pushed a commit that referenced this issue Jul 19, 2023
After this commit:

  commit baab375
  Date:   Tue Jul 13 14:44:27 2021 -0400

      gdb: building inferior strings from within GDB

It was pointed out that a new ASan failure had been introduced which
was triggered by gdb.base/internal-string-values.exp:

  (gdb) PASS: gdb.base/internal-string-values.exp: test_setting: all langs: lang=ada: ptype "foo"
  print $_gdb_maint_setting("test-settings string")
  =================================================================
  ==80377==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x603000068034 at pc 0x564785cba682 bp 0x7ffd20644620 sp 0x7ffd20644610
  READ of size 1 at 0x603000068034 thread T0
      #0 0x564785cba681 in find_command_name_length(char const*) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2129
      #1 0x564785cbacb2 in lookup_cmd_1(char const**, cmd_list_element*, cmd_list_element**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, bool) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2186
      #2 0x564785cbb539 in lookup_cmd_1(char const**, cmd_list_element*, cmd_list_element**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, bool) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2248
      #3 0x564785cbbcf3 in lookup_cmd(char const**, cmd_list_element*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2339
      #4 0x564785c82df2 in setting_cmd /tmp/src/binutils-gdb/gdb/cli/cli-cmds.c:2219
      #5 0x564785c84274 in gdb_maint_setting_internal_fn /tmp/src/binutils-gdb/gdb/cli/cli-cmds.c:2348
      #6 0x564788167b3b in call_internal_function(gdbarch*, language_defn const*, value*, int, value**) /tmp/src/binutils-gdb/gdb/value.c:2321
      #7 0x5647854b6ebd in expr::ada_funcall_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:11254
      #8 0x564786658266 in expression::evaluate(type*, noside) /tmp/src/binutils-gdb/gdb/eval.c:111
      #9 0x5647871242d6 in process_print_command_args /tmp/src/binutils-gdb/gdb/printcmd.c:1322
      #10 0x5647871244b3 in print_command_1 /tmp/src/binutils-gdb/gdb/printcmd.c:1335
      #11 0x564787125384 in print_command /tmp/src/binutils-gdb/gdb/printcmd.c:1468
      #12 0x564785caac44 in do_simple_func /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:95
      #13 0x564785cc18f0 in cmd_func(cmd_list_element*, char const*, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2735
      #14 0x564787c70c68 in execute_command(char const*, int) /tmp/src/binutils-gdb/gdb/top.c:574
      #15 0x564786686180 in command_handler(char const*) /tmp/src/binutils-gdb/gdb/event-top.c:543
      #16 0x56478668752f in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /tmp/src/binutils-gdb/gdb/event-top.c:779
      #17 0x564787dcb29a in tui_command_line_handler /tmp/src/binutils-gdb/gdb/tui/tui-interp.c:104
      #18 0x56478668443d in gdb_rl_callback_handler /tmp/src/binutils-gdb/gdb/event-top.c:250
      #19 0x7f4efd506246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)
      #20 0x564786683dea in gdb_rl_callback_read_char_wrapper_noexcept /tmp/src/binutils-gdb/gdb/event-top.c:192
      #21 0x564786684042 in gdb_rl_callback_read_char_wrapper /tmp/src/binutils-gdb/gdb/event-top.c:225
      #22 0x564787f1b119 in stdin_event_handler /tmp/src/binutils-gdb/gdb/ui.c:155
      #23 0x56478862438d in handle_file_event /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:573
      #24 0x564788624d23 in gdb_wait_for_event /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:694
      #25 0x56478862297c in gdb_do_one_event(int) /tmp/src/binutils-gdb/gdbsupport/event-loop.cc:264
      #26 0x564786df99f0 in start_event_loop /tmp/src/binutils-gdb/gdb/main.c:412
      #27 0x564786dfa069 in captured_command_loop /tmp/src/binutils-gdb/gdb/main.c:476
      #28 0x564786dff61f in captured_main /tmp/src/binutils-gdb/gdb/main.c:1320
      #29 0x564786dff75c in gdb_main(captured_main_args*) /tmp/src/binutils-gdb/gdb/main.c:1339
      #30 0x564785381b6d in main /tmp/src/binutils-gdb/gdb/gdb.c:32
      #31 0x7f4efbc3984f  (/usr/lib/libc.so.6+0x2384f) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
      #32 0x7f4efbc39909 in __libc_start_main (/usr/lib/libc.so.6+0x23909) (BuildId: 2f005a79cd1a8e385972f5a102f16adba414d75e)
      #33 0x564785381934 in _start (/tmp/build/binutils-gdb/gdb/gdb+0xabc5934) (BuildId: 90de353ac158646e7dab501b76a18a76628fca33)

  0x603000068034 is located 0 bytes after 20-byte region [0x603000068020,0x603000068034) allocated by thread T0 here:
      #0 0x7f4efcee0cd1 in __interceptor_calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
      #1 0x5647856265d8 in xcalloc /tmp/src/binutils-gdb/gdb/alloc.c:97
      #2 0x564788610c6b in xzalloc(unsigned long) /tmp/src/binutils-gdb/gdbsupport/common-utils.cc:29
      #3 0x56478815721a in value::allocate_contents(bool) /tmp/src/binutils-gdb/gdb/value.c:929
      #4 0x564788157285 in value::allocate(type*, bool) /tmp/src/binutils-gdb/gdb/value.c:941
      #5 0x56478815733a in value::allocate(type*) /tmp/src/binutils-gdb/gdb/value.c:951
      #6 0x5647854ae81c in expr::ada_string_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:10675
      #7 0x5647854b63b8 in expr::ada_funcall_operation::evaluate(type*, expression*, noside) /tmp/src/binutils-gdb/gdb/ada-lang.c:11184
      #8 0x564786658266 in expression::evaluate(type*, noside) /tmp/src/binutils-gdb/gdb/eval.c:111
      #9 0x5647871242d6 in process_print_command_args /tmp/src/binutils-gdb/gdb/printcmd.c:1322
      #10 0x5647871244b3 in print_command_1 /tmp/src/binutils-gdb/gdb/printcmd.c:1335
      #11 0x564787125384 in print_command /tmp/src/binutils-gdb/gdb/printcmd.c:1468
      #12 0x564785caac44 in do_simple_func /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:95
      #13 0x564785cc18f0 in cmd_func(cmd_list_element*, char const*, int) /tmp/src/binutils-gdb/gdb/cli/cli-decode.c:2735
      #14 0x564787c70c68 in execute_command(char const*, int) /tmp/src/binutils-gdb/gdb/top.c:574
      #15 0x564786686180 in command_handler(char const*) /tmp/src/binutils-gdb/gdb/event-top.c:543
      #16 0x56478668752f in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) /tmp/src/binutils-gdb/gdb/event-top.c:779
      #17 0x564787dcb29a in tui_command_line_handler /tmp/src/binutils-gdb/gdb/tui/tui-interp.c:104
      #18 0x56478668443d in gdb_rl_callback_handler /tmp/src/binutils-gdb/gdb/event-top.c:250
      #19 0x7f4efd506246 in rl_callback_read_char (/usr/lib/libreadline.so.8+0x3b246) (BuildId: 092e91fc4361b0ef94561e3ae03a75f69398acbb)

The problem is in cli/cli-cmds.c, in the function setting_cmd, where
we do this:

  const char *a0 = (const char *) argv[0]->contents ().data ();

Here argv[0] is a value* which we know is either a TYPE_CODE_ARRAY or
a TYPE_CODE_STRING.  The problem is that the above line is casting the
value contents directly to a C-string, i.e. one that is assumed to
have a null-terminator at the end.

After the above commit this can no longer be assumed to be true.  A
string value will be represented just as it would be in the current
language, so for Ada and Fortran the string will be an array of
characters with no null-terminator at the end.

My proposed solution is to copy the string contents into a std::string
object, and then use the std::string::c_str() value, this will ensure
that a null-terminator has been added.

I had a check through GDB at places TYPE_CODE_STRING was used and
couldn't see any other obvious places where this type of assumption
was being made, so hopefully this is the only offender.

Running the above test with ASan compiled in no longer gives an error.

Reviewed-By: Tom Tromey <[email protected]>
palves pushed a commit that referenced this issue Feb 20, 2024
Expect a `.MIPS.options' section alternatively to `.reginfo' and ignore
contents of either as irrelevant for all the affected compact EH tests,
removing these regressions:

mips64-openbsd  -FAIL: Compact EH EB #1 with personality ID and FDE data
mips64-openbsd  -FAIL: Compact EH EB #2 with personality routine and FDE data
mips64-openbsd  -FAIL: Compact EH EB #3 with personality id and large FDE data
mips64-openbsd  -FAIL: Compact EH EB #4 with personality id, FDE data and LSDA
mips64-openbsd  -FAIL: Compact EH EB #5 with personality routine, FDE data and LSDA
mips64-openbsd  -FAIL: Compact EH EB #6 with personality id, LSDA and large FDE data
mips64-openbsd  -FAIL: Compact EH EL #1 with personality ID and FDE data
mips64-openbsd  -FAIL: Compact EH EL #2 with personality routine and FDE data
mips64-openbsd  -FAIL: Compact EH EL #3 with personality id and large FDE data
mips64-openbsd  -FAIL: Compact EH EL #4 with personality id, FDE data and LSDA
mips64-openbsd  -FAIL: Compact EH EL #5 with personality routine, FDE data and LSDA
mips64-openbsd  -FAIL: Compact EH EL #6 with personality id, LSDA and large FDE data
mips64el-openbsd  -FAIL: Compact EH EB #1 with personality ID and FDE data
mips64el-openbsd  -FAIL: Compact EH EB #2 with personality routine and FDE data
mips64el-openbsd  -FAIL: Compact EH EB #3 with personality id and large FDE data
mips64el-openbsd  -FAIL: Compact EH EB #4 with personality id, FDE data and LSDA
mips64el-openbsd  -FAIL: Compact EH EB #5 with personality routine, FDE data and LSDA
mips64el-openbsd  -FAIL: Compact EH EB #6 with personality id, LSDA and large FDE data
mips64el-openbsd  -FAIL: Compact EH EL #1 with personality ID and FDE data
mips64el-openbsd  -FAIL: Compact EH EL #2 with personality routine and FDE data
mips64el-openbsd  -FAIL: Compact EH EL #3 with personality id and large FDE data
mips64el-openbsd  -FAIL: Compact EH EL #4 with personality id, FDE data and LSDA
mips64el-openbsd  -FAIL: Compact EH EL #5 with personality routine, FDE data and LSDA
mips64el-openbsd  -FAIL: Compact EH EL #6 with personality id, LSDA and large FDE data

Co-Authored-By: Maciej W. Rozycki <[email protected]>

	gas/
	* testsuite/gas/mips/compact-eh-eb-1.d: Accept `.MIPS.options'
	section as an alternative to `.reginfo' and ignore contents of
	either.
	* testsuite/gas/mips/compact-eh-eb-2.d: Likewise.
	* testsuite/gas/mips/compact-eh-eb-3.d: Likewise.
	* testsuite/gas/mips/compact-eh-eb-4.d: Likewise.
	* testsuite/gas/mips/compact-eh-eb-5.d: Likewise.
	* testsuite/gas/mips/compact-eh-eb-6.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-1.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-2.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-3.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-4.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-5.d: Likewise.
	* testsuite/gas/mips/compact-eh-el-6.d: Likewise.
palves pushed a commit that referenced this issue Feb 20, 2024
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
palves pushed a commit that referenced this issue Feb 20, 2024
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 <[email protected]>

PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
palves pushed a commit that referenced this issue Feb 20, 2024
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 <[email protected]>

PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
palves pushed a commit that referenced this issue Feb 20, 2024
…s_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 <[email protected]>

PR symtab/30392
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30392
palves pushed a commit that referenced this issue Feb 20, 2024
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
palves pushed a commit that referenced this issue Feb 20, 2024
…g_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
palves pushed a commit that referenced this issue Feb 20, 2024
It was pointed out on the mailing list[1] that after this commit:

  commit b1e0126
  Date:   Wed Jun 21 14:18:54 2023 +0100

      gdb: don't resume vfork parent while child is still running

the test gdb.base/vfork-follow-parent.exp now has some failures when
run with the native-gdbserver or native-extended-gdbserver boards:

  FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to end of inferior 2 (timeout)
  FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: inferior 1 (timeout)
  FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: print unblock_parent = 1 (timeout)
  FAIL: gdb.base/vfork-follow-parent.exp: resolution_method=schedule-multiple: continue to break_parent (timeout)

The reason that these failures don't show up when run on the standard
unix board is that the test is only run in the default operating mode,
so for Linux this will be all-stop on top of non-stop.

If we adjust the test script so that it runs in the default mode and
with target-non-stop turned off, then we see the same failures on the
unix board.  This commit includes this change.

The way that the test is written means that it is not (currently)
possible to turn on non-stop mode and have the test still work, so
this commit does not do that.

I have also updated the test script so that the vfork child performs
an exec as well as the current exit.  Exec and exit are the two ways
in which a vfork child can release the vfork parent, so testing both
of these cases is useful I think.

In this test the inferior performs a vfork and the vfork-child
immediately exits.  The vfork-parent will wait for the vfork-child and
then blocks waiting for gdb.  Once gdb has released the vfork-parent,
the vfork-parent also exits.

In the test that fails, GDB sets 'detach-on-fork off' and then runs to
the vfork.  At this point the test tries to just "continue", but this
fails as the vfork-parent is still selected, and the parent can't
continue until the vfork-child completes.  As the vfork-child is
stopped by GDB the parent will never stop once resumed, so GDB refuses
to resume it.

The test script then sets 'schedule-multiple on' and once again
continues.  This time GDB, in theory, resumes both the parent and the
child, the parent will be held blocked by the kernel, but the child
will run until it exits, and which point GDB stops again, this time
with inferior 2, the newly exited vfork-child, selected.

What happens after this in the test script is irrelevant as far as
this failure is concerned.

To understand why the test started failing we should consider the
behaviour of four different cases:

  1. All-stop-on-non-stop before commit b1e0126,

  2. All-stop-on-non-stop after commit b1e0126,

  3. All-stop-on-all-stop before commit b1e0126, and

  4. All-stop-on-all-stop after commit b1e0126.

Only case #4 is failing after commit b1e0126, but I think the
other cases are interesting because, (a) they inform how we might fix
the regression, and (b) it turns out the behaviour of #2 changed too
with the commit, but the change was harmless.

For #1 All-stop-on-non-stop before commit b1e0126, what happens
is:

  1. GDB calls proceed with the vfork-parent selected, as schedule
     multiple is on user_visible_resume_ptid returns -1 (everything)
     as the resume_ptid (see proceed function),

  2. As this is all-stop-on-non-stop, every thread is resumed
    individually, so GDB tries to resume both the vfork-parent and the
    vfork-child, both of which succeed,

  3. The vfork-parent is held stopped by the kernel,

  4. The vfork-child completes (exits) at which point the GDB sees the
     EXITED event for the vfork-child and the VFORK_DONE event for the
     vfork-parent,

  5. At this point we might take two paths depending on which event
     GDB handles first, if GDB handles the VFORK_DONE first then:

     (a) As GDB is controlling both parent and child the VFORK_DONE is
         ignored (see handle_vfork_done), the vfork-parent will be
	 resumed,

     (b) GDB processes the EXITED event, selects the (now defunct)
         vfork-child, and stops, returning control to the user.

     Alternatively, if GDB selects the EXITED event first then:

     (c) GDB processes the EXITED event, selects the (now defunct)
         vfork-child, and stops, returning control to the user.

     (d) At some future time the user resumes the vfork-parent, at
         which point the VFORK_DONE is reported to GDB, however, GDB
	 is ignoring the VFORK_DONE (see handle_vfork_done), so the
	 parent is resumed.

For case #2, all-stop-on-non-stop after commit b1e0126, the
important difference is in step (2) above, now, instead of resuming
both the vfork-parent and the vfork-child, only the vfork-child is
resumed.  As such, when we get to step (5), only a single event, the
EXITED event is reported.

GDB handles the EXITED just as in (5)(c), then, later, when the user
resumes the vfork-parent, the VFORKED_DONE is immediately delivered
from the kernel, but this is ignored just as in (5)(d), and so,
though the pattern of when the vfork-parent is resumed changes, the
overall pattern of which events are reported and when, doesn't
actually change.  In fact, by not resuming the vfork-parent, the order
of events (in this test) is now deterministic, which (maybe?) is a
good thing.

If we now consider case #3, all-stop-on-all-stop before commit
b1e0126, then what happens is:

  1. GDB calls proceed with the vfork-parent selected, as schedule
     multiple is on user_visible_resume_ptid returns -1 (everything)
     as the resume_ptid (see proceed function),

  2. As this is all-stop-on-all-stop, the resume is passed down to the
     linux-nat target, the vfork-parent is the event thread, while the
     vfork-child is a sibling of the event thread,

  3. In linux_nat_target::resume, GDB calls linux_nat_resume_callback
     for all threads, this causes the vfork-child to be resumed.  Then
     in linux_nat_target::resume, the event thread, the vfork-parent,
     is also resumed.

  4. The vfork-parent is held stopped by the kernel,

  5. The vfork-child completes (exits) at which point the GDB sees the
     EXITED event for the vfork-child and the VFORK_DONE event for the
     vfork-parent,

  6. We are now in a situation identical to step (5) as for
     all-stop-on-non-stop above, GDB selects one of the events to
     handle, and whichever we select the user sees the correct
     behaviour.

And so, finally, we can consider #4, all-stop-on-all-stop after commit
b1e0126, this is the case that started failing.

We start out just like above, in proceed, the resume_ptid is
-1 (resume everything), due to schedule multiple being on.  And just
like above, due to the target being all-stop, we call
proceed_resume_thread_checked just once, for the current thread,
which, remember, is the vfork-parent thread.

The change in commit b1e0126 was to avoid resuming a vfork-parent
thread, read the commit message for the justification for this change.

However, this means that GDB now rejects resuming the vfork-parent in
this case, which means that nothing gets resumed!  Obviously, if
nothing resumes, then nothing will ever stop, and so GDB appears to
hang.

I considered a couple of solutions which, in the end, I didn't go
with, these were:

  1. Move the vfork-parent check out of proceed_resume_thread_checked,
     and place it in proceed, but only on the all-stop-on-non-stop
     path, this should still address the issue seen in b1e0126,
     but would avoid the issue seen here.  I rejected this just
     because it didn't feel great to split the checks that exist in
     proceed_resume_thread_checked like this,

  2. Extend the condition in proceed_resume_thread_checked by adding a
     target_is_non_stop_p check.  This would have the same effect as
     idea 1, but leaves all the checks in the same place, which I
     think would be better, but this still just didn't feel right to
     me, and so,

What I noticed was that for the all-stop-on-non-stop, after commit
b1e0126, we only resumed the vfork-child, and this seems fine.
The vfork-parent isn't going to run anyway (the kernel will hold it
back), so if feels like we there's no harm in just waiting for the
child to complete, and then resuming the parent.

So then I started looking at follow_fork, which is called from the top
of proceed.  This function already has the task of switching between
the parent and child based on which the user wishes to follow.  So, I
wondered, could we use this to switch to the vfork-child in the case
that we are attached to both?

Turns out this is pretty simple to do.

Having done that, now the process is for all-stop-on-all-stop after
commit b1e0126, and with this new fix is:

  1. GDB calls proceed with the vfork-parent selected, but,

  2. In follow_fork, and follow_fork_inferior, GDB switches the
     selected thread to be that of the vfork-child,

  3. Back in proceed user_visible_resume_ptid returns -1 (everything)
     as the resume_ptid still, but now,

  4. When GDB calls proceed_resume_thread_checked, the vfork-child is
     the current selected thread, this is not a vfork-parent, and so
     GDB allows the proceed to continue to the linux-nat target,

  5. In linux_nat_target::resume, GDB calls linux_nat_resume_callback
     for all threads, this does not resume the vfork-parent (because
     it is a vfork-parent), and then the vfork-child is resumed as
     this is the event thread,

At this point we are back in the same situation as for
all-stop-on-non-stop after commit b1e0126, that is, the
vfork-child is resumed, while the vfork-parent is held stopped by
GDB.

Eventually the vfork-child will exit or exec, at which point the
vfork-parent will be resumed.

[1] https://inbox.sourceware.org/gdb-patches/[email protected]/
palves added a commit that referenced this issue Feb 20, 2024
After running a number of programs under Windows gdb and detaching
them, I typed run in gdb, and got a hang, here:

 (top-gdb) bt
 #0  sharing_input_terminal (pid=4672) at /home/pedro/gdb/src/gdb/mingw-hdep.c:388
 #1  0x00007ff71a2d8678 in sharing_input_terminal (inf=0x23bf23dafb0) at /home/pedro/gdb/src/gdb/inflow.c:269
 #2  0x00007ff71a2d887b in child_terminal_save_inferior (self=0x23bf23de060) at /home/pedro/gdb/src/gdb/inflow.c:423
 #3  0x00007ff71a2c80c0 in inf_child_target::terminal_save_inferior (this=0x23bf23de060) at /home/pedro/gdb/src/gdb/inf-child.c:111
 #4  0x00007ff71a429c0f in target_terminal_is_ours_kind (desired_state=target_terminal_state::is_ours_for_output) at /home/pedro/gdb/src/gdb/target.c:1037
 #5  0x00007ff71a429e02 in target_terminal::ours_for_output () at /home/pedro/gdb/src/gdb/target.c:1094
 #6  0x00007ff71a2ccc8e in post_create_inferior (from_tty=0) at /home/pedro/gdb/src/gdb/infcmd.c:245
 #7  0x00007ff71a2cd431 in run_command_1 (args=0x0, from_tty=0, run_how=RUN_NORMAL) at /home/pedro/gdb/src/gdb/infcmd.c:502
 #8  0x00007ff71a2cd58b in run_command (args=0x0, from_tty=0) at /home/pedro/gdb/src/gdb/infcmd.c:527

The problem is that the loop around GetConsoleProcessList looped
forever, because there were exactly 10 processes to return.
GetConsoleProcessList's documentation says:

  If the buffer is too small to hold all the valid process identifiers,
  the return value is the required number of array elements. The
  function will have stored no identifiers in the buffer. In this
  situation, use the return value to allocate a buffer that is large
  enough to store the entire list and call the function again.

In this case, the buffer wasn't too small, it was exactly the right
size, so we should have broken out of the loop.  We didn't due to a
"<" check that should have been "<=".  That is fixed by this patch.

Approved-By: Tom Tromey <[email protected]>
Reviewed-By: Eli Zaretskii <[email protected]>
Change-Id: I14e4909f2ac2fa83d0d9b6e64418b5831ac4e4e3
palves pushed a commit that referenced this issue Feb 20, 2024
This commit fixes an issue that was discovered while writing the tests
for the previous commit.

I noticed that, when GDB restarts an inferior, the executable_changed
event would trigger twice.  The first notification would originate
from:

  #0  exec_file_attach (filename=0x4046680 "/tmp/hello.x", from_tty=0) at ../../src/gdb/exec.c:513
  #1  0x00000000006f3adb in reopen_exec_file () at ../../src/gdb/corefile.c:122
  #2  0x0000000000e6a3f2 in generic_mourn_inferior () at ../../src/gdb/target.c:3682
  #3  0x0000000000995121 in inf_child_target::mourn_inferior (this=0x2fe95c0 <the_amd64_linux_nat_target>) at ../../src/gdb/inf-child.c:192
  #4  0x0000000000995cff in inf_ptrace_target::mourn_inferior (this=0x2fe95c0 <the_amd64_linux_nat_target>) at ../../src/gdb/inf-ptrace.c:125
  #5  0x0000000000a32472 in linux_nat_target::mourn_inferior (this=0x2fe95c0 <the_amd64_linux_nat_target>) at ../../src/gdb/linux-nat.c:3609
  #6  0x0000000000e68a40 in target_mourn_inferior (ptid=...) at ../../src/gdb/target.c:2761
  #7  0x0000000000a323ec in linux_nat_target::kill (this=0x2fe95c0 <the_amd64_linux_nat_target>) at ../../src/gdb/linux-nat.c:3593
  #8  0x0000000000e64d1c in target_kill () at ../../src/gdb/target.c:924
  #9  0x00000000009a19bc in kill_if_already_running (from_tty=1) at ../../src/gdb/infcmd.c:328
  #10 0x00000000009a1a6f in run_command_1 (args=0x0, from_tty=1, run_how=RUN_STOP_AT_MAIN) at ../../src/gdb/infcmd.c:381
  #11 0x00000000009a20a5 in start_command (args=0x0, from_tty=1) at ../../src/gdb/infcmd.c:527
  #12 0x000000000068dc5d in do_simple_func (args=0x0, from_tty=1, c=0x35c7200) at ../../src/gdb/cli/cli-decode.c:95

While the second originates from:

  #0  exec_file_attach (filename=0x3d7a1d0 "/tmp/hello.x", from_tty=0) at ../../src/gdb/exec.c:513
  #1  0x0000000000dfe525 in reread_symbols (from_tty=1) at ../../src/gdb/symfile.c:2517
  #2  0x00000000009a1a98 in run_command_1 (args=0x0, from_tty=1, run_how=RUN_STOP_AT_MAIN) at ../../src/gdb/infcmd.c:398
  #3  0x00000000009a20a5 in start_command (args=0x0, from_tty=1) at ../../src/gdb/infcmd.c:527
  #4  0x000000000068dc5d in do_simple_func (args=0x0, from_tty=1, c=0x35c7200) at ../../src/gdb/cli/cli-decode.c:95

In the first case the call to exec_file_attach first passes through
reopen_exec_file.  The reopen_exec_file performs a modification time
check on the executable file, and only calls exec_file_attach if the
executable has changed on disk since it was last loaded.

However, in the second case things work a little differently.  In this
case GDB is really trying to reread the debug symbol.  As such, we
iterate over the objfiles list, and for each of those we check the
modification time, if the file on disk has changed then we reload the
debug symbols from that file.

However, there is an additional check, if the objfile has the same
name as the executable then we will call exec_file_attach, but we do
so without checking the cached modification time that indicates when
the executable was last reloaded, as a result, we reload the
executable twice.

In this commit I propose that reread_symbols be changed to
unconditionally call reopen_exec_file before performing the objfile
iteration.  This will ensure that, if the executable has changed, then
the executable will be reloaded, however, if the executable has
already been recently reloaded, we will not reload it for a second
time.

After handling the executable, GDB can then iterate over the objfiles
list and reload them in the normal way.

With this done I now see the executable reloaded only once when GDB
restarts an inferior, which means I can remove the kfail that I added
to the gdb.python/py-exec-file.exp test in the previous commit.

Approved-By: Tom Tromey <[email protected]>
palves pushed a commit that referenced this issue Feb 20, 2024
It was pointed out on the mailing list that a recently added
test (gdb.python/py-progspace-events.exp) was failing when run with
the native-extended-gdbserver board.  This test was added with this
commit:

  commit 59912fb
  Date:   Tue Sep 19 11:45:36 2023 +0100

      gdb: add Python events for program space addition and removal

It turns out though that the test is failing due to a existing bug
in GDB, the new test just exposes the problem.  Additionally, the
failure really doesn't even rely on the new functionality added in the
above commit.  I reduced the test to a simple set of steps that
reproduced the failure and tested against GDB 13, and the test passes;
so the bug was introduced since then.  In fact, the bug was introduced
with this commit:

  commit a282736
  Date:   Fri Sep 8 15:48:16 2023 +0100

      gdb: remove final user of the executable_changed observer

This commit changed how the per-inferior auxv data cache is managed,
specifically, when the cache is cleared, and it is this that leads to
the failure.

This bug is interesting because it exposes a number of issues with
GDB, I'll explain all of the problems I see, though ultimately, I only
propose fixing one problem in this commit, which is enough to resolve
the crash we are currently seeing.

The crash that we are seeing manifests like this:

  ...
  [Inferior 2 (process 3970384) exited normally]
  +inferior 1
  [Switching to inferior 1 [process 3970383] (/tmp/build/gdb/testsuite/outputs/gdb.python/py-progspace-events/py-progspace-events)]
  [Switching to thread 1.1 (Thread 3970383.3970383)]
  #0  breakpt () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.python/py-progspace-events.c:28
  28	{ /* Nothing.  */ }
  (gdb) step
  +step
  terminate called after throwing an instance of 'gdb_exception_error'

  Fatal signal: Aborted
  ... etc ...

What's happening is that GDB attempts to refill the auxv cache as a
result of the gdbarch_has_shared_address_space call in
program_space::~program_space, the backtrace looks like this:

  #0  0x00007fb4f419a9a5 in raise () from /lib64/libpthread.so.0
  #1  0x00000000008b635d in handle_fatal_signal (sig=6) at ../../src/gdb/event-top.c:912
  #2  <signal handler called>
  #3  0x00007fb4f38e3625 in raise () from /lib64/libc.so.6
  #4  0x00007fb4f38cc8d9 in abort () from /lib64/libc.so.6
  #5  0x00007fb4f3c70756 in __gnu_cxx::__verbose_terminate_handler() [clone .cold] () from /lib64/libstdc++.so.6
  #6  0x00007fb4f3c7c6dc in __cxxabiv1::__terminate(void (*)()) () from /lib64/libstdc++.so.6
  #7  0x00007fb4f3c7b6e9 in __cxa_call_terminate () from /lib64/libstdc++.so.6
  #8  0x00007fb4f3c7c094 in __gxx_personality_v0 () from /lib64/libstdc++.so.6
  #9  0x00007fb4f3a80c63 in _Unwind_RaiseException_Phase2 () from /lib64/libgcc_s.so.1
  #10 0x00007fb4f3a8154e in _Unwind_Resume () from /lib64/libgcc_s.so.1
  #11 0x0000000000e8832d in target_read_alloc_1<unsigned char> (ops=0x408a3a0, object=TARGET_OBJECT_AUXV, annex=0x0) at ../../src/gdb/target.c:2266
  #12 0x0000000000e73dea in target_read_alloc (ops=0x408a3a0, object=TARGET_OBJECT_AUXV, annex=0x0) at ../../src/gdb/target.c:2315
  #13 0x000000000058248c in target_read_auxv_raw (ops=0x408a3a0) at ../../src/gdb/auxv.c:379
  #14 0x000000000058243d in target_read_auxv () at ../../src/gdb/auxv.c:368
  #15 0x000000000058255c in target_auxv_search (match=0x0, valp=0x7ffdee17c598) at ../../src/gdb/auxv.c:415
  #16 0x0000000000a464bb in linux_is_uclinux () at ../../src/gdb/linux-tdep.c:433
  #17 0x0000000000a464f6 in linux_has_shared_address_space (gdbarch=0x409a2d0) at ../../src/gdb/linux-tdep.c:440
  #18 0x0000000000510eae in gdbarch_has_shared_address_space (gdbarch=0x409a2d0) at ../../src/gdb/gdbarch.c:4889
  #19 0x0000000000bc7558 in program_space::~program_space (this=0x4544aa0, __in_chrg=<optimized out>) at ../../src/gdb/progspace.c:124
  #20 0x00000000009b245d in delete_inferior (inf=0x47b3de0) at ../../src/gdb/inferior.c:290
  #21 0x00000000009b2c10 in prune_inferiors () at ../../src/gdb/inferior.c:480
  #22 0x00000000009c5e3e in fetch_inferior_event () at ../../src/gdb/infrun.c:4558
  #23 0x000000000099b4dc in inferior_event_handler (event_type=INF_REG_EVENT) at ../../src/gdb/inf-loop.c:42
  #24 0x0000000000cbc64f in remote_async_serial_handler (scb=0x4090a30, context=0x408a6b0) at ../../src/gdb/remote.c:14859
  #25 0x0000000000d83d3a in run_async_handler_and_reschedule (scb=0x4090a30) at ../../src/gdb/ser-base.c:138
  #26 0x0000000000d83e1f in fd_event (error=0, context=0x4090a30) at ../../src/gdb/ser-base.c:189

So this is problem #1, if we throw an exception while deleting a
program_space then this is not caught, and is going to crash GDB.

Problem #2 becomes evident when we ask why GDB is throwing an error in
this case; the error is thrown because the remote target, operating in
non-async mode, can't read the auxv data while an inferior is running
and GDB is waiting for a stop reply.  The problem here then, is why
does GDB get into a position where it tries to interact with the
remote target in this way, at this time?  The problem is caused by the
prune_inferiors call which can be seen in the above backtrace.

In prune_inferiors we check if the inferior is deletable, and if it
is, we delete it.  The problem is, I think, we should also check if
the target is currently in a state that would allow us to delete the
inferior.  We don't currently have such a check available, we'd need
to add one, but for the remote target, this would return false if the
remote is in async mode and the remote is currently waiting for a stop
reply.  With this change in place GDB would defer deleting the
inferior until the remote target has stopped, at which point GDB would
be able to refill the auxv cache successfully.

And then, problem #3 becomes evident when we ask why GDB is needing to
refill the auxv cache now when it didn't need to for GDB 13.  This is
where the second commit mentioned above (a282736) comes in.
Prior to this commit, the auxv cache was cleared by the
executable_changed observer, while after that commit the auxv cache
was cleared by the new_objfile observer -- but only when the
new_objfile observer is used in the special mode that actually means
that all objfiles have been unloaded (I know, the overloading of the
new_objfile observer is horrible, and unnecessary, but it's not really
important for this bug).

The difference arises because the new_objfile observer is triggered
from clear_symtab_users, which in turn is called from
program_space::~program_space.  The new_objfile observer for auxv does
this:

  static void
  auxv_new_objfile_observer (struct objfile *objfile)
  {
    if (objfile == nullptr)
      invalidate_auxv_cache_inf (current_inferior ());
  }

That is, when all the objfiles are unloaded, we clear the auxv cache
for the current inferior.

The problem is, then when we look at the prune_inferiors ->
delete_inferior -> ~program_space path, we see that the current
inferior is not going to be an inferior that exists within the
program_space being deleted; delete_inferior removes the deleted
inferior from the global inferior list, and then only deletes the
program_space if program_space::empty() returns true, which is only
the case if the current inferior isn't within the program_space to
delete, and no other inferior exists within that program_space
either.

What this means is that when the new_objfile observer is called we
can't rely on the current inferior having any relationship with the
program space in which the objfiles were removed.  This was an error
in the commit a282736, the only thing we can rely on is the
current program space.  As a result of this mistake, after commit
a282736, GDB was sometimes clearing the auxv cache for a random
inferior.  In the native target case this was harmless as we can
always refill the cache when needed, but in the remote target case, if
we need to refill the cache when the remote target is executing, then
we get the crash we observed.

And additionally, if we think about this a little more, we see that
commit a282736 made another mistake.  When all the objfiles are
removed, they are removed from a program_space, a program_space might
contain multiple inferiors, so surely, we should clear the auxv cache
for all of the matching inferiors?

Given these two insights, that the current_inferior is not relevant,
only the current_program_space, and that we should be clearing the
cache for all inferiors in the current_program_space, we can update
auxv_new_objfile_observer to:

  if (objfile == nullptr)
    {
      for (inferior *inf : all_inferiors ())
	{
	  if (inf->pspace == current_program_space)
	    invalidate_auxv_cache_inf (inf);
	}
    }

With this change we now correctly clear the auxv cache for the correct
inferiors, and GDB no longer needs to refill the cache at an
inconvenient time, this avoids the crash we were seeing.

And finally, we reach problem #4.  Inspired by the observation that
using the current_inferior from within the ~program_space function was
not correct, I added some debug to see if current_inferior() was
called anywhere else (below ~program_space), and the answer is yes,
it's called a often.  Mostly the culprit is GDB doing:

  current_inferior ()->top_target ()-> ....

But I think all of these calls are most likely doing the wrong thing,
and only work because the top target in all these cases is shared
between all inferiors, e.g. it's the native target, or the remote
target for all inferiors.  But if we had a truly multi-connection
setup, then we might start to see odd behaviour.

Problem #1 I'm just ignoring for now, I guess at some point we might
run into this again, and then we'd need to solve this.  But in this
case I wasn't sure what a "good" solution would look like.  We need
the auxv data in order to implement the linux_is_uclinux() function.
If we can't get the auxv data then what should we do, assume yes, or
assume no?  The right answer would probably be to propagate the error
back up the stack, but then we reach ~program_space, and throwing
exceptions from a destructor is problematic, so we'd need to catch and
deal at this point.  The linux_is_uclinux() call is made from within
gdbarch_has_shared_address_space(), which is used like:

  if (!gdbarch_has_shared_address_space (target_gdbarch ()))
    delete this->aspace;

So, we would have to choose; delete the address space or not.  If we
delete it on error, then we might delete an address space that is
shared within another program space.  If we don't delete the address
space, then we might leak it.  Neither choice is great.

A better solution might be to have the address spaces be reference
counted, then we could remove the gdbarch_has_shared_address_space
call completely, and just rely on the reference count to auto-delete
the address space when appropriate.

The solution for problem #2 I already hinted at above, we should have
a new target_can_delete_inferiors() call, which should be called from
prune_inferiors, this would prevent GDB from trying to delete
inferiors when a (remote) target is in a state where we know it can't
delete the inferior.  Deleting an inferior often (always?) requires
sending packets to the remote, and if the remote is waiting for a stop
reply then this will never work, so the pruning should be deferred in
this case.

The solution for problem #3 is included in this commit.

And, for problem #4, I'm not sure what the right solution is.  Maybe
delete_inferior should ensure the inferior to be deleted is in place
when ~program_space is called?  But that seems a little weird, as the
current inferior would, in theory, still be using the current
program_space...

Anyway, after this commit, the gdb.python/py-progspace-events.exp test
now passes when run with the native-extended-remote board.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30935
Approved-By: Simon Marchi <[email protected]>
Change-Id: I41f0e6e2d7ecc1e5e55ec170f37acd4052f46eaf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant