#ifdef IA64
# include <asm/ptrace_offsets.h>
-#endif /* !IA64 */
+#endif
#if defined (LINUX) && defined (SPARC64)
# undef PTRACE_GETREGS
#endif /* M68K */
#endif /* !I386 */
#endif /* !HAVE_ASM_SIGCONTEXT_H */
+
#ifndef NSIG
+#warning: NSIG is not defined, using 32
#define NSIG 32
#endif
#ifdef ARM
+/* Ugh. Is this really correct? ARM has no RT signals?! */
#undef NSIG
#define NSIG 32
#endif
-#endif /* LINUX */
-
-const char *const signalent0[] = {
-#include "signalent.h"
-};
-const int nsignals0 = ARRAY_SIZE(signalent0);
-
-#if SUPPORTED_PERSONALITIES >= 2
-const char *const signalent1[] = {
-#include "signalent1.h"
-};
-const int nsignals1 = ARRAY_SIZE(signalent1);
-#endif /* SUPPORTED_PERSONALITIES >= 2 */
-
-#if SUPPORTED_PERSONALITIES >= 3
-const char *const signalent2[] = {
-#include "signalent2.h"
-};
-const int nsignals2 = ARRAY_SIZE(signalent2);
-#endif /* SUPPORTED_PERSONALITIES >= 3 */
-const char *const *signalent;
-int nsignals;
+#endif /* LINUX */
#if defined(SUNOS4) || defined(FREEBSD)
#if defined LINUX && (defined I386 || defined X86_64)
/* The libc headers do not define this constant since it should only be
- used by the implementation. So wwe define it here. */
+ used by the implementation. So we define it here. */
# ifndef SA_RESTORER
# define SA_RESTORER 0x04000000
# endif
#endif
#endif
+/* Note on the size of sigset_t:
+ *
+ * In glibc, sigset_t is an array with space for 1024 bits (!),
+ * even though all arches supported by Linux have only 64 signals
+ * except MIPS, which has 128. IOW, it is 128 bytes long.
+ *
+ * In-kernel sigset_t is sized correctly (it is either 64 or 128 bit long).
+ * However, some old syscall return only 32 lower bits (one word).
+ * Example: sys_sigpending vs sys_rt_sigpending.
+ *
+ * Be aware of this fact when you try to
+ * memcpy(&tcp->u_arg[1], &something, sizeof(sigset_t))
+ * - sizeof(sigset_t) is much bigger than you think,
+ * it may overflow tcp->u_arg[] array, and it may try to copy more data
+ * than is really available in <something>.
+ * Similarly,
+ * umoven(tcp, addr, sizeof(sigset_t), &sigset)
+ * may be a bad idea: it'll try to read much more data than needed
+ * to fetch a sigset_t.
+ * Use (NSIG / 8) as a size instead.
+ */
+
const char *
signame(int sig)
{
- static char buf[30];
- if (sig >= 0 && sig < nsignals) {
+ static char buf[sizeof("SIGRT_%d") + sizeof(int)*3];
+
+ if (sig >= 0 && sig < nsignals)
return signalent[sig];
#ifdef SIGRTMIN
- } else if (sig >= __SIGRTMIN && sig <= __SIGRTMAX) {
- sprintf(buf, "SIGRT_%ld", (long)(sig - __SIGRTMIN));
- return buf;
-#endif /* SIGRTMIN */
- } else {
- sprintf(buf, "%d", sig);
+ if (sig >= __SIGRTMIN && sig <= __SIGRTMAX) {
+ sprintf(buf, "SIGRT_%d", (int)(sig - __SIGRTMIN));
return buf;
}
+#endif
+ sprintf(buf, "%d", sig);
+ return buf;
}
#ifndef UNIXWARE
sprintsigmask(const char *str, sigset_t *mask, int rt)
/* set might include realtime sigs */
{
+ /* Was [8 * sizeof(sigset_t) * 8], but
+ * glibc sigset_t is huge (1024 bits = 128 *bytes*),
+ * and we were ending up with 8k (!) buffer here.
+ *
+ * No Unix system can have sig > 255
+ * (waitpid API won't be able to indicate death from one)
+ * and sig 0 doesn't exist either.
+ * Therefore max possible no of sigs is 255: 1..255
+ */
+ static char outstr[8 * 255];
+
int i, nsigs;
int maxsigs;
const char *format;
char *s;
- static char outstr[8 * sizeof(sigset_t) * 8];
strcpy(outstr, str);
s = outstr + strlen(outstr);
#endif /* SVR4 || LINUX */
-#ifdef LINUX
-
-static void
-parse_sigset_t(const char *str, sigset_t *set)
-{
- const char *p;
- unsigned int digit;
- int i;
-
- sigemptyset(set);
-
- p = strchr(str, '\n');
- if (p == NULL)
- p = strchr(str, '\0');
- for (i = 0; p-- > str; i += 4) {
- if (*p >= '0' && *p <= '9')
- digit = *p - '0';
- else if (*p >= 'a' && *p <= 'f')
- digit = *p - 'a' + 10;
- else if (*p >= 'A' && *p <= 'F')
- digit = *p - 'A' + 10;
- else
- break;
- if (digit & 1)
- sigaddset(set, i + 1);
- if (digit & 2)
- sigaddset(set, i + 2);
- if (digit & 4)
- sigaddset(set, i + 3);
- if (digit & 8)
- sigaddset(set, i + 4);
- }
-}
-
-#endif
-
-/*
- * Check process TCP for the disposition of signal SIG.
- * Return 1 if the process would somehow manage to survive signal SIG,
- * else return 0. This routine will never be called with SIGKILL.
- */
-int
-sigishandled(struct tcb *tcp, int sig)
-{
-#ifdef LINUX
- int sfd;
- char sname[32];
- char buf[2048];
- const char *s;
- int i;
- sigset_t ignored, caught;
-#endif
-#ifdef SVR4
- /*
- * Since procfs doesn't interfere with wait I think it is safe
- * to punt on this question. If not, the information is there.
- */
- return 1;
-#else /* !SVR4 */
- switch (sig) {
- case SIGCONT:
- case SIGSTOP:
- case SIGTSTP:
- case SIGTTIN:
- case SIGTTOU:
- case SIGCHLD:
- case SIGIO:
-#if defined(SIGURG) && SIGURG != SIGIO
- case SIGURG:
-#endif
- case SIGWINCH:
- /* Gloria Gaynor says ... */
- return 1;
- default:
- break;
- }
-#endif /* !SVR4 */
-#ifdef LINUX
-
- /* This is incredibly costly but it's worth it. */
- /* NOTE: LinuxThreads internally uses SIGRTMIN, SIGRTMIN + 1 and
- SIGRTMIN + 2, so we can't use the obsolete /proc/%d/stat which
- doesn't handle real-time signals). */
- sprintf(sname, "/proc/%d/status", tcp->pid);
- if ((sfd = open(sname, O_RDONLY)) == -1) {
- perror(sname);
- return 1;
- }
- i = read(sfd, buf, sizeof(buf));
- buf[i] = '\0';
- close(sfd);
- /*
- * Skip the extraneous fields. We need to skip
- * command name has any spaces in it. So be it.
- */
- s = strstr(buf, "SigIgn:\t");
- if (!s)
- {
- fprintf(stderr, "/proc/pid/status format error\n");
- return 1;
- }
- parse_sigset_t(s + 8, &ignored);
-
- s = strstr(buf, "SigCgt:\t");
- if (!s)
- {
- fprintf(stderr, "/proc/pid/status format error\n");
- return 1;
- }
- parse_sigset_t(s + 8, &caught);
-
-#ifdef DEBUG
- fprintf(stderr, "sigs: %016qx %016qx (sig=%d)\n",
- *(long long *) &ignored, *(long long *) &caught, sig);
-#endif
- if (sigismember(&ignored, sig) || sigismember(&caught, sig))
- return 1;
-#endif /* LINUX */
-
-#ifdef SUNOS4
- void (*u_signal)();
-
- if (upeek(tcp, uoff(u_signal[0]) + sig*sizeof(u_signal),
- (long *) &u_signal) < 0) {
- return 0;
- }
- if (u_signal != SIG_DFL)
- return 1;
-#endif /* SUNOS4 */
-
- return 0;
-}
-
#if defined(SUNOS4) || defined(FREEBSD)
int
if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
- memcpy(&tcp->u_arg[1], &sc.oldmask[0], sizeof(sigset_t));
+ memcpy(&tcp->u_arg[1], &sc.oldmask[0], NSIG / 8);
} else {
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
- memcpy(tcp->u_arg + 1, &sc.sc_mask, sizeof(sc.sc_mask));
+ memcpy(tcp->u_arg + 1, &sc.sc_mask, NSIG / 8);
}
else {
sigset_t sigm;
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
- memcpy(&sigm, tcp->u_arg + 1, sizeof(sigm));
+ sigemptyset(&sigm);
+ memcpy(&sigm, tcp->u_arg + 1, NSIG / 8);
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
if (umove(tcp, sp + SIGFRAME_UC_OFFSET, &uc) < 0)
return 0;
tcp->u_arg[0] = 1;
- memcpy(tcp->u_arg + 1, &uc.uc_sigmask, sizeof(uc.uc_sigmask));
+ memcpy(tcp->u_arg + 1, &uc.uc_sigmask, NSIG / 8);
}
else {
sigset_t sigm;
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
- memcpy(&sigm, tcp->u_arg + 1, sizeof(sigm));
+ sigemptyset(&sigm);
+ memcpy(&sigm, tcp->u_arg + 1, NSIG / 8);
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
}
else {
if (!tcp->u_arg[2])
-
tprintf("NULL");
else if (syserror(tcp))
tprintf("%#lx", tcp->u_arg[2]);