]> granicus.if.org Git - strace/blobdiff - signal.c
Add multi-personality support to struct old_sigaction decoding
[strace] / signal.c
index 436039b2e5060cb0787f9c8cb99ec53a168c0dc9..ce8ec0a4e3fd3b62c3484e114e50d778464db93f 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -691,10 +691,19 @@ struct old_sigaction {
 #endif /* !MIPS */
 };
 
+struct old_sigaction32 {
+       /* sa_handler may be a libc #define, need to use other name: */
+       uint32_t __sa_handler;
+       uint32_t sa_mask;
+       uint32_t sa_flags;
+       uint32_t sa_restorer;
+};
+
 static void
 decode_old_sigaction(struct tcb *tcp, long addr)
 {
        struct old_sigaction sa;
+       int r;
 
        if (!addr) {
                tprints("NULL");
@@ -704,7 +713,24 @@ decode_old_sigaction(struct tcb *tcp, long addr)
                tprintf("%#lx", addr);
                return;
        }
-       if (umove(tcp, addr, &sa) < 0) {
+
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+       if (current_wordsize != sizeof(sa.__sa_handler) && current_wordsize == 4) {
+               struct old_sigaction32 sa32;
+               r = umove(tcp, addr, &sa32);
+               if (r >= 0) {
+                       memset(&sa, 0, sizeof(sa));
+                       sa.__sa_handler = (void*)(uintptr_t)sa32.__sa_handler;
+                       sa.sa_flags = sa32.sa_flags;
+                       sa.sa_restorer = (void*)(uintptr_t)sa32.sa_restorer;
+                       sa.sa_mask = sa32.sa_mask;
+               }
+       } else
+#endif
+       {
+               r = umove(tcp, addr, &sa);
+       }
+       if (r < 0) {
                tprints("{...}");
                return;
        }