From: Ulrich Weigand Date: Wed, 27 Apr 2011 13:29:15 +0000 (+0000) Subject: * target.h (struct target_ops): Remove to_notice_signals; X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2455069d930b37918b92281be109444d1e38dc6d;p=binutils-gdb.git * target.h (struct target_ops): Remove to_notice_signals; add to_pass_signals. (target_notice_signals): Remove. (target_pass_signals): Add prototype. * target.c (update_current_target): Remove to_notice_signals; mention to_pass_signals. (target_pass_signals): New function. (debug_to_notice_signals): Remove. (setup_target_debug): Do not install debug_to_notice_signals. * infrun.c (signal_pass): New global. (resume): Call target_pass_signals. (handle_inferior_event): Report all signals while stepping over non-steppable watchpoint. Reset trap_expected to ensure breakpoints are re-inserted when stepping over a signal handler. (signal_cache_update): New function. (signal_stop_update): Call it. (signal_print_update): Likewise. (signal_pass_update): Likewise. (handle_command): Call signal_cache_update and target_pass_signals instead of target_notice_signals. (_initialize_infrun): Initialize signal_pass. * linux-nat.c (pass_mask): New global. (linux_nat_pass_signals): New function. (linux_nat_create_inferior): Report all signals initially. (linux_nat_attach): Likewise. (linux_nat_resume): Use pass_mask to decide whether to directly handle an inferior signal. (linux_nat_wait_1): Likewise. (linux_nat_add_target): Install to_pass_signals callback. * nto-procfs.c (notice_signals): Remove. (procfs_resume): Do not call notice_signals. (procfs_notice_signals): Remove. (procfs_pass_signals): New function. (init_procfs_ops): Install to_pass_signals callback instead of to_notice_signals callback. (_initialize_procfs): Report all signals initially. * procfs.c (procfs_notice_signals): Remove. (procfs_pass_signals): New function. (procfs_target): Install to_pass_signals callback instead of to_notice_signals callback. (register_gdb_signals): Remove. (procfs_debug_inferior): Report all signals initially. (procfs_init_inferior): Remove redundant register_gdb_signals call. * remote.c (remote_pass_signals): Add numsigs and pass_signals parameters; use them instead of calling signal_..._state routines. (remote_notice_signals): Remove. (remote_start_remote): Report all signals initially. (remote_resume): Do not call remote_pass_signals. (_initialize_remote): Install to_pass_signals callback instead of to_notice_signals callback. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3511bc0c1e1..d829658a141 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,61 @@ +2011-04-27 Ulrich Weigand + + * target.h (struct target_ops): Remove to_notice_signals; + add to_pass_signals. + (target_notice_signals): Remove. + (target_pass_signals): Add prototype. + * target.c (update_current_target): Remove to_notice_signals; + mention to_pass_signals. + (target_pass_signals): New function. + (debug_to_notice_signals): Remove. + (setup_target_debug): Do not install debug_to_notice_signals. + + * infrun.c (signal_pass): New global. + (resume): Call target_pass_signals. + (handle_inferior_event): Report all signals while stepping over + non-steppable watchpoint. Reset trap_expected to ensure breakpoints + are re-inserted when stepping over a signal handler. + (signal_cache_update): New function. + (signal_stop_update): Call it. + (signal_print_update): Likewise. + (signal_pass_update): Likewise. + (handle_command): Call signal_cache_update and target_pass_signals + instead of target_notice_signals. + (_initialize_infrun): Initialize signal_pass. + + * linux-nat.c (pass_mask): New global. + (linux_nat_pass_signals): New function. + (linux_nat_create_inferior): Report all signals initially. + (linux_nat_attach): Likewise. + (linux_nat_resume): Use pass_mask to decide whether to directly + handle an inferior signal. + (linux_nat_wait_1): Likewise. + (linux_nat_add_target): Install to_pass_signals callback. + + * nto-procfs.c (notice_signals): Remove. + (procfs_resume): Do not call notice_signals. + (procfs_notice_signals): Remove. + (procfs_pass_signals): New function. + (init_procfs_ops): Install to_pass_signals callback instead of + to_notice_signals callback. + (_initialize_procfs): Report all signals initially. + + * procfs.c (procfs_notice_signals): Remove. + (procfs_pass_signals): New function. + (procfs_target): Install to_pass_signals callback instead of + to_notice_signals callback. + (register_gdb_signals): Remove. + (procfs_debug_inferior): Report all signals initially. + (procfs_init_inferior): Remove redundant register_gdb_signals call. + + * remote.c (remote_pass_signals): Add numsigs and pass_signals + parameters; use them instead of calling signal_..._state routines. + (remote_notice_signals): Remove. + (remote_start_remote): Report all signals initially. + (remote_resume): Do not call remote_pass_signals. + (_initialize_remote): Install to_pass_signals callback instead of + to_notice_signals callback. + 2011-04-27 Pedro Alves * breakpoint.c (user_settable_breakpoint): Delete. diff --git a/gdb/infrun.c b/gdb/infrun.c index 8eccb60a4fe..67381fafce6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -276,6 +276,11 @@ static unsigned char *signal_stop; static unsigned char *signal_print; static unsigned char *signal_program; +/* Table of signals that the target may silently handle. + This is automatically determined from the flags above, + and simply cached here. */ +static unsigned char *signal_pass; + #define SET_SIGS(nsigs,sigs,flags) \ do { \ int signum = (nsigs); \ @@ -1787,6 +1792,18 @@ a command like `return' or `jump' to continue execution.")); happens to apply to another thread. */ tp->suspend.stop_signal = TARGET_SIGNAL_0; + /* Advise target which signals may be handled silently. If we have + removed breakpoints because we are stepping over one (which can + happen only if we are not using displaced stepping), we need to + receive all signals to avoid accidentally skipping a breakpoint + during execution of a signal handler. */ + if ((step || singlestep_breakpoints_inserted_p) + && tp->control.trap_expected + && !use_displaced_stepping (gdbarch)) + target_pass_signals (0, NULL); + else + target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass); + target_resume (resume_ptid, step, sig); } @@ -3818,7 +3835,12 @@ handle_inferior_event (struct execution_control_state *ecs) int hw_step = 1; if (!target_have_steppable_watchpoint) - remove_breakpoints (); + { + remove_breakpoints (); + /* See comment in resume why we need to stop bypassing signals + while breakpoints have been removed. */ + target_pass_signals (0, NULL); + } /* Single step */ hw_step = maybe_software_singlestep (gdbarch, stop_pc); target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0); @@ -4090,6 +4112,8 @@ process_event_stop_test: insert_step_resume_breakpoint_at_frame (frame); ecs->event_thread->step_after_step_resume_breakpoint = 1; + /* Reset trap_expected to ensure breakpoints are re-inserted. */ + ecs->event_thread->control.trap_expected = 0; keep_going (ecs); return; } @@ -4117,6 +4141,8 @@ process_event_stop_test: "single-step range\n"); insert_step_resume_breakpoint_at_frame (frame); + /* Reset trap_expected to ensure breakpoints are re-inserted. */ + ecs->event_thread->control.trap_expected = 0; keep_going (ecs); return; } @@ -5853,12 +5879,29 @@ signal_pass_state (int signo) return signal_program[signo]; } +static void +signal_cache_update (int signo) +{ + if (signo == -1) + { + for (signo = 0; signo < (int) TARGET_SIGNAL_LAST; signo++) + signal_cache_update (signo); + + return; + } + + signal_pass[signo] = (signal_stop[signo] == 0 + && signal_print[signo] == 0 + && signal_program[signo] == 1); +} + int signal_stop_update (int signo, int state) { int ret = signal_stop[signo]; signal_stop[signo] = state; + signal_cache_update (signo); return ret; } @@ -5868,6 +5911,7 @@ signal_print_update (int signo, int state) int ret = signal_print[signo]; signal_print[signo] = state; + signal_cache_update (signo); return ret; } @@ -5877,6 +5921,7 @@ signal_pass_update (int signo, int state) int ret = signal_program[signo]; signal_program[signo] = state; + signal_cache_update (signo); return ret; } @@ -6068,7 +6113,8 @@ Are you sure you want to change it? "), for (signum = 0; signum < nsigs; signum++) if (sigs[signum]) { - target_notice_signals (inferior_ptid); + signal_cache_update (-1); + target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass); if (from_tty) { @@ -6920,6 +6966,8 @@ leave it stopped or free to run as needed."), xmalloc (sizeof (signal_print[0]) * numsigs); signal_program = (unsigned char *) xmalloc (sizeof (signal_program[0]) * numsigs); + signal_pass = (unsigned char *) + xmalloc (sizeof (signal_program[0]) * numsigs); for (i = 0; i < numsigs; i++) { signal_stop[i] = 1; @@ -6963,6 +7011,9 @@ leave it stopped or free to run as needed."), signal_stop[TARGET_SIGNAL_CANCEL] = 0; signal_print[TARGET_SIGNAL_CANCEL] = 0; + /* Update cached state. */ + signal_cache_update (-1); + add_setshow_zinteger_cmd ("stop-on-solib-events", class_support, &stop_on_solib_events, _("\ Set stopping for shared library events."), _("\ diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 741d5f81d95..08f49e484c9 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1041,6 +1041,26 @@ restore_child_signals_mask (sigset_t *prev_mask) { sigprocmask (SIG_SETMASK, prev_mask, NULL); } + +/* Mask of signals to pass directly to the inferior. */ +static sigset_t pass_mask; + +/* Update signals to pass to the inferior. */ +static void +linux_nat_pass_signals (int numsigs, unsigned char *pass_signals) +{ + int signo; + + sigemptyset (&pass_mask); + + for (signo = 1; signo < NSIG; signo++) + { + int target_signo = target_signal_from_host (signo); + if (target_signo < numsigs && pass_signals[target_signo]) + sigaddset (&pass_mask, signo); + } +} + /* Prototypes for local functions. */ @@ -1506,6 +1526,9 @@ linux_nat_create_inferior (struct target_ops *ops, } #endif /* HAVE_PERSONALITY */ + /* Make sure we report all signals during startup. */ + linux_nat_pass_signals (0, NULL); + linux_ops->to_create_inferior (ops, exec_file, allargs, env, from_tty); #ifdef HAVE_PERSONALITY @@ -1527,6 +1550,9 @@ linux_nat_attach (struct target_ops *ops, char *args, int from_tty) int status; ptid_t ptid; + /* Make sure we report all signals during attach. */ + linux_nat_pass_signals (0, NULL); + linux_ops->to_attach (ops, args, from_tty); /* The ptrace base target adds the main thread with (pid,0,0) @@ -1885,19 +1911,9 @@ linux_nat_resume (struct target_ops *ops, if (lp->status && WIFSTOPPED (lp->status)) { - enum target_signal saved_signo; - struct inferior *inf; - - inf = find_inferior_pid (ptid_get_pid (lp->ptid)); - gdb_assert (inf); - saved_signo = target_signal_from_host (WSTOPSIG (lp->status)); - - /* Defer to common code if we're gaining control of the - inferior. */ - if (inf->control.stop_soon == NO_STOP_QUIETLY - && signal_stop_state (saved_signo) == 0 - && signal_print_state (saved_signo) == 0 - && signal_pass_state (saved_signo) == 1) + if (!lp->step + && WSTOPSIG (lp->status) + && sigismember (&pass_mask, WSTOPSIG (lp->status))) { if (debug_linux_nat) fprintf_unfiltered (gdb_stdlog, @@ -1907,7 +1923,7 @@ linux_nat_resume (struct target_ops *ops, /* FIXME: What should we do if we are supposed to continue this thread with a signal? */ gdb_assert (signo == TARGET_SIGNAL_0); - signo = saved_signo; + signo = target_signal_from_host (WSTOPSIG (lp->status)); lp->status = 0; } } @@ -3553,20 +3569,11 @@ retry: if (WIFSTOPPED (status)) { enum target_signal signo = target_signal_from_host (WSTOPSIG (status)); - struct inferior *inf; - - inf = find_inferior_pid (ptid_get_pid (lp->ptid)); - gdb_assert (inf); - /* Defer to common code if we get a signal while - single-stepping, since that may need special care, e.g. to - skip the signal handler, or, if we're gaining control of the - inferior. */ + /* When using hardware single-step, we need to report every signal. + Otherwise, signals in pass_mask may be short-circuited. */ if (!lp->step - && inf->control.stop_soon == NO_STOP_QUIETLY - && signal_stop_state (signo) == 0 - && signal_print_state (signo) == 0 - && signal_pass_state (signo) == 1) + && WSTOPSIG (status) && sigismember (&pass_mask, WSTOPSIG (status))) { /* FIMXE: kettenis/2001-06-06: Should we resume all threads here? It is not clear we should. GDB may not expect @@ -5675,6 +5682,7 @@ linux_nat_add_target (struct target_ops *t) t->to_detach = linux_nat_detach; t->to_resume = linux_nat_resume; t->to_wait = linux_nat_wait; + t->to_pass_signals = linux_nat_pass_signals; t->to_xfer_partial = linux_nat_xfer_partial; t->to_kill = linux_nat_kill; t->to_mourn_inferior = linux_nat_mourn_inferior; diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c index 3519f33092f..38247755a19 100644 --- a/gdb/nto-procfs.c +++ b/gdb/nto-procfs.c @@ -64,8 +64,6 @@ static int procfs_xfer_memory (CORE_ADDR, gdb_byte *, int, int, struct mem_attrib *attrib, struct target_ops *); -static void notice_signals (void); - static void init_procfs_ops (void); static ptid_t do_attach (ptid_t ptid); @@ -985,8 +983,6 @@ procfs_resume (struct target_ops *ops, run.flags |= _DEBUG_RUN_ARM; - sigemptyset (&run.trace); - notice_signals (); signal_to_pass = target_signal_to_host (signo); if (signal_to_pass) @@ -1334,34 +1330,23 @@ procfs_store_registers (struct target_ops *ops, } } +/* Set list of signals to be handled in the target. */ + static void -notice_signals (void) +procfs_pass_signals (int numsigs, unsigned char *pass_signals) { int signo; + sigfillset (&run.trace); + for (signo = 1; signo < NSIG; signo++) { - if (signal_stop_state (target_signal_from_host (signo)) == 0 - && signal_print_state (target_signal_from_host (signo)) == 0 - && signal_pass_state (target_signal_from_host (signo)) == 1) - sigdelset (&run.trace, signo); - else - sigaddset (&run.trace, signo); + int target_signo = target_signal_from_host (signo); + if (target_signo < numsigs && pass_signals[target_signo]) + sigdelset (&run.trace, signo); } } -/* When the user changes the state of gdb's signal handling via the - "handle" command, this function gets called to see if any change - in the /proc interface is required. It is also called internally - by other /proc interface functions to initialize the state of - the traced signal set. */ -static void -procfs_notice_signals (ptid_t ptid) -{ - sigemptyset (&run.trace); - notice_signals (); -} - static struct tidinfo * procfs_thread_info (pid_t pid, short tid) { @@ -1426,7 +1411,7 @@ init_procfs_ops (void) procfs_ops.to_create_inferior = procfs_create_inferior; procfs_ops.to_mourn_inferior = procfs_mourn_inferior; procfs_ops.to_can_run = procfs_can_run; - procfs_ops.to_notice_signals = procfs_notice_signals; + procfs_ops.to_pass_signals = procfs_pass_signals; procfs_ops.to_thread_alive = procfs_thread_alive; procfs_ops.to_find_new_threads = procfs_find_new_threads; procfs_ops.to_pid_to_str = procfs_pid_to_str; @@ -1458,8 +1443,8 @@ _initialize_procfs (void) sigaddset (&set, SIGUSR1); sigprocmask (SIG_BLOCK, &set, NULL); - /* Set up trace and fault sets, as gdb expects them. */ - sigemptyset (&run.trace); + /* Initially, make sure all signals are reported. */ + sigfillset (&run.trace); /* Stuff some information. */ nto_cpuinfo_flags = SYSPAGE_ENTRY (cpuinfo)->flags; diff --git a/gdb/procfs.c b/gdb/procfs.c index 5d7cb239542..2a21526f557 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -120,7 +120,7 @@ static void procfs_fetch_registers (struct target_ops *, struct regcache *, int); static void procfs_store_registers (struct target_ops *, struct regcache *, int); -static void procfs_notice_signals (ptid_t); +static void procfs_pass_signals (ptid_t, int, unsigned char *); static void procfs_kill_inferior (struct target_ops *ops); static void procfs_mourn_inferior (struct target_ops *ops); static void procfs_create_inferior (struct target_ops *, char *, @@ -201,7 +201,7 @@ procfs_target (void) t->to_store_registers = procfs_store_registers; t->to_xfer_partial = procfs_xfer_partial; t->deprecated_xfer_memory = procfs_xfer_memory; - t->to_notice_signals = procfs_notice_signals; + t->to_pass_signals = procfs_pass_signals; t->to_files_info = procfs_files_info; t->to_stop = procfs_stop; @@ -3147,7 +3147,6 @@ proc_iterate_over_threads (procinfo *pi, static ptid_t do_attach (ptid_t ptid); static void do_detach (int signo); -static int register_gdb_signals (procinfo *, gdb_sigset_t *); static void proc_trace_syscalls_1 (procinfo *pi, int syscallnum, int entry_or_exit, int mode, int from_tty); @@ -3186,9 +3185,9 @@ procfs_debug_inferior (procinfo *pi) if (!proc_set_traced_faults (pi, &traced_faults)) return __LINE__; - /* Register to trace selected signals in the child. */ - premptyset (&traced_signals); - if (!register_gdb_signals (pi, &traced_signals)) + /* Initially, register to trace all signals in the child. */ + prfillset (&traced_signals); + if (!proc_set_traced_signals (pi, &traced_signals)) return __LINE__; @@ -4464,40 +4463,26 @@ procfs_resume (struct target_ops *ops, } } -/* Traverse the list of signals that GDB knows about (see "handle" - command), and arrange for the target to be stopped or not, - according to these settings. Returns non-zero for success, zero - for failure. */ - -static int -register_gdb_signals (procinfo *pi, gdb_sigset_t *signals) -{ - int signo; - - for (signo = 0; signo < NSIG; signo ++) - if (signal_stop_state (target_signal_from_host (signo)) == 0 && - signal_print_state (target_signal_from_host (signo)) == 0 && - signal_pass_state (target_signal_from_host (signo)) == 1) - gdb_prdelset (signals, signo); - else - gdb_praddset (signals, signo); - - return proc_set_traced_signals (pi, signals); -} - /* Set up to trace signals in the child process. */ static void -procfs_notice_signals (ptid_t ptid) +procfs_pass_signals (int numsigs, unsigned char *pass_signals) { gdb_sigset_t signals; - procinfo *pi = find_procinfo_or_die (PIDGET (ptid), 0); + procinfo *pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); + int signo; - if (proc_get_traced_signals (pi, &signals) && - register_gdb_signals (pi, &signals)) - return; - else - proc_error (pi, "notice_signals", __LINE__); + prfillset (&signals); + + for (signo = 0; signo < NSIG; signo++) + { + int target_signo = target_signal_from_host (signo); + if (target_signo < numsigs && pass_signals[target_signo]) + gdb_prdelset (&signals, signo); + } + + if (!proc_set_traced_signals (pi, &signals)) + proc_error (pi, "pass_signals", __LINE__); } /* Print status information about the child process. */ @@ -4679,11 +4664,6 @@ procfs_init_inferior (struct target_ops *ops, int pid) if (!proc_get_traced_sysexit (pi, pi->saved_exitset)) proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__); - /* Register to trace selected signals in the child. */ - prfillset (&signals); - if (!register_gdb_signals (pi, &signals)) - proc_error (pi, "init_inferior, register_signals", __LINE__); - if ((fail = procfs_debug_inferior (pi)) != 0) proc_error (pi, "init_inferior (procfs_debug_inferior)", fail); diff --git a/gdb/remote.c b/gdb/remote.c index 9a0eae0a857..76c137a2d1d 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1596,20 +1596,17 @@ static char *last_pass_packet; it can simply pass through to the inferior without reporting. */ static void -remote_pass_signals (void) +remote_pass_signals (int numsigs, unsigned char *pass_signals) { if (remote_protocol_packets[PACKET_QPassSignals].support != PACKET_DISABLE) { char *pass_packet, *p; - int numsigs = (int) TARGET_SIGNAL_LAST; int count = 0, i; gdb_assert (numsigs < 256); for (i = 0; i < numsigs; i++) { - if (signal_stop_state (i) == 0 - && signal_print_state (i) == 0 - && signal_pass_state (i) == 1) + if (pass_signals[i]) count++; } pass_packet = xmalloc (count * 3 + strlen ("QPassSignals:") + 1); @@ -1617,9 +1614,7 @@ remote_pass_signals (void) p = pass_packet + strlen (pass_packet); for (i = 0; i < numsigs; i++) { - if (signal_stop_state (i) == 0 - && signal_print_state (i) == 0 - && signal_pass_state (i) == 1) + if (pass_signals[i]) { if (i >= 16) *p++ = tohex (i >> 4); @@ -1649,14 +1644,6 @@ remote_pass_signals (void) } } -static void -remote_notice_signals (ptid_t ptid) -{ - /* Update the remote on signals to silently pass, if they've - changed. */ - remote_pass_signals (); -} - /* If PTID is MAGIC_NULL_PTID, don't set any thread. If PTID is MINUS_ONE_PTID, set the thread to -1, so the stub returns the thread. If GEN is set, set the general thread, if not, then set @@ -3378,10 +3365,8 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) the stop reply queue. */ gdb_assert (wait_status == NULL); - /* Update the remote on signals to silently pass, or more - importantly, which to not ignore, in case a previous session - had set some different set of signals to be ignored. */ - remote_pass_signals (); + /* Report all signals during attach/startup. */ + remote_pass_signals (0, NULL); } /* If we connected to a live target, do some additional setup. */ @@ -4549,9 +4534,6 @@ remote_resume (struct target_ops *ops, last_sent_signal = siggnal; last_sent_step = step; - /* Update the inferior on signals to silently pass, if they've changed. */ - remote_pass_signals (); - /* The vCont packet doesn't need to specify threads via Hc. */ /* No reverse support (yet) for vCont. */ if (execution_direction != EXEC_REVERSE) @@ -10293,7 +10275,7 @@ Specify the serial device it is connected to\n\ remote_ops.to_kill = remote_kill; remote_ops.to_load = generic_load; remote_ops.to_mourn_inferior = remote_mourn; - remote_ops.to_notice_signals = remote_notice_signals; + remote_ops.to_pass_signals = remote_pass_signals; remote_ops.to_thread_alive = remote_thread_alive; remote_ops.to_find_new_threads = remote_threads_info; remote_ops.to_pid_to_str = remote_pid_to_str; diff --git a/gdb/target.c b/gdb/target.c index a032052229f..1e1c38e0ea6 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -149,8 +149,6 @@ static void debug_to_load (char *, int); static int debug_to_can_run (void); -static void debug_to_notice_signals (ptid_t); - static void debug_to_stop (ptid_t); /* Pointer to array of target architecture structures; the size of the @@ -625,7 +623,7 @@ update_current_target (void) INHERIT (to_has_exited, t); /* Do not inherit to_mourn_inferior. */ INHERIT (to_can_run, t); - INHERIT (to_notice_signals, t); + /* Do not inherit to_pass_signals. */ /* Do not inherit to_thread_alive. */ /* Do not inherit to_find_new_threads. */ /* Do not inherit to_pid_to_str. */ @@ -793,9 +791,6 @@ update_current_target (void) return_zero); de_fault (to_can_run, return_zero); - de_fault (to_notice_signals, - (void (*) (ptid_t)) - target_ignore); de_fault (to_extra_thread_info, (char *(*) (struct thread_info *)) return_zero); @@ -2587,6 +2582,37 @@ target_resume (ptid_t ptid, int step, enum target_signal signal) noprocess (); } + +void +target_pass_signals (int numsigs, unsigned char *pass_signals) +{ + struct target_ops *t; + + for (t = current_target.beneath; t != NULL; t = t->beneath) + { + if (t->to_pass_signals != NULL) + { + if (targetdebug) + { + int i; + + fprintf_unfiltered (gdb_stdlog, "target_pass_signals (%d, {", + numsigs); + + for (i = 0; i < numsigs; i++) + if (pass_signals[i]) + fprintf_unfiltered (gdb_stdlog, " %s", + target_signal_to_name (i)); + + fprintf_unfiltered (gdb_stdlog, " })\n"); + } + + (*t->to_pass_signals) (numsigs, pass_signals); + return; + } + } +} + /* Look through the list of possible targets for a target that can follow forks. */ @@ -3914,15 +3940,6 @@ debug_to_can_run (void) return retval; } -static void -debug_to_notice_signals (ptid_t ptid) -{ - debug_target.to_notice_signals (ptid); - - fprintf_unfiltered (gdb_stdlog, "target_notice_signals (%d)\n", - PIDGET (ptid)); -} - static struct gdbarch * debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid) { @@ -4010,7 +4027,6 @@ setup_target_debug (void) current_target.to_remove_exec_catchpoint = debug_to_remove_exec_catchpoint; current_target.to_has_exited = debug_to_has_exited; current_target.to_can_run = debug_to_can_run; - current_target.to_notice_signals = debug_to_notice_signals; current_target.to_stop = debug_to_stop; current_target.to_rcmd = debug_to_rcmd; current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file; diff --git a/gdb/target.h b/gdb/target.h index f0b2e43fe7d..11380edf299 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -494,7 +494,11 @@ struct target_ops int (*to_has_exited) (int, int, int *); void (*to_mourn_inferior) (struct target_ops *); int (*to_can_run) (void); - void (*to_notice_signals) (ptid_t ptid); + + /* Documentation of this routine is provided with the corresponding + target_* macro. */ + void (*to_pass_signals) (int, unsigned char *); + int (*to_thread_alive) (struct target_ops *, ptid_t ptid); void (*to_find_new_threads) (struct target_ops *); char *(*to_pid_to_str) (struct target_ops *, ptid_t); @@ -1120,10 +1124,19 @@ void target_mourn_inferior (void); #define target_can_run(t) \ ((t)->to_can_run) () -/* post process changes to signal handling in the inferior. */ +/* Set list of signals to be handled in the target. + + PASS_SIGNALS is an array of size NSIG, indexed by target signal number + (enum target_signal). For every signal whose entry in this array is + non-zero, the target is allowed -but not required- to skip reporting + arrival of the signal to the GDB core by returning from target_wait, + and to pass the signal directly to the inferior instead. + + However, if the target is hardware single-stepping a thread that is + about to receive a signal, it needs to be reported in any case, even + if mentioned in a previous target_pass_signals call. */ -#define target_notice_signals(ptid) \ - (*current_target.to_notice_signals) (ptid) +extern void target_pass_signals (int nsig, unsigned char *pass_signals); /* Check to see if a thread is still alive. */