diff options
author | Elliott Hughes <enh@google.com> | 2014-02-28 23:21:35 +0000 |
---|---|---|
committer | Dmitry V. Levin <ldv@altlinux.org> | 2014-02-28 23:35:21 +0000 |
commit | 458b3f2fd964d23cf779c235ecb2b8f1c40d994c (patch) | |
tree | 91199c2ce5a7a8f68a0b3d40695f6428afcfc3b0 | |
parent | fb642bb6d63f7ffe2228bf48a6008bc8f56f67ff (diff) | |
download | strace-458b3f2fd964d23cf779c235ecb2b8f1c40d994c.tar.gz strace-458b3f2fd964d23cf779c235ecb2b8f1c40d994c.tar.bz2 strace-458b3f2fd964d23cf779c235ecb2b8f1c40d994c.tar.xz |
Add multi-personality support to struct old_sigaction decoding
struct sigaction is another structure that contains members
whose size differs between 32-bit and 64-bit personalities.
* signal.c [HAVE_SIGACTION] (old_sigaction32): New structure.
[HAVE_SIGACTION] (decode_old_sigaction): Decode 32-bit struct
old_sigaction on a 64-bit host.
Signed-off-by: Elliott Hughes <enh@google.com>
-rw-r--r-- | signal.c | 28 |
1 files changed, 27 insertions, 1 deletions
@@ -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; } |