diff mbox series

linux-user: Fix stracing in-memory mmap arguments

Message ID 20220630165901.2459135-1-iii@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series linux-user: Fix stracing in-memory mmap arguments | expand

Commit Message

Ilya Leoshkevich June 30, 2022, 4:59 p.m. UTC
On some architectures mmap() arguments are passed via an in-memory
array, and qemu's strace support does not recognize that. Fix by
sharing the argument fetching logic between mmap() implementation and
tracing.

An alternative approach would be to fetch arguments only once at the
beginning of do_syscall(), however, that would change what the
qemu_plugin_register_vcpu_syscall_cb() users get.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 linux-user/mmap.c      | 20 ++++++++++++++++++++
 linux-user/strace.c    | 24 ++++++++++++++++++++----
 linux-user/syscall.c   | 25 +++----------------------
 linux-user/user-mmap.h | 12 ++++++++++++
 4 files changed, 55 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 4e7a6be6ee..fbb50e3e98 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -899,3 +899,23 @@  abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
 
     return ret;
 }
+
+abi_long old_mmap_get_args(abi_long *arg1, abi_long *arg2, abi_long *arg3,
+                           abi_long *arg4, abi_long *arg5, abi_long *arg6)
+{
+    abi_long orig_arg1 = *arg1, *v;
+
+    v = lock_user(VERIFY_READ, orig_arg1, 6 * sizeof(abi_ulong), 1);
+    if (!v) {
+        return -TARGET_EFAULT;
+    }
+    *arg1 = tswapal(v[0]);
+    *arg2 = tswapal(v[1]);
+    *arg3 = tswapal(v[2]);
+    *arg4 = tswapal(v[3]);
+    *arg5 = tswapal(v[4]);
+    *arg6 = tswapal(v[5]);
+    unlock_user(v, orig_arg1, 0);
+
+    return 0;
+}
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 7d882526da..f25195ae85 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -16,6 +16,7 @@ 
 #include <sched.h>
 #include "qemu.h"
 #include "user-internals.h"
+#include "user-mmap.h"
 #include "strace.h"
 
 struct syscallname {
@@ -3532,9 +3533,9 @@  print_utimensat(CPUArchState *cpu_env, const struct syscallname *name,
 
 #if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
 static void
-print_mmap(CPUArchState *cpu_env, const struct syscallname *name,
-           abi_long arg0, abi_long arg1, abi_long arg2,
-           abi_long arg3, abi_long arg4, abi_long arg5)
+print_mmap2(CPUArchState *cpu_env, const struct syscallname *name,
+            abi_long arg0, abi_long arg1, abi_long arg2,
+            abi_long arg3, abi_long arg4, abi_long arg5)
 {
     print_syscall_prologue(name);
     print_pointer(arg0, 0);
@@ -3545,7 +3546,22 @@  print_mmap(CPUArchState *cpu_env, const struct syscallname *name,
     print_raw_param("%#x", arg5, 1);
     print_syscall_epilogue(name);
 }
-#define print_mmap2     print_mmap
+#endif
+
+#if defined(TARGET_NR_mmap)
+static void
+print_mmap(CPUArchState *cpu_env, const struct syscallname *name,
+           abi_long arg0, abi_long arg1, abi_long arg2,
+           abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    if (mmap_get_args(&arg0, &arg1, &arg2, &arg3, &arg4, &arg5)) {
+        print_syscall_prologue(name);
+        print_pointer(arg0, 0);
+        print_syscall_epilogue(name);
+        return;
+    }
+    print_mmap2(cpu_env, name, arg0, arg1, arg2, arg3, arg4, arg5);
+}
 #endif
 
 #ifdef TARGET_NR_mprotect
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 669add74c1..00d4be9094 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9917,33 +9917,14 @@  static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
         return ret;
 #ifdef TARGET_NR_mmap
     case TARGET_NR_mmap:
-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
-    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
-    defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
-    || defined(TARGET_S390X)
-        {
-            abi_ulong *v;
-            abi_ulong v1, v2, v3, v4, v5, v6;
-            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
-                return -TARGET_EFAULT;
-            v1 = tswapal(v[0]);
-            v2 = tswapal(v[1]);
-            v3 = tswapal(v[2]);
-            v4 = tswapal(v[3]);
-            v5 = tswapal(v[4]);
-            v6 = tswapal(v[5]);
-            unlock_user(v, arg1, 0);
-            ret = get_errno(target_mmap(v1, v2, v3,
-                                        target_to_host_bitmask(v4, mmap_flags_tbl),
-                                        v5, v6));
+        ret = mmap_get_args(&arg1, &arg2, &arg3, &arg4, &arg5, &arg6);
+        if (ret) {
+            return ret;
         }
-#else
-        /* mmap pointers are always untagged */
         ret = get_errno(target_mmap(arg1, arg2, arg3,
                                     target_to_host_bitmask(arg4, mmap_flags_tbl),
                                     arg5,
                                     arg6));
-#endif
         return ret;
 #endif
 #ifdef TARGET_NR_mmap2
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index 480ce1c114..f48474bd1d 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -31,5 +31,17 @@  extern abi_ulong mmap_next_start;
 abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
 void mmap_fork_start(void);
 void mmap_fork_end(int child);
+abi_long old_mmap_get_args(abi_long *arg1, abi_long *arg2, abi_long *arg3,
+                           abi_long *arg4, abi_long *arg5, abi_long *arg6);
+
+#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
+    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
+    defined(TARGET_M68K) || defined(TARGET_CRIS) || \
+    defined(TARGET_MICROBLAZE) || defined(TARGET_S390X)
+/* __ARCH_WANT_SYS_OLD_MMAP */
+#define mmap_get_args old_mmap_get_args
+#else
+#define mmap_get_args(arg1, arg2, arg3, arg4, arg5, arg6) 0
+#endif
 
 #endif /* LINUX_USER_USER_MMAP_H */