Преглед на файлове

Merge tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging

linux-user branch pull request 20230204

Implement execveat()
un-parent OBJECT(cpu) when closing thread
Revert fix for glibc >= 2.36 sys/mount.h
Fix/update strace
move target_flat.h to target subdirs
Fix SO_ERROR return code of getsockopt()
Fix /proc/cpuinfo output for hppa
Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise()
Implement SOL_ALG encryption support
linux-user: Allow sendmsg() without IOV

# -----BEGIN PGP SIGNATURE-----
#
# iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmPeguUSHGxhdXJlbnRA
# dml2aWVyLmV1AAoJEPMMOL0/L748tnQP/1A4eu33pLe4+tjBuDGt2zcGAVuz+wN9
# rcwN5BQgjILwfECfRsy9QIkC8+M496tLk4W7pNkW9x/GSpzBp9x0+066uUghsa1Q
# c0bFU0FM8xpywEXvOrz3LvEWaWqeBV/R+XYMqKFaiBQXf/5kmmteei9guH42L3gV
# a+d0s1cWT48TslTaga9ECbiPD9lK+yfW879+wRhex1/BetkJPzLU1hZB4vfC5YQo
# XagcmLWiseT4U8uCysikOgKQE4g2bv1oJXUuYjBxW15s5/llg8e57dEboO7MFEPK
# a9P3Hl1qiA5Ol3scF1I7WURmGP6UVfdhTYe1aKYHhKY7QVBVjbU7r/NkdQ3dR6Nv
# db58Lkurnrf5dMksZk8+25F/fvJT0nZpnbipunZejetNjrDVPk19XK5E6kJf91hk
# 3W3vOeWMp4QjThpqghnlQ3gm2XfVmCGSMIOywTKZ4/M/TP28+9zY7GZqQXQXCBMy
# nJFahfVTCfiYaGAYGjlMe5CMOQ6tJ6lwxuTCl9O1X565ifMBNUj3rcte1FvO/i24
# Rk0/lQVO+tD9ImxHJrei0Y2C0xzo7V8kaB9+foAf6Ku91SY1X1FIOm81DEyAhK61
# Biv2zlNwUV0aCierrn3oLuDkviVaAg6FkLO9snPG+lQy2uxgyJJ2/Pv0OCZhniWI
# 9WifjYZKAXDa
# =AcC6
# -----END PGP SIGNATURE-----
# gpg: Signature made Sat 04 Feb 2023 16:08:05 GMT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu: (22 commits)
  linux-user: Allow sendmsg() without IOV
  linux-user: Implement SOL_ALG encryption support
  linux-user: Enhance strace output for various syscalls
  linux-user: Show 4th argument of rt_sigprocmask() in strace
  linux-user: Add emulation for MADV_WIPEONFORK and MADV_KEEPONFORK in madvise()
  linux-user: Improve strace output of personality() and sysinfo()
  linux-user: Fix /proc/cpuinfo output for hppa
  linux-user: Fix SO_ERROR return code of getsockopt()
  linux-user: move target_flat.h to target subdirs
  linux-user: Improve strace output of getgroups() and setgroups()
  linux-user: Add strace output for clock_getres_time64() and futex_time64()
  Revert "linux-user: fix compat with glibc >= 2.36 sys/mount.h"
  Revert "linux-user: add more compat ioctl definitions"
  linux-user: add more netlink protocol constants
  linux-user: fix strace build w/out munlockall
  linux-user: un-parent OBJECT(cpu) when closing thread
  linux-user: Add missing MAP_HUGETLB and MAP_STACK flags in strace
  linux-user/syscall: Implement execveat()
  linux-user/syscall: Extract do_execve() from do_syscall1()
  linux-user/strace: Add output for execveat() syscall
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Peter Maydell преди 2 години
родител
ревизия
ceabf6e500

+ 1 - 0
linux-user/aarch64/target_flat.h

@@ -0,0 +1 @@
+#include "../generic/target_flat.h"

+ 1 - 0
linux-user/arm/target_flat.h

@@ -0,0 +1 @@
+#include "../generic/target_flat.h"

+ 0 - 0
linux-user/target_flat.h → linux-user/generic/target_flat.h


+ 1 - 0
linux-user/m68k/target_flat.h

@@ -0,0 +1 @@
+#include "../generic/target_flat.h"

+ 1 - 0
linux-user/microblaze/target_flat.h

@@ -0,0 +1 @@
+#include "../generic/target_flat.h"

+ 43 - 13
linux-user/mmap.c

@@ -857,7 +857,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
     return new_addr;
     return new_addr;
 }
 }
 
 
-static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end)
+static bool can_passthrough_madvise(abi_ulong start, abi_ulong end)
 {
 {
     ulong addr;
     ulong addr;
 
 
@@ -901,23 +901,53 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
         return -TARGET_EINVAL;
         return -TARGET_EINVAL;
     }
     }
 
 
+    /* Translate for some architectures which have different MADV_xxx values */
+    switch (advice) {
+    case TARGET_MADV_DONTNEED:      /* alpha */
+        advice = MADV_DONTNEED;
+        break;
+    case TARGET_MADV_WIPEONFORK:    /* parisc */
+        advice = MADV_WIPEONFORK;
+        break;
+    case TARGET_MADV_KEEPONFORK:    /* parisc */
+        advice = MADV_KEEPONFORK;
+        break;
+    /* we do not care about the other MADV_xxx values yet */
+    }
+
     /*
     /*
-     * A straight passthrough may not be safe because qemu sometimes turns
-     * private file-backed mappings into anonymous mappings.
+     * Most advice values are hints, so ignoring and returning success is ok.
+     *
+     * However, some advice values such as MADV_DONTNEED, MADV_WIPEONFORK and
+     * MADV_KEEPONFORK are not hints and need to be emulated.
      *
      *
-     * This is a hint, so ignoring and returning success is ok.
+     * A straight passthrough for those may not be safe because qemu sometimes
+     * turns private file-backed mappings into anonymous mappings.
+     * can_passthrough_madvise() helps to check if a passthrough is possible by
+     * comparing mappings that are known to have the same semantics in the host
+     * and the guest. In this case passthrough is safe.
      *
      *
-     * This breaks MADV_DONTNEED, completely implementing which is quite
-     * complicated. However, there is one low-hanging fruit: mappings that are
-     * known to have the same semantics in the host and the guest. In this case
-     * passthrough is safe, so do it.
+     * We pass through MADV_WIPEONFORK and MADV_KEEPONFORK if possible and
+     * return failure if not.
+     *
+     * MADV_DONTNEED is passed through as well, if possible.
+     * If passthrough isn't possible, we nevertheless (wrongly!) return
+     * success, which is broken but some userspace programs fail to work
+     * otherwise. Completely implementing such emulation is quite complicated
+     * though.
      */
      */
     mmap_lock();
     mmap_lock();
