From: Denys Vlasenko Date: Wed, 15 Apr 2009 13:22:59 +0000 (+0000) Subject: * signal (sys_rt_sigaction): Print struct sigaction correctly X-Git-Tag: v4.5.19~59 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7a862d76203181c8df053a69f18d46146b81d508;p=strace * signal (sys_rt_sigaction): Print struct sigaction correctly in 32/64 environment. * desc.c (printflock): Add #ifdefs around earlier flock 32/64 fix so that we don't waste time on arches with one personality. --- diff --git a/ChangeLog b/ChangeLog index 2f04c629..901331da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-04-15 Denys Vlasenko + + * signal (sys_rt_sigaction): Print struct sigaction correctly + in 32/64 environment. + * desc.c (printflock): Add #ifdefs around earlier flock 32/64 fix + so that we don't waste time on arches with one personality. + 2009-04-14 Denys Vlasenko * signal.c: Whitespace, comment, and style fixes, no code changes. diff --git a/desc.c b/desc.c index 3aae9908..383107e3 100644 --- a/desc.c +++ b/desc.c @@ -236,34 +236,39 @@ printflock(struct tcb *tcp, long addr, int getlk) { struct flock fl; - if (personality_wordsize[current_personality] == sizeof(fl.l_start)) { - if (umove(tcp, addr, &fl) < 0) { - tprintf("{...}"); +#if SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] != sizeof(fl.l_start)) { + if (personality_wordsize[current_personality] == 4) { + /* 32-bit x86 app on x86_64 and similar cases */ + struct { + short int l_type; + short int l_whence; + int32_t l_start; /* off_t */ + int32_t l_len; /* off_t */ + int32_t l_pid; /* pid_t */ + } fl32; + if (umove(tcp, addr, &fl32) < 0) { + tprintf("{...}"); + return; + } + fl.l_type = fl32.l_type; + fl.l_whence = fl32.l_whence; + fl.l_start = fl32.l_start; + fl.l_len = fl32.l_len; + fl.l_pid = fl32.l_pid; + } else { + /* let people know we have a problem here */ + tprintf("{ }", + personality_wordsize[current_personality]); return; } - } else if (personality_wordsize[current_personality] == 4) { - /* 32-bit x86 app on x86_64 and similar cases */ - struct { - short int l_type; - short int l_whence; - int32_t l_start; /* off_t */ - int32_t l_len; /* off_t */ - int32_t l_pid; /* pid_t */ - } fl32; - if (umove(tcp, addr, &fl32) < 0) { + } else +#endif + { + if (umove(tcp, addr, &fl) < 0) { tprintf("{...}"); return; } - fl.l_type = fl32.l_type; - fl.l_whence = fl32.l_whence; - fl.l_start = fl32.l_start; - fl.l_len = fl32.l_len; - fl.l_pid = fl32.l_pid; - } else { - /* let people know we have a problem here */ - tprintf("{ }", - personality_wordsize[current_personality]); - return; } tprintf("{type="); printxval(lockfcmds, fl.l_type, "F_???"); diff --git a/signal.c b/signal.c index 1794f7df..e2a4af6f 100644 --- a/signal.c +++ b/signal.c @@ -35,6 +35,7 @@ #include "defs.h" +#include #include #include #include @@ -1860,15 +1861,19 @@ sys_rt_sigprocmask(tcp) /* 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)]; }; @@ -1878,6 +1883,7 @@ 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]); @@ -1885,41 +1891,79 @@ sys_rt_sigaction(struct tcb *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 { - if (sa.__sigaction_handler.__sa_handler == SIG_ERR) - tprintf("{SIG_ERR, "); - else if (sa.__sigaction_handler.__sa_handler == SIG_DFL) - tprintf("{SIG_DFL, "); - else if (sa.__sigaction_handler.__sa_handler == SIG_IGN) - tprintf("{SIG_IGN, "); - else - tprintf("{%#lx, ", - (long) sa.__sigaction_handler.__sa_handler); - sigemptyset(&sigset); + goto after_sa; + } + + if (sa.__sa_handler == SIG_ERR) + tprintf("{SIG_ERR, "); + else if (sa.__sa_handler == SIG_DFL) + tprintf("{SIG_DFL, "); + else if (sa.__sa_handler == 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(", "); - printflags(sigact_flags, sa.sa_flags, "SA_???"); + 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); + if (sa.sa_flags & SA_RESTORER) + tprintf(", %p", sa.sa_restorer); #endif - tprintf("}"); - } + tprintf("}"); + + after_sa: if (entering(tcp)) tprintf(", "); else @@ -1928,7 +1972,7 @@ sys_rt_sigaction(struct tcb *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; }