From 2020b7abd8daa9b0204aa39bfcda2d6f9f45a1f1 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 8 Sep 2008 21:51:18 +0000 Subject: [PATCH] Remove the global stop_signal in favour of a per-thread stop_signal. * inferior.h (stop_signal): Delete. * gdbthread.h (save_infrun_state, load_infrun_state): Remove stop_signal argument. * thread.c (load_infrun_state, save_infrun_state): Remove stop_signal argument. Don't reference it. * infcmd.c (stop_signal): Delete. (program_info): Adjust. * infrun.c (resume): Clear stop_signal. (proceed): Adjust. Pass the last stop_signal to the thread we're resuming. (context_switch): Don't context-switch stop_signal. (handle_inferior_event, keep_going): Adjust. (save_inferior_status, restore_inferior_status): Adjust. * fbsd-nat.c: Include "gdbthread.h". (find_signalled_thread, find_stop_signal): New. (fbsd_make_corefile_notes): Use it. * fork-child.c (startup_inferior): Adjust. * linux-nat.c (get_pending_status): Adjust. (linux_nat_do_thread_registers): Adjust. (find_signalled_thread, find_stop_signal): New. (linux_nat_do_thread_registers): Add stop_signal parameter. (struct linux_nat_corefile_thread_data): Add stop_signal member. (linux_nat_corefile_thread_callback): Pass stop_signal. (linux_nat_do_registers): Delete. (linux_nat_make_corefile_notes): Use find_stop_signal. Assume there's always a thread. * procfs.c (find_signalled_thread, find_stop_signal): New. (find_stop_signal): New. (procfs_do_thread_registers): Add stop_signal parameter. (struct procfs_corefile_thread_data): Add stop_signal member. (procfs_corefile_thread_callback): Pass args->stop_signal. (procfs_make_note_section): Find the last stop_signal. * solib-irix.c: Include gdbthread.h. (irix_solib_create_inferior_hook): Adjust. * solib-osf.c: Include gdbthread.h. (osf_solib_create_inferior_hook): Adjust. * solib-sunos.c: Include gdbthread.h. (sunos_solib_create_inferior_hook): Adjust. * solib-svr4.c: Include gdbthread.h. (svr4_solib_create_inferior_hook): Adjust. * win32-nat.c (do_initial_win32_stuff): Adjust. --- gdb/ChangeLog | 53 +++++++++++++++++++ gdb/fbsd-nat.c | 25 ++++++++- gdb/fork-child.c | 7 ++- gdb/gdbthread.h | 7 ++- gdb/infcmd.c | 10 ++-- gdb/inferior.h | 4 -- gdb/infrun.c | 131 +++++++++++++++++++++++++++++----------------- gdb/linux-nat.c | 77 +++++++++++++-------------- gdb/procfs.c | 30 ++++++++++- gdb/solib-irix.c | 10 ++-- gdb/solib-osf.c | 10 ++-- gdb/solib-sunos.c | 10 ++-- gdb/solib-svr4.c | 11 ++-- gdb/thread.c | 8 +-- gdb/win32-nat.c | 6 ++- gdb/windows-nat.c | 6 ++- 16 files changed, 274 insertions(+), 131 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c0f2597a6dd..b6b451b0197 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,56 @@ +2008-09-08 Pedro Alves + + Remove the global stop_signal in favour of a per-thread + stop_signal. + + * inferior.h (stop_signal): Delete. + * gdbthread.h (save_infrun_state, load_infrun_state): Remove + stop_signal argument. + * thread.c (load_infrun_state, save_infrun_state): Remove + stop_signal argument. Don't reference it. + + * infcmd.c (stop_signal): Delete. + (program_info): Adjust. + * infrun.c (resume): Clear stop_signal. + (proceed): Adjust. Pass the last stop_signal to the thread we're + resuming. + (context_switch): Don't context-switch stop_signal. + (handle_inferior_event, keep_going): Adjust. + (save_inferior_status, restore_inferior_status): Adjust. + + * fbsd-nat.c: Include "gdbthread.h". + (find_signalled_thread, find_stop_signal): New. + (fbsd_make_corefile_notes): Use it. + * fork-child.c (startup_inferior): Adjust. + + * linux-nat.c (get_pending_status): Adjust. + (linux_nat_do_thread_registers): Adjust. + (find_signalled_thread, find_stop_signal): New. + (linux_nat_do_thread_registers): Add stop_signal parameter. + (struct linux_nat_corefile_thread_data): Add stop_signal member. + (linux_nat_corefile_thread_callback): Pass stop_signal. + (linux_nat_do_registers): Delete. + (linux_nat_make_corefile_notes): Use find_stop_signal. Assume + there's always a thread. + + * procfs.c (find_signalled_thread, find_stop_signal): New. + (find_stop_signal): New. + (procfs_do_thread_registers): Add stop_signal parameter. + (struct procfs_corefile_thread_data): Add stop_signal member. + (procfs_corefile_thread_callback): Pass args->stop_signal. + (procfs_make_note_section): Find the last stop_signal. + + * solib-irix.c: Include gdbthread.h. + (irix_solib_create_inferior_hook): Adjust. + * solib-osf.c: Include gdbthread.h. + (osf_solib_create_inferior_hook): Adjust. + * solib-sunos.c: Include gdbthread.h. + (sunos_solib_create_inferior_hook): Adjust. + * solib-svr4.c: Include gdbthread.h. + (svr4_solib_create_inferior_hook): Adjust. + + * win32-nat.c (do_initial_win32_stuff): Adjust. + 2008-09-08 Pedro Alves * gdbthread.h (struct thread_info): Add comments around diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index 6f442cc7cb3..215d2a78f61 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -22,6 +22,7 @@ #include "inferior.h" #include "regcache.h" #include "regset.h" +#include "gdbthread.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -137,6 +138,28 @@ fbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, return 0; } +static int +find_signalled_thread (struct thread_info *info, void *data) +{ + if (info->stop_signal != TARGET_SIGNAL_0 + && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) + return 1; + + return 0; +} + +static enum target_signal +find_stop_signal (void) +{ + struct thread_info *info = + iterate_over_threads (find_signalled_thread, NULL); + + if (info) + return info->stop_signal; + else + return TARGET_SIGNAL_0; +} + /* Create appropriate note sections for a corefile, returning them in allocated memory. */ @@ -165,7 +188,7 @@ fbsd_make_corefile_notes (bfd *obfd, int *note_size) note_data = elfcore_write_prstatus (obfd, note_data, note_size, ptid_get_pid (inferior_ptid), - stop_signal, &gregs); + find_stop_signal (), &gregs); size = sizeof fpregs; regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size); diff --git a/gdb/fork-child.c b/gdb/fork-child.c index 229770f154b..269dd4319ef 100644 --- a/gdb/fork-child.c +++ b/gdb/fork-child.c @@ -434,15 +434,18 @@ startup_inferior (int ntraps) while (1) { + struct thread_info *tp; + /* Make wait_for_inferior be quiet. */ stop_soon = STOP_QUIETLY; wait_for_inferior (1); - if (stop_signal != TARGET_SIGNAL_TRAP) + tp = inferior_thread (); + if (tp->stop_signal != TARGET_SIGNAL_TRAP) { /* Let shell child handle its own signals in its own way. FIXME: what if child has exited? Must exit loop somehow. */ - resume (0, stop_signal); + resume (0, tp->stop_signal); } else { diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index ca74976fb87..3082abf439d 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -149,6 +149,7 @@ struct thread_info int stop_step; int step_multi; + /* Last signal that the inferior received (why it stopped). */ enum target_signal stop_signal; /* Chain containing status of breakpoint(s) the thread stopped @@ -224,8 +225,7 @@ extern void save_infrun_state (ptid_t ptid, struct continuation *continuations, struct continuation *intermediate_continuations, int stop_step, - int step_multi, - enum target_signal stop_signal); + int step_multi); /* infrun context switch: load the debugger state previously saved for the given thread. */ @@ -233,8 +233,7 @@ extern void load_infrun_state (ptid_t ptid, struct continuation **continuations, struct continuation **intermediate_continuations, int *stop_step, - int *step_multi, - enum target_signal *stop_signal); + int *step_multi); /* Switch from one thread to another. */ extern void switch_to_thread (ptid_t ptid); diff --git a/gdb/infcmd.c b/gdb/infcmd.c index a86f236cf5c..055b2282eee 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -147,10 +147,6 @@ static char *inferior_io_terminal; ptid_t inferior_ptid; -/* Last signal that the inferior received (why it stopped). */ - -enum target_signal stop_signal; - /* Address at which inferior stopped. */ CORE_ADDR stop_pc; @@ -1505,11 +1501,11 @@ It stopped at a breakpoint that has since been deleted.\n")); stat = bpstat_num (&bs, &num); } } - else if (stop_signal != TARGET_SIGNAL_0) + else if (tp->stop_signal != TARGET_SIGNAL_0) { printf_filtered (_("It stopped with signal %s, %s.\n"), - target_signal_to_name (stop_signal), - target_signal_to_string (stop_signal)); + target_signal_to_name (tp->stop_signal), + target_signal_to_string (tp->stop_signal)); } if (!from_tty) diff --git a/gdb/inferior.h b/gdb/inferior.h index f39cc2c1797..78af8c2bfc1 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -279,10 +279,6 @@ extern void interrupt_target_command (char *args, int from_tty); extern void interrupt_target_1 (int all_threads); -/* Last signal that the inferior received (why it stopped). */ - -extern enum target_signal stop_signal; - /* Address at which inferior stopped. */ extern CORE_ADDR stop_pc; diff --git a/gdb/infrun.c b/gdb/infrun.c index 4e28c220c1e..d34fc206e10 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; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 07ded105618..42e19b5969e 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1453,18 +1453,10 @@ get_pending_status (struct lwp_info *lp, int *status) { /* If the core knows the thread is not executing, then we have the last signal recorded in - thread_info->stop_signal, unless this is inferior_ptid, - in which case, it's in the global stop_signal, due to - context switching. */ + thread_info->stop_signal. */ - if (ptid_equal (lp->ptid, inferior_ptid)) - signo = stop_signal; - else - { - struct thread_info *tp = find_thread_pid (lp->ptid); - gdb_assert (tp); - signo = tp->stop_signal; - } + struct thread_info *tp = find_thread_pid (lp->ptid); + signo = tp->stop_signal; } if (signo != TARGET_SIGNAL_0 @@ -1492,9 +1484,10 @@ GPT: lwp %s had signal %s, but it is in no pass state\n", { if (GET_LWP (lp->ptid) == GET_LWP (last_ptid)) { - if (stop_signal != TARGET_SIGNAL_0 - && signal_pass_state (stop_signal)) - *status = W_STOPCODE (target_signal_to_host (stop_signal)); + struct thread_info *tp = find_thread_pid (lp->ptid); + if (tp->stop_signal != TARGET_SIGNAL_0 + && signal_pass_state (tp->stop_signal)) + *status = W_STOPCODE (target_signal_to_host (tp->stop_signal)); } else if (target_can_async_p ()) queued_waitpid (GET_LWP (lp->ptid), status, __WALL); @@ -3338,12 +3331,35 @@ linux_nat_find_memory_regions (int (*func) (CORE_ADDR, return 0; } +static int +find_signalled_thread (struct thread_info *info, void *data) +{ + if (info->stop_signal != TARGET_SIGNAL_0 + && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) + return 1; + + return 0; +} + +static enum target_signal +find_stop_signal (void) +{ + struct thread_info *info = + iterate_over_threads (find_signalled_thread, NULL); + + if (info) + return info->stop_signal; + else + return TARGET_SIGNAL_0; +} + /* Records the thread's register state for the corefile note section. */ static char * linux_nat_do_thread_registers (bfd *obfd, ptid_t ptid, - char *note_data, int *note_size) + char *note_data, int *note_size, + enum target_signal stop_signal) { gdb_gregset_t gregs; gdb_fpregset_t fpregs; @@ -3438,6 +3454,7 @@ struct linux_nat_corefile_thread_data char *note_data; int *note_size; int num_notes; + enum target_signal stop_signal; }; /* Called by gdbthread.c once per thread. Records the thread's @@ -3451,25 +3468,13 @@ linux_nat_corefile_thread_callback (struct lwp_info *ti, void *data) args->note_data = linux_nat_do_thread_registers (args->obfd, ti->ptid, args->note_data, - args->note_size); + args->note_size, + args->stop_signal); args->num_notes++; return 0; } -/* Records the register state for the corefile note section. */ - -static char * -linux_nat_do_registers (bfd *obfd, ptid_t ptid, - char *note_data, int *note_size) -{ - return linux_nat_do_thread_registers (obfd, - ptid_build (ptid_get_pid (inferior_ptid), - ptid_get_pid (inferior_ptid), - 0), - note_data, note_size); -} - /* Fills the "to_make_corefile_note" target vector. Builds the note section for a corefile, and returns it in a malloc buffer. */ @@ -3516,18 +3521,10 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size) thread_args.note_data = note_data; thread_args.note_size = note_size; thread_args.num_notes = 0; + thread_args.stop_signal = find_stop_signal (); iterate_over_lwps (linux_nat_corefile_thread_callback, &thread_args); - if (thread_args.num_notes == 0) - { - /* iterate_over_threads didn't come up with any threads; just - use inferior_ptid. */ - note_data = linux_nat_do_registers (obfd, inferior_ptid, - note_data, note_size); - } - else - { - note_data = thread_args.note_data; - } + gdb_assert (thread_args.num_notes != 0); + note_data = thread_args.note_data; auxv_len = target_read_alloc (¤t_target, TARGET_OBJECT_AUXV, NULL, &auxv); diff --git a/gdb/procfs.c b/gdb/procfs.c index beeb4f5701c..e8cd6d94bfc 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -6045,13 +6045,36 @@ procfs_first_available (void) return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1); } +static int +find_signalled_thread (struct thread_info *info, void *data) +{ + if (info->stop_signal != TARGET_SIGNAL_0 + && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) + return 1; + + return 0; +} + +static enum target_signal +find_stop_signal (void) +{ + struct thread_info *info = + iterate_over_threads (find_signalled_thread, NULL); + + if (info) + return info->stop_signal; + else + return TARGET_SIGNAL_0; +} + /* =================== GCORE .NOTE "MODULE" =================== */ #if defined (UNIXWARE) || defined (PIOCOPENLWP) || defined (PCAGENT) /* gcore only implemented on solaris and unixware (so far) */ static char * procfs_do_thread_registers (bfd *obfd, ptid_t ptid, - char *note_data, int *note_size) + char *note_data, int *note_size, + enum target_signal stop_signal) { struct regcache *regcache = get_thread_regcache (ptid); gdb_gregset_t gregs; @@ -6089,6 +6112,7 @@ struct procfs_corefile_thread_data { bfd *obfd; char *note_data; int *note_size; + enum target_signal stop_signal; }; static int @@ -6102,7 +6126,8 @@ procfs_corefile_thread_callback (procinfo *pi, procinfo *thread, void *data) inferior_ptid = MERGEPID (pi->pid, thread->tid); args->note_data = procfs_do_thread_registers (args->obfd, inferior_ptid, args->note_data, - args->note_size); + args->note_size, + args->stop_signal); inferior_ptid = saved_ptid; } return 0; @@ -6156,6 +6181,7 @@ procfs_make_note_section (bfd *obfd, int *note_size) thread_args.obfd = obfd; thread_args.note_data = note_data; thread_args.note_size = note_size; + thread_args.stop_signal = find_stop_signal (); proc_iterate_over_threads (pi, procfs_corefile_thread_callback, &thread_args); /* There should be always at least one thread. */ diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c index 0e80b94d9b8..5b612ec6c62 100644 --- a/gdb/solib-irix.c +++ b/gdb/solib-irix.c @@ -31,6 +31,7 @@ #include "gdbcore.h" #include "target.h" #include "inferior.h" +#include "gdbthread.h" #include "solist.h" #include "solib.h" @@ -421,6 +422,8 @@ enable_break (void) static void irix_solib_create_inferior_hook (void) { + struct thread_info *tp; + if (!enable_break ()) { warning (_("shared library handler failed to enable breakpoint")); @@ -432,15 +435,16 @@ irix_solib_create_inferior_hook (void) can go groveling around in the dynamic linker structures to find out what we need to know about them. */ + tp = inferior_thread (); clear_proceed_status (); stop_soon = STOP_QUIETLY; - stop_signal = TARGET_SIGNAL_0; + tp->stop_signal = TARGET_SIGNAL_0; do { - target_resume (pid_to_ptid (-1), 0, stop_signal); + target_resume (pid_to_ptid (-1), 0, tp->stop_signal); wait_for_inferior (0); } - while (stop_signal != TARGET_SIGNAL_TRAP); + while (tp->stop_signal != TARGET_SIGNAL_TRAP); /* We are now either at the "mapping complete" breakpoint (or somewhere else, a condition we aren't prepared to deal with anyway), so adjust diff --git a/gdb/solib-osf.c b/gdb/solib-osf.c index 3f9dca4939f..b83a8ec8ea4 100644 --- a/gdb/solib-osf.c +++ b/gdb/solib-osf.c @@ -53,6 +53,7 @@ #include "objfiles.h" #include "target.h" #include "inferior.h" +#include "gdbthread.h" #include "solist.h" #ifdef USE_LDR_ROUTINES @@ -306,6 +307,8 @@ osf_clear_solib (void) static void osf_solib_create_inferior_hook (void) { + struct thread_info *tp; + /* If we are attaching to the inferior, the shared libraries have already been mapped, so nothing more to do. */ if (attach_flag) @@ -330,15 +333,16 @@ osf_solib_create_inferior_hook (void) if (!target_can_run (¤t_target)) return; + tp = inferior_thread (); clear_proceed_status (); stop_soon = STOP_QUIETLY; - stop_signal = TARGET_SIGNAL_0; + tp->stop_signal = TARGET_SIGNAL_0; do { - target_resume (minus_one_ptid, 0, stop_signal); + target_resume (minus_one_ptid, 0, tp->stop_signal); wait_for_inferior (0); } - while (stop_signal != TARGET_SIGNAL_TRAP); + while (tp->stop_signal != TARGET_SIGNAL_TRAP); /* solib_add will call reinit_frame_cache. But we are stopped in the runtime loader and we do not have symbols diff --git a/gdb/solib-sunos.c b/gdb/solib-sunos.c index 6e5b440fa4c..c83b0577eed 100644 --- a/gdb/solib-sunos.c +++ b/gdb/solib-sunos.c @@ -36,6 +36,7 @@ #include "objfiles.h" #include "gdbcore.h" #include "inferior.h" +#include "gdbthread.h" #include "solist.h" #include "bcache.h" #include "regcache.h" @@ -737,6 +738,8 @@ sunos_special_symbol_handling (void) static void sunos_solib_create_inferior_hook (void) { + struct thread_info *tp; + if ((debug_base = locate_base ()) == 0) { /* Can't find the symbol or the executable is statically linked. */ @@ -758,15 +761,16 @@ sunos_solib_create_inferior_hook (void) can go groveling around in the dynamic linker structures to find out what we need to know about them. */ + tp = inferior_thread (); clear_proceed_status (); stop_soon = STOP_QUIETLY; - stop_signal = TARGET_SIGNAL_0; + tp->stop_signal = TARGET_SIGNAL_0; do { - target_resume (pid_to_ptid (-1), 0, stop_signal); + target_resume (pid_to_ptid (-1), 0, tp->stop_signal); wait_for_inferior (0); } - while (stop_signal != TARGET_SIGNAL_TRAP); + while (tp->stop_signal != TARGET_SIGNAL_TRAP); stop_soon = NO_STOP_QUIETLY; /* We are now either at the "mapping complete" breakpoint (or somewhere diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index fc6bf6fc4c7..032ae1953b2 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -31,6 +31,7 @@ #include "gdbcore.h" #include "target.h" #include "inferior.h" +#include "gdbthread.h" #include "gdb_assert.h" @@ -1560,6 +1561,8 @@ svr4_relocate_main_executable (void) static void svr4_solib_create_inferior_hook (void) { + struct thread_info *tp; + /* Relocate the main executable if necessary. */ svr4_relocate_main_executable (); @@ -1579,15 +1582,17 @@ svr4_solib_create_inferior_hook (void) can go groveling around in the dynamic linker structures to find out what we need to know about them. */ + tp = inferior_thread (); + clear_proceed_status (); stop_soon = STOP_QUIETLY; - stop_signal = TARGET_SIGNAL_0; + tp->stop_signal = TARGET_SIGNAL_0; do { - target_resume (pid_to_ptid (-1), 0, stop_signal); + target_resume (pid_to_ptid (-1), 0, tp->stop_signal); wait_for_inferior (0); } - while (stop_signal != TARGET_SIGNAL_TRAP); + while (tp->stop_signal != TARGET_SIGNAL_TRAP); stop_soon = NO_STOP_QUIETLY; #endif /* defined(_SCO_DS) */ } diff --git a/gdb/thread.c b/gdb/thread.c index 9d9831c2f15..33b47955c8e 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -446,8 +446,7 @@ load_infrun_state (ptid_t ptid, struct continuation **continuations, struct continuation **intermediate_continuations, int *stop_step, - int *step_multi, - enum target_signal *stop_signal) + int *step_multi) { struct thread_info *tp; @@ -467,7 +466,6 @@ load_infrun_state (ptid_t ptid, tp->intermediate_continuations = NULL; *stop_step = tp->stop_step; *step_multi = tp->step_multi; - *stop_signal = tp->stop_signal; } } @@ -478,8 +476,7 @@ save_infrun_state (ptid_t ptid, struct continuation *continuations, struct continuation *intermediate_continuations, int stop_step, - int step_multi, - enum target_signal stop_signal) + int step_multi) { struct thread_info *tp; @@ -497,7 +494,6 @@ save_infrun_state (ptid_t ptid, tp->intermediate_continuations = intermediate_continuations; tp->stop_step = stop_step; tp->step_multi = step_multi; - tp->stop_signal = stop_signal; } } diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c index e84214d31bf..0671470e391 100644 --- a/gdb/win32-nat.c +++ b/gdb/win32-nat.c @@ -1523,6 +1523,7 @@ do_initial_win32_stuff (DWORD pid) { extern int stop_after_trap; int i; + struct thread_info *tp; last_sig = TARGET_SIGNAL_0; event_count = 0; @@ -1551,8 +1552,9 @@ do_initial_win32_stuff (DWORD pid) { stop_after_trap = 1; wait_for_inferior (0); - if (stop_signal != TARGET_SIGNAL_TRAP) - resume (0, stop_signal); + tp = inferior_thread (); + if (tp->stop_signal != TARGET_SIGNAL_TRAP) + resume (0, tp->stop_signal); else break; } diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index e84214d31bf..0671470e391 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1523,6 +1523,7 @@ do_initial_win32_stuff (DWORD pid) { extern int stop_after_trap; int i; + struct thread_info *tp; last_sig = TARGET_SIGNAL_0; event_count = 0; @@ -1551,8 +1552,9 @@ do_initial_win32_stuff (DWORD pid) { stop_after_trap = 1; wait_for_inferior (0); - if (stop_signal != TARGET_SIGNAL_TRAP) - resume (0, stop_signal); + tp = inferior_thread (); + if (tp->stop_signal != TARGET_SIGNAL_TRAP) + resume (0, tp->stop_signal); else break; } -- 2.39.2