diff options
Diffstat (limited to 'gdbsupport/signals.c')
-rw-r--r-- | gdbsupport/signals.c | 653 |
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; +} |