-    if (advice == TARGET_MADV_DONTNEED &&
-        can_passthrough_madv_dontneed(start, end)) {
-        ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED));
-        if (ret == 0) {
-            page_reset_target_data(start, start + len);
+    switch (advice) {
+    case MADV_WIPEONFORK:
+    case MADV_KEEPONFORK:
+        ret = -EINVAL;
+        /* fall through */
+    case MADV_DONTNEED:
+        if (can_passthrough_madvise(start, end)) {
+            ret = get_errno(madvise(g2h_untagged(start), len, advice));
+            if ((advice == MADV_DONTNEED) && (ret == 0)) {
+                page_reset_target_data(start, start + len);
+            }
         }
         }
     }
     }
     mmap_unlock();
     mmap_unlock();

+ 1 - 0
linux-user/sh4/target_flat.h

@@ -0,0 +1 @@
+#include "../generic/target_flat.h"

+ 136 - 53
linux-user/strace.c

@@ -506,21 +506,69 @@ print_socket_protocol(int domain, int type, int protocol)
         case NETLINK_ROUTE:
         case NETLINK_ROUTE:
             qemu_log("NETLINK_ROUTE");
             qemu_log("NETLINK_ROUTE");
             break;
             break;
+        case NETLINK_UNUSED:
+            qemu_log("NETLINK_UNUSED");
+            break;
+        case NETLINK_USERSOCK:
+            qemu_log("NETLINK_USERSOCK");
+            break;
+        case NETLINK_FIREWALL:
+            qemu_log("NETLINK_FIREWALL");
+            break;
+        case NETLINK_SOCK_DIAG:
+            qemu_log("NETLINK_SOCK_DIAG");
+            break;
+        case NETLINK_NFLOG:
+            qemu_log("NETLINK_NFLOG");
+            break;
+        case NETLINK_XFRM:
+            qemu_log("NETLINK_XFRM");
+            break;
+        case NETLINK_SELINUX:
+            qemu_log("NETLINK_SELINUX");
+            break;
+        case NETLINK_ISCSI:
+            qemu_log("NETLINK_ISCSI");
+            break;
         case NETLINK_AUDIT:
         case NETLINK_AUDIT:
             qemu_log("NETLINK_AUDIT");
             qemu_log("NETLINK_AUDIT");
             break;
             break;
+        case NETLINK_FIB_LOOKUP:
+            qemu_log("NETLINK_FIB_LOOKUP");
+            break;
+        case NETLINK_CONNECTOR:
+            qemu_log("NETLINK_CONNECTOR");
+            break;
         case NETLINK_NETFILTER:
         case NETLINK_NETFILTER:
             qemu_log("NETLINK_NETFILTER");
             qemu_log("NETLINK_NETFILTER");
             break;
             break;
+        case NETLINK_IP6_FW:
+            qemu_log("NETLINK_IP6_FW");
+            break;
+        case NETLINK_DNRTMSG:
+            qemu_log("NETLINK_DNRTMSG");
+            break;
         case NETLINK_KOBJECT_UEVENT:
         case NETLINK_KOBJECT_UEVENT:
             qemu_log("NETLINK_KOBJECT_UEVENT");
             qemu_log("NETLINK_KOBJECT_UEVENT");
             break;
             break;
+        case NETLINK_GENERIC:
+            qemu_log("NETLINK_GENERIC");
+            break;
+        case NETLINK_SCSITRANSPORT:
+            qemu_log("NETLINK_SCSITRANSPORT");
+            break;
+        case NETLINK_ECRYPTFS:
+            qemu_log("NETLINK_ECRYPTFS");
+            break;
         case NETLINK_RDMA:
         case NETLINK_RDMA:
             qemu_log("NETLINK_RDMA");
             qemu_log("NETLINK_RDMA");
             break;
             break;
         case NETLINK_CRYPTO:
         case NETLINK_CRYPTO:
             qemu_log("NETLINK_CRYPTO");
             qemu_log("NETLINK_CRYPTO");
             break;
             break;
+        case NETLINK_SMC:
+            qemu_log("NETLINK_SMC");
+            break;
         default:
         default:
             qemu_log("%d", protocol);
             qemu_log("%d", protocol);
             break;
             break;
@@ -616,38 +664,6 @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name,
 }
 }
 #endif
 #endif
 
 
-static void
-print_execve(CPUArchState *cpu_env, const struct syscallname *name,
-             abi_long arg1, abi_long arg2, abi_long arg3,
-             abi_long arg4, abi_long arg5, abi_long arg6)
-{
-    abi_ulong arg_ptr_addr;
-    char *s;
-
-    if (!(s = lock_user_string(arg1)))
-        return;
-    qemu_log("%s(\"%s\",{", name->name, s);
-    unlock_user(s, arg1, 0);
-
-    for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
-        abi_ulong *arg_ptr, arg_addr;
-
-        arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
-        if (!arg_ptr)
-            return;
-    arg_addr = tswapal(*arg_ptr);
-        unlock_user(arg_ptr, arg_ptr_addr, 0);
-        if (!arg_addr)
-            break;
-        if ((s = lock_user_string(arg_addr))) {
-            qemu_log("\"%s\",", s);
-            unlock_user(s, arg_addr, 0);
-        }
-    }
-
-    qemu_log("NULL})");
-}
-
 #ifdef TARGET_NR_ipc
 #ifdef TARGET_NR_ipc
 static void
 static void
 print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
 print_ipc(CPUArchState *cpu_env, const struct syscallname *name,
@@ -945,7 +961,7 @@ print_syscall_ret_ioctl(CPUArchState *cpu_env, const struct syscallname *name,
 }
 }
 #endif
 #endif
 
 
