diff options
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 131 |
1 files changed, 82 insertions, 49 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 4e28c22..d34fc20 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1078,6 +1078,10 @@ a command like `return' or `jump' to continue execution.")); } target_resume (resume_ptid, step, sig); + + /* Avoid confusing the next resume, if the next stop/resume + happens to apply to another thread. */ + tp->stop_signal = TARGET_SIGNAL_0; } discard_cleanups (old_cleanups); @@ -1182,6 +1186,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) struct thread_info *tp; CORE_ADDR pc = regcache_read_pc (regcache); int oneproc = 0; + enum target_signal stop_signal; if (step > 0) step_start_function = find_pc_function (pc); @@ -1256,12 +1261,37 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) if (! tp->trap_expected || use_displaced_stepping (gdbarch)) insert_breakpoints (); + if (!non_stop) + { + /* Pass the last stop signal to the thread we're resuming, + irrespective of whether the current thread is the thread that + got the last event or not. This was historically GDB's + behaviour before keeping a stop_signal per thread. */ + + struct thread_info *last_thread; + ptid_t last_ptid; + struct target_waitstatus last_status; + + get_last_target_status (&last_ptid, &last_status); + if (!ptid_equal (inferior_ptid, last_ptid) + && !ptid_equal (last_ptid, null_ptid) + && !ptid_equal (last_ptid, minus_one_ptid)) + { + last_thread = find_thread_pid (last_ptid); + if (last_thread) + { + tp->stop_signal = last_thread->stop_signal; + last_thread->stop_signal = TARGET_SIGNAL_0; + } + } + } + if (siggnal != TARGET_SIGNAL_DEFAULT) - stop_signal = siggnal; + tp->stop_signal = siggnal; /* If this signal should not be seen by program, give it zero. Used for debugging signals. */ - else if (!signal_program[stop_signal]) - stop_signal = TARGET_SIGNAL_0; + else if (!signal_program[tp->stop_signal]) + tp->stop_signal = TARGET_SIGNAL_0; annotate_starting (); @@ -1300,7 +1330,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) init_infwait_state (); /* Resume inferior. */ - resume (oneproc || step || bpstat_should_step (), stop_signal); + resume (oneproc || step || bpstat_should_step (), tp->stop_signal); /* Wait for it to stop (if not standalone) and in any case decode why it stopped, and act accordingly. */ @@ -1355,9 +1385,6 @@ init_wait_for_inferior (void) breakpoint_init_inferior (inf_starting); - /* Don't confuse first call to proceed(). */ - stop_signal = TARGET_SIGNAL_0; - /* The first resume is not following a fork/vfork/exec. */ pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */ @@ -1712,15 +1739,13 @@ context_switch (ptid_t ptid) save_infrun_state (inferior_ptid, cmd_continuation, intermediate_continuation, stop_step, - step_multi, - stop_signal); + step_multi); /* Load infrun state for the new thread. */ load_infrun_state (ptid, &cmd_continuation, &intermediate_continuation, &stop_step, - &step_multi, - &stop_signal); + &step_multi); } switch_to_thread (ptid); @@ -2023,7 +2048,6 @@ handle_inferior_event (struct execution_control_state *ecs) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n"); stop_print_frame = 0; - stop_signal = ecs->ws.value.sig; target_terminal_ours (); /* Must do this before mourn anyway */ /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't @@ -2033,7 +2057,7 @@ handle_inferior_event (struct execution_control_state *ecs) may be needed. */ target_mourn_inferior (); - print_stop_reason (SIGNAL_EXITED, stop_signal); + print_stop_reason (SIGNAL_EXITED, ecs->ws.value.sig); singlestep_breakpoints_inserted_p = 0; stop_stepping (ecs); return; @@ -2044,7 +2068,6 @@ handle_inferior_event (struct execution_control_state *ecs) case TARGET_WAITKIND_VFORKED: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n"); - stop_signal = TARGET_SIGNAL_TRAP; pending_follow.kind = ecs->ws.kind; pending_follow.fork_event.parent_pid = ecs->ptid; @@ -2065,17 +2088,16 @@ handle_inferior_event (struct execution_control_state *ecs) /* If no catchpoint triggered for this, then keep going. */ if (ecs->random_signal) { - stop_signal = TARGET_SIGNAL_0; + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; keep_going (ecs); return; } + ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; goto process_event_stop_test; case TARGET_WAITKIND_EXECD: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n"); - stop_signal = TARGET_SIGNAL_TRAP; - pending_follow.execd_pathname = savestring (ecs->ws.value.execd_pathname, strlen (ecs->ws.value.execd_pathname)); @@ -2109,10 +2131,11 @@ handle_inferior_event (struct execution_control_state *ecs) /* If no catchpoint triggered for this, then keep going. */ if (ecs->random_signal) { - stop_signal = TARGET_SIGNAL_0; + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; keep_going (ecs); return; } + ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; goto process_event_stop_test; /* Be careful not to try to gather much state about a thread @@ -2139,7 +2162,7 @@ handle_inferior_event (struct execution_control_state *ecs) case TARGET_WAITKIND_STOPPED: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n"); - stop_signal = ecs->ws.value.sig; + ecs->event_thread->stop_signal = ecs->ws.value.sig; break; /* We had an event in the inferior, but we are not interested @@ -2182,7 +2205,8 @@ targets should add new threads to the thread list themselves in non-stop mode.") /* Do we need to clean up the state of a thread that has completed a displaced single-step? (Doing so usually affects the PC, so do it here, before we set stop_pc.) */ - displaced_step_fixup (ecs->ptid, stop_signal); + if (ecs->ws.kind == TARGET_WAITKIND_STOPPED) + displaced_step_fixup (ecs->ptid, ecs->event_thread->stop_signal); stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid)); @@ -2216,7 +2240,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") /* We've either finished single-stepping past the single-step breakpoint, or stopped for some other reason. It would be nice if we could tell, but we can't reliably. */ - if (stop_signal == TARGET_SIGNAL_TRAP) + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n"); @@ -2245,7 +2269,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") /* If we stopped for some other reason than single-stepping, ignore the fact that we were supposed to switch back. */ - if (stop_signal == TARGET_SIGNAL_TRAP) + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP) { struct thread_info *tp; @@ -2279,7 +2303,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") another thread. If so, then step that thread past the breakpoint, and continue it. */ - if (stop_signal == TARGET_SIGNAL_TRAP) + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP) { int thread_hop_needed = 0; @@ -2333,6 +2357,8 @@ targets should add new threads to the thread list themselves in non-stop mode.") if (new_singlestep_pc != singlestep_pc) { + enum target_signal stop_signal; + if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: unexpected thread," " but expected thread advanced also\n"); @@ -2341,8 +2367,11 @@ targets should add new threads to the thread list themselves in non-stop mode.") singlestep_ptid. Don't swap here, since that's the context we want to use. Just fudge our state and continue. */ + stop_signal = ecs->event_thread->stop_signal; + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; ecs->ptid = singlestep_ptid; ecs->event_thread = find_thread_pid (ecs->ptid); + ecs->event_thread->stop_signal = stop_signal; stop_pc = new_singlestep_pc; } else @@ -2498,7 +2527,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") ecs->random_signal = 0; stopped_by_random_signal = 0; - if (stop_signal == TARGET_SIGNAL_TRAP + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && ecs->event_thread->trap_expected && gdbarch_single_step_through_delay_p (current_gdbarch) && currently_stepping (ecs->event_thread)) @@ -2555,16 +2584,16 @@ targets should add new threads to the thread list themselves in non-stop mode.") If we're doing a displaced step past a breakpoint, then the breakpoint is always inserted at the original instruction; non-standard signals can't be explained by the breakpoint. */ - if (stop_signal == TARGET_SIGNAL_TRAP + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP || (! ecs->event_thread->trap_expected && breakpoint_inserted_here_p (stop_pc) - && (stop_signal == TARGET_SIGNAL_ILL - || stop_signal == TARGET_SIGNAL_SEGV - || stop_signal == TARGET_SIGNAL_EMT)) + && (ecs->event_thread->stop_signal == TARGET_SIGNAL_ILL + || ecs->event_thread->stop_signal == TARGET_SIGNAL_SEGV + || ecs->event_thread->stop_signal == TARGET_SIGNAL_EMT)) || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP || stop_soon == STOP_QUIETLY_REMOTE) { - if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap) + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n"); @@ -2596,11 +2625,11 @@ targets should add new threads to the thread list themselves in non-stop mode.") (e.g. gdbserver). We already rely on SIGTRAP being our signal, so this is no exception. */ if (stop_soon == STOP_QUIETLY_NO_SIGSTOP - && (stop_signal == TARGET_SIGNAL_STOP - || stop_signal == TARGET_SIGNAL_TRAP)) + && (ecs->event_thread->stop_signal == TARGET_SIGNAL_STOP + || ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)) { stop_stepping (ecs); - stop_signal = TARGET_SIGNAL_0; + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; return; } @@ -2631,7 +2660,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") be necessary for call dummies on a non-executable stack on SPARC. */ - if (stop_signal == TARGET_SIGNAL_TRAP) + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP) ecs->random_signal = !(bpstat_explains_signal (ecs->event_thread->stop_bpstat) || ecs->event_thread->trap_expected @@ -2641,7 +2670,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") { ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); if (!ecs->random_signal) - stop_signal = TARGET_SIGNAL_TRAP; + ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; } } @@ -2662,17 +2691,18 @@ process_event_stop_test: int printed = 0; if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n", stop_signal); + fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n", + ecs->event_thread->stop_signal); stopped_by_random_signal = 1; - if (signal_print[stop_signal]) + if (signal_print[ecs->event_thread->stop_signal]) { printed = 1; target_terminal_ours_for_output (); - print_stop_reason (SIGNAL_RECEIVED, stop_signal); + print_stop_reason (SIGNAL_RECEIVED, ecs->event_thread->stop_signal); } - if (signal_stop_state (stop_signal)) + if (signal_stop_state (ecs->event_thread->stop_signal)) { stop_stepping (ecs); return; @@ -2683,8 +2713,8 @@ process_event_stop_test: target_terminal_inferior (); /* Clear the signal if it should not be passed. */ - if (signal_program[stop_signal] == 0) - stop_signal = TARGET_SIGNAL_0; + if (signal_program[ecs->event_thread->stop_signal] == 0) + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; if (ecs->event_thread->prev_pc == read_pc () && ecs->event_thread->trap_expected @@ -2712,7 +2742,7 @@ process_event_stop_test: } if (ecs->event_thread->step_range_end != 0 - && stop_signal != TARGET_SIGNAL_0 + && ecs->event_thread->stop_signal != TARGET_SIGNAL_0 && (ecs->event_thread->step_range_start <= stop_pc && stop_pc < ecs->event_thread->step_range_end) && frame_id_eq (get_frame_id (get_current_frame ()), @@ -3517,12 +3547,14 @@ keep_going (struct execution_control_state *ecs) /* If we did not do break;, it means we should keep running the inferior and not return to debugger. */ - if (ecs->event_thread->trap_expected && stop_signal != TARGET_SIGNAL_TRAP) + if (ecs->event_thread->trap_expected + && ecs->event_thread->stop_signal != TARGET_SIGNAL_TRAP) { /* We took a signal (which we are supposed to pass through to the inferior, else we'd not get here) and we haven't yet gotten our trap. Simply continue. */ - resume (currently_stepping (ecs->event_thread), stop_signal); + resume (currently_stepping (ecs->event_thread), + ecs->event_thread->stop_signal); } else { @@ -3577,11 +3609,12 @@ keep_going (struct execution_control_state *ecs) simulator; the simulator then delivers the hardware equivalent of a SIGNAL_TRAP to the program being debugged. */ - if (stop_signal == TARGET_SIGNAL_TRAP && !signal_program[stop_signal]) - stop_signal = TARGET_SIGNAL_0; - + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP + && !signal_program[ecs->event_thread->stop_signal]) + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; - resume (currently_stepping (ecs->event_thread), stop_signal); + resume (currently_stepping (ecs->event_thread), + ecs->event_thread->stop_signal); } prepare_to_wait (ecs); @@ -4366,7 +4399,7 @@ save_inferior_status (int restore_stack_info) struct inferior_status *inf_status = XMALLOC (struct inferior_status); struct thread_info *tp = inferior_thread (); - inf_status->stop_signal = stop_signal; + inf_status->stop_signal = tp->stop_signal; inf_status->stop_pc = stop_pc; inf_status->stop_step = stop_step; inf_status->stop_stack_dummy = stop_stack_dummy; @@ -4420,7 +4453,7 @@ restore_inferior_status (struct inferior_status *inf_status) { struct thread_info *tp = inferior_thread (); - stop_signal = inf_status->stop_signal; + tp->stop_signal = inf_status->stop_signal; stop_pc = inf_status->stop_pc; stop_step = inf_status->stop_step; stop_stack_dummy = inf_status->stop_stack_dummy; |