[PATCH] [RFC, docs RFA] gdbserver and gdb.threads/attach-into-signal.exp.

Pedro Alves palves@redhat.com
Tue Mar 6 18:26:00 GMT 2012


Hi!

Any further comments on this?  Eli, this needs a documentation review.

<http://sourceware.org/ml/gdb-patches/2012-02/msg00481.html>

Thanks!

-- 
Pedro Alves

On 02/22/2012 05:19 PM, Pedro Alves wrote:

> This patch fixes gdbserver so that it passes attach-into-signal.exp.
> 
> Currently, we get (with the extended-remote board):
> 
> Running ../../../src/gdb/testsuite/gdb.threads/attach-into-signal.exp ...
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> FAIL: gdb.threads/attach-into-signal.exp: nonthreaded: detach (the program is no longer running)
> (...)
> 
> The test exercises attaching and findind the program stops with a
> signal not SIGSTOP, and then detaching, then attaching, etc, in a
> loop.
> 
> In gdb.log, we see:
> 
> (gdb) attach 28431
> Attaching to program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.threads/attach-into-signal-nothr, process 28431
> Attached; pid = 28431
> 
> Program received signal SIGALRM, Alarm clock.
> Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
> Loaded symbols for /lib64/libm.so.6
> Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
> Loaded symbols for /lib64/libc.so.6
> Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
> Loaded symbols for /lib64/ld-linux-x86-64.so.2
> 0x000000339e636285 in raise () from /lib64/libc.so.6
> (gdb) PASS: gdb.threads/attach-into-signal.exp: nonthreaded: attach (pass 1), pending signal catch
> attach (pass 1), pending signal catch succeeded on the attempt # 2 of 100
> detach
> Detaching from program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.threads/attach-into-signal-nothr, process 28431
> Detaching from process 28431
> (gdb) attach 28431
> Attaching to program: /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.threads/attach-into-signal-nothr, process 28431
> Attached; pid = 28431
> 
> Child terminated with signal = 0x6 (SIGABRT)
> warning: Selected architecture i386:x86-64 is not compatible with reported target architecture i386
> warning: Architecture rejected target-supplied description
> 
> Program terminated with signal SIGABRT, Aborted.
> 
> The test code reads:
> 
>   raise (SIGALRM);
> 
>   /* We must not get past this point, either in a free standing or debugged
>      state.  */
> 
>   abort ();
> 
> The issue is that when GDBserver detaches the inferior, it forgets the
> SIGALRM signal it had found when it attached, so the inferior doesn't
> get the signal (it is suppressed) and reaches the abort.  The fix is
> to make sure we forward the pending signals to the inferior on detach,
> like gdb/linux-nat.c does.  gdb/linux-nat.c does not pass down to the
> inferior signals that are in the "handle SIG nopass" state, however.
> GDBserver has no idea currently about the pass/nopass state of
> signals, so in order for GDBserver to do the same GDB, we need to make
> GDB tell GDBserver about the pass/nopass state of all signals.  This
> is recorded in GDB in the infrun.c:signal_program array.  The patch
> adds a new RSP packet QProgramSignals (similar to QPassSignals, though
> with different semantics) to do exactly that.
> 
> Comments on the approach?  I first thought of augmenting the detach
> packet, but I quickly gave up, due to pending signals and
> multi-threading (any, or multiple threads can have pending signals
> that need to be delivered).  I went back and forth between caring
> about "handle SIG nopass" at all.  It is always possible a signal gets
> queued right after we check for "handle SIG nopass", so we could just
> punt it, but I think this handles 99.99% of the cases and its what a
> users expect in the common case (especially for the case of the signal
> that _has_ been reported to GDB, if one gets program stopped by
> SIGFOO, and SIGFOO is nopass, I think it's reasonable to expect that
> detach suppresses it).
> 
> Tested on x86_64 Fedora 16, extended-remote gdbserver.  No
> regressions.  The test gdb.threads/attach-into-signal.exp test passes
> cleanly with the patch applied.
> 
> 2012-02-22  Pedro Alves  <palves@redhat.com>
> 
> 	gdb/doc/
> 	* gdb.texinfo (): Document new QProgramSignals packet.
> 	* gdb.texinfo (Remote configuration): Mention
> 	"program-signals-packet".
> 	(General Query Packets): Document QProgramSignals.
> 
> 	gdb/gdbserver/
> 	* linux-low.c (get_pending_signal): New.
> 	(linux_detach_one_lwp): Get rid of a pending SIGSTOP with SIGCONT.
> 	Pass on pending signals to PTRACE_DETACH.  Check the result of the
> 	ptrace call.
> 	* server.c (program_signals, program_signals_p): New.
> 	(handle_general_set): Handle QProgramSignals.
> 	* server.h (program_signals, program_signals_p): Declare.
> 
> 	gdb/
> 	* inferior.h (update_signals_program_target): Declare.
> 	* infrun.c: (update_signals_program_target): New.
> 	(handle_command): Update the target of the new program signals
> 	array changes.
> 	* remote.c (PACKET_QProgramSignals): New enum.
> 	(last_program_signals_packet): New global.
> 	(remote_program_signals): New.
> 	(remote_start_remote): Update the target with the program signals
> 	list.
> 	(remote_protocol_features): Add entry for QPassSignals.
> 	(remote_open_1): Free anc clear last_program_signals_packet.
> 	(init_remote_ops): Install remote_program_signals.
> 	* target.c (update_current_target): Adjust.
> 	(target_program_signals): New.
> 	* target.h (struct target_ops) <to_program_signals>: New field.
> 	(target_program_signals): Declare.
> ---
>  gdb/doc/gdb.texinfo       |   46 ++++++++++++++++++++
>  gdb/gdbserver/linux-low.c |  105 ++++++++++++++++++++++++++++++++++++++++++---
>  gdb/gdbserver/server.c    |   33 ++++++++++++++
>  gdb/gdbserver/server.h    |    2 +
>  gdb/inferior.h            |    2 +
>  gdb/infrun.c              |   10 ++++
>  gdb/remote.c              |   75 ++++++++++++++++++++++++++++++++
>  gdb/target.c              |   31 +++++++++++++
>  gdb/target.h              |   20 +++++++++
>  9 files changed, 315 insertions(+), 9 deletions(-)
> 
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 73779a7..8223931 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -17453,6 +17453,10 @@ are:
>  @tab @code{QPassSignals}
>  @tab @code{handle @var{signal}}
>  
> +@item @code{program-signals}
> +@tab @code{QProgramSignals}
> +@tab @code{handle @var{signal}}
> +
>  @item @code{hostio-close-packet}
>  @tab @code{vFile:close}
>  @tab @code{remote get}, @code{remote put}
> @@ -34817,6 +34821,48 @@ command (@pxref{Remote Configuration, set remote pass-signals}).
>  This packet is not probed by default; the remote stub must request it,
>  by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
>  
> +@item QProgramSignals: @var{signal} @r{[};@var{signal}@r{]}@dots{}
> +@cindex signals the inferior may see, remote request
> +@cindex @samp{QProgramSignals} packet
> +@anchor{QProgramSignals}
> +Each listed @var{signal} may be delivered to the inferior process.
> +Others should be silently discarded.
> +
> +In some cases, the remote stub may need to decide whether to deliver a
> +signal to the program or not without @value{GDBN} involvement.  One
> +example of that is while detaching --- the program's threads may have
> +stopped for signals that haven't yet had a chance of being reported to
> +@value{GDBN}, and so the remote stub can use the signal list specified
> +by this packet to know whether to deliver or ignore those pending
> +signals.
> +
> +This does not influence whether to deliver a signal as requested by a
> +resumption packet (@pxref{vCont packet}).
> +
> +Signals are numbered identically to continue packets and stop replies
> +(@pxref{Stop Reply Packets}).  Each @var{signal} list item should be
> +strictly greater than the previous item.  Multiple
> +@samp{QProgramSignals} packets do not combine; any earlier
> +@samp{QProgramSignals} list is completely replaced by the new list.
> +
> +Reply:
> +@table @samp
> +@item OK
> +The request succeeded.
> +
> +@item E @var{nn}
> +An error occurred.  @var{nn} are hex digits.
> +
> +@item
> +An empty reply indicates that @samp{QProgramSignals} is not supported
> +by the stub.
> +@end table
> +
> +Use of this packet is controlled by the @code{set remote program-signals}
> +command (@pxref{Remote Configuration, set remote program-signals}).
> +This packet is not probed by default; the remote stub must request it,
> +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
> +
>  @item qRcmd,@var{command}
>  @cindex execute remote command, remote request
>  @cindex @samp{qRcmd} packet
> diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
> index ab34d84..5353cff 100644
> --- a/gdb/gdbserver/linux-low.c
> +++ b/gdb/gdbserver/linux-low.c
> @@ -928,36 +928,125 @@ linux_kill (int pid)
>    return 0;
>  }
>  
> +/* Get pending signal of LP, for detaching purposes.  */
> +
> +static int
> +get_pending_signal (struct thread_info *thread)
> +{
> +  enum target_signal signo = TARGET_SIGNAL_0;
> +  int status;
> +  struct lwp_info *lp = get_thread_lwp (thread);
> +
> +  if (lp->status_pending_p)
> +    status = lp->status_pending;
> +  else
> +    {
> +      /* If the thread had been suspended by gdbserver, and it stopped
> +	 cleanly, then it'll have stopped with SIGSTOP.  But we don't
> +	 want to deliver that SIGSTOP.  */
> +      if (thread->last_status.kind != TARGET_WAITKIND_STOPPED
> +	  || thread->last_status.value.sig == TARGET_SIGNAL_0)
> +	return 0;
> +
> +      /* Otherwise, we may need to deliver the signal we
> +	 intercepted.  */
> +      status = lp->last_status;
> +    }
> +
> +  if (!WIFSTOPPED (status))
> +    {
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "GPS: lwp %s hasn't stopped: no pending signal\n",
> +		 target_pid_to_str (ptid_of (lp)));
> +      return 0;
> +    }
> +
> +  /* Extended wait statuses aren't real SIGTRAPs.  */
> +  if (WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
> +    {
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "GPS: lwp %s had stopped with extended "
> +		 "status: no pending signal\n",
> +		 target_pid_to_str (ptid_of (lp)));
> +      return 0;
> +    }
> +
> +  signo = target_signal_from_host (WSTOPSIG (status));
> +
> +  if (program_signals_p && !program_signals[signo])
> +    {
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "GPS: lwp %s had signal %s, but it is in nopass state\n",
> +		 target_pid_to_str (ptid_of (lp)),
> +		 target_signal_to_string (signo));
> +      return 0;
> +    }
> +  else if (!program_signals_p
> +	   /* If we have no way to know which signals GDB does not
> +	      want to have passed to the program, assume
> +	      SIGTRAP/SIGINT, which is GDB's default.  */
> +	   && (signo == TARGET_SIGNAL_TRAP || signo == TARGET_SIGNAL_INT))
> +    {
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "GPS: lwp %s had signal %s, "
> +		 "but we don't know if we should pass it.  Default to not.\n",
> +		 target_pid_to_str (ptid_of (lp)),
> +		 target_signal_to_string (signo));
> +      return 0;
> +    }
> +  else
> +    {
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "GPS: lwp %s has pending signal %s: delivering it.\n",
> +		 target_pid_to_str (ptid_of (lp)),
> +		 target_signal_to_string (signo));
> +
> +      return WSTOPSIG (status);
> +    }
> +}
> +
>  static int
>  linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
>  {
>    struct thread_info *thread = (struct thread_info *) entry;
>    struct lwp_info *lwp = get_thread_lwp (thread);
>    int pid = * (int *) args;
> +  int sig;
>  
>    if (ptid_get_pid (entry->id) != pid)
>      return 0;
>  
> -  /* If this process is stopped but is expecting a SIGSTOP, then make
> -     sure we take care of that now.  This isn't absolutely guaranteed
> -     to collect the SIGSTOP, but is fairly likely to.  */
> +  /* If there is a pending SIGSTOP, get rid of it.  */
>    if (lwp->stop_expected)
>      {
> -      int wstat;
> -      /* Clear stop_expected, so that the SIGSTOP will be reported.  */
> +      if (debug_threads)
> +	fprintf (stderr,
> +		 "Sending SIGCONT to %s\n",
> +		 target_pid_to_str (ptid_of (lwp)));
> +
> +      kill_lwp (lwpid_of (lwp), SIGCONT);
>        lwp->stop_expected = 0;
> -      linux_resume_one_lwp (lwp, 0, 0, NULL);
> -      linux_wait_for_event (lwp->head.id, &wstat, __WALL);
>      }
>  
>    /* Flush any pending changes to the process's registers.  */
>    regcache_invalidate_one ((struct inferior_list_entry *)
>  			   get_lwp_thread (lwp));
>  
> +  /* Pass on any pending signal for this thread.  */
> +  sig = get_pending_signal (thread);
> +
>    /* Finally, let it resume.  */
>    if (the_low_target.prepare_to_resume != NULL)
>      the_low_target.prepare_to_resume (lwp);
> -  ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, 0);
> +  if (ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, sig) < 0)
> +    error (_("Can't detach %s: %s"),
> +	   target_pid_to_str (ptid_of (lwp)),
> +	   strerror (errno));
>  
>    delete_lwp (lwp);
>    return 0;
> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index 37dc8d1..96429cb 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -58,6 +58,8 @@ int debug_threads;
>  int debug_hw_points;
>  
>  int pass_signals[TARGET_SIGNAL_LAST];
> +int program_signals[TARGET_SIGNAL_LAST];
> +int program_signals_p;
>  
>  jmp_buf toplevel;
>  
> @@ -454,6 +456,33 @@ handle_general_set (char *own_buf)
>        return;
>      }
>  
> +  if (strncmp ("QProgramSignals:", own_buf, strlen ("QProgramSignals:")) == 0)
> +    {
> +      int numsigs = (int) TARGET_SIGNAL_LAST, i;
> +      const char *p = own_buf + strlen ("QProgramSignals:");
> +      CORE_ADDR cursig;
> +
> +      program_signals_p = 1;
> +
> +      p = decode_address_to_semicolon (&cursig, p);
> +      for (i = 0; i < numsigs; i++)
> +	{
> +	  if (i == cursig)
> +	    {
> +	      program_signals[i] = 1;
> +	      if (*p == '\0')
> +		/* Keep looping, to clear the remaining signals.  */
> +		cursig = -1;
> +	      else
> +		p = decode_address_to_semicolon (&cursig, p);
> +	    }
> +	  else
> +	    program_signals[i] = 0;
> +	}
> +      strcpy (own_buf, "OK");
> +      return;
> +    }
> +
>    if (strcmp (own_buf, "QStartNoAckMode") == 0)
>      {
>        if (remote_debug)
> @@ -1559,7 +1588,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
>  	  free (qsupported);
>  	}
>  
> -      sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
> +      sprintf (own_buf,
> +	       "PacketSize=%x;QPassSignals+;QProgramSignals+",
> +	       PBUFSIZ - 1);
>  
>        if (the_target->qxfer_libraries_svr4 != NULL)
>  	strcat (own_buf, ";qXfer:libraries-svr4:read+");
> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index d3b4463..0a19664 100644
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -288,6 +288,8 @@ extern int server_waiting;
>  extern int debug_threads;
>  extern int debug_hw_points;
>  extern int pass_signals[];
> +extern int program_signals[];
> +extern int program_signals_p;
>  
>  extern jmp_buf toplevel;
>  
> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index 65abf26..2cd8be4 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -645,4 +645,6 @@ extern struct inferior *add_inferior_with_spaces (void);
>  
>  extern void update_observer_mode (void);
>  
> +extern void update_signals_program_target (void);
> +
>  #endif /* !defined (INFERIOR_H) */
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 1b2da67..ee4b9a7 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -335,6 +335,15 @@ static unsigned char *signal_pass;
>  	(flags)[signum] = 0; \
>    } while (0)
>  
> +/* Update the target's copy of SIGNAL_PROGRAM.  The sole purpose of
> +   this function is to avoid exporting `signal_program'.  */
> +
> +void
> +update_signals_program_target (void)
> +{
> +  target_program_signals ((int) TARGET_SIGNAL_LAST, signal_program);
> +}
> +
>  /* Value to pass to target_resume() to cause all threads to resume.  */
>  
>  #define RESUME_ALL minus_one_ptid
> @@ -6358,6 +6367,7 @@ Are you sure you want to change it? "),
>        {
>  	signal_cache_update (-1);
>  	target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass);
> +	target_program_signals ((int) TARGET_SIGNAL_LAST, signal_program);
>  
>  	if (from_tty)
>  	  {
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 14c343b..4e6ff1c 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -1254,6 +1254,7 @@ enum {
>    PACKET_qGetTLSAddr,
>    PACKET_qSupported,
>    PACKET_QPassSignals,
> +  PACKET_QProgramSignals,
>    PACKET_qSearch_memory,
>    PACKET_vAttach,
>    PACKET_vRun,
> @@ -1662,6 +1663,65 @@ remote_pass_signals (int numsigs, unsigned char *pass_signals)
>      }
>  }
>  
> +/* The last QProgramSignals packet sent to the target.  We bypass
> +   sending a new program signals list down to the target if the new
> +   packet is exactly the same as the last we sent.  IOW, we only let
> +   the target know about program signals list changes.  */
> +
> +static char *last_program_signals_packet;
> +
> +/* If 'QProgramSignals' is supported, tell the remote stub what
> +   signals it should pass through to the inferior when detaching.  */
> +
> +static void
> +remote_program_signals (int numsigs, unsigned char *signals)
> +{
> +  if (remote_protocol_packets[PACKET_QProgramSignals].support != PACKET_DISABLE)
> +    {
> +      char *packet, *p;
> +      int count = 0, i;
> +
> +      gdb_assert (numsigs < 256);
> +      for (i = 0; i < numsigs; i++)
> +	{
> +	  if (signals[i])
> +	    count++;
> +	}
> +      packet = xmalloc (count * 3 + strlen ("QProgramSignals:") + 1);
> +      strcpy (packet, "QProgramSignals:");
> +      p = packet + strlen (packet);
> +      for (i = 0; i < numsigs; i++)
> +	{
> +	  if (signal_pass_state (i))
> +	    {
> +	      if (i >= 16)
> +		*p++ = tohex (i >> 4);
> +	      *p++ = tohex (i & 15);
> +	      if (count)
> +		*p++ = ';';
> +	      else
> +		break;
> +	      count--;
> +	    }
> +	}
> +      *p = 0;
> +      if (!last_program_signals_packet
> +	  || strcmp (last_program_signals_packet, packet) != 0)
> +	{
> +	  struct remote_state *rs = get_remote_state ();
> +	  char *buf = rs->buf;
> +
> +	  putpkt (packet);
> +	  getpkt (&rs->buf, &rs->buf_size, 0);
> +	  packet_ok (buf, &remote_protocol_packets[PACKET_QProgramSignals]);
> +	  xfree (last_program_signals_packet);
> +	  last_program_signals_packet = packet;
> +	}
> +      else
> +	xfree (packet);
> +    }
> +}
> +
>  /* 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
> @@ -3253,6 +3313,10 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
>        getpkt (&rs->buf, &rs->buf_size, 0);
>      }
>  
> +  /* Let the target know which signals it is allowed to pass down to
> +     the program.  */
> +  update_signals_program_target ();
> +
>    /* Next, if the target can specify a description, read it.  We do
>       this before anything involving memory or registers.  */
>    target_find_description ();
> @@ -3800,6 +3864,8 @@ static struct protocol_feature remote_protocol_features[] = {
>      PACKET_qXfer_traceframe_info },
>    { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
>      PACKET_QPassSignals },
> +  { "QProgramSignals", PACKET_DISABLE, remote_supported_packet,
> +    PACKET_QProgramSignals },
>    { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
>      PACKET_QStartNoAckMode },
>    { "multiprocess", PACKET_DISABLE, remote_multi_process_feature, -1 },
> @@ -4065,6 +4131,11 @@ remote_open_1 (char *name, int from_tty,
>    xfree (last_pass_packet);
>    last_pass_packet = NULL;
>  
> +  /* Make sure we send the program signals list the next time we
> +     resume.  */
> +  xfree (last_program_signals_packet);
> +  last_program_signals_packet = NULL;
> +
>    remote_fileio_reset ();
>    reopen_exec_file ();
>    reread_symbols ();
> @@ -10715,6 +10786,7 @@ Specify the serial device it is connected to\n\
>    remote_ops.to_load = generic_load;
>    remote_ops.to_mourn_inferior = remote_mourn;
>    remote_ops.to_pass_signals = remote_pass_signals;
> +  remote_ops.to_program_signals = remote_program_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;
> @@ -11156,6 +11228,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_QPassSignals],
>  			 "QPassSignals", "pass-signals", 0);
>  
> +  add_packet_config_cmd (&remote_protocol_packets[PACKET_QProgramSignals],
> +			 "QProgramSignals", "program-signals", 0);
> +
>    add_packet_config_cmd (&remote_protocol_packets[PACKET_qSymbol],
>  			 "qSymbol", "symbol-lookup", 0);
>  
> diff --git a/gdb/target.c b/gdb/target.c
> index ad304bc..6098bd9 100644
> --- a/gdb/target.c
> +++ b/gdb/target.c
> @@ -638,6 +638,7 @@ update_current_target (void)
>        /* Do not inherit to_mourn_inferior.  */
>        INHERIT (to_can_run, t);
>        /* Do not inherit to_pass_signals.  */
> +      /* Do not inherit to_program_signals.  */
>        /* Do not inherit to_thread_alive.  */
>        /* Do not inherit to_find_new_threads.  */
>        /* Do not inherit to_pid_to_str.  */
> @@ -2713,6 +2714,36 @@ target_pass_signals (int numsigs, unsigned char *pass_signals)
>      }
>  }
>  
> +void
> +target_program_signals (int numsigs, unsigned char *program_signals)
> +{
> +  struct target_ops *t;
> +
> +  for (t = current_target.beneath; t != NULL; t = t->beneath)
> +    {
> +      if (t->to_program_signals != NULL)
> +	{
> +	  if (targetdebug)
> +	    {
> +	      int i;
> +
> +	      fprintf_unfiltered (gdb_stdlog, "target_program_signals (%d, {",
> +				  numsigs);
> +
> +	      for (i = 0; i < numsigs; i++)
> +		if (program_signals[i])
> +		  fprintf_unfiltered (gdb_stdlog, " %s",
> +				      target_signal_to_name (i));
> +
> +	      fprintf_unfiltered (gdb_stdlog, " })\n");
> +	    }
> +
> +	  (*t->to_program_signals) (numsigs, program_signals);
> +	  return;
> +	}
> +    }
> +}
> +
>  /* Look through the list of possible targets for a target that can
>     follow forks.  */
>  
> diff --git a/gdb/target.h b/gdb/target.h
> index d4605ae..f824ed4 100644
> --- a/gdb/target.h
> +++ b/gdb/target.h
> @@ -509,6 +509,10 @@ struct target_ops
>         target_* macro.  */
>      void (*to_pass_signals) (int, unsigned char *);
>  
> +    /* Documentation of this routine is provided with the
> +       corresponding target_* function.  */
> +    void (*to_program_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);
> @@ -1242,6 +1246,22 @@ void target_mourn_inferior (void);
>  
>  extern void target_pass_signals (int nsig, unsigned char *pass_signals);
>  
> +/* Set list of signals the target may pass to the inferior.  This
> +   directly maps to the "handle SIGNAL pass/nopass" setting.
> +
> +   PROGRAM_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 to pass the signal to the
> +   inferior.  Signals not present in the array shall be silently
> +   discarded.  This does not influence whether to pass signals to the
> +   inferior as a result of a target_resume call.  This is useful in
> +   scenarios where the target needs to decide whether to pass or not a
> +   signal to the inferior without GDB core involvement, such as for
> +   example, when detaching (as threads may have been suspended with
> +   pending signals not reported to GDB).  */
> +
> +extern void target_program_signals (int nsig, unsigned char *program_signals);
> +
>  /* Check to see if a thread is still alive.  */
>  
>  extern int target_thread_alive (ptid_t ptid);
> 




More information about the Gdb-patches mailing list