4 commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
Pedro Alves
|
8d707a12ef |
gdb/18216: displaced step+deliver signal, a thread needs step-over, crash
The problem is that with hardware step targets and displaced stepping, "signal FOO" when stopped at a breakpoint steps the breakpoint instruction at the same time it delivers a signal. This results in tp->stepped_breakpoint set, but no step-resume breakpoint set. When the next stop event arrives, GDB crashes. Irrespective of whether we should do something more/different to step past the breakpoint in this scenario (e.g., PR 18225), it's just wrong to assume there'll be a step-resume breakpoint set (and was not the original intention). gdb/ChangeLog: 2015-04-10 Pedro Alves <palves@redhat.com> PR gdb/18216 * infrun.c (process_event_stop_test): Don't assume a step-resume is set if tp->stepped_breakpoint is true. gdb/testsuite/ChangeLog: 2015-04-10 Pedro Alves <palves@redhat.com> PR gdb/18216 * gdb.threads/multiple-step-overs.exp: Remove expected eof. |
||
Pedro Alves
|
f3770638ca |
Add test for PR18214 and PR18216 - multiple step-overs with queued signals
Both PRs are triggered by the same use case. PR18214 is about software single-step targets. On those, the 'resume' code that detects that we're stepping over a breakpoint and delivering a signal at the same time: /* Currently, our software single-step implementation leads to different results than hardware single-stepping in one situation: when stepping into delivering a signal which has an associated signal handler, hardware single-step will stop at the first instruction of the handler, while software single-step will simply skip execution of the handler. ... Fortunately, we can at least fix this particular issue. We detect here the case where we are about to deliver a signal while software single-stepping with breakpoints removed. In this situation, we revert the decisions to remove all breakpoints and insert single- step breakpoints, and instead we install a step-resume breakpoint at the current address, deliver the signal without stepping, and once we arrive back at the step-resume breakpoint, actually step over the breakpoint we originally wanted to step over. */ doesn't handle the case of _another_ thread also needing to step over a breakpoint. Because the other thread is just resumed at the PC where it had stopped and a breakpoint is still inserted there, the thread immediately re-traps the same breakpoint. This test exercises that. On software single-step targets, it fails like this: KFAIL: gdb.threads/multiple-step-overs.exp: displaced=off: signal thr3: continue to sigusr1_handler KFAIL: gdb.threads/multiple-step-overs.exp: displaced=off: signal thr2: continue to sigusr1_handler gdb.log (simplified): (gdb) continue Continuing. Breakpoint 4, child_function_2 (arg=0x0) at src/gdb/testsuite/gdb.threads/multiple-step-overs.c:66 66 callme (); /* set breakpoint thread 2 here */ (gdb) thread 3 (gdb) queue-signal SIGUSR1 (gdb) thread 1 [Switching to thread 1 (Thread 0x7ffff7fc1740 (LWP 24824))] #0 main () at src/gdb/testsuite/gdb.threads/multiple-step-overs.c:106 106 wait_threads (); /* set wait-threads breakpoint here */ (gdb) break sigusr1_handler Breakpoint 5 at 0x400837: file src/gdb/testsuite/gdb.threads/multiple-step-overs.c, line 31. (gdb) continue Continuing. [Switching to Thread 0x7ffff7fc0700 (LWP 24828)] Breakpoint 4, child_function_2 (arg=0x0) at src/gdb/testsuite/gdb.threads/multiple-step-overs.c:66 66 callme (); /* set breakpoint thread 2 here */ (gdb) KFAIL: gdb.threads/multiple-step-overs.exp: displaced=off: signal thr3: continue to sigusr1_handler For good measure, I made the test try displaced stepping too. And then I found it crashes GDB on x86-64 (a hardware step target), but only when displaced stepping... : KFAIL: gdb.threads/multiple-step-overs.exp: displaced=on: signal thr1: continue to sigusr1_handler (PRMS: gdb/18216) KFAIL: gdb.threads/multiple-step-overs.exp: displaced=on: signal thr2: continue to sigusr1_handler (PRMS: gdb/18216) KFAIL: gdb.threads/multiple-step-overs.exp: displaced=on: signal thr3: continue to sigusr1_handler (PRMS: gdb/18216) Program terminated with signal SIGSEGV, Segmentation fault. #0 0x000000000062a83a in process_event_stop_test (ecs=0x7fff847eeee0) at src/gdb/infrun.c:4964 4964 if (sr_bp->loc->permanent Setting up the environment for debugging gdb. Breakpoint 1 at 0x79fcfc: file src/gdb/common/errors.c, line 54. Breakpoint 2 at 0x50a26c: file src/gdb/cli/cli-cmds.c, line 217. (top-gdb) p sr_bp $1 = (struct breakpoint *) 0x0 (top-gdb) bt #0 0x000000000062a83a in process_event_stop_test (ecs=0x7fff847eeee0) at src/gdb/infrun.c:4964 #1 0x000000000062a1af in handle_signal_stop (ecs=0x7fff847eeee0) at src/gdb/infrun.c:4715 #2 0x0000000000629097 in handle_inferior_event (ecs=0x7fff847eeee0) at src/gdb/infrun.c:4165 #3 0x0000000000627482 in fetch_inferior_event (client_data=0x0) at src/gdb/infrun.c:3298 #4 0x000000000064ad7b in inferior_event_handler (event_type=INF_REG_EVENT, client_data=0x0) at src/gdb/inf-loop.c:56 #5 0x00000000004c375f in handle_target_event (error=0, client_data=0x0) at src/gdb/linux-nat.c:4658 #6 0x0000000000648c47 in handle_file_event (file_ptr=0x2e0eaa0, ready_mask=1) at src/gdb/event-loop.c:658 The all-stop-non-stop series fixes this, but meanwhile, this augments the multiple-step-overs.exp test to cover this, KFAILed. gdb/testsuite/ChangeLog: 2015-04-08 Pedro Alves <palves@redhat.com> PR gdb/18214 PR gdb/18216 * gdb.threads/multiple-step-overs.c (sigusr1_handler): New function. (main): Install it as SIGUSR1 handler. * gdb.threads/multiple-step-overs.exp (setup): Remove 'prefix' parameter. Always use "setup" as prefix. Toggle "set displaced-stepping" off/on depending on global. Don't switch to thread 1 here. (top level): Add displaced stepping "off/on" test axis. Update "setup" calls. Wrap each subtest with with_test_prefix. Test continuing with a queued signal in each thread. |
||
Joel Brobecker
|
32d0add0a6 |
Update year range in copyright notice of all files owned by the GDB project.
gdb/ChangeLog: Update year range in copyright notice of all files. |
||
Pedro Alves
|
99619beac6 |
Handle multiple step-overs.
This test fails with current mainline. If the program stopped for a breakpoint in thread 1, and then the user switches to thread 2, and resumes the program, GDB first switches back to thread 1 to step it over the breakpoint, in order to make progress. However, that logic only considers the last reported event, assuming only one thread needs that stepping over dance. That's actually not true when we play with scheduler-locking. The patch adds an example to the testsuite of multiple threads needing a step-over before the stepping thread can be resumed. With current mainline, the program re-traps the same breakpoint it had already trapped before. E.g.: Breakpoint 2, main () at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:99 99 wait_threads (); /* set wait-threads breakpoint here */ (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: continue to breakpoint: run to breakpoint info threads Id Target Id Frame 3 Thread 0x7ffff77c9700 (LWP 4310) "multiple-step-o" 0x00000000004007ca in child_function_3 (arg=0x1) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:43 2 Thread 0x7ffff7fca700 (LWP 4309) "multiple-step-o" 0x0000000000400827 in child_function_2 (arg=0x0) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:60 * 1 Thread 0x7ffff7fcb740 (LWP 4305) "multiple-step-o" main () at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:99 (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: info threads shows all threads set scheduler-locking on (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: set scheduler-locking on break 44 Breakpoint 3 at 0x4007d3: file ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c, line 44. (gdb) break 61 Breakpoint 4 at 0x40082d: file ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c, line 61. (gdb) thread 3 [Switching to thread 3 (Thread 0x7ffff77c9700 (LWP 4310))] #0 0x00000000004007ca in child_function_3 (arg=0x1) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:43 43 (*myp) ++; (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: thread 3 continue Continuing. Breakpoint 3, child_function_3 (arg=0x1) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:44 44 callme (); /* set breakpoint thread 3 here */ (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: continue to breakpoint: run to breakpoint in thread 3 p *myp = 0 $1 = 0 (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: unbreak loop in thread 3 thread 2 [Switching to thread 2 (Thread 0x7ffff7fca700 (LWP 4309))] #0 0x0000000000400827 in child_function_2 (arg=0x0) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:60 60 (*myp) ++; (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: thread 2 continue Continuing. Breakpoint 4, child_function_2 (arg=0x0) at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:61 61 callme (); /* set breakpoint thread 2 here */ (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: continue to breakpoint: run to breakpoint in thread 2 p *myp = 0 $2 = 0 (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: unbreak loop in thread 2 thread 1 [Switching to thread 1 (Thread 0x7ffff7fcb740 (LWP 4305))] #0 main () at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:99 99 wait_threads (); /* set wait-threads breakpoint here */ (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: thread 1 set scheduler-locking off (gdb) PASS: gdb.threads/multiple-step-overs.exp: step: set scheduler-locking off At this point all thread are stopped for a breakpoint that needs stepping over. (gdb) step Breakpoint 2, main () at ../../../src/gdb/testsuite/gdb.threads/multiple-step-overs.c:99 99 wait_threads (); /* set wait-threads breakpoint here */ (gdb) FAIL: gdb.threads/multiple-step-overs.exp: step But that "step" retriggers the same breakpoint instead of making progress. The patch teaches GDB to step over all breakpoints of all threads before resuming the stepping thread. Tested on x86_64 Fedora 17, against pristine mainline, and also my branch that implements software single-stepping on x86. gdb/ 2014-03-20 Pedro Alves <palves@redhat.com> * infrun.c (prepare_to_proceed): Delete. (thread_still_needs_step_over): New function. (find_thread_needs_step_over): New function. (proceed): If the current thread needs a step-over, set its steping_over_breakpoint flag. Adjust to use find_thread_needs_step_over instead of prepare_to_proceed. (process_event_stop_test): For BPSTAT_WHAT_STOP_NOISY and BPSTAT_WHAT_STOP_SILENT, assume the thread stopped for a breakpoint. (switch_back_to_stepped_thread): Step over breakpoints of all threads not the stepping thread, before switching back to the stepping thread. gdb/testsuite/ 2014-03-20 Pedro Alves <palves@redhat.com> * gdb.threads/multiple-step-overs.c: New file. * gdb.threads/multiple-step-overs.exp: New file. * gdb.threads/signal-while-stepping-over-bp-other-thread.exp: Adjust expected infrun debug output. |