X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=signal.c;h=84af14f4cf98028056be0f6d3bbcfec72c627f30;hb=5940e6593911dcace424c668a1c0934c71fccb9e;hp=ce090900d55912f5ebf8b88c9d0e2e4b4fd7a276;hpb=c792698a99b640e7d256e8692c992bd967f0c5b2;p=strace diff --git a/signal.c b/signal.c index ce090900..84af14f4 100644 --- a/signal.c +++ b/signal.c @@ -35,6 +35,7 @@ #include "defs.h" +#include #include #include #include @@ -53,7 +54,15 @@ #endif #elif defined(HAVE_LINUX_PTRACE_H) #undef PTRACE_SYSCALL +# ifdef HAVE_STRUCT_IA64_FPREG +# define ia64_fpreg XXX_ia64_fpreg +# endif +# ifdef HAVE_STRUCT_PT_ALL_USER_REGS +# define pt_all_user_regs XXX_pt_all_user_regs +# endif #include +# undef ia64_fpreg +# undef pt_all_user_regs #endif @@ -61,19 +70,26 @@ #ifdef IA64 # include -#endif /* !IA64 */ +#endif -#ifdef HAVE_ASM_SIGCONTEXT_H -#include -#ifdef SPARC -#include +#if defined (LINUX) && defined (SPARC64) +# undef PTRACE_GETREGS +# define PTRACE_GETREGS PTRACE_GETREGS64 +# undef PTRACE_SETREGS +# define PTRACE_SETREGS PTRACE_SETREGS64 +#endif /* LINUX && SPARC64 */ + +#if defined (SPARC) || defined (SPARC64) || defined (MIPS) typedef struct { - struct regs si_regs; + struct pt_regs si_regs; int si_mask; } m_siginfo_t; -#endif +#elif defined HAVE_ASM_SIGCONTEXT_H +#if !defined(IA64) && !defined(X86_64) +#include +#endif /* !IA64 && !X86_64 */ #else /* !HAVE_ASM_SIGCONTEXT_H */ -#ifdef I386 +#if defined I386 && !defined HAVE_STRUCT_SIGCONTEXT_STRUCT struct sigcontext_struct { unsigned short gs, __gsh; unsigned short fs, __fsh; @@ -99,7 +115,7 @@ struct sigcontext_struct { unsigned long cr2; }; #else /* !I386 */ -#ifdef M68K +#if defined M68K && !defined HAVE_STRUCT_SIGCONTEXT struct sigcontext { unsigned long sc_mask; @@ -115,40 +131,22 @@ struct sigcontext #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 */ - -char *signalent0[] = { -#include "signalent.h" -}; -int nsignals0 = sizeof signalent0 / sizeof signalent0[0]; - -#if SUPPORTED_PERSONALITIES >= 2 -char *signalent1[] = { -#include "signalent1.h" -}; -int nsignals1 = sizeof signalent1 / sizeof signalent1[0]; -#endif /* SUPPORTED_PERSONALITIES >= 2 */ - -#if SUPPORTED_PERSONALITIES >= 3 -char *signalent2[] = { -#include "signalent2.h" -}; -int nsignals2 = sizeof signalent2 / sizeof signalent2[0]; -#endif /* SUPPORTED_PERSONALITIES >= 3 */ -char **signalent; -int nsignals; +#endif /* LINUX */ -#ifdef SUNOS4 +#if defined(SUNOS4) || defined(FREEBSD) -static struct xlat sigvec_flags[] = { +static const struct xlat sigvec_flags[] = { { SV_ONSTACK, "SV_ONSTACK" }, { SV_INTERRUPT, "SV_INTERRUPT" }, { SV_RESETHAND, "SV_RESETHAND" }, @@ -156,11 +154,19 @@ static struct xlat sigvec_flags[] = { { 0, NULL }, }; -#endif /* SUNOS4 */ +#endif /* SUNOS4 || FREEBSD */ #ifdef HAVE_SIGACTION -static struct xlat sigact_flags[] = { +#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 we define it here. */ +# ifndef SA_RESTORER +# define SA_RESTORER 0x04000000 +# endif +#endif + +static const struct xlat sigact_flags[] = { #ifdef SA_RESTORER { SA_RESTORER, "SA_RESTORER" }, #endif @@ -173,10 +179,16 @@ static struct xlat sigact_flags[] = { #ifdef SA_INTERRUPT { SA_INTERRUPT, "SA_INTERRUPT" }, #endif -#ifdef SA_NOMASK +#ifdef SA_NODEFER + { SA_NODEFER, "SA_NODEFER" }, +#endif +#if defined SA_NOMASK && SA_NODEFER != SA_NOMASK { SA_NOMASK, "SA_NOMASK" }, #endif -#ifdef SA_ONESHOT +#ifdef SA_RESETHAND + { SA_RESETHAND, "SA_RESETHAND" }, +#endif +#if defined SA_ONESHOT && SA_ONESHOT != SA_RESETHAND { SA_ONESHOT, "SA_ONESHOT" }, #endif #ifdef SA_SIGINFO @@ -199,11 +211,14 @@ static struct xlat sigact_flags[] = { #endif #ifdef _SA_BSDCALL { _SA_BSDCALL, "_SA_BSDCALL" }, +#endif +#ifdef SA_NOPTRACE + { SA_NOPTRACE, "SA_NOPTRACE" }, #endif { 0, NULL }, }; -static struct xlat sigprocmaskcmds[] = { +static const struct xlat sigprocmaskcmds[] = { { SIG_BLOCK, "SIG_BLOCK" }, { SIG_UNBLOCK, "SIG_UNBLOCK" }, { SIG_SETMASK, "SIG_SETMASK" }, @@ -225,29 +240,48 @@ static struct xlat sigprocmaskcmds[] = { #endif #endif -char * -signame(sig) -int sig; +/* 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 . + * 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 < 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 static void -long_to_sigset(l, s) -long l; -sigset_t *s; +long_to_sigset(long l, sigset_t *s) { sigemptyset(s); *(long *)s = l; @@ -255,11 +289,7 @@ sigset_t *s; #endif static int -copy_sigset_len(tcp, addr, s, len) -struct tcb *tcp; -long addr; -sigset_t *s; -int len; +copy_sigset_len(struct tcb *tcp, long addr, sigset_t *s, int len) { if (len > sizeof(*s)) len = sizeof(*s); @@ -276,18 +306,27 @@ int len; #define copy_sigset(tcp, addr, s) copy_sigset_len(tcp, addr, s, sizeof(sigset_t)) #endif -static char * -sprintsigmask(s, mask, rt) -char *s; -sigset_t *mask; -int rt; /* set might include realtime sigs */ +static const char * +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; - char *format; - static char outstr[256]; + const char *format; + char *s; - strcpy(outstr, s); + strcpy(outstr, str); s = outstr + strlen(outstr); nsigs = 0; maxsigs = nsignals; @@ -316,7 +355,25 @@ int rt; /* set might include realtime sigs */ *s++ = '['; for (i = 1; i < maxsigs; i++) { if (sigismember(mask, i) == 1) { - sprintf(s, format, signame(i) + 3); s += strlen(s); + /* real-time signals on solaris don't have + * signalent entries + */ + if (i < nsignals) { + sprintf(s, format, signalent[i] + 3); + } +#ifdef SIGRTMIN + else if (i >= __SIGRTMIN && i <= __SIGRTMAX) { + char tsig[40]; + sprintf(tsig, "RT_%u", i - __SIGRTMIN); + sprintf(s, format, tsig); + } +#endif /* SIGRTMIN */ + else { + char tsig[32]; + sprintf(tsig, "%u", i); + sprintf(s, format, tsig); + } + s += strlen(s); format = " %s"; } } @@ -326,275 +383,597 @@ int rt; /* set might include realtime sigs */ } static void -printsigmask(mask, rt) -sigset_t *mask; -int rt; +printsigmask(sigset_t *mask, int rt) { - tprintf("%s", sprintsigmask("", mask, rt)); + tprints(sprintsigmask("", mask, rt)); } void -printsignal(nr) -int nr; -{ - tprintf(signame(nr)); -} - -/* - * 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(tcp, sig) -struct tcb *tcp; -int sig; +printsignal(int nr) { -#ifdef LINUX - int sfd; - char sname[32]; - char buf[1024]; - char *s; - int i; - unsigned int signalled, blocked, ignored, caught; - - /* This is incredibly costly but it's worth it. */ - sprintf(sname, "/proc/%d/stat", tcp->pid); - if ((sfd = open(sname, O_RDONLY)) == -1) { - perror(sname); - return 1; - } - i = read(sfd, buf, 1024); - buf[i] = '\0'; - close(sfd); - /* - * Skip the extraneous fields. This loses if the - * command name has any spaces in it. So be it. - */ - for (i = 0, s = buf; i < 30; i++) { - while (*++s != ' ') { - if (!*s) - break; - } - } - if (sscanf(s, "%u%u%u%u", - &signalled, &blocked, &ignored, &caught) != 4) { - fprintf(stderr, "/proc/pid/stat format error\n"); - return 1; - } -#ifdef DEBUG - fprintf(stderr, "sigs: %08x %08x %08x %08x\n", - signalled, blocked, ignored, caught); -#endif - if ((ignored & sigmask(sig)) || (caught & sigmask(sig))) - return 1; -#endif /* LINUX */ - -#ifdef SUNOS4 - void (*u_signal)(); - - if (upeek(tcp->pid, uoff(u_signal[0]) + sig*sizeof(u_signal), - (long *) &u_signal) < 0) { - return 0; - } - if (u_signal != SIG_DFL) - return 1; -#endif /* SUNOS4 */ - -#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; - } - return 0; -#endif /* !SVR4 */ + tprints(signame(nr)); } -#if defined(SUNOS4) - -int -sys_sigvec(tcp) -struct tcb *tcp; +void +print_sigset(struct tcb *tcp, long addr, int rt) { - struct sigvec sv; - long addr; + sigset_t ss; - if (entering(tcp)) { - printsignal(tcp->u_arg[0]); - tprintf(", "); - addr = tcp->u_arg[1]; - } else { - addr = tcp->u_arg[2]; - } - if (addr == 0) + if (!addr) tprintf("NULL"); - else if (!verbose(tcp)) + else if (copy_sigset(tcp, addr, &ss) < 0) 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(", "); - if (!printflags(sigvec_flags, sv.sv_flags)) - tprintf("0"); - tprintf("}"); - } - } - if (entering(tcp)) - tprintf(", "); - return 0; -} - -int -sys_sigpause(tcp) -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(tcp) -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; + printsigmask(&ss, rt); } -int -sys_sigcleanup(tcp) -struct tcb *tcp; -{ - return 0; -} +#ifdef LINUX + +#ifndef ILL_ILLOPC +#define ILL_ILLOPC 1 /* illegal opcode */ +#define ILL_ILLOPN 2 /* illegal operand */ +#define ILL_ILLADR 3 /* illegal addressing mode */ +#define ILL_ILLTRP 4 /* illegal trap */ +#define ILL_PRVOPC 5 /* privileged opcode */ +#define ILL_PRVREG 6 /* privileged register */ +#define ILL_COPROC 7 /* coprocessor error */ +#define ILL_BADSTK 8 /* internal stack error */ +#define FPE_INTDIV 1 /* integer divide by zero */ +#define FPE_INTOVF 2 /* integer overflow */ +#define FPE_FLTDIV 3 /* floating point divide by zero */ +#define FPE_FLTOVF 4 /* floating point overflow */ +#define FPE_FLTUND 5 /* floating point underflow */ +#define FPE_FLTRES 6 /* floating point inexact result */ +#define FPE_FLTINV 7 /* floating point invalid operation */ +#define FPE_FLTSUB 8 /* subscript out of range */ +#define SEGV_MAPERR 1 /* address not mapped to object */ +#define SEGV_ACCERR 2 /* invalid permissions for mapped object */ +#define BUS_ADRALN 1 /* invalid address alignment */ +#define BUS_ADRERR 2 /* non-existant physical address */ +#define BUS_OBJERR 3 /* object specific hardware error */ +#define TRAP_BRKPT 1 /* process breakpoint */ +#define TRAP_TRACE 2 /* process trace trap */ +#define CLD_EXITED 1 /* child has exited */ +#define CLD_KILLED 2 /* child was killed */ +#define CLD_DUMPED 3 /* child terminated abnormally */ +#define CLD_TRAPPED 4 /* traced child has trapped */ +#define CLD_STOPPED 5 /* child has stopped */ +#define CLD_CONTINUED 6 /* stopped child has continued */ +#define POLL_IN 1 /* data input available */ +#define POLL_OUT 2 /* output buffers available */ +#define POLL_MSG 3 /* input message available */ +#define POLL_ERR 4 /* i/o error */ +#define POLL_PRI 5 /* high priority input available */ +#define POLL_HUP 6 /* device disconnected */ +#define SI_KERNEL 0x80 /* sent by kernel */ +#define SI_USER 0 /* sent by kill, sigsend, raise */ +#define SI_QUEUE -1 /* sent by sigqueue */ +#define SI_TIMER -2 /* sent by timer expiration */ +#define SI_MESGQ -3 /* sent by real time mesq state change */ +#define SI_ASYNCIO -4 /* sent by AIO completion */ +#define SI_SIGIO -5 /* sent by SIGIO */ +#define SI_TKILL -6 /* sent by tkill */ +#define SI_ASYNCNL -60 /* sent by asynch name lookup completion */ -#endif /* SUNOS4 */ +#define SI_FROMUSER(sip) ((sip)->si_code <= 0) -#ifndef SVR4 +#endif /* LINUX */ -int -sys_sigsetmask(tcp) -struct tcb *tcp; +#if __GLIBC_MINOR__ < 1 +/* Type for data associated with a signal. */ +typedef union sigval { - if (entering(tcp)) { - sigset_t sigm; - long_to_sigset(tcp->u_arg[0], &sigm); - printsigmask(&sigm, 0); - if ((tcp->u_arg[0] & sigmask(SIGTRAP))) { - /* Mark attempt to block SIGTRAP */ - tcp->flags |= TCB_SIGTRAPPED; - /* Send unblockable signal */ - kill(tcp->pid, SIGSTOP); - } - } - else if (!syserror(tcp)) { - sigset_t sigm; - long_to_sigset(tcp->u_rval, &sigm); - tcp->auxstr = sprintsigmask("old mask ", &sigm, 0); + int sival_int; + void *sival_ptr; +} sigval_t; - return RVAL_HEX | RVAL_STR; - } - return 0; -} +# define __SI_MAX_SIZE 128 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof(int)) - 3) -int -sys_sigblock(tcp) -struct tcb *tcp; +typedef struct siginfo { - return sys_sigsetmask(tcp); -} - -#endif /* !SVR4 */ + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ -#ifdef HAVE_SIGACTION + union + { + int _pad[__SI_PAD_SIZE]; -#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 */ + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; -#ifndef SA_HANDLER -#define SA_HANDLER sa_handler -#endif + /* 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 int -sys_sigaction(tcp) -struct tcb *tcp; +sys_sigaction(struct tcb *tcp) { long addr; - sigset_t sigset; #ifdef LINUX + sigset_t sigset; struct old_sigaction sa; #else struct sigaction sa; @@ -614,39 +993,47 @@ struct tcb *tcp; else if (umove(tcp, addr, &sa) < 0) tprintf("{...}"); else { - switch ((long) sa.SA_HANDLER) { - case (long) SIG_ERR: - tprintf("{SIG_ERR}"); - break; - case (long) SIG_DFL: - tprintf("{SIG_DFL}"); - break; - case (long) SIG_IGN: -#ifndef SVR4 + /* Architectures using function pointers, like + * hppa, may need to manipulate the function pointer + * to compute the result of a comparison. However, + * the SA_HANDLER function pointer exists only in + * the address space of the traced process, and can't + * be manipulated by strace. In order to prevent the + * compiler from generating code to manipulate + * SA_HANDLER we cast the function pointers to long. */ + if ((long)sa.SA_HANDLER == (long)SIG_ERR) + tprintf("{SIG_ERR, "); + else if ((long)sa.SA_HANDLER == (long)SIG_DFL) + tprintf("{SIG_DFL, "); + else if ((long)sa.SA_HANDLER == (long)SIG_IGN) { +#ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } -#endif /* !SVR4 */ - tprintf("{SIG_IGN}"); - break; - default: -#ifndef SVR4 +#endif /* !USE_PROCFS */ + tprintf("{SIG_IGN, "); + } + else { +#ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ tprintf("{%#lx, ", (long) sa.SA_HANDLER); #ifndef LINUX - printsigmask (&sa.sa_mask, 0); + printsigmask(&sa.sa_mask, 0); #else long_to_sigset(sa.sa_mask, &sigset); printsigmask(&sigset, 0); #endif tprintf(", "); - if (!printflags(sigact_flags, sa.sa_flags)) - tprintf("0"); + printflags(sigact_flags, sa.sa_flags, "SA_???"); +#ifdef SA_RESTORER + if (sa.sa_flags & SA_RESTORER) + tprintf(", %p", sa.sa_restorer); +#endif tprintf("}"); } } @@ -660,76 +1047,118 @@ struct tcb *tcp; } int -sys_signal(tcp) -struct tcb *tcp; +sys_signal(struct tcb *tcp) { if (entering(tcp)) { printsignal(tcp->u_arg[0]); + tprintf(", "); switch (tcp->u_arg[1]) { - case (int) SIG_ERR: + case (long) SIG_ERR: tprintf("SIG_ERR"); break; - case (int) SIG_DFL: + case (long) SIG_DFL: tprintf("SIG_DFL"); break; - case (int) SIG_IGN: -#ifndef SVR4 + case (long) SIG_IGN: +#ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ tprintf("SIG_IGN"); break; default: -#ifndef SVR4 +#ifndef USE_PROCFS if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ tprintf("%#lx", tcp->u_arg[1]); } + return 0; + } + else if (!syserror(tcp)) { + switch (tcp->u_rval) { + case (long) SIG_ERR: + tcp->auxstr = "SIG_ERR"; break; + case (long) SIG_DFL: + tcp->auxstr = "SIG_DFL"; break; + case (long) SIG_IGN: + tcp->auxstr = "SIG_IGN"; break; + default: + tcp->auxstr = NULL; + } + return RVAL_HEX | RVAL_STR; } return 0; } +#ifdef SVR4 +int +sys_sighold(struct tcb *tcp) +{ + if (entering(tcp)) { + printsignal(tcp->u_arg[0]); + } + return 0; +} +#endif /* SVR4 */ + #endif /* HAVE_SIGACTION */ #ifdef LINUX int -sys_sigreturn(tcp) -struct tcb *tcp; +sys_sigreturn(struct tcb *tcp) { -#ifdef S390 - long usp; - struct sigcontext_struct sc; - - if (entering(tcp)) { - tcp->u_arg[0] = 0; - if (upeek(tcp->pid,PT_GPR15,&usp)<0) - return 0; - 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)); - } else { - tcp->u_rval = tcp->u_error = 0; - if (tcp->u_arg[0] == 0) - return 0; - tcp->auxstr = sprintsigmask("mask now ",(sigset_t *)&tcp->u_arg[1]); - return RVAL_NONE | RVAL_STR; - } - return 0; -#else -#ifdef I386 - long esp; - struct sigcontext_struct sc; - +#if defined(ARM) + if (entering(tcp)) { + struct pt_regs regs; + struct sigcontext_struct sc; + tcp->u_arg[0] = 0; + if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)®s) == -1) + return 0; + if (umove(tcp, regs.ARM_sp, &sc) < 0) + return 0; + tcp->u_arg[0] = 1; + tcp->u_arg[1] = sc.oldmask; + } else { + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined(S390) || defined(S390X) + if (entering(tcp)) { + long usp; + struct sigcontext_struct sc; + tcp->u_arg[0] = 0; + if (upeek(tcp, PT_GPR15, &usp) < 0) + return 0; + if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0) + return 0; + tcp->u_arg[0] = 1; + memcpy(&tcp->u_arg[1], &sc.oldmask[0], NSIG / 8); + } else { + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + tcp->auxstr = sprintsigmask("mask now ", (sigset_t *)&tcp->u_arg[1], 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined(I386) if (entering(tcp)) { + long esp; + struct sigcontext_struct sc; tcp->u_arg[0] = 0; - if (upeek(tcp->pid, 4*UESP, &esp) < 0) + if (upeek(tcp, 4*UESP, &esp) < 0) return 0; if (umove(tcp, esp, &sc) < 0) return 0; @@ -738,171 +1167,272 @@ struct tcb *tcp; } else { sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined(IA64) + if (entering(tcp)) { + struct sigcontext sc; + long sp; + /* offset of sigcontext in the kernel's sigframe structure: */ +# define SIGFRAME_SC_OFFSET 0x90 + tcp->u_arg[0] = 0; + if (upeek(tcp, PT_R12, &sp) < 0) + return 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, NSIG / 8); + } + else { + sigset_t sigm; tcp->u_rval = tcp->u_error = 0; if (tcp->u_arg[0] == 0) return 0; + sigemptyset(&sigm); + memcpy(&sigm, tcp->u_arg + 1, NSIG / 8); tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); return RVAL_NONE | RVAL_STR; } return 0; -#else /* !I386 */ -#ifdef IA64 - struct sigcontext sc; - long sp; - +#elif defined(POWERPC) if (entering(tcp)) { + long esp; + struct sigcontext_struct sc; tcp->u_arg[0] = 0; - if (upeek(tcp->pid, PT_R12, &sp) < 0) + if (upeek(tcp, sizeof(unsigned long)*PT_R1, &esp) < 0) return 0; - if (umove(tcp, sp + 16, &sc) < 0) + /* Skip dummy stack frame. */ +#ifdef POWERPC64 + if (current_personality == 0) + esp += 128; + else + esp += 64; +#else + esp += 64; +#endif + if (umove(tcp, esp, &sc) < 0) return 0; tcp->u_arg[0] = 1; - memcpy(tcp->u_arg + 1, &sc.sc_mask, sizeof(tcp->u_arg[1])); + tcp->u_arg[1] = sc.oldmask; } else { + sigset_t sigm; tcp->u_rval = tcp->u_error = 0; if (tcp->u_arg[0] == 0) return 0; - tcp->auxstr = sprintsigmask("mask now ", tcp->u_arg[1]); + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); return RVAL_NONE | RVAL_STR; } return 0; -#else /* !IA64 */ -#ifdef POWERPC - long esp; - struct sigcontext_struct sc; - - if (entering(tcp)) { - tcp->u_arg[0] = 0; - if (upeek(tcp->pid, 4*PT_R1, &esp) < 0) - return 0; - if (umove(tcp, esp, &sc) < 0) - return 0; - tcp->u_arg[0] = 1; - tcp->u_arg[1] = sc.oldmask; - } - else { - sigset_t sigm; - long_to_sigset(tcp->u_arg[1], &sigm); - tcp->u_rval = tcp->u_error = 0; - if (tcp->u_arg[0] == 0) - return 0; - tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); - return RVAL_NONE | RVAL_STR; - } - return 0; -#else /* !POWERPC */ -#ifdef M68K - long usp; - struct sigcontext sc; - +#elif defined(M68K) if (entering(tcp)) { - tcp->u_arg[0] = 0; - if (upeek(tcp->pid, 4*PT_USP, &usp) < 0) + long usp; + struct sigcontext sc; + tcp->u_arg[0] = 0; + if (upeek(tcp, 4*PT_USP, &usp) < 0) return 0; - if (umove(tcp, usp, &sc) < 0) + if (umove(tcp, usp, &sc) < 0) return 0; - tcp->u_arg[0] = 1; - tcp->u_arg[1] = sc.sc_mask; + tcp->u_arg[0] = 1; + tcp->u_arg[1] = sc.sc_mask; } else { - sigset_t sigm; - long_to_sigset(tcp->u_arg[1], &sigm); - tcp->u_rval = tcp->u_error = 0; - if (tcp->u_arg[0] == 0) + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) return 0; - tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); - return RVAL_NONE | RVAL_STR; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; } return 0; -#else /* !M68K */ -#ifdef ALPHA - long fp; - struct sigcontext_struct sc; - +#elif defined(ALPHA) if (entering(tcp)) { - tcp->u_arg[0] = 0; - if (upeek(tcp->pid, REG_FP, &fp) < 0) + long fp; + struct sigcontext_struct sc; + tcp->u_arg[0] = 0; + if (upeek(tcp, REG_FP, &fp) < 0) return 0; - if (umove(tcp, fp, &sc) < 0) + if (umove(tcp, fp, &sc) < 0) return 0; - tcp->u_arg[0] = 1; - tcp->u_arg[1] = sc.sc_mask; + tcp->u_arg[0] = 1; + tcp->u_arg[1] = sc.sc_mask; } else { - sigset_t sigm; - long_to_sigset(tcp->u_arg[1], &sigm); - tcp->u_rval = tcp->u_error = 0; - if (tcp->u_arg[0] == 0) + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) return 0; - tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); - return RVAL_NONE | RVAL_STR; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; } return 0; -#else -#ifdef SPARC - long i1; - struct regs regs; - m_siginfo_t si; - - if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { - perror("sigreturn: PTRACE_GETREGS "); - return 0; +#elif defined (SPARC) || defined (SPARC64) + if (entering(tcp)) { + long i1; + struct pt_regs regs; + m_siginfo_t si; + tcp->u_arg[0] = 0; + if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { + perror("sigreturn: PTRACE_GETREGS"); + return 0; + } + i1 = regs.u_regs[U_REG_O1]; + if (umove(tcp, i1, &si) < 0) { + perror("sigreturn: umove"); + return 0; + } + tcp->u_arg[0] = 1; + tcp->u_arg[1] = si.si_mask; + } else { + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64) + /* This decodes rt_sigreturn. The 64-bit ABIs do not have + sigreturn. */ + if (entering(tcp)) { + long sp; + struct ucontext uc; + tcp->u_arg[0] = 0; + if (upeek(tcp, REG_SP, &sp) < 0) + return 0; + /* There are six words followed by a 128-byte siginfo. */ + sp = sp + 6 * 4 + 128; + if (umove(tcp, sp, &uc) < 0) + return 0; + tcp->u_arg[0] = 1; + tcp->u_arg[1] = *(long *) &uc.uc_sigmask; + } else { + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; } - if(entering(tcp)) { + return 0; +#elif defined(MIPS) + if (entering(tcp)) { + long sp; + struct pt_regs regs; + m_siginfo_t si; tcp->u_arg[0] = 0; - i1 = regs.r_o1; - if(umove(tcp, i1, &si) < 0) { - perror("sigreturn: umove "); + if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { + perror("sigreturn: PTRACE_GETREGS"); return 0; } + sp = regs.regs[29]; + if (umove(tcp, sp, &si) < 0) + return 0; tcp->u_arg[0] = 1; tcp->u_arg[1] = si.si_mask; } else { sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined(CRISV10) || defined(CRISV32) + if (entering(tcp)) { + struct sigcontext sc; + long regs[PT_MAX+1]; + tcp->u_arg[0] = 0; + if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) { + perror("sigreturn: PTRACE_GETREGS"); + return 0; + } + if (umove(tcp, regs[PT_USP], &sc) < 0) + return 0; + tcp->u_arg[0] = 1; + tcp->u_arg[1] = sc.oldmask; + } else { + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); + return RVAL_NONE | RVAL_STR; + } + return 0; +#elif defined(TILE) + if (entering(tcp)) { + struct ucontext uc; + long sp; + + /* offset of ucontext in the kernel's sigframe structure */ +# define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(struct siginfo) + tcp->u_arg[0] = 0; + if (upeek(tcp, PTREGS_OFFSET_SP, &sp) < 0) + return 0; + if (umove(tcp, sp + SIGFRAME_UC_OFFSET, &uc) < 0) + return 0; + tcp->u_arg[0] = 1; + 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) + if (tcp->u_arg[0] == 0) return 0; + sigemptyset(&sigm); + memcpy(&sigm, tcp->u_arg + 1, NSIG / 8); tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); return RVAL_NONE | RVAL_STR; } return 0; -#else -#ifdef MIPS - long sp; - struct sigcontext sc; - - if(entering(tcp)) { - tcp->u_arg[0] = 0; - if (upeek(tcp->pid, REG_SP, &sp) < 0) - return 0; +#elif defined(MICROBLAZE) + /* TODO: Verify that this is correct... */ + if (entering(tcp)) { + struct sigcontext sc; + long sp; + tcp->u_arg[0] = 0; + /* Read r1, the stack pointer. */ + if (upeek(tcp, 1 * 4, &sp) < 0) + return 0; if (umove(tcp, sp, &sc) < 0) - return 0; + return 0; tcp->u_arg[0] = 1; - tcp->u_arg[1] = sc.sc_sigset; + tcp->u_arg[1] = sc.oldmask; } else { - tcp->u_rval = tcp->u_error = 0; - if(tcp->u_arg[0] == 0) - return 0; - tcp->auxstr = sprintsigmask("mask now ", tcp->u_arg[1]); + sigset_t sigm; + tcp->u_rval = tcp->u_error = 0; + if (tcp->u_arg[0] == 0) + return 0; + long_to_sigset(tcp->u_arg[1], &sigm); + tcp->auxstr = sprintsigmask("mask now ", &sigm, 0); return RVAL_NONE | RVAL_STR; } return 0; -#endif /* MIPS */ -#endif /* SPARC */ -#endif /* ALPHA */ -#endif /* !M68K */ -#endif /* !POWERPC */ -#endif /* !IA64 */ -#endif /* !I386 */ -#endif /* S390 */ +#else +#warning No sys_sigreturn() for this architecture +#warning (no problem, just a reminder :-) + return 0; +#endif } int -sys_siggetmask(tcp) -struct tcb *tcp; +sys_siggetmask(struct tcb *tcp) { if (exiting(tcp)) { sigset_t sigm; @@ -913,17 +1443,11 @@ struct tcb *tcp; } int -sys_sigsuspend(tcp) -struct tcb *tcp; +sys_sigsuspend(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigm; long_to_sigset(tcp->u_arg[2], &sigm); -#if 0 - /* first two are not really arguments, but print them anyway */ - /* nevermind, they are an anachronism now, too bad... */ - tprintf("%d, %#x, ", tcp->u_arg[0], tcp->u_arg[1]); -#endif printsigmask(&sigm, 0); } return 0; @@ -931,11 +1455,10 @@ struct tcb *tcp; #endif /* LINUX */ -#ifdef SVR4 +#if defined(SVR4) || defined(FREEBSD) int -sys_sigsuspend(tcp) -struct tcb *tcp; +sys_sigsuspend(struct tcb *tcp) { sigset_t sigset; @@ -947,7 +1470,8 @@ struct tcb *tcp; } return 0; } -static struct xlat ucontext_flags[] = { +#ifndef FREEBSD +static const struct xlat ucontext_flags[] = { { UC_SIGMASK, "UC_SIGMASK" }, { UC_STACK, "UC_STACK" }, { UC_CPU, "UC_CPU" }, @@ -959,10 +1483,10 @@ static struct xlat ucontext_flags[] = { #endif { 0, NULL }, }; +#endif /* !FREEBSD */ +#endif /* SVR4 || FREEBSD */ -#endif - -#if defined SVR4 || defined LINUX +#if defined SVR4 || defined LINUX || defined FREEBSD #if defined LINUX && !defined SS_ONSTACK #define SS_ONSTACK 1 #define SS_DISABLE 2 @@ -975,8 +1499,11 @@ typedef struct } stack_t; #endif #endif +#ifdef FREEBSD +#define stack_t struct sigaltstack +#endif -static struct xlat sigaltstack_flags[] = { +static const struct xlat sigaltstack_flags[] = { { SS_ONSTACK, "SS_ONSTACK" }, { SS_DISABLE, "SS_DISABLE" }, { 0, NULL }, @@ -985,38 +1512,35 @@ static struct xlat sigaltstack_flags[] = { #ifdef SVR4 static void -printcontext(tcp, ucp) -struct tcb *tcp; -ucontext_t *ucp; +printcontext(struct tcb *tcp, ucontext_t *ucp) { tprintf("{"); if (!abbrev(tcp)) { tprintf("uc_flags="); - if (!printflags(ucontext_flags, ucp->uc_flags)) - tprintf("0"); + printflags(ucontext_flags, ucp->uc_flags, "UC_???"); tprintf(", uc_link=%#lx, ", (unsigned long) ucp->uc_link); } tprintf("uc_sigmask="); - printsigmask(ucp->uc_sigmask, 0); + printsigmask(&ucp->uc_sigmask, 0); if (!abbrev(tcp)) { tprintf(", uc_stack={ss_sp=%#lx, ss_size=%d, ss_flags=", (unsigned long) ucp->uc_stack.ss_sp, ucp->uc_stack.ss_size); - if (!printflags(sigaltstack_flags, ucp->uc_stack.ss_flags)) - tprintf("0"); + printflags(sigaltstack_flags, ucp->uc_stack.ss_flags, "SS_???"); tprintf("}"); } tprintf(", ...}"); } int -sys_getcontext(tcp) -struct tcb *tcp; +sys_getcontext(struct tcb *tcp) { ucontext_t uc; - if (entering(tcp)) { - if (!tcp->u_arg[0]) + if (exiting(tcp)) { + if (tcp->u_error) + tprintf("%#lx", tcp->u_arg[0]); + else if (!tcp->u_arg[0]) tprintf("NULL"); else if (umove(tcp, tcp->u_arg[0], &uc) < 0) tprintf("{...}"); @@ -1027,8 +1551,7 @@ struct tcb *tcp; } int -sys_setcontext(tcp) -struct tcb *tcp; +sys_setcontext(struct tcb *tcp) { ucontext_t uc; @@ -1051,26 +1574,22 @@ struct tcb *tcp; #endif /* SVR4 */ -#ifdef LINUX +#if defined(LINUX) || defined(FREEBSD) static int -print_stack_t(tcp, addr) -struct tcb *tcp; -unsigned long addr; +print_stack_t(struct tcb *tcp, unsigned long addr) { stack_t ss; if (umove(tcp, addr, &ss) < 0) return -1; tprintf("{ss_sp=%#lx, ss_flags=", (unsigned long) ss.ss_sp); - if (!printflags(sigaltstack_flags, ss.ss_flags)) - tprintf("0"); + printflags(sigaltstack_flags, ss.ss_flags, "SS_???"); tprintf(", ss_size=%lu}", (unsigned long) ss.ss_size); return 0; } int -sys_sigaltstack(tcp) - struct tcb *tcp; +sys_sigaltstack(struct tcb *tcp) { if (entering(tcp)) { if (tcp->u_arg[0] == 0) @@ -1092,8 +1611,7 @@ sys_sigaltstack(tcp) #ifdef HAVE_SIGACTION int -sys_sigprocmask(tcp) -struct tcb *tcp; +sys_sigprocmask(struct tcb *tcp) { #ifdef ALPHA if (entering(tcp)) { @@ -1106,8 +1624,6 @@ struct tcb *tcp; return RVAL_HEX | RVAL_STR; } #else /* !ALPHA */ - sigset_t sigset; - if (entering(tcp)) { #ifdef SVR4 if (tcp->u_arg[0] == 0) @@ -1116,24 +1632,16 @@ struct tcb *tcp; #endif /* SVR4 */ printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???"); tprintf(", "); - if (!tcp->u_arg[1]) - tprintf("NULL, "); - else if (copy_sigset(tcp, tcp->u_arg[1], &sigset) < 0) - tprintf("%#lx, ", tcp->u_arg[1]); - else { - printsigmask(&sigset, 0); - tprintf(", "); - } + print_sigset(tcp, tcp->u_arg[1], 0); + tprintf(", "); } else { if (!tcp->u_arg[2]) tprintf("NULL"); else if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[2]); - else if (copy_sigset(tcp, tcp->u_arg[2], &sigset) < 0) - tprintf("[?]"); else - printsigmask(&sigset, 0); + print_sigset(tcp, tcp->u_arg[2], 0); } #endif /* !ALPHA */ return 0; @@ -1142,25 +1650,42 @@ struct tcb *tcp; #endif /* HAVE_SIGACTION */ int -sys_kill(tcp) -struct tcb *tcp; +sys_kill(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, %s", tcp->u_arg[0], signame(tcp->u_arg[1])); + long pid = tcp->u_arg[0]; +#if SUPPORTED_PERSONALITIES > 1 + /* Sign-extend a 32-bit value when that's what it is. */ + if (personality_wordsize[current_personality] < sizeof pid) + pid = (long) (int) pid; +#endif + tprintf("%ld, %s", pid, signame(tcp->u_arg[1])); } return 0; } +#if defined(FREEBSD) || defined(SUNOS4) int -sys_killpg(tcp) -struct tcb *tcp; +sys_killpg(struct tcb *tcp) { return sys_kill(tcp); } +#endif /* FREEBSD || SUNOS4 */ + +#ifdef LINUX +int +sys_tgkill(struct tcb *tcp) +{ + if (entering(tcp)) { + tprintf("%ld, %ld, %s", + tcp->u_arg[0], tcp->u_arg[1], signame(tcp->u_arg[2])); + } + return 0; +} +#endif int -sys_sigpending(tcp) -struct tcb *tcp; +sys_sigpending(struct tcb *tcp) { sigset_t sigset; @@ -1175,11 +1700,31 @@ struct tcb *tcp; return 0; } +#ifdef SVR4 +int sys_sigwait(struct tcb *tcp) +{ + sigset_t sigset; + + if (entering(tcp)) { + if (copy_sigset(tcp, tcp->u_arg[0], &sigset) < 0) + tprintf("[?]"); + else + printsigmask(&sigset, 0); + } + else { + if (!syserror(tcp)) { + tcp->auxstr = signalent[tcp->u_rval]; + return RVAL_DECIMAL | RVAL_STR; + } + } + return 0; +} +#endif /* SVR4 */ + #ifdef LINUX - int -sys_rt_sigprocmask(tcp) - struct tcb *tcp; +int +sys_rt_sigprocmask(struct tcb *tcp) { sigset_t sigset; @@ -1198,7 +1743,6 @@ sys_rt_sigprocmask(tcp) } else { if (!tcp->u_arg[2]) - tprintf("NULL"); else if (syserror(tcp)) tprintf("%#lx", tcp->u_arg[2]); @@ -1211,97 +1755,33 @@ sys_rt_sigprocmask(tcp) return 0; } -#if __GLIBC_MINOR__ < 1 -/* Type for data associated with a signal. */ -typedef union sigval -{ - int sival_int; - void *sival_ptr; -} sigval_t; - -# define __SI_MAX_SIZE 128 -# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) - -typedef struct siginfo -{ - int si_signo; /* Signal number. */ - int si_errno; /* If non-zero, an errno value associated with - this signal, as defined in . */ - int si_code; /* Signal code. */ - - union - { - int _pad[__SI_PAD_SIZE]; - - /* kill(). */ - struct - { - __pid_t si_pid; /* Sending process ID. */ - __uid_t si_uid; /* Real user ID of sending process. */ - } _kill; - - /* 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; -#endif /* Structure describing the action to be taken when a signal arrives. */ struct new_sigaction { - union - { - __sighandler_t __sa_handler; - void (*__sa_sigaction) (int, siginfo_t *, void *); - } - __sigaction_handler; + __sighandler_t __sa_handler; unsigned long sa_flags; void (*sa_restorer) (void); - unsigned long int sa_mask[2]; + /* Kernel treats sa_mask as an array of longs. */ + unsigned long sa_mask[NSIG / sizeof(long) ? NSIG / sizeof(long) : 1]; +}; +/* Same for i386-on-x86_64 and similar cases */ +struct new_sigaction32 +{ + uint32_t __sa_handler; + uint32_t sa_flags; + uint32_t sa_restorer; + uint32_t sa_mask[2 * (NSIG / sizeof(long) ? NSIG / sizeof(long) : 1)]; }; - int -sys_rt_sigaction(tcp) - struct tcb *tcp; +int +sys_rt_sigaction(struct tcb *tcp) { struct new_sigaction sa; sigset_t sigset; long addr; + int r; if (entering(tcp)) { printsignal(tcp->u_arg[0]); @@ -1309,43 +1789,86 @@ sys_rt_sigaction(tcp) addr = tcp->u_arg[1]; } else addr = tcp->u_arg[2]; - if (addr == 0) + + if (addr == 0) { tprintf("NULL"); - else if (!verbose(tcp)) + goto after_sa; + } + if (!verbose(tcp)) { tprintf("%#lx", addr); - else if (umove(tcp, addr, &sa) < 0) + goto after_sa; + } +#if SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] != sizeof(sa.sa_flags) + && personality_wordsize[current_personality] == 4 + ) { + struct new_sigaction32 sa32; + r = umove(tcp, addr, &sa32); + if (r >= 0) { + memset(&sa, 0, sizeof(sa)); + sa.__sa_handler = (void*)(unsigned long)sa32.__sa_handler; + sa.sa_flags = sa32.sa_flags; + sa.sa_restorer = (void*)(unsigned long)sa32.sa_restorer; + /* Kernel treats sa_mask as an array of longs. + * For 32-bit process, "long" is uint32_t, thus, for example, + * 32th bit in sa_mask will end up as bit 0 in sa_mask[1]. + * But for (64-bit) kernel, 32th bit in sa_mask is + * 32th bit in 0th (64-bit) long! + * For little-endian, it's the same. + * For big-endian, we swap 32-bit words. + */ + sa.sa_mask[0] = sa32.sa_mask[0] + ((long)(sa32.sa_mask[1]) << 32); + } + } else +#endif + { + r = umove(tcp, addr, &sa); + } + if (r < 0) { tprintf("{...}"); - else { - switch ((long) sa.__sigaction_handler.__sa_handler) { - case (long) SIG_ERR: - tprintf("{SIG_ERR}"); - break; - case (long) SIG_DFL: - tprintf("{SIG_DFL}"); - break; - case (long) SIG_IGN: - tprintf("{SIG_IGN}"); - break; - default: - tprintf("{%#lx, ", - (long) sa.__sigaction_handler.__sa_handler); - sigemptyset(&sigset); + goto after_sa; + } + /* Architectures using function pointers, like + * hppa, may need to manipulate the function pointer + * to compute the result of a comparison. However, + * the SA_HANDLER function pointer exists only in + * the address space of the traced process, and can't + * be manipulated by strace. In order to prevent the + * compiler from generating code to manipulate + * SA_HANDLER we cast the function pointers to long. */ + if ((long)sa.__sa_handler == (long)SIG_ERR) + tprintf("{SIG_ERR, "); + else if ((long)sa.__sa_handler == (long)SIG_DFL) + tprintf("{SIG_DFL, "); + else if ((long)sa.__sa_handler == (long)SIG_IGN) + tprintf("{SIG_IGN, "); + else + tprintf("{%#lx, ", (long) sa.__sa_handler); + /* Questionable code below. + * Kernel won't handle sys_rt_sigaction + * with wrong sigset size (just returns EINVAL) + * therefore tcp->u_arg[3(4)] _must_ be NSIG / 8 here, + * and we always use smaller memcpy. */ + sigemptyset(&sigset); #ifdef LINUXSPARC - if (tcp->u_arg[4] <= sizeof(sigset)) - memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]); + if (tcp->u_arg[4] <= sizeof(sigset)) + memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]); #else - if (tcp->u_arg[3] <= sizeof(sigset)) - memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]); + if (tcp->u_arg[3] <= sizeof(sigset)) + memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]); #endif - else - memcpy(&sigset, &sa.sa_mask, sizeof(sigset)); - printsigmask(&sigset, 1); - tprintf(", "); - if (!printflags(sigact_flags, sa.sa_flags)) - tprintf("0"); - tprintf("}"); - } - } + else + memcpy(&sigset, &sa.sa_mask, sizeof(sigset)); + printsigmask(&sigset, 1); + tprintf(", "); + printflags(sigact_flags, sa.sa_flags, "SA_???"); +#ifdef SA_RESTORER + if (sa.sa_flags & SA_RESTORER) + tprintf(", %p", sa.sa_restorer); +#endif + tprintf("}"); + + after_sa: if (entering(tcp)) tprintf(", "); else @@ -1354,14 +1877,13 @@ sys_rt_sigaction(tcp) #elif defined(ALPHA) tprintf(", %lu, %#lx", tcp->u_arg[3], tcp->u_arg[4]); #else - tprintf(", %lu", addr = tcp->u_arg[3]); + tprintf(", %lu", tcp->u_arg[3]); #endif return 0; } - int -sys_rt_sigpending(tcp) - struct tcb *tcp; +int +sys_rt_sigpending(struct tcb *tcp) { sigset_t sigset; @@ -1376,9 +1898,9 @@ sys_rt_sigpending(tcp) } return 0; } - int -sys_rt_sigsuspend(tcp) - struct tcb *tcp; + +int +sys_rt_sigsuspend(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigm; @@ -1389,216 +1911,9 @@ sys_rt_sigsuspend(tcp) } return 0; } -#ifndef ILL_ILLOPC -#define ILL_ILLOPC 1 /* illegal opcode */ -#define ILL_ILLOPN 2 /* illegal operand */ -#define ILL_ILLADR 3 /* illegal addressing mode */ -#define ILL_ILLTRP 4 /* illegal trap */ -#define ILL_PRVOPC 5 /* privileged opcode */ -#define ILL_PRVREG 6 /* privileged register */ -#define ILL_COPROC 7 /* coprocessor error */ -#define ILL_BADSTK 8 /* internal stack error */ -#define FPE_INTDIV 1 /* integer divide by zero */ -#define FPE_INTOVF 2 /* integer overflow */ -#define FPE_FLTDIV 3 /* floating point divide by zero */ -#define FPE_FLTOVF 4 /* floating point overflow */ -#define FPE_FLTUND 5 /* floating point underflow */ -#define FPE_FLTRES 6 /* floating point inexact result */ -#define FPE_FLTINV 7 /* floating point invalid operation */ -#define FPE_FLTSUB 8 /* subscript out of range */ -#define SEGV_MAPERR 1 /* address not mapped to object */ -#define SEGV_ACCERR 2 /* invalid permissions for mapped object */ -#define BUS_ADRALN 1 /* invalid address alignment */ -#define BUS_ADRERR 2 /* non-existant physical address */ -#define BUS_OBJERR 3 /* object specific hardware error */ -#define TRAP_BRKPT 1 /* process breakpoint */ -#define TRAP_TRACE 2 /* process trace trap */ -#define CLD_EXITED 1 /* child has exited */ -#define CLD_KILLED 2 /* child was killed */ -#define CLD_DUMPED 3 /* child terminated abnormally */ -#define CLD_TRAPPED 4 /* traced child has trapped */ -#define CLD_STOPPED 5 /* child has stopped */ -#define CLD_CONTINUED 6 /* stopped child has continued */ -#define POLL_IN 1 /* data input available */ -#define POLL_OUT 2 /* output buffers available */ -#define POLL_MSG 3 /* input message available */ -#define POLL_ERR 4 /* i/o error */ -#define POLL_PRI 5 /* high priority input available */ -#define POLL_HUP 6 /* device disconnected */ -#define SI_USER 0 /* sent by kill, sigsend, raise */ -#define SI_QUEUE -1 /* sent by sigqueue */ -#define SI_TIMER -2 /* sent by timer expiration */ -#define SI_MESGQ -3 /* sent by real time mesq state change */ -#define SI_ASYNCIO -4 /* sent by AIO completion */ -#else -#undef si_pid -#undef si_uid -#undef si_status -#undef si_utime -#undef si_stime -#undef si_value -#undef si_int -#undef si_ptr -#undef si_addr -#undef si_band -#undef si_fd -#endif - -static struct xlat sigill_flags[] = { - {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 struct xlat sigfpe_flags[] = { - {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 struct xlat sigsegv_flags[] = { - {SEGV_MAPERR, "SEGV_MAPERR"}, - {SEGV_ACCERR, "SEGV_ACCERR"}, - {0, NULL} -}; - -static struct xlat sigbus_flags[] = { - {BUS_ADRALN, "BUS_ADRALN"}, - {BUS_ADRERR, "BUS_ADRERR"}, - {BUS_OBJERR, "BUS_OBJERR"}, - {0, NULL} -}; - -static struct xlat sigtrap_flags[] = { - {TRAP_BRKPT, "TRAP_BRKPT"}, - {TRAP_TRACE, "TRAP_TRACE"}, - {0, NULL} -}; - -static struct xlat sigchld_flags[] = { - {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 struct xlat sigpoll_flags[] = { - {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 struct xlat siginfo_flags[] = { - {SI_USER, "SI_USER"}, - {SI_QUEUE, "SI_QUEUE"}, - {SI_TIMER, "SI_TIMER"}, - {SI_MESGQ, "SI_MESGQ"}, - {SI_ASYNCIO, "SI_ASYNCIO"}, - {0, NULL} -}; - - static void -printsiginfo(tcp, si) - struct tcb *tcp; - siginfo_t *si; -{ - tprintf("{si_signo="); - printsignal(si->si_signo); - tprintf(", si_errno=%d, si_code=", si->si_errno); - switch(si->si_signo) - { - case SIGILL: - if (!printflags(sigill_flags, si->si_code)) - tprintf("%d /* ILL_??? */", si->si_code); - tprintf(", si_addr=%lx", - (unsigned long) si->_sifields._sigfault.si_addr); - break; - case SIGFPE: - if (!printflags(sigfpe_flags, si->si_code)) - tprintf("%d /* FPE_??? */", si->si_code); - tprintf(", si_addr=%lx", - (unsigned long) si->_sifields._sigfault.si_addr); - break; - case SIGSEGV: - if (!printflags(sigsegv_flags, si->si_code)) - tprintf("%d /* SEGV_??? */", si->si_code); - tprintf(", si_addr=%lx", - (unsigned long) si->_sifields._sigfault.si_addr); - break; - case SIGBUS: - if (!printflags(sigbus_flags, si->si_code)) - tprintf("%d /* BUS_??? */", si->si_code); - tprintf(", si_addr=%lx", - (unsigned long) si->_sifields._sigfault.si_addr); - break; - case SIGTRAP: - if (!printflags(sigtrap_flags, si->si_code)) - tprintf("%d /* TRAP_??? */", si->si_code); - break; - case SIGCHLD: - if (!printflags(sigchld_flags, si->si_code)) - tprintf("%d /* CLD_??? */", si->si_code); - if (!verbose(tcp)) - tprintf(", ..."); - else - tprintf(", si_pid=%d, si_uid=%d, si_status=%d, si_utime=%lu, si_stime=%lu", - si->_sifields._kill.si_pid, - si->_sifields._kill.si_uid, - si->_sifields._sigchld.si_status, - si->_sifields._sigchld.si_utime, - si->_sifields._sigchld.si_stime); - break; - case SIGPOLL: - if (!printflags(sigpoll_flags, si->si_code)) - tprintf("%d /* POLL_??? */", si->si_code); - if (si->si_code == POLL_IN - || si->si_code == POLL_OUT - || si->si_code == POLL_MSG) - tprintf(", si_bind=%lu, si_fd=%d", - (unsigned long) si->_sifields._sigpoll.si_band, - si->_sifields._sigpoll.si_fd); - break; - default: - if (!printflags(siginfo_flags, si->si_code)) - tprintf("%d /* SI_??? */", si->si_code); - tprintf(", si_pid=%lu, si_uid=%lu, si_value={", - (unsigned long) si->_sifields._rt.si_pid, - (unsigned long) si->_sifields._rt.si_uid); - if (!verbose(tcp)) - tprintf("..."); - else { - tprintf("sival_int=%u, sival_ptr=%#lx", - si->_sifields._rt.si_sigval.sival_int, - (unsigned long) si->_sifields._rt.si_sigval.sival_ptr); - } - tprintf("}"); - break; - } - tprintf("}"); -} - int -sys_rt_sigqueueinfo(tcp) - struct tcb *tcp; +int +sys_rt_sigqueueinfo(struct tcb *tcp) { if (entering(tcp)) { siginfo_t si; @@ -1608,40 +1923,84 @@ sys_rt_sigqueueinfo(tcp) if (umove(tcp, tcp->u_arg[2], &si) < 0) tprintf("%#lx", tcp->u_arg[2]); else - printsiginfo(&si); + printsiginfo(&si, verbose(tcp)); } return 0; } -int sys_rt_sigtimedwait(tcp) - struct tcb *tcp; +int sys_rt_sigtimedwait(struct tcb *tcp) { if (entering(tcp)) { sigset_t sigset; - if (copy_sigset_len(tcp, tcp->u_arg[0], + if (copy_sigset_len(tcp, tcp->u_arg[0], &sigset, tcp->u_arg[3]) < 0) tprintf("[?]"); else printsigmask(&sigset, 1); tprintf(", "); + /* This is the only "return" parameter, */ + if (tcp->u_arg[1] != 0) + return 0; + /* ... if it's NULL, can decode all on entry */ + tprintf("NULL, "); } - else { + else if (tcp->u_arg[1] != 0) { + /* syscall exit, and u_arg[1] wasn't NULL */ if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[0]); + tprintf("%#lx, ", tcp->u_arg[1]); else { siginfo_t si; if (umove(tcp, tcp->u_arg[1], &si) < 0) - tprintf("%#lx", tcp->u_arg[1]); - else - printsiginfo(&si); - /* XXX For now */ - tprintf(", %#lx", tcp->u_arg[2]); - tprintf(", %d", (int) tcp->u_arg[3]); + tprintf("%#lx, ", tcp->u_arg[1]); + else { + printsiginfo(&si, verbose(tcp)); + tprintf(", "); + } } } + else { + /* syscall exit, and u_arg[1] was NULL */ + return 0; + } + print_timespec(tcp, tcp->u_arg[2]); + tprintf(", %d", (int) tcp->u_arg[3]); return 0; }; -#endif /* LINUX */ +int +sys_restart_syscall(struct tcb *tcp) +{ + if (entering(tcp)) + tprintf("<... resuming interrupted call ...>"); + return 0; +} + +static int +do_signalfd(struct tcb *tcp, int flags_arg) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); + print_sigset(tcp, tcp->u_arg[1], 1); + tprintf(", %lu", tcp->u_arg[2]); + if (flags_arg >= 0) { + tprintf(", "); + printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); + } + } + return 0; +} +int +sys_signalfd(struct tcb *tcp) +{ + return do_signalfd(tcp, -1); +} + +int +sys_signalfd4(struct tcb *tcp) +{ + return do_signalfd(tcp, 3); +} +#endif /* LINUX */