Add multi-personality support to stack_t decoding
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 26 Feb 2014 22:29:27 +0000 (22:29 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 27 Feb 2014 22:35:39 +0000 (22:35 +0000)
stack_t is one of many structures that contain members
whose size differs between 32-bit and 64-bit personalities.

* signal.c (print_stack_t): Decode 32-bit stack_t on a 64-bit host.

Reported-by: Elliott Hughes <enh@google.com>
signal.c

index a13f7ace33ed4187a7c8ee9baf0e5a73980e7f3a..436039b2e5060cb0787f9c8cb99ec53a168c0dc9 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -1084,10 +1084,33 @@ static void
 print_stack_t(struct tcb *tcp, unsigned long addr)
 {
        stack_t ss;
+       int r;
 
        if (!addr) {
                tprints("NULL");
-       } else if (umove(tcp, addr, &ss) < 0) {
+               return;
+       }
+
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+       if (current_wordsize != sizeof(ss.ss_sp) && current_wordsize == 4) {
+               struct {
+                       uint32_t ss_sp;
+                       int32_t ss_flags;
+                       uint32_t ss_size;
+               } ss32;
+               r = umove(tcp, addr, &ss32);
+               if (r >= 0) {
+                       memset(&ss, 0, sizeof(ss));
+                       ss.ss_sp = (void*)(unsigned long) ss32.ss_sp;
+                       ss.ss_flags = ss32.ss_flags;
+                       ss.ss_size = (unsigned long) ss32.ss_size;
+               }
+       } else
+#endif
+       {
+               r = umove(tcp, addr, &ss);
+       }
+       if (r < 0) {
                tprintf("%#lx", addr);
        } else {
                tprintf("{ss_sp=%#lx, ss_flags=", (unsigned long) ss.ss_sp);