Handle recv[m]msg for non-native 32-bit personality syscalls

* 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>
diff --git a/net.c b/net.c
index fbdfe63..31e63dd 100644
--- a/net.c
+++ b/net.c
@@ -1428,11 +1428,42 @@
 	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 @@
 		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);