+ /* POSIX.1b timers. */
+ struct
+ {
+ unsigned int _timer1;
+ unsigned int _timer2;
+ } _timer;
+
+ /* POSIX.1b signals. */
+ struct
+ {
+ __pid_t si_pid; /* Sending process ID. */
+ __uid_t si_uid; /* Real user ID of sending process. */
+ sigval_t si_sigval; /* Signal value. */
+ } _rt;
+
+ /* SIGCHLD. */
+ struct
+ {
+ __pid_t si_pid; /* Which child. */
+ int si_status; /* Exit value or signal. */
+ __clock_t si_utime;
+ __clock_t si_stime;
+ } _sigchld;
+
+ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */
+ struct
+ {
+ void *si_addr; /* Faulting insn/memory ref. */
+ } _sigfault;
+
+ /* SIGPOLL. */
+ struct
+ {
+ int si_band; /* Band event for SIGPOLL. */
+ int si_fd;
+ } _sigpoll;
+ } _sifields;
+} siginfo_t;
+
+#define si_pid _sifields._kill.si_pid
+#define si_uid _sifields._kill.si_uid
+#define si_status _sifields._sigchld.si_status
+#define si_utime _sifields._sigchld.si_utime
+#define si_stime _sifields._sigchld.si_stime
+#define si_value _sifields._rt.si_sigval
+#define si_int _sifields._rt.si_sigval.sival_int
+#define si_ptr _sifields._rt.si_sigval.sival_ptr
+#define si_addr _sifields._sigfault.si_addr
+#define si_band _sifields._sigpoll.si_band
+#define si_fd _sifields._sigpoll.si_fd
+
+#endif
+
+#endif
+
+#if defined (SVR4) || defined (LINUX)
+
+static const struct xlat siginfo_codes[] = {
+#ifdef SI_KERNEL
+ { SI_KERNEL, "SI_KERNEL" },
+#endif
+#ifdef SI_USER
+ { SI_USER, "SI_USER" },
+#endif
+#ifdef SI_QUEUE
+ { SI_QUEUE, "SI_QUEUE" },
+#endif
+#ifdef SI_TIMER
+ { SI_TIMER, "SI_TIMER" },
+#endif
+#ifdef SI_MESGQ
+ { SI_MESGQ, "SI_MESGQ" },
+#endif
+#ifdef SI_ASYNCIO
+ { SI_ASYNCIO, "SI_ASYNCIO" },
+#endif
+#ifdef SI_SIGIO
+ { SI_SIGIO, "SI_SIGIO" },
+#endif
+#ifdef SI_TKILL
+ { SI_TKILL, "SI_TKILL" },
+#endif
+#ifdef SI_ASYNCNL
+ { SI_ASYNCNL, "SI_ASYNCNL" },
+#endif
+#ifdef SI_NOINFO
+ { SI_NOINFO, "SI_NOINFO" },
+#endif
+#ifdef SI_LWP
+ { SI_LWP, "SI_LWP" },
+#endif
+ { 0, NULL },
+};
+
+static const struct xlat sigill_codes[] = {
+ { ILL_ILLOPC, "ILL_ILLOPC" },
+ { ILL_ILLOPN, "ILL_ILLOPN" },
+ { ILL_ILLADR, "ILL_ILLADR" },
+ { ILL_ILLTRP, "ILL_ILLTRP" },
+ { ILL_PRVOPC, "ILL_PRVOPC" },
+ { ILL_PRVREG, "ILL_PRVREG" },
+ { ILL_COPROC, "ILL_COPROC" },
+ { ILL_BADSTK, "ILL_BADSTK" },
+ { 0, NULL },
+};
+
+static const struct xlat sigfpe_codes[] = {
+ { FPE_INTDIV, "FPE_INTDIV" },
+ { FPE_INTOVF, "FPE_INTOVF" },
+ { FPE_FLTDIV, "FPE_FLTDIV" },
+ { FPE_FLTOVF, "FPE_FLTOVF" },
+ { FPE_FLTUND, "FPE_FLTUND" },
+ { FPE_FLTRES, "FPE_FLTRES" },
+ { FPE_FLTINV, "FPE_FLTINV" },
+ { FPE_FLTSUB, "FPE_FLTSUB" },
+ { 0, NULL },
+};
+
+static const struct xlat sigtrap_codes[] = {
+ { TRAP_BRKPT, "TRAP_BRKPT" },
+ { TRAP_TRACE, "TRAP_TRACE" },
+ { 0, NULL },
+};
+
+static const struct xlat sigchld_codes[] = {
+ { CLD_EXITED, "CLD_EXITED" },
+ { CLD_KILLED, "CLD_KILLED" },
+ { CLD_DUMPED, "CLD_DUMPED" },
+ { CLD_TRAPPED, "CLD_TRAPPED" },
+ { CLD_STOPPED, "CLD_STOPPED" },
+ { CLD_CONTINUED,"CLD_CONTINUED" },
+ { 0, NULL },
+};
+
+static const struct xlat sigpoll_codes[] = {
+ { POLL_IN, "POLL_IN" },
+ { POLL_OUT, "POLL_OUT" },
+ { POLL_MSG, "POLL_MSG" },
+ { POLL_ERR, "POLL_ERR" },
+ { POLL_PRI, "POLL_PRI" },
+ { POLL_HUP, "POLL_HUP" },
+ { 0, NULL },
+};
+
+static const struct xlat sigprof_codes[] = {
+#ifdef PROF_SIG
+ { PROF_SIG, "PROF_SIG" },
+#endif
+ { 0, NULL },
+};
+
+#ifdef SIGEMT
+static const struct xlat sigemt_codes[] = {
+#ifdef EMT_TAGOVF
+ { EMT_TAGOVF, "EMT_TAGOVF" },
+#endif
+ { 0, NULL },
+};
+#endif
+
+static const struct xlat sigsegv_codes[] = {
+ { SEGV_MAPERR, "SEGV_MAPERR" },
+ { SEGV_ACCERR, "SEGV_ACCERR" },
+ { 0, NULL },
+};
+
+static const struct xlat sigbus_codes[] = {
+ { BUS_ADRALN, "BUS_ADRALN" },
+ { BUS_ADRERR, "BUS_ADRERR" },
+ { BUS_OBJERR, "BUS_OBJERR" },
+ { 0, NULL },
+};
+
+void
+printsiginfo(siginfo_t *sip, int verbose)
+{
+ const char *code;
+
+ if (sip->si_signo == 0) {
+ tprintf("{}");
+ return;
+ }
+ tprintf("{si_signo=");
+ printsignal(sip->si_signo);
+ code = xlookup(siginfo_codes, sip->si_code);
+ if (!code) {
+ switch (sip->si_signo) {
+ case SIGTRAP:
+ code = xlookup(sigtrap_codes, sip->si_code);
+ break;
+ case SIGCHLD:
+ code = xlookup(sigchld_codes, sip->si_code);
+ break;
+ case SIGPOLL:
+ code = xlookup(sigpoll_codes, sip->si_code);
+ break;
+ case SIGPROF:
+ code = xlookup(sigprof_codes, sip->si_code);
+ break;
+ case SIGILL:
+ code = xlookup(sigill_codes, sip->si_code);
+ break;
+#ifdef SIGEMT
+ case SIGEMT:
+ code = xlookup(sigemt_codes, sip->si_code);
+ break;
+#endif
+ case SIGFPE:
+ code = xlookup(sigfpe_codes, sip->si_code);
+ break;
+ case SIGSEGV:
+ code = xlookup(sigsegv_codes, sip->si_code);
+ break;
+ case SIGBUS:
+ code = xlookup(sigbus_codes, sip->si_code);
+ break;
+ }
+ }
+ if (code)
+ tprintf(", si_code=%s", code);
+ else
+ tprintf(", si_code=%#x", sip->si_code);
+#ifdef SI_NOINFO
+ if (sip->si_code != SI_NOINFO)
+#endif
+ {
+ if (sip->si_errno) {
+ if (sip->si_errno < 0 || sip->si_errno >= nerrnos)
+ tprintf(", si_errno=%d", sip->si_errno);
+ else
+ tprintf(", si_errno=%s",
+ errnoent[sip->si_errno]);
+ }
+#ifdef SI_FROMUSER
+ if (SI_FROMUSER(sip)) {
+ tprintf(", si_pid=%lu, si_uid=%lu",
+ (unsigned long) sip->si_pid,
+ (unsigned long) sip->si_uid);
+ switch (sip->si_code) {
+#ifdef SI_USER
+ case SI_USER:
+ break;
+#endif
+#ifdef SI_TKILL
+ case SI_TKILL:
+ break;
+#endif
+#ifdef SI_TIMER
+ case SI_TIMER:
+ tprintf(", si_value=%d", sip->si_int);
+ break;
+#endif
+#ifdef LINUX
+ default:
+ if (!sip->si_ptr)
+ break;
+ if (!verbose)
+ tprintf(", ...");
+ else
+ tprintf(", si_value={int=%u, ptr=%#lx}",
+ sip->si_int,
+ (unsigned long) sip->si_ptr);
+ break;
+#endif
+ }
+ }
+ else
+#endif /* SI_FROMUSER */
+ {
+ switch (sip->si_signo) {
+ case SIGCHLD:
+ tprintf(", si_pid=%ld, si_status=",
+ (long) sip->si_pid);
+ if (sip->si_code == CLD_EXITED)
+ tprintf("%d", sip->si_status);
+ else
+ printsignal(sip->si_status);
+#if LINUX
+ if (!verbose)
+ tprintf(", ...");
+ else
+ tprintf(", si_utime=%lu, si_stime=%lu",
+ sip->si_utime,
+ sip->si_stime);
+#endif
+ break;
+ case SIGILL: case SIGFPE:
+ case SIGSEGV: case SIGBUS:
+ tprintf(", si_addr=%#lx",
+ (unsigned long) sip->si_addr);
+ break;
+ case SIGPOLL:
+ switch (sip->si_code) {
+ case POLL_IN: case POLL_OUT: case POLL_MSG:
+ tprintf(", si_band=%ld",
+ (long) sip->si_band);
+ break;
+ }
+ break;
+#ifdef LINUX
+ default:
+ if (sip->si_pid || sip->si_uid)
+ tprintf(", si_pid=%lu, si_uid=%lu",
+ (unsigned long) sip->si_pid,
+ (unsigned long) sip->si_uid);
+ if (!sip->si_ptr)
+ break;
+ if (!verbose)
+ tprintf(", ...");
+ else {
+ tprintf(", si_value={int=%u, ptr=%#lx}",
+ sip->si_int,
+ (unsigned long) sip->si_ptr);
+ }
+#endif
+
+ }
+ }
+ }
+ tprintf("}");
+}
+
+#endif /* SVR4 || LINUX */
+
+#if defined(SUNOS4) || defined(FREEBSD)
+
+int
+sys_sigvec(struct tcb *tcp)
+{
+ struct sigvec sv;
+ long addr;
+
+ if (entering(tcp)) {
+ printsignal(tcp->u_arg[0]);
+ tprintf(", ");
+ addr = tcp->u_arg[1];
+ } else {
+ addr = tcp->u_arg[2];
+ }
+ if (addr == 0)
+ tprintf("NULL");
+ else if (!verbose(tcp))
+ tprintf("%#lx", addr);
+ else if (umove(tcp, addr, &sv) < 0)
+ tprintf("{...}");
+ else {
+ switch ((int) sv.sv_handler) {
+ case (int) SIG_ERR:
+ tprintf("{SIG_ERR}");
+ break;
+ case (int) SIG_DFL:
+ tprintf("{SIG_DFL}");
+ break;
+ case (int) SIG_IGN:
+ if (tcp->u_arg[0] == SIGTRAP) {
+ tcp->flags |= TCB_SIGTRAPPED;
+ kill(tcp->pid, SIGSTOP);
+ }
+ tprintf("{SIG_IGN}");
+ break;
+ case (int) SIG_HOLD:
+ if (tcp->u_arg[0] == SIGTRAP) {
+ tcp->flags |= TCB_SIGTRAPPED;
+ kill(tcp->pid, SIGSTOP);
+ }
+ tprintf("SIG_HOLD");
+ break;
+ default:
+ if (tcp->u_arg[0] == SIGTRAP) {
+ tcp->flags |= TCB_SIGTRAPPED;
+ kill(tcp->pid, SIGSTOP);
+ }
+ tprintf("{%#lx, ", (unsigned long) sv.sv_handler);
+ printsigmask(&sv.sv_mask, 0);
+ tprintf(", ");
+ printflags(sigvec_flags, sv.sv_flags, "SV_???");
+ tprintf("}");
+ }
+ }
+ if (entering(tcp))
+ tprintf(", ");
+ return 0;
+}
+
+int
+sys_sigpause(struct tcb *tcp)
+{
+ if (entering(tcp)) { /* WTA: UD had a bug here: he forgot the braces */
+ sigset_t sigm;
+ long_to_sigset(tcp->u_arg[0], &sigm);
+ printsigmask(&sigm, 0);
+ }
+ return 0;
+}
+
+int
+sys_sigstack(struct tcb *tcp)
+{
+ struct sigstack ss;
+ long addr;
+
+ if (entering(tcp))
+ addr = tcp->u_arg[0];
+ else
+ addr = tcp->u_arg[1];
+ if (addr == 0)
+ tprintf("NULL");
+ else if (umove(tcp, addr, &ss) < 0)
+ tprintf("%#lx", addr);
+ else {
+ tprintf("{ss_sp %#lx ", (unsigned long) ss.ss_sp);
+ tprintf("ss_onstack %s}", ss.ss_onstack ? "YES" : "NO");
+ }
+ if (entering(tcp))
+ tprintf(", ");
+ return 0;
+}
+
+int
+sys_sigcleanup(struct tcb *tcp)
+{
+ return 0;
+}
+
+#endif /* SUNOS4 || FREEBSD */
+
+#ifndef SVR4
+
+int
+sys_sigsetmask(struct tcb *tcp)
+{
+ if (entering(tcp)) {
+ sigset_t sigm;
+ long_to_sigset(tcp->u_arg[0], &sigm);
+ printsigmask(&sigm, 0);
+#ifndef USE_PROCFS
+ if ((tcp->u_arg[0] & sigmask(SIGTRAP))) {
+ /* Mark attempt to block SIGTRAP */
+ tcp->flags |= TCB_SIGTRAPPED;
+ /* Send unblockable signal */
+ kill(tcp->pid, SIGSTOP);
+ }
+#endif /* !USE_PROCFS */
+ }
+ else if (!syserror(tcp)) {
+ sigset_t sigm;
+ long_to_sigset(tcp->u_rval, &sigm);
+ tcp->auxstr = sprintsigmask("old mask ", &sigm, 0);
+
+ return RVAL_HEX | RVAL_STR;
+ }
+ return 0;
+}
+
+#if defined(SUNOS4) || defined(FREEBSD)
+int
+sys_sigblock(struct tcb *tcp)
+{
+ return sys_sigsetmask(tcp);
+}
+#endif /* SUNOS4 || FREEBSD */
+
+#endif /* !SVR4 */
+
+#ifdef HAVE_SIGACTION
+
+#ifdef LINUX
+struct old_sigaction {
+ __sighandler_t __sa_handler;
+ unsigned long sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+#define SA_HANDLER __sa_handler
+#endif /* LINUX */
+
+#ifndef SA_HANDLER
+#define SA_HANDLER sa_handler
+#endif