]> granicus.if.org Git - strace/commitdiff
* signal (sys_rt_sigaction): Print struct sigaction correctly
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 15 Apr 2009 13:22:59 +0000 (13:22 +0000)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 15 Apr 2009 13:22:59 +0000 (13:22 +0000)
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.

ChangeLog
desc.c
signal.c

index 2f04c6293c78b049db167362d16a767baac0b857..901331daee490bbf1e74f0c68258c79f339ad79b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-15  Denys Vlasenko  <dvlasenk@redhat.com>
+
+       * 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  <dvlasenk@redhat.com>
 
        * signal.c: Whitespace, comment, and style fixes, no code changes.
diff --git a/desc.c b/desc.c
index 3aae9908472037c3ca75ade6dd1412324d04db3c..383107e30d7056f71de7f9bb7ebeb8b3f0baf8fd 100644 (file)
--- 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("{ <decode error: unsupported wordsize %d> }",
+                               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("{ <decode error: unsupported wordsize %d> }",
-                               personality_wordsize[current_personality]);
-               return;
        }
        tprintf("{type=");
        printxval(lockfcmds, fl.l_type, "F_???");
index 1794f7df2153d3b9e0c357a1cd39caaa38cd1d34..e2a4af6f703d2c8fd7d3d906461b6a4f9a01c95c 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -35,6 +35,7 @@
 
 #include "defs.h"
 
+#include <stdint.h>
 #include <signal.h>
 #include <sys/user.h>
 #include <fcntl.h>
@@ -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;
 }