-UNUSED static struct flags access_flags[] = {
+UNUSED static const struct flags access_flags[] = {
     FLAG_GENERIC(F_OK),
     FLAG_GENERIC(F_OK),
     FLAG_GENERIC(R_OK),
     FLAG_GENERIC(R_OK),
     FLAG_GENERIC(W_OK),
     FLAG_GENERIC(W_OK),
@@ -953,7 +969,7 @@ UNUSED static struct flags access_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags at_file_flags[] = {
+UNUSED static const struct flags at_file_flags[] = {
 #ifdef AT_EACCESS
 #ifdef AT_EACCESS
     FLAG_GENERIC(AT_EACCESS),
     FLAG_GENERIC(AT_EACCESS),
 #endif
 #endif
@@ -963,14 +979,14 @@ UNUSED static struct flags at_file_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags unlinkat_flags[] = {
+UNUSED static const struct flags unlinkat_flags[] = {
 #ifdef AT_REMOVEDIR
 #ifdef AT_REMOVEDIR
     FLAG_GENERIC(AT_REMOVEDIR),
     FLAG_GENERIC(AT_REMOVEDIR),
 #endif
 #endif
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags mode_flags[] = {
+UNUSED static const struct flags mode_flags[] = {
     FLAG_GENERIC(S_IFSOCK),
     FLAG_GENERIC(S_IFSOCK),
     FLAG_GENERIC(S_IFLNK),
     FLAG_GENERIC(S_IFLNK),
     FLAG_GENERIC(S_IFREG),
     FLAG_GENERIC(S_IFREG),
@@ -981,14 +997,14 @@ UNUSED static struct flags mode_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags open_access_flags[] = {
+UNUSED static const struct flags open_access_flags[] = {
     FLAG_TARGET(O_RDONLY),
     FLAG_TARGET(O_RDONLY),
     FLAG_TARGET(O_WRONLY),
     FLAG_TARGET(O_WRONLY),
     FLAG_TARGET(O_RDWR),
     FLAG_TARGET(O_RDWR),
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags open_flags[] = {
+UNUSED static const struct flags open_flags[] = {
     FLAG_TARGET(O_APPEND),
     FLAG_TARGET(O_APPEND),
     FLAG_TARGET(O_CREAT),
     FLAG_TARGET(O_CREAT),
     FLAG_TARGET(O_DIRECTORY),
     FLAG_TARGET(O_DIRECTORY),
@@ -1019,7 +1035,7 @@ UNUSED static struct flags open_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags mount_flags[] = {
+UNUSED static const struct flags mount_flags[] = {
 #ifdef MS_BIND
 #ifdef MS_BIND
     FLAG_GENERIC(MS_BIND),
     FLAG_GENERIC(MS_BIND),
 #endif
 #endif
@@ -1044,7 +1060,7 @@ UNUSED static struct flags mount_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags umount2_flags[] = {
+UNUSED static const struct flags umount2_flags[] = {
 #ifdef MNT_FORCE
 #ifdef MNT_FORCE
     FLAG_GENERIC(MNT_FORCE),
     FLAG_GENERIC(MNT_FORCE),
 #endif
 #endif
@@ -1057,7 +1073,7 @@ UNUSED static struct flags umount2_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags mmap_prot_flags[] = {
+UNUSED static const struct flags mmap_prot_flags[] = {
     FLAG_GENERIC(PROT_NONE),
     FLAG_GENERIC(PROT_NONE),
     FLAG_GENERIC(PROT_EXEC),
     FLAG_GENERIC(PROT_EXEC),
     FLAG_GENERIC(PROT_READ),
     FLAG_GENERIC(PROT_READ),
@@ -1068,7 +1084,7 @@ UNUSED static struct flags mmap_prot_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags mmap_flags[] = {
+UNUSED static const struct flags mmap_flags[] = {
     FLAG_TARGET(MAP_SHARED),
     FLAG_TARGET(MAP_SHARED),
     FLAG_TARGET(MAP_PRIVATE),
     FLAG_TARGET(MAP_PRIVATE),
     FLAG_TARGET(MAP_ANONYMOUS),
     FLAG_TARGET(MAP_ANONYMOUS),
@@ -1089,10 +1105,12 @@ UNUSED static struct flags mmap_flags[] = {
 #ifdef TARGET_MAP_UNINITIALIZED
 #ifdef TARGET_MAP_UNINITIALIZED
     FLAG_TARGET(MAP_UNINITIALIZED),
     FLAG_TARGET(MAP_UNINITIALIZED),
 #endif
 #endif
+    FLAG_TARGET(MAP_HUGETLB),
+    FLAG_TARGET(MAP_STACK),
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags clone_flags[] = {
+UNUSED static const struct flags clone_flags[] = {
     FLAG_GENERIC(CLONE_VM),
     FLAG_GENERIC(CLONE_VM),
     FLAG_GENERIC(CLONE_FS),
     FLAG_GENERIC(CLONE_FS),
     FLAG_GENERIC(CLONE_FILES),
     FLAG_GENERIC(CLONE_FILES),
@@ -1136,7 +1154,17 @@ UNUSED static struct flags clone_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags msg_flags[] = {
+UNUSED static const struct flags execveat_flags[] = {
+#ifdef AT_EMPTY_PATH
+    FLAG_GENERIC(AT_EMPTY_PATH),
+#endif
+#ifdef AT_SYMLINK_NOFOLLOW
+    FLAG_GENERIC(AT_SYMLINK_NOFOLLOW),
+#endif
+    FLAG_END,
+};
+
+UNUSED static const struct flags msg_flags[] = {
     /* send */
     /* send */
     FLAG_GENERIC(MSG_CONFIRM),
     FLAG_GENERIC(MSG_CONFIRM),
     FLAG_GENERIC(MSG_DONTROUTE),
     FLAG_GENERIC(MSG_DONTROUTE),
@@ -1156,7 +1184,7 @@ UNUSED static struct flags msg_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags statx_flags[] = {
+UNUSED static const struct flags statx_flags[] = {
 #ifdef AT_EMPTY_PATH
 #ifdef AT_EMPTY_PATH
     FLAG_GENERIC(AT_EMPTY_PATH),
     FLAG_GENERIC(AT_EMPTY_PATH),
 #endif
 #endif
@@ -1178,7 +1206,7 @@ UNUSED static struct flags statx_flags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags statx_mask[] = {
+UNUSED static const struct flags statx_mask[] = {
 /* This must come first, because it includes everything.  */
 /* This must come first, because it includes everything.  */
 #ifdef STATX_ALL
 #ifdef STATX_ALL
     FLAG_GENERIC(STATX_ALL),
     FLAG_GENERIC(STATX_ALL),
@@ -1226,7 +1254,7 @@ UNUSED static struct flags statx_mask[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags falloc_flags[] = {
+UNUSED static const struct flags falloc_flags[] = {
     FLAG_GENERIC(FALLOC_FL_KEEP_SIZE),
     FLAG_GENERIC(FALLOC_FL_KEEP_SIZE),
     FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE),
     FLAG_GENERIC(FALLOC_FL_PUNCH_HOLE),
 #ifdef FALLOC_FL_NO_HIDE_STALE
 #ifdef FALLOC_FL_NO_HIDE_STALE
@@ -1246,7 +1274,7 @@ UNUSED static struct flags falloc_flags[] = {
 #endif
 #endif
 };
 };
 
 
-UNUSED static struct flags termios_iflags[] = {
+UNUSED static const struct flags termios_iflags[] = {
     FLAG_TARGET(IGNBRK),
     FLAG_TARGET(IGNBRK),
     FLAG_TARGET(BRKINT),
     FLAG_TARGET(BRKINT),
     FLAG_TARGET(IGNPAR),
     FLAG_TARGET(IGNPAR),
@@ -1265,7 +1293,7 @@ UNUSED static struct flags termios_iflags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags termios_oflags[] = {
+UNUSED static const struct flags termios_oflags[] = {
     FLAG_TARGET(OPOST),
     FLAG_TARGET(OPOST),
     FLAG_TARGET(OLCUC),
     FLAG_TARGET(OLCUC),
     FLAG_TARGET(ONLCR),
     FLAG_TARGET(ONLCR),
@@ -1349,7 +1377,7 @@ UNUSED static struct enums termios_cflags_CSIZE[] = {
     ENUM_END,
     ENUM_END,
 };
 };
 
 
-UNUSED static struct flags termios_cflags[] = {
+UNUSED static const struct flags termios_cflags[] = {
     FLAG_TARGET(CSTOPB),
     FLAG_TARGET(CSTOPB),
     FLAG_TARGET(CREAD),
     FLAG_TARGET(CREAD),
     FLAG_TARGET(PARENB),
     FLAG_TARGET(PARENB),
@@ -1360,7 +1388,7 @@ UNUSED static struct flags termios_cflags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags termios_lflags[] = {
+UNUSED static const struct flags termios_lflags[] = {
     FLAG_TARGET(ISIG),
     FLAG_TARGET(ISIG),
     FLAG_TARGET(ICANON),
     FLAG_TARGET(ICANON),
     FLAG_TARGET(XCASE),
     FLAG_TARGET(XCASE),
@@ -1380,7 +1408,8 @@ UNUSED static struct flags termios_lflags[] = {
     FLAG_END,
     FLAG_END,
 };
 };
 
 
-UNUSED static struct flags mlockall_flags[] = {
+#ifdef TARGET_NR_mlockall
+static const struct flags mlockall_flags[] = {
     FLAG_TARGET(MCL_CURRENT),
     FLAG_TARGET(MCL_CURRENT),
     FLAG_TARGET(MCL_FUTURE),
     FLAG_TARGET(MCL_FUTURE),
 #ifdef MCL_ONFAULT
 #ifdef MCL_ONFAULT
@@ -1388,6 +1417,7 @@ UNUSED static struct flags mlockall_flags[] = {
 #endif
 #endif
     FLAG_END,
     FLAG_END,
 };
 };
+#endif
 
 
 /* IDs of the various system clocks */
 /* IDs of the various system clocks */
 #define TARGET_CLOCK_REALTIME              0
 #define TARGET_CLOCK_REALTIME              0
@@ -1969,6 +1999,58 @@ print_execv(CPUArchState *cpu_env, const struct syscallname *name,
 }
 }
 #endif
 #endif
 
 
+static void
+print_execve_argv(abi_long argv, int last)
+{
+    abi_ulong arg_ptr_addr;
+    char *s;
+
+    qemu_log("{");
+    for (arg_ptr_addr = argv; ; arg_ptr_addr += sizeof(abi_ulong)) {
+        abi_ulong *arg_ptr, arg_addr;
+
+        arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
+        if (!arg_ptr) {
+            return;
+        }
+        arg_addr = tswapal(*arg_ptr);
+        unlock_user(arg_ptr, arg_ptr_addr, 0);
+        if (!arg_addr) {
+            break;
+        }
+        s = lock_user_string(arg_addr);
+        if (s) {
+            qemu_log("\"%s\",", s);
+            unlock_user(s, arg_addr, 0);
+        }
+    }
+    qemu_log("NULL}%s", get_comma(last));
+}
+
+static void
+print_execve(CPUArchState *cpu_env, const struct syscallname *name,
+             abi_long arg1, abi_long arg2, abi_long arg3,
+             abi_long arg4, abi_long arg5, abi_long arg6)
+{
+    print_syscall_prologue(name);
+    print_string(arg1, 0);
+    print_execve_argv(arg2, 1);
+    print_syscall_epilogue(name);
+}
+
+static void
+print_execveat(CPUArchState *cpu_env, const struct syscallname *name,
+               abi_long arg1, abi_long arg2, abi_long arg3,
+               abi_long arg4, abi_long arg5, abi_long arg6)
+{
+    print_syscall_prologue(name);
+    print_at_dirfd(arg1, 0);
+    print_string(arg2, 0);
+    print_execve_argv(arg3, 0);
+    print_flags(execveat_flags, arg5, 1);
+    print_syscall_epilogue(name);
+}
+
 #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2)
 #if defined(TARGET_NR_faccessat) || defined(TARGET_NR_faccessat2)
 static void
 static void
 print_faccessat(CPUArchState *cpu_env, const struct syscallname *name,
 print_faccessat(CPUArchState *cpu_env, const struct syscallname *name,
@@ -3142,7 +3224,8 @@ print_rt_sigprocmask(CPUArchState *cpu_env, const struct syscallname *name,
     }
     }
     qemu_log("%s,", how);
     qemu_log("%s,", how);
     print_pointer(arg1, 0);
     print_pointer(arg1, 0);
-    print_pointer(arg2, 1);
+    print_pointer(arg2, 0);
+    print_raw_param("%u", arg3, 1);
     print_syscall_epilogue(name);
     print_syscall_epilogue(name);
 }
 }
 #endif
 #endif

+ 37 - 27
linux-user/strace.list

@@ -86,6 +86,9 @@
 { TARGET_NR_clock_getres, "clock_getres" , NULL, print_clock_getres,
 { TARGET_NR_clock_getres, "clock_getres" , NULL, print_clock_getres,
                           print_syscall_ret_clock_getres },
                           print_syscall_ret_clock_getres },
 #endif
 #endif
+#ifdef TARGET_NR_clock_getres_time64
+{ TARGET_NR_clock_getres_time64, "clock_getres_time64" , NULL, NULL, NULL },
+#endif
 #ifdef TARGET_NR_clock_gettime
 #ifdef TARGET_NR_clock_gettime
 { TARGET_NR_clock_gettime, "clock_gettime" , NULL, print_clock_gettime,
 { TARGET_NR_clock_gettime, "clock_gettime" , NULL, print_clock_gettime,
                            print_syscall_ret_clock_gettime },
                            print_syscall_ret_clock_gettime },
@@ -164,7 +167,7 @@
 { TARGET_NR_execve, "execve" , NULL, print_execve, NULL },
 { TARGET_NR_execve, "execve" , NULL, print_execve, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_execveat
 #ifdef TARGET_NR_execveat
-{ TARGET_NR_execveat, "execveat" , NULL, NULL, NULL },
+{ TARGET_NR_execveat, "execveat" , NULL, print_execveat, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_exec_with_loader
 #ifdef TARGET_NR_exec_with_loader
 { TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL },
 { TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL },
@@ -275,6 +278,9 @@
 #ifdef TARGET_NR_futex
 #ifdef TARGET_NR_futex
 { TARGET_NR_futex, "futex" , NULL, print_futex, NULL },
 { TARGET_NR_futex, "futex" , NULL, print_futex, NULL },
 #endif
 #endif
+#ifdef TARGET_NR_futex_time64
+{ TARGET_NR_futex_time64, "futex_time64" , NULL, NULL, NULL },
+#endif
 #ifdef TARGET_NR_futimesat
 #ifdef TARGET_NR_futimesat
 { TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL },
 { TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL },
 #endif
 #endif
@@ -315,10 +321,10 @@
 { TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL },
 { TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getgroups
 #ifdef TARGET_NR_getgroups
-{ TARGET_NR_getgroups, "getgroups" , NULL, NULL, NULL },
+{ TARGET_NR_getgroups, "getgroups" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getgroups32
 #ifdef TARGET_NR_getgroups32
-{ TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL },
+{ TARGET_NR_getgroups32, "getgroups32" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_gethostname
 #ifdef TARGET_NR_gethostname
 { TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL },
 { TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL },
@@ -337,7 +343,7 @@
 { TARGET_NR_getpagesize, "getpagesize" , NULL, NULL, NULL },
 { TARGET_NR_getpagesize, "getpagesize" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getpeername
 #ifdef TARGET_NR_getpeername
-{ TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL },
+{ TARGET_NR_getpeername, "getpeername" , "%s(%d,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getpgid
 #ifdef TARGET_NR_getpgid
 { TARGET_NR_getpgid, "getpgid" , "%s(%u)", NULL, NULL },
 { TARGET_NR_getpgid, "getpgid" , "%s(%u)", NULL, NULL },
@@ -361,19 +367,19 @@
 { TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL },
 { TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getresgid
 #ifdef TARGET_NR_getresgid
-{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL },
+{ TARGET_NR_getresgid, "getresgid" , "%s(%p,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getresgid32
 #ifdef TARGET_NR_getresgid32
 { TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL },
 { TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getresuid
 #ifdef TARGET_NR_getresuid
-{ TARGET_NR_getresuid, "getresuid" , NULL, NULL, NULL },
+{ TARGET_NR_getresuid, "getresuid" , "%s(%p,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getresuid32
 #ifdef TARGET_NR_getresuid32
 { TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL },
 { TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getrlimit
 #ifdef TARGET_NR_getrlimit
-{ TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL },
+{ TARGET_NR_getrlimit, "getrlimit" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_get_robust_list
 #ifdef TARGET_NR_get_robust_list
 { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL },
 { TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL },
@@ -385,10 +391,10 @@
 { TARGET_NR_getsid, "getsid" , "%s(%d)", NULL, NULL },
 { TARGET_NR_getsid, "getsid" , "%s(%d)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getsockname
 #ifdef TARGET_NR_getsockname
-{ TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL },
+{ TARGET_NR_getsockname, "getsockname" , "%s(%d,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_getsockopt
 #ifdef TARGET_NR_getsockopt
-{ TARGET_NR_getsockopt, "getsockopt" , NULL, NULL, NULL },
+{ TARGET_NR_getsockopt, "getsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_get_thread_area
 #ifdef TARGET_NR_get_thread_area
 #if defined(TARGET_I386) && defined(TARGET_ABI32)
 #if defined(TARGET_I386) && defined(TARGET_ABI32)
@@ -1043,7 +1049,8 @@
 { TARGET_NR_perfctr, "perfctr" , NULL, NULL, NULL },
 { TARGET_NR_perfctr, "perfctr" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_personality
 #ifdef TARGET_NR_personality
-{ TARGET_NR_personality, "personality" , NULL, NULL, NULL },
+{ TARGET_NR_personality, "personality" , "%s(0x"TARGET_ABI_FMT_lx")", NULL,
+  print_syscall_ret_addr },
 #endif
 #endif
 #ifdef TARGET_NR_pipe
 #ifdef TARGET_NR_pipe
 { TARGET_NR_pipe, "pipe" , NULL, NULL, NULL },
 { TARGET_NR_pipe, "pipe" , NULL, NULL, NULL },
@@ -1052,10 +1059,10 @@
 { TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL },
 { TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_poll
 #ifdef TARGET_NR_poll
-{ TARGET_NR_poll, "poll" , NULL, NULL, NULL },
+{ TARGET_NR_poll, "poll" , "%s(%p,%u,%d)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_ppoll
 #ifdef TARGET_NR_ppoll
-{ TARGET_NR_ppoll, "ppoll" , NULL, NULL, NULL },
+{ TARGET_NR_ppoll, "ppoll" , "%s(%p,%u,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_prctl
 #ifdef TARGET_NR_prctl
 { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
 { TARGET_NR_prctl, "prctl" , NULL, NULL, NULL },
@@ -1124,7 +1131,7 @@
 { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL },
 { TARGET_NR_reboot, "reboot" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_recv
 #ifdef TARGET_NR_recv
-{ TARGET_NR_recv, "recv" , NULL, NULL, NULL },
+{ TARGET_NR_recv, "recv" , "%s(%d,%p,%u,%d)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_recvfrom
 #ifdef TARGET_NR_recvfrom
 { TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL },
 { TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL },
@@ -1184,7 +1191,7 @@
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_rt_sigreturn
 #ifdef TARGET_NR_rt_sigreturn
-{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , "%s(%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_rt_sigsuspend
 #ifdef TARGET_NR_rt_sigsuspend
 { TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL },
 { TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL },
@@ -1196,16 +1203,19 @@
 { TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
 { TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_getaffinity
 #ifdef TARGET_NR_sched_getaffinity
-{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
+{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , "%s(%d,%u,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_get_affinity
 #ifdef TARGET_NR_sched_get_affinity
 { TARGET_NR_sched_get_affinity, "sched_get_affinity" , NULL, NULL, NULL },
 { TARGET_NR_sched_get_affinity, "sched_get_affinity" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_getattr
 #ifdef TARGET_NR_sched_getattr
-{ TARGET_NR_sched_getattr, "sched_getattr" , NULL, NULL, NULL },
+{ TARGET_NR_sched_getattr, "sched_getattr" , "%s(%d,%p,%u,%u)", NULL, NULL },
+#endif
+#ifdef TARGET_NR_sched_setattr
+{ TARGET_NR_sched_setattr, "sched_setattr" , "%s(%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_getparam
 #ifdef TARGET_NR_sched_getparam
-{ TARGET_NR_sched_getparam, "sched_getparam" , NULL, NULL, NULL },
+{ TARGET_NR_sched_getparam, "sched_getparam" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_get_priority_max
 #ifdef TARGET_NR_sched_get_priority_max
 { TARGET_NR_sched_get_priority_max, "sched_get_priority_max" , NULL, NULL, NULL },
 { TARGET_NR_sched_get_priority_max, "sched_get_priority_max" , NULL, NULL, NULL },
@@ -1220,7 +1230,7 @@
 { TARGET_NR_sched_rr_get_interval, "sched_rr_get_interval" , NULL, NULL, NULL },
 { TARGET_NR_sched_rr_get_interval, "sched_rr_get_interval" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_setaffinity
 #ifdef TARGET_NR_sched_setaffinity
-{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , NULL, NULL, NULL },
+{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , "%s(%d,%u,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sched_setatt
 #ifdef TARGET_NR_sched_setatt
 { TARGET_NR_sched_setatt, "sched_setatt" , NULL, NULL, NULL },
 { TARGET_NR_sched_setatt, "sched_setatt" , NULL, NULL, NULL },
@@ -1298,10 +1308,10 @@
 { TARGET_NR_setgid32, "setgid32" , "%s(%u)", NULL, NULL },
 { TARGET_NR_setgid32, "setgid32" , "%s(%u)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_setgroups
 #ifdef TARGET_NR_setgroups
-{ TARGET_NR_setgroups, "setgroups" , NULL, NULL, NULL },
+{ TARGET_NR_setgroups, "setgroups" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_setgroups32
 #ifdef TARGET_NR_setgroups32
-{ TARGET_NR_setgroups32, "setgroups32" , NULL, NULL, NULL },
+{ TARGET_NR_setgroups32, "setgroups32" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sethae
 #ifdef TARGET_NR_sethae
 { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL },
 { TARGET_NR_sethae, "sethae" , NULL, NULL, NULL },
@@ -1353,23 +1363,23 @@
 { TARGET_NR_setreuid32, "setreuid32" , "%s(%u,%u)", NULL, NULL },
 { TARGET_NR_setreuid32, "setreuid32" , "%s(%u,%u)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_setrlimit
 #ifdef TARGET_NR_setrlimit
-{ TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL },
+{ TARGET_NR_setrlimit, "setrlimit" , "%s(%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_set_robust_list
 #ifdef TARGET_NR_set_robust_list
-{ TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL },
+{ TARGET_NR_set_robust_list, "set_robust_list" , "%s(%p,%u)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_setsid
 #ifdef TARGET_NR_setsid
 { TARGET_NR_setsid, "setsid" , "%s()", NULL, NULL },
 { TARGET_NR_setsid, "setsid" , "%s()", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_setsockopt
 #ifdef TARGET_NR_setsockopt
-{ TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL },
+{ TARGET_NR_setsockopt, "setsockopt" , "%s(%d,%d,%d,%p,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_set_thread_area
 #ifdef TARGET_NR_set_thread_area
 { TARGET_NR_set_thread_area, "set_thread_area", "%s(0x"TARGET_ABI_FMT_lx")",
 { TARGET_NR_set_thread_area, "set_thread_area", "%s(0x"TARGET_ABI_FMT_lx")",
   NULL, NULL },
   NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_set_tid_address
 #ifdef TARGET_NR_set_tid_address
-{ TARGET_NR_set_tid_address, "set_tid_address" , NULL, NULL, NULL },
+{ TARGET_NR_set_tid_address, "set_tid_address" , "%s(%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_settimeofday
 #ifdef TARGET_NR_settimeofday
 { TARGET_NR_settimeofday, "settimeofday" , NULL, print_settimeofday, NULL },
 { TARGET_NR_settimeofday, "settimeofday" , NULL, print_settimeofday, NULL },
@@ -1498,7 +1508,7 @@
 { TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL },
 { TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sysinfo
 #ifdef TARGET_NR_sysinfo
-{ TARGET_NR_sysinfo, "sysinfo" , NULL, NULL, NULL },
+{ TARGET_NR_sysinfo, "sysinfo" , "%s(%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_sys_kexec_load
 #ifdef TARGET_NR_sys_kexec_load
 { TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL },
 { TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL },
@@ -1648,7 +1658,7 @@
 { TARGET_NR_vserver, "vserver" , NULL, NULL, NULL },
 { TARGET_NR_vserver, "vserver" , NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_wait4
 #ifdef TARGET_NR_wait4
-{ TARGET_NR_wait4, "wait4" , NULL, NULL, NULL },
+{ TARGET_NR_wait4, "wait4" , "%s(%d,%p,%d,%p)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_waitid
 #ifdef TARGET_NR_waitid
 { TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL },
 { TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL },
@@ -1672,7 +1682,7 @@
 { TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL },
 { TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_pipe2
 #ifdef TARGET_NR_pipe2
-{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
+{ TARGET_NR_pipe2, "pipe2", "%s(%p,%d)", NULL, NULL },
 #endif
 #endif
 #ifdef TARGET_NR_pidfd_open
 #ifdef TARGET_NR_pidfd_open
 { TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL },
 { TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL },

+ 157 - 155
linux-user/syscall.c

@@ -95,50 +95,7 @@
 #include <linux/soundcard.h>
 #include <linux/soundcard.h>
 #include <linux/kd.h>
 #include <linux/kd.h>
 #include <linux/mtio.h>
 #include <linux/mtio.h>
-
-#ifdef HAVE_SYS_MOUNT_FSCONFIG
-/*
- * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h,
- * which in turn prevents use of linux/fs.h. So we have to
- * define the constants ourselves for now.
- */
-#define FS_IOC_GETFLAGS                _IOR('f', 1, long)
-#define FS_IOC_SETFLAGS                _IOW('f', 2, long)
-#define FS_IOC_GETVERSION              _IOR('v', 1, long)
-#define FS_IOC_SETVERSION              _IOW('v', 2, long)
-#define FS_IOC_FIEMAP                  _IOWR('f', 11, struct fiemap)
-#define FS_IOC32_GETFLAGS              _IOR('f', 1, int)
-#define FS_IOC32_SETFLAGS              _IOW('f', 2, int)
-#define FS_IOC32_GETVERSION            _IOR('v', 1, int)
-#define FS_IOC32_SETVERSION            _IOW('v', 2, int)
-
-#define BLKGETSIZE64 _IOR(0x12,114,size_t)
-#define BLKDISCARD _IO(0x12,119)
-#define BLKIOMIN _IO(0x12,120)
-#define BLKIOOPT _IO(0x12,121)
-#define BLKALIGNOFF _IO(0x12,122)
-#define BLKPBSZGET _IO(0x12,123)
-#define BLKDISCARDZEROES _IO(0x12,124)
-#define BLKSECDISCARD _IO(0x12,125)
-#define BLKROTATIONAL _IO(0x12,126)
-#define BLKZEROOUT _IO(0x12,127)
-
-#define FIBMAP     _IO(0x00,1)
-#define FIGETBSZ   _IO(0x00,2)
-
-struct file_clone_range {
-        __s64 src_fd;
-        __u64 src_offset;
-        __u64 src_length;
-        __u64 dest_offset;
-};
-
-#define FICLONE         _IOW(0x94, 9, int)
-#define FICLONERANGE    _IOW(0x94, 13, struct file_clone_range)
-
-#else
 #include <linux/fs.h>
 #include <linux/fs.h>
-#endif
 #include <linux/fd.h>
 #include <linux/fd.h>
 #if defined(CONFIG_FIEMAP)
 #if defined(CONFIG_FIEMAP)
 #include <linux/fiemap.h>
 #include <linux/fiemap.h>
@@ -696,7 +653,8 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
 #endif
 #endif
 safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
 safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
               int, options, struct rusage *, rusage)
               int, options, struct rusage *, rusage)
-safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
+safe_syscall5(int, execveat, int, dirfd, const char *, filename,
+              char **, argv, char **, envp, int, flags)
 #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
 #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
     defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
     defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
 safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
 safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
@@ -1871,6 +1829,14 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
             __get_user(cred->pid, &target_cred->pid);
             __get_user(cred->pid, &target_cred->pid);
             __get_user(cred->uid, &target_cred->uid);
             __get_user(cred->uid, &target_cred->uid);
             __get_user(cred->gid, &target_cred->gid);
             __get_user(cred->gid, &target_cred->gid);
+        } else if (cmsg->cmsg_level == SOL_ALG) {
+            uint32_t *dst = (uint32_t *)data;
+
+            memcpy(dst, target_data, len);
+            /* fix endianess of first 32-bit word */
+            if (len >= sizeof(uint32_t)) {
+                *dst = tswap32(*dst);
+            }
         } else {
         } else {
             qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
             qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
                           cmsg->cmsg_level, cmsg->cmsg_type);
                           cmsg->cmsg_level, cmsg->cmsg_type);
@@ -2800,8 +2766,13 @@ get_timeout:
         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
         if (ret < 0)
         if (ret < 0)
             return ret;
             return ret;
-        if (optname == SO_TYPE) {
+        switch (optname) {
+        case SO_TYPE:
             val = host_to_target_sock_type(val);
             val = host_to_target_sock_type(val);
+            break;
+        case SO_ERROR:
+            val = host_to_target_errno(val);
+            break;
         }
         }
         if (len > lv)
         if (len > lv)
             len = lv;
             len = lv;
@@ -3322,7 +3293,10 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
                      target_vec, count, send);
                      target_vec, count, send);
     if (vec == NULL) {
     if (vec == NULL) {
         ret = -host_to_target_errno(errno);
         ret = -host_to_target_errno(errno);
-        goto out2;
+        /* allow sending packet without any iov, e.g. with MSG_MORE flag */
+        if (!send || ret) {
+            goto out2;
+        }
     }
     }
     msg.msg_iovlen = count;
     msg.msg_iovlen = count;
     msg.msg_iov = vec;
     msg.msg_iov = vec;
@@ -3374,7 +3348,9 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
     }
     }
 
 
 out:
 out:
-    unlock_iovec(vec, target_vec, count, !send);
+    if (vec) {
+        unlock_iovec(vec, target_vec, count, !send);
+    }
 out2:
 out2:
     return ret;
     return ret;
 }
 }
@@ -8269,11 +8245,17 @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd)
 #if defined(TARGET_HPPA)
 #if defined(TARGET_HPPA)
 static int open_cpuinfo(CPUArchState *cpu_env, int fd)
 static int open_cpuinfo(CPUArchState *cpu_env, int fd)
 {
 {
-    dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
-    dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
-    dprintf(fd, "capabilities\t: os32\n");
-    dprintf(fd, "model\t\t: 9000/778/B160L\n");
-    dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
+    int i, num_cpus;
+
+    num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+    for (i = 0; i < num_cpus; i++) {
+        dprintf(fd, "processor\t: %d\n", i);
+        dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
+        dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
+        dprintf(fd, "capabilities\t: os32\n");
+        dprintf(fd, "model\t\t: 9000/778/B160L - "
+                    "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
+    }
     return 0;
     return 0;
 }
 }
 #endif
 #endif
@@ -8357,6 +8339,119 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int
     return safe_openat(dirfd, path(pathname), flags, mode);
     return safe_openat(dirfd, path(pathname), flags, mode);
 }
 }
 
 
+static int do_execveat(CPUArchState *cpu_env, int dirfd,
+                       abi_long pathname, abi_long guest_argp,
+                       abi_long guest_envp, int flags)
+{
+    int ret;
+    char **argp, **envp;
+    int argc, envc;
+    abi_ulong gp;
+    abi_ulong addr;
+    char **q;
+    void *p;
+
+    argc = 0;
+
+    for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        argc++;
+    }
+    envc = 0;
+    for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
+        if (get_user_ual(addr, gp)) {
+            return -TARGET_EFAULT;
+        }
+        if (!addr) {
+            break;
+        }
+        envc++;
+    }
+
+    argp = g_new0(char *, argc + 1);
+    envp = g_new0(char *, envc + 1);
+
+    for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            goto execve_efault;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (!*q) {
+            goto execve_efault;
+        }
+    }
+    *q = NULL;
+
+    for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp)) {
+            goto execve_efault;
+        }
+        if (!addr) {
+            break;
+        }
+        *q = lock_user_string(addr);
+        if (!*q) {
+            goto execve_efault;
+        }
+    }
+    *q = NULL;
+
+    /*
+     * Although execve() is not an interruptible syscall it is
+     * a special case where we must use the safe_syscall wrapper:
+     * if we allow a signal to happen before we make the host
+     * syscall then we will 'lose' it, because at the point of
+     * execve the process leaves QEMU's control. So we use the
+     * safe syscall wrapper to ensure that we either take the
+     * signal as a guest signal, or else it does not happen
+     * before the execve completes and makes it the other
+     * program's problem.
+     */
+    p = lock_user_string(pathname);
+    if (!p) {
+        goto execve_efault;
+    }
+
+    if (is_proc_myself(p, "exe")) {
+        ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags));
+    } else {
+        ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
+    }
+
+    unlock_user(p, pathname, 0);
+
+    goto execve_end;
+
+execve_efault:
+    ret = -TARGET_EFAULT;
+
+execve_end:
+    for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+    for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
+        if (get_user_ual(addr, gp) || !addr) {
+            break;
+        }
+        unlock_user(*q, addr, 0);
+    }
+
+    g_free(argp);
+    g_free(envp);
+    return ret;
+}
+
 #define TIMER_MAGIC 0x0caf0000
 #define TIMER_MAGIC 0x0caf0000
 #define TIMER_MAGIC_MASK 0xffff0000
 #define TIMER_MAGIC_MASK 0xffff0000
 
 
@@ -8642,7 +8737,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
         if (CPU_NEXT(first_cpu)) {
         if (CPU_NEXT(first_cpu)) {
             TaskState *ts = cpu->opaque;
             TaskState *ts = cpu->opaque;
 
 
-            object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
+            if (ts->child_tidptr) {
+                put_user_u32(0, ts->child_tidptr);
+                do_sys_futex(g2h(cpu, ts->child_tidptr),
+                             FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
+            }
+
+            object_unparent(OBJECT(cpu));
             object_unref(OBJECT(cpu));
             object_unref(OBJECT(cpu));
             /*
             /*
              * At this point the CPU should be unrealized and removed
              * At this point the CPU should be unrealized and removed
@@ -8652,11 +8753,6 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
 
 
             pthread_mutex_unlock(&clone_lock);
             pthread_mutex_unlock(&clone_lock);
 
 
-            if (ts->child_tidptr) {
-                put_user_u32(0, ts->child_tidptr);
-                do_sys_futex(g2h(cpu, ts->child_tidptr),
-                             FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
-            }
             thread_cpu = NULL;
             thread_cpu = NULL;
             g_free(ts);
             g_free(ts);
             rcu_unregister_thread();
             rcu_unregister_thread();
@@ -8866,104 +8962,10 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
         unlock_user(p, arg2, 0);
         unlock_user(p, arg2, 0);
         return ret;
         return ret;
 #endif
 #endif
+    case TARGET_NR_execveat:
+        return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5);
     case TARGET_NR_execve:
     case TARGET_NR_execve:
-        {
-            char **argp, **envp;
-            int argc, envc;
-            abi_ulong gp;
-            abi_ulong guest_argp;
-            abi_ulong guest_envp;
-            abi_ulong addr;
-            char **q;
-
-            argc = 0;
-            guest_argp = arg2;
-            for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
-                if (get_user_ual(addr, gp))
-                    return -TARGET_EFAULT;
-                if (!addr)
-                    break;
-                argc++;
-            }
-            envc = 0;
-            guest_envp = arg3;
-            for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
-                if (get_user_ual(addr, gp))
-                    return -TARGET_EFAULT;
-                if (!addr)
-                    break;
-                envc++;
-            }
-
-            argp = g_new0(char *, argc + 1);
-            envp = g_new0(char *, envc + 1);
-
-            for (gp = guest_argp, q = argp; gp;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp))
-                    goto execve_efault;
-                if (!addr)
-                    break;
-                if (!(*q = lock_user_string(addr)))
-                    goto execve_efault;
-            }
-            *q = NULL;
-
-            for (gp = guest_envp, q = envp; gp;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp))
-                    goto execve_efault;
-                if (!addr)
-                    break;
-                if (!(*q = lock_user_string(addr)))
-                    goto execve_efault;
-            }
-            *q = NULL;
-
-            if (!(p = lock_user_string(arg1)))
-                goto execve_efault;
-            /* Although execve() is not an interruptible syscall it is
-             * a special case where we must use the safe_syscall wrapper:
-             * if we allow a signal to happen before we make the host
-             * syscall then we will 'lose' it, because at the point of
-             * execve the process leaves QEMU's control. So we use the
-             * safe syscall wrapper to ensure that we either take the
-             * signal as a guest signal, or else it does not happen
-             * before the execve completes and makes it the other
-             * program's problem.
-             */
-            if (is_proc_myself(p, "exe")) {
-                ret = get_errno(safe_execve(exec_path, argp, envp));
-            } else {
-                ret = get_errno(safe_execve(p, argp, envp));
-            }
-            unlock_user(p, arg1, 0);
-
-            goto execve_end;
-
-        execve_efault:
-            ret = -TARGET_EFAULT;
-
-        execve_end:
-            for (gp = guest_argp, q = argp; *q;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp)
-                    || !addr)
-                    break;
-                unlock_user(*q, addr, 0);
-            }
-            for (gp = guest_envp, q = envp; *q;
-                  gp += sizeof(abi_ulong), q++) {
-                if (get_user_ual(addr, gp)
-                    || !addr)
-                    break;
-                unlock_user(*q, addr, 0);
-            }
-
-            g_free(argp);
-            g_free(envp);
-        }
-        return ret;
+        return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
     case TARGET_NR_chdir:
     case TARGET_NR_chdir:
         if (!(p = lock_user_string(arg1)))
         if (!(p = lock_user_string(arg1)))
             return -TARGET_EFAULT;
             return -TARGET_EFAULT;

+ 0 - 2
meson.build

@@ -2040,8 +2040,6 @@ config_host_data.set('HAVE_OPTRESET',
                      cc.has_header_symbol('getopt.h', 'optreset'))
                      cc.has_header_symbol('getopt.h', 'optreset'))
 config_host_data.set('HAVE_IPPROTO_MPTCP',
 config_host_data.set('HAVE_IPPROTO_MPTCP',
                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
                      cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP'))
-config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG',
-                     cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG'))
 
 
 # has_member
 # has_member
 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',
 config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID',