aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport/signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/signals.c')
-rw-r--r--gdbsupport/signals.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/gdbsupport/signals.c b/gdbsupport/signals.c
new file mode 100644
index 0000000..485e0f0
--- /dev/null
+++ b/gdbsupport/signals.c
@@ -0,0 +1,653 @@
+/* Target signal translation functions for GDB.
+ Copyright (C) 1990-2020 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "common-defs.h"
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#include "gdb_signals.h"
+
+struct gdbarch;
+
+/* Always use __SIGRTMIN if it's available. SIGRTMIN is the lowest
+ _available_ realtime signal, not the lowest supported; glibc takes
+ several for its own use. */
+
+#ifndef REALTIME_LO
+# if defined(__SIGRTMIN)
+# define REALTIME_LO __SIGRTMIN
+# define REALTIME_HI (__SIGRTMAX + 1)
+# elif defined(SIGRTMIN)
+# define REALTIME_LO SIGRTMIN
+# define REALTIME_HI (SIGRTMAX + 1)
+# endif
+#endif
+
+/* This table must match in order and size the signals in enum
+ gdb_signal. */
+
+static const struct {
+ const char *symbol;
+ const char *name;
+ const char *string;
+ } signals [] =
+{
+#define SET(symbol, constant, name, string) { #symbol, name, string },
+#include "gdb/signals.def"
+#undef SET
+};
+
+const char *
+gdb_signal_to_symbol_string (enum gdb_signal sig)
+{
+ gdb_assert ((int) sig >= GDB_SIGNAL_FIRST && (int) sig <= GDB_SIGNAL_LAST);
+
+ return signals[sig].symbol;
+}
+
+/* Return the string for a signal. */
+const char *
+gdb_signal_to_string (enum gdb_signal sig)
+{
+ if ((int) sig >= GDB_SIGNAL_FIRST && (int) sig <= GDB_SIGNAL_LAST)
+ return signals[sig].string;
+ else
+ return signals[GDB_SIGNAL_UNKNOWN].string;
+}
+
+/* Return the name for a signal. */
+const char *
+gdb_signal_to_name (enum gdb_signal sig)
+{
+ if ((int) sig >= GDB_SIGNAL_FIRST && (int) sig <= GDB_SIGNAL_LAST
+ && signals[sig].name != NULL)
+ return signals[sig].name;
+ else
+ /* I think the code which prints this will always print it along
+ with the string, so no need to be verbose (very old comment). */
+ return "?";
+}
+
+/* Given a name, return its signal. */
+enum gdb_signal
+gdb_signal_from_name (const char *name)
+{
+ enum gdb_signal sig;
+
+ /* It's possible we also should allow "SIGCLD" as well as "SIGCHLD"
+ for GDB_SIGNAL_SIGCHLD. SIGIOT, on the other hand, is more
+ questionable; seems like by now people should call it SIGABRT
+ instead. */
+
+ /* This ugly cast brought to you by the native VAX compiler. */
+ for (sig = GDB_SIGNAL_HUP;
+ sig < GDB_SIGNAL_LAST;
+ sig = (enum gdb_signal) ((int) sig + 1))
+ if (signals[sig].name != NULL
+ && strcmp (name, signals[sig].name) == 0)
+ return sig;
+ return GDB_SIGNAL_UNKNOWN;
+}
+
+/* The following functions are to help certain targets deal
+ with the signal/waitstatus stuff. They could just as well be in
+ a file called native-utils.c or unixwaitstatus-utils.c or whatever. */
+
+/* Convert host signal to our signals. */
+enum gdb_signal
+gdb_signal_from_host (int hostsig)
+{
+ /* A switch statement would make sense but would require special
+ kludges to deal with the cases where more than one signal has the
+ same number. Signals are ordered ANSI-standard signals first,
+ other signals second, with signals in each block ordered by their
+ numerical values on a typical POSIX platform. */
+
+ if (hostsig == 0)
+ return GDB_SIGNAL_0;
+
+ /* SIGINT, SIGILL, SIGABRT, SIGFPE, SIGSEGV and SIGTERM
+ are ANSI-standard signals and are always available. */
+ if (hostsig == SIGINT)
+ return GDB_SIGNAL_INT;
+ if (hostsig == SIGILL)
+ return GDB_SIGNAL_ILL;
+ if (hostsig == SIGABRT)
+ return GDB_SIGNAL_ABRT;
+ if (hostsig == SIGFPE)
+ return GDB_SIGNAL_FPE;
+ if (hostsig == SIGSEGV)
+ return GDB_SIGNAL_SEGV;
+ if (hostsig == SIGTERM)
+ return GDB_SIGNAL_TERM;
+
+ /* All other signals need preprocessor conditionals. */
+#if defined (SIGHUP)
+ if (hostsig == SIGHUP)
+ return GDB_SIGNAL_HUP;
+#endif
+#if defined (SIGQUIT)
+ if (hostsig == SIGQUIT)
+ return GDB_SIGNAL_QUIT;
+#endif
+#if defined (SIGTRAP)
+ if (hostsig == SIGTRAP)
+ return GDB_SIGNAL_TRAP;
+#endif
+#if defined (SIGEMT)
+ if (hostsig == SIGEMT)
+ return GDB_SIGNAL_EMT;
+#endif
+#if defined (SIGKILL)
+ if (hostsig == SIGKILL)
+ return GDB_SIGNAL_KILL;
+#endif
+#if defined (SIGBUS)
+ if (hostsig == SIGBUS)
+ return GDB_SIGNAL_BUS;
+#endif
+#if defined (SIGSYS)
+ if (hostsig == SIGSYS)
+ return GDB_SIGNAL_SYS;
+#endif
+#if defined (SIGPIPE)
+ if (hostsig == SIGPIPE)
+ return GDB_SIGNAL_PIPE;
+#endif
+#if defined (SIGALRM)
+ if (hostsig == SIGALRM)
+ return GDB_SIGNAL_ALRM;
+#endif
+#if defined (SIGUSR1)
+ if (hostsig == SIGUSR1)
+ return GDB_SIGNAL_USR1;
+#endif
+#if defined (SIGUSR2)
+ if (hostsig == SIGUSR2)
+ return GDB_SIGNAL_USR2;
+#endif
+#if defined (SIGCLD)
+ if (hostsig == SIGCLD)
+ return GDB_SIGNAL_CHLD;
+#endif
+#if defined (SIGCHLD)
+ if (hostsig == SIGCHLD)
+ return GDB_SIGNAL_CHLD;
+#endif
+#if defined (SIGPWR)
+ if (hostsig == SIGPWR)
+ return GDB_SIGNAL_PWR;
+#endif
+#if defined (SIGWINCH)
+ if (hostsig == SIGWINCH)
+ return GDB_SIGNAL_WINCH;
+#endif
+#if defined (SIGURG)
+ if (hostsig == SIGURG)
+ return GDB_SIGNAL_URG;
+#endif
+#if defined (SIGIO)
+ if (hostsig == SIGIO)
+ return GDB_SIGNAL_IO;
+#endif
+#if defined (SIGPOLL)
+ if (hostsig == SIGPOLL)
+ return GDB_SIGNAL_POLL;
+#endif
+#if defined (SIGSTOP)
+ if (hostsig == SIGSTOP)
+ return GDB_SIGNAL_STOP;
+#endif
+#if defined (SIGTSTP)
+ if (hostsig == SIGTSTP)
+ return GDB_SIGNAL_TSTP;
+#endif
+#if defined (SIGCONT)
+ if (hostsig == SIGCONT)
+ return GDB_SIGNAL_CONT;
+#endif
+#if defined (SIGTTIN)
+ if (hostsig == SIGTTIN)
+ return GDB_SIGNAL_TTIN;
+#endif
+#if defined (SIGTTOU)
+ if (hostsig == SIGTTOU)
+ return GDB_SIGNAL_TTOU;
+#endif
+#if defined (SIGVTALRM)
+ if (hostsig == SIGVTALRM)
+ return GDB_SIGNAL_VTALRM;
+#endif
+#if defined (SIGPROF)
+ if (hostsig == SIGPROF)
+ return GDB_SIGNAL_PROF;
+#endif
+#if defined (SIGXCPU)
+ if (hostsig == SIGXCPU)
+ return GDB_SIGNAL_XCPU;
+#endif
+#if defined (SIGXFSZ)
+ if (hostsig == SIGXFSZ)
+ return GDB_SIGNAL_XFSZ;
+#endif
+#if defined (SIGWIND)
+ if (hostsig == SIGWIND)
+ return GDB_SIGNAL_WIND;
+#endif
+#if defined (SIGPHONE)
+ if (hostsig == SIGPHONE)
+ return GDB_SIGNAL_PHONE;
+#endif
+#if defined (SIGLOST)
+ if (hostsig == SIGLOST)
+ return GDB_SIGNAL_LOST;
+#endif
+#if defined (SIGWAITING)
+ if (hostsig == SIGWAITING)
+ return GDB_SIGNAL_WAITING;
+#endif
+#if defined (SIGCANCEL)
+ if (hostsig == SIGCANCEL)
+ return GDB_SIGNAL_CANCEL;
+#endif
+#if defined (SIGLWP)
+ if (hostsig == SIGLWP)
+ return GDB_SIGNAL_LWP;
+#endif
+#if defined (SIGDANGER)
+ if (hostsig == SIGDANGER)
+ return GDB_SIGNAL_DANGER;
+#endif
+#if defined (SIGGRANT)
+ if (hostsig == SIGGRANT)
+ return GDB_SIGNAL_GRANT;
+#endif
+#if defined (SIGRETRACT)
+ if (hostsig == SIGRETRACT)
+ return GDB_SIGNAL_RETRACT;
+#endif
+#if defined (SIGMSG)
+ if (hostsig == SIGMSG)
+ return GDB_SIGNAL_MSG;
+#endif
+#if defined (SIGSOUND)
+ if (hostsig == SIGSOUND)
+ return GDB_SIGNAL_SOUND;
+#endif
+#if defined (SIGSAK)
+ if (hostsig == SIGSAK)
+ return GDB_SIGNAL_SAK;
+#endif
+#if defined (SIGPRIO)
+ if (hostsig == SIGPRIO)
+ return GDB_SIGNAL_PRIO;
+#endif
+
+ /* Mach exceptions. Assumes that the values for EXC_ are positive! */
+#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BAD_ACCESS)
+ return GDB_EXC_BAD_ACCESS;
+#endif
+#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BAD_INSTRUCTION)
+ return GDB_EXC_BAD_INSTRUCTION;
+#endif
+#if defined (EXC_ARITHMETIC) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_ARITHMETIC)
+ return GDB_EXC_ARITHMETIC;
+#endif
+#if defined (EXC_EMULATION) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_EMULATION)
+ return GDB_EXC_EMULATION;
+#endif
+#if defined (EXC_SOFTWARE) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_SOFTWARE)
+ return GDB_EXC_SOFTWARE;
+#endif
+#if defined (EXC_BREAKPOINT) && defined (_NSIG)
+ if (hostsig == _NSIG + EXC_BREAKPOINT)
+ return GDB_EXC_BREAKPOINT;
+#endif
+
+#if defined (SIGINFO)
+ if (hostsig == SIGINFO)
+ return GDB_SIGNAL_INFO;
+#endif
+#if defined (SIGLIBRT)
+ if (hostsig == SIGLIBRT)
+ return GDB_SIGNAL_LIBRT;
+#endif
+
+#if defined (REALTIME_LO)
+ if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
+ {
+ /* This block of GDB_SIGNAL_REALTIME value is in order. */
+ if (33 <= hostsig && hostsig <= 63)
+ return (enum gdb_signal)
+ (hostsig - 33 + (int) GDB_SIGNAL_REALTIME_33);
+ else if (hostsig == 32)
+ return GDB_SIGNAL_REALTIME_32;
+ else if (64 <= hostsig && hostsig <= 127)
+ return (enum gdb_signal)
+ (hostsig - 64 + (int) GDB_SIGNAL_REALTIME_64);
+ else
+ error (_("GDB bug: target.c (gdb_signal_from_host): "
+ "unrecognized real-time signal"));
+ }
+#endif
+
+ return GDB_SIGNAL_UNKNOWN;
+}
+
+/* Convert a OURSIG (an enum gdb_signal) to the form used by the
+ target operating system (refered to as the ``host'') or zero if the
+ equivalent host signal is not available. Set/clear OURSIG_OK
+ accordingly. */
+
+static int
+do_gdb_signal_to_host (enum gdb_signal oursig,
+ int *oursig_ok)
+{
+ int retsig;
+ /* Silence the 'not used' warning, for targets that
+ do not support signals. */
+ (void) retsig;
+
+ /* Signals are ordered ANSI-standard signals first, other signals
+ second, with signals in each block ordered by their numerical
+ values on a typical POSIX platform. */
+
+ *oursig_ok = 1;
+ switch (oursig)
+ {
+ case GDB_SIGNAL_0:
+ return 0;
+
+ /* SIGINT, SIGILL, SIGABRT, SIGFPE, SIGSEGV and SIGTERM
+ are ANSI-standard signals and are always available. */
+ case GDB_SIGNAL_INT:
+ return SIGINT;
+ case GDB_SIGNAL_ILL:
+ return SIGILL;
+ case GDB_SIGNAL_ABRT:
+ return SIGABRT;
+ case GDB_SIGNAL_FPE:
+ return SIGFPE;
+ case GDB_SIGNAL_SEGV:
+ return SIGSEGV;
+ case GDB_SIGNAL_TERM:
+ return SIGTERM;
+
+ /* All other signals need preprocessor conditionals. */
+#if defined (SIGHUP)
+ case GDB_SIGNAL_HUP:
+ return SIGHUP;
+#endif
+#if defined (SIGQUIT)
+ case GDB_SIGNAL_QUIT:
+ return SIGQUIT;
+#endif
+#if defined (SIGTRAP)
+ case GDB_SIGNAL_TRAP:
+ return SIGTRAP;
+#endif
+#if defined (SIGEMT)
+ case GDB_SIGNAL_EMT:
+ return SIGEMT;
+#endif
+#if defined (SIGKILL)
+ case GDB_SIGNAL_KILL:
+ return SIGKILL;
+#endif
+#if defined (SIGBUS)
+ case GDB_SIGNAL_BUS:
+ return SIGBUS;
+#endif
+#if defined (SIGSYS)
+ case GDB_SIGNAL_SYS:
+ return SIGSYS;
+#endif
+#if defined (SIGPIPE)
+ case GDB_SIGNAL_PIPE:
+ return SIGPIPE;
+#endif
+#if defined (SIGALRM)
+ case GDB_SIGNAL_ALRM:
+ return SIGALRM;
+#endif
+#if defined (SIGUSR1)
+ case GDB_SIGNAL_USR1:
+ return SIGUSR1;
+#endif
+#if defined (SIGUSR2)
+ case GDB_SIGNAL_USR2:
+ return SIGUSR2;
+#endif
+#if defined (SIGCHLD) || defined (SIGCLD)
+ case GDB_SIGNAL_CHLD:
+#if defined (SIGCHLD)
+ return SIGCHLD;
+#else
+ return SIGCLD;
+#endif
+#endif /* SIGCLD or SIGCHLD */
+#if defined (SIGPWR)
+ case GDB_SIGNAL_PWR:
+ return SIGPWR;
+#endif
+#if defined (SIGWINCH)
+ case GDB_SIGNAL_WINCH:
+ return SIGWINCH;
+#endif
+#if defined (SIGURG)
+ case GDB_SIGNAL_URG:
+ return SIGURG;
+#endif
+#if defined (SIGIO)
+ case GDB_SIGNAL_IO:
+ return SIGIO;
+#endif
+#if defined (SIGPOLL)
+ case GDB_SIGNAL_POLL:
+ return SIGPOLL;
+#endif
+#if defined (SIGSTOP)
+ case GDB_SIGNAL_STOP:
+ return SIGSTOP;
+#endif
+#if defined (SIGTSTP)
+ case GDB_SIGNAL_TSTP:
+ return SIGTSTP;
+#endif
+#if defined (SIGCONT)
+ case GDB_SIGNAL_CONT:
+ return SIGCONT;
+#endif
+#if defined (SIGTTIN)
+ case GDB_SIGNAL_TTIN:
+ return SIGTTIN;
+#endif
+#if defined (SIGTTOU)
+ case GDB_SIGNAL_TTOU:
+ return SIGTTOU;
+#endif
+#if defined (SIGVTALRM)
+ case GDB_SIGNAL_VTALRM:
+ return SIGVTALRM;
+#endif
+#if defined (SIGPROF)
+ case GDB_SIGNAL_PROF:
+ return SIGPROF;
+#endif
+#if defined (SIGXCPU)
+ case GDB_SIGNAL_XCPU:
+ return SIGXCPU;
+#endif
+#if defined (SIGXFSZ)
+ case GDB_SIGNAL_XFSZ:
+ return SIGXFSZ;
+#endif
+#if defined (SIGWIND)
+ case GDB_SIGNAL_WIND:
+ return SIGWIND;
+#endif
+#if defined (SIGPHONE)
+ case GDB_SIGNAL_PHONE:
+ return SIGPHONE;
+#endif
+#if defined (SIGLOST)
+ case GDB_SIGNAL_LOST:
+ return SIGLOST;
+#endif
+#if defined (SIGWAITING)
+ case GDB_SIGNAL_WAITING:
+ return SIGWAITING;
+#endif
+#if defined (SIGCANCEL)
+ case GDB_SIGNAL_CANCEL:
+ return SIGCANCEL;
+#endif
+#if defined (SIGLWP)
+ case GDB_SIGNAL_LWP:
+ return SIGLWP;
+#endif
+#if defined (SIGDANGER)
+ case GDB_SIGNAL_DANGER:
+ return SIGDANGER;
+#endif
+#if defined (SIGGRANT)
+ case GDB_SIGNAL_GRANT:
+ return SIGGRANT;
+#endif
+#if defined (SIGRETRACT)
+ case GDB_SIGNAL_RETRACT:
+ return SIGRETRACT;
+#endif
+#if defined (SIGMSG)
+ case GDB_SIGNAL_MSG:
+ return SIGMSG;
+#endif
+#if defined (SIGSOUND)
+ case GDB_SIGNAL_SOUND:
+ return SIGSOUND;
+#endif
+#if defined (SIGSAK)
+ case GDB_SIGNAL_SAK:
+ return SIGSAK;
+#endif
+#if defined (SIGPRIO)
+ case GDB_SIGNAL_PRIO:
+ return SIGPRIO;
+#endif
+
+ /* Mach exceptions. Assumes that the values for EXC_ are positive! */
+#if defined (EXC_BAD_ACCESS) && defined (_NSIG)
+ case GDB_EXC_BAD_ACCESS:
+ return _NSIG + EXC_BAD_ACCESS;
+#endif
+#if defined (EXC_BAD_INSTRUCTION) && defined (_NSIG)
+ case GDB_EXC_BAD_INSTRUCTION:
+ return _NSIG + EXC_BAD_INSTRUCTION;
+#endif
+#if defined (EXC_ARITHMETIC) && defined (_NSIG)
+ case GDB_EXC_ARITHMETIC:
+ return _NSIG + EXC_ARITHMETIC;
+#endif
+#if defined (EXC_EMULATION) && defined (_NSIG)
+ case GDB_EXC_EMULATION:
+ return _NSIG + EXC_EMULATION;
+#endif
+#if defined (EXC_SOFTWARE) && defined (_NSIG)
+ case GDB_EXC_SOFTWARE:
+ return _NSIG + EXC_SOFTWARE;
+#endif
+#if defined (EXC_BREAKPOINT) && defined (_NSIG)
+ case GDB_EXC_BREAKPOINT:
+ return _NSIG + EXC_BREAKPOINT;
+#endif
+
+#if defined (SIGINFO)
+ case GDB_SIGNAL_INFO:
+ return SIGINFO;
+#endif
+#if defined (SIGLIBRT)
+ case GDB_SIGNAL_LIBRT:
+ return SIGLIBRT;
+#endif
+
+ default:
+#if defined (REALTIME_LO)
+ retsig = 0;
+
+ if (oursig >= GDB_SIGNAL_REALTIME_33
+ && oursig <= GDB_SIGNAL_REALTIME_63)
+ {
+ /* This block of signals is continuous, and
+ GDB_SIGNAL_REALTIME_33 is 33 by definition. */
+ retsig = (int) oursig - (int) GDB_SIGNAL_REALTIME_33 + 33;
+ }
+ else if (oursig == GDB_SIGNAL_REALTIME_32)
+ {
+ /* GDB_SIGNAL_REALTIME_32 isn't contiguous with
+ GDB_SIGNAL_REALTIME_33. It is 32 by definition. */
+ retsig = 32;
+ }
+ else if (oursig >= GDB_SIGNAL_REALTIME_64
+ && oursig <= GDB_SIGNAL_REALTIME_127)
+ {
+ /* This block of signals is continuous, and
+ GDB_SIGNAL_REALTIME_64 is 64 by definition. */
+ retsig = (int) oursig - (int) GDB_SIGNAL_REALTIME_64 + 64;
+ }
+
+ if (retsig >= REALTIME_LO && retsig < REALTIME_HI)
+ return retsig;
+#endif
+
+ *oursig_ok = 0;
+ return 0;
+ }
+}
+
+int
+gdb_signal_to_host_p (enum gdb_signal oursig)
+{
+ int oursig_ok;
+ do_gdb_signal_to_host (oursig, &oursig_ok);
+ return oursig_ok;
+}
+
+int
+gdb_signal_to_host (enum gdb_signal oursig)
+{
+ int oursig_ok;
+ int targ_signo = do_gdb_signal_to_host (oursig, &oursig_ok);
+ if (!oursig_ok)
+ {
+ /* The user might be trying to do "signal SIGSAK" where this system
+ doesn't have SIGSAK. */
+ warning (_("Signal %s does not exist on this system."),
+ gdb_signal_to_name (oursig));
+ return 0;
+ }
+ else
+ return targ_signo;
+}