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 <i...@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 --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 */ -- 2.35.3