]> granicus.if.org Git - strace/commitdiff
Handle recv[m]msg for non-native 32-bit personality syscalls
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 12 Feb 2013 10:57:48 +0000 (11:57 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 12 Feb 2013 10:57:48 +0000 (11:57 +0100)
* net.c (printmsghdr): If current_wordsize is 4 and long is wider than it,
read 32-bit struct msghdr and expand it into a native one before using it.
(printmmsghdr): Likewise for struct mmsghdr.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
net.c

diff --git a/net.c b/net.c
index fbdfe632f62b936a047ae9ec3045c9e818eda4b9..31e63dd95f70293902b92d6d7aadb75883b1f94a 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1428,11 +1428,42 @@ do_msghdr(struct tcb *tcp, struct msghdr *msg, unsigned long data_size)
        tprints("}");
 }
 
+struct msghdr32 {
+       uint32_t /* void* */    msg_name;
+       uint32_t /* socklen_t */msg_namelen;
+       uint32_t /* iovec* */   msg_iov;
+       uint32_t /* size_t */   msg_iovlen;
+       uint32_t /* void* */    msg_control;
+       uint32_t /* size_t */   msg_controllen;
+       uint32_t /* int */      msg_flags;
+};
+struct mmsghdr32 {
+       struct msghdr32         msg_hdr;
+       uint32_t /* unsigned */ msg_len;
+};
+
 static void
 printmsghdr(struct tcb *tcp, long addr, unsigned long data_size)
 {
        struct msghdr msg;
 
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+       if (current_wordsize == 4) {
+               struct msghdr32 msg32;
+
+               if (umove(tcp, addr, &msg32) < 0) {
+                       tprintf("%#lx", addr);
+                       return;
+               }
+               msg.msg_name       = (void*)(long)msg32.msg_name;
+               msg.msg_namelen    =              msg32.msg_namelen;
+               msg.msg_iov        = (void*)(long)msg32.msg_iov;
+               msg.msg_iovlen     =              msg32.msg_iovlen;
+               msg.msg_control    = (void*)(long)msg32.msg_control;
+               msg.msg_controllen =              msg32.msg_controllen;
+               msg.msg_flags      =              msg32.msg_flags;
+       } else
+#endif
        if (umove(tcp, addr, &msg) < 0) {
                tprintf("%#lx", addr);
                return;
@@ -1448,10 +1479,31 @@ printmmsghdr(struct tcb *tcp, long addr, unsigned int idx, unsigned long msg_len
                unsigned msg_len;
        } mmsg;
 
-       addr += sizeof(mmsg) * idx;
-       if (umove(tcp, addr, &mmsg) < 0) {
-               tprintf("%#lx", addr);
-               return;
+#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
+       if (current_wordsize == 4) {
+               struct mmsghdr32 mmsg32;
+
+               addr += sizeof(mmsg32) * idx;
+               if (umove(tcp, addr, &mmsg32) < 0) {
+                       tprintf("%#lx", addr);
+                       return;
+               }
+               mmsg.msg_hdr.msg_name       = (void*)(long)mmsg32.msg_hdr.msg_name;
+               mmsg.msg_hdr.msg_namelen    =              mmsg32.msg_hdr.msg_namelen;
+               mmsg.msg_hdr.msg_iov        = (void*)(long)mmsg32.msg_hdr.msg_iov;
+               mmsg.msg_hdr.msg_iovlen     =              mmsg32.msg_hdr.msg_iovlen;
+               mmsg.msg_hdr.msg_control    = (void*)(long)mmsg32.msg_hdr.msg_control;
+               mmsg.msg_hdr.msg_controllen =              mmsg32.msg_hdr.msg_controllen;
+               mmsg.msg_hdr.msg_flags      =              mmsg32.msg_hdr.msg_flags;
+               mmsg.msg_len                =              mmsg32.msg_len;
+       } else
+#endif
+       {
+               addr += sizeof(mmsg) * idx;
+               if (umove(tcp, addr, &mmsg) < 0) {
+                       tprintf("%#lx", addr);
+                       return;
+               }
        }
        tprints("{");
        do_msghdr(tcp, &mmsg.msg_hdr, msg_len ? msg_len : mmsg.msg_len);