2008-08-16 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. --- 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 | 123 ++++++++++++++++++++++++++++++++---------------------- 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 +- 14 files changed, 209 insertions(+), 129 deletions(-) Index: src/gdb/inferior.h =================================================================== --- src.orig/gdb/inferior.h 2008-08-16 14:20:52.000000000 +0100 +++ src/gdb/inferior.h 2008-08-16 16:13:44.000000000 +0100 @@ -279,10 +279,6 @@ extern void interrupt_target_command (ch 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; Index: src/gdb/gdbthread.h =================================================================== --- src.orig/gdb/gdbthread.h 2008-08-16 14:20:56.000000000 +0100 +++ src/gdb/gdbthread.h 2008-08-16 16:13:44.000000000 +0100 @@ -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 pt 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 pt 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); Index: src/gdb/thread.c =================================================================== --- src.orig/gdb/thread.c 2008-08-16 14:20:56.000000000 +0100 +++ src/gdb/thread.c 2008-08-16 16:13:44.000000000 +0100 @@ -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; } } Index: src/gdb/infcmd.c =================================================================== --- src.orig/gdb/infcmd.c 2008-08-16 14:20:56.000000000 +0100 +++ src/gdb/infcmd.c 2008-08-16 16:13:44.000000000 +0100 @@ -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; @@ -1528,11 +1524,11 @@ It stopped at a breakpoint that has sinc 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) Index: src/gdb/infrun.c =================================================================== --- src.orig/gdb/infrun.c 2008-08-16 14:20:56.000000000 +0100 +++ src/gdb/infrun.c 2008-08-16 16:14:01.000000000 +0100 @@ -1074,6 +1074,10 @@ a command like `return' or `jump' to con } 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); @@ -1178,6 +1182,7 @@ proceed (CORE_ADDR addr, enum target_sig 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); @@ -1252,12 +1257,34 @@ proceed (CORE_ADDR addr, enum target_sig 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); + 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 (); @@ -1299,7 +1326,7 @@ proceed (CORE_ADDR addr, enum target_sig 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. */ @@ -1354,9 +1381,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. */ @@ -1701,15 +1725,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); @@ -2010,7 +2032,6 @@ handle_inferior_event (struct execution_ 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 @@ -2020,7 +2041,7 @@ handle_inferior_event (struct execution_ 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; @@ -2031,7 +2052,6 @@ handle_inferior_event (struct execution_ 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; @@ -2052,17 +2072,16 @@ handle_inferior_event (struct execution_ /* 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)); @@ -2096,10 +2115,11 @@ handle_inferior_event (struct execution_ /* 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 @@ -2126,7 +2146,7 @@ handle_inferior_event (struct execution_ 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 @@ -2169,7 +2189,8 @@ targets should add new threads to the th /* 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)); @@ -2203,7 +2224,7 @@ targets should add new threads to the th /* 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"); @@ -2232,7 +2253,7 @@ targets should add new threads to the th /* 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; @@ -2266,7 +2287,7 @@ targets should add new threads to the th 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; @@ -2485,7 +2506,7 @@ targets should add new threads to the th 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)) @@ -2542,16 +2563,16 @@ targets should add new threads to the th 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"); @@ -2583,11 +2604,11 @@ targets should add new threads to the th (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; } @@ -2618,7 +2639,7 @@ targets should add new threads to the th 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 @@ -2628,7 +2649,7 @@ targets should add new threads to the th { 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; } } @@ -2649,17 +2670,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; @@ -2670,8 +2692,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 @@ -2699,7 +2721,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 ()), @@ -3531,12 +3553,14 @@ keep_going (struct execution_control_sta /* 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 { @@ -3591,11 +3615,12 @@ keep_going (struct execution_control_sta 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); @@ -4380,7 +4405,7 @@ save_inferior_status (int restore_stack_ 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; @@ -4434,7 +4459,7 @@ restore_inferior_status (struct inferior { 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; Index: src/gdb/fbsd-nat.c =================================================================== --- src.orig/gdb/fbsd-nat.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/fbsd-nat.c 2008-08-16 14:20:57.000000000 +0100 @@ -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) (C 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_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); Index: src/gdb/fork-child.c =================================================================== --- src.orig/gdb/fork-child.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/fork-child.c 2008-08-16 14:20:57.000000000 +0100 @@ -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 { Index: src/gdb/linux-nat.c =================================================================== --- src.orig/gdb/linux-nat.c 2008-08-16 14:20:45.000000000 +0100 +++ src/gdb/linux-nat.c 2008-08-16 14:20:57.000000000 +0100 @@ -1456,18 +1456,10 @@ get_pending_status (struct lwp_info *lp, { /* 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 @@ -1495,9 +1487,10 @@ GPT: lwp %s had signal %s, but it is in { 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); @@ -3341,12 +3334,35 @@ linux_nat_find_memory_regions (int (*fun 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; @@ -3441,6 +3457,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 @@ -3454,25 +3471,13 @@ linux_nat_corefile_thread_callback (stru 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. */ @@ -3519,18 +3524,10 @@ linux_nat_make_corefile_notes (bfd *obfd 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); Index: src/gdb/procfs.c =================================================================== --- src.orig/gdb/procfs.c 2008-08-16 14:19:34.000000000 +0100 +++ src/gdb/procfs.c 2008-08-16 14:22:11.000000000 +0100 @@ -6051,13 +6051,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; @@ -6095,6 +6118,7 @@ struct procfs_corefile_thread_data { bfd *obfd; char *note_data; int *note_size; + enum target_signal stop_signal; }; static int @@ -6108,7 +6132,8 @@ procfs_corefile_thread_callback (procinf 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; @@ -6162,6 +6187,7 @@ procfs_make_note_section (bfd *obfd, int 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. */ Index: src/gdb/solib-irix.c =================================================================== --- src.orig/gdb/solib-irix.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/solib-irix.c 2008-08-16 14:20:57.000000000 +0100 @@ -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 Index: src/gdb/solib-osf.c =================================================================== --- src.orig/gdb/solib-osf.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/solib-osf.c 2008-08-16 14:30:08.000000000 +0100 @@ -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 Index: src/gdb/solib-sunos.c =================================================================== --- src.orig/gdb/solib-sunos.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/solib-sunos.c 2008-08-16 14:30:18.000000000 +0100 @@ -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" @@ -738,6 +739,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. */ @@ -759,15 +762,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 Index: src/gdb/solib-svr4.c =================================================================== --- src.orig/gdb/solib-svr4.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/solib-svr4.c 2008-08-16 14:29:51.000000000 +0100 @@ -31,6 +31,7 @@ #include "gdbcore.h" #include "target.h" #include "inferior.h" +#include "gdbthread.h" #include "gdb_assert.h" @@ -1388,6 +1389,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 (); @@ -1407,15 +1410,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) */ } Index: src/gdb/win32-nat.c =================================================================== --- src.orig/gdb/win32-nat.c 2008-08-16 14:18:51.000000000 +0100 +++ src/gdb/win32-nat.c 2008-08-16 14:20:57.000000000 +0100 @@ -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; }