x86_64 defines MAP_32BIT which forces `mmap()` to return a 32-bit
address. This commit adds support for this flag if supported by the
host.

Signed-off-by: Jean-Christian CÎRSTEA <[email protected]>
---
 include/user/abitypes.h         |  2 ++
 include/user/thunk.h            |  3 ++
 linux-user/strace.c             | 26 ++++++++++++++++-
 linux-user/strace.list          |  4 +--
 linux-user/syscall.c            | 50 ++++++++++++++++-----------------
 linux-user/x86_64/target_mman.h |  3 ++
 6 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/include/user/abitypes.h b/include/user/abitypes.h
index be7a876523..0228e1b77c 100644
--- a/include/user/abitypes.h
+++ b/include/user/abitypes.h
@@ -47,6 +47,8 @@ typedef uint32_t abi_uint 
__attribute__((aligned(ABI_INT_ALIGNMENT)));
 typedef int64_t abi_llong __attribute__((aligned(ABI_LLONG_ALIGNMENT)));
 typedef uint64_t abi_ullong __attribute__((aligned(ABI_LLONG_ALIGNMENT)));
 
+#define TARGET_ABI_FMT_x  "%08x"
+
 #ifdef TARGET_ABI32
 typedef uint32_t abi_ulong __attribute__((aligned(ABI_LONG_ALIGNMENT)));
 typedef int32_t abi_long __attribute__((aligned(ABI_LONG_ALIGNMENT)));
diff --git a/include/user/thunk.h b/include/user/thunk.h
index 2a2104b568..e4cfb5fe46 100644
--- a/include/user/thunk.h
+++ b/include/user/thunk.h
@@ -73,6 +73,9 @@ typedef struct bitmask_transtbl {
     unsigned int host_bits;
 } bitmask_transtbl;
 
+#define BITMASK_BIT(target, host) \
+    { target, target, host, host }
+
 void thunk_register_struct(int id, const char *name, const argtype *types);
 void thunk_register_struct_direct(int id, const char *name,
                                   const StructEntry *se1);
diff --git a/linux-user/strace.c b/linux-user/strace.c
index 758c5d32b6..616c801e6b 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -802,6 +802,27 @@ print_syscall_ret_addr(CPUArchState *cpu_env, const struct 
syscallname *name,
     qemu_log("\n");
 }
 
+static void
+print_mmap_ret(CPUArchState *cpu_env, const struct syscallname *name,
+               abi_long ret, abi_long arg0, abi_long arg1,
+               abi_long arg2, abi_long arg3, abi_long arg4,
+               abi_long arg5)
+{
+    if (!print_syscall_err(ret)) {
+        const abi_ulong mmap_flags = (abi_ulong)arg3;
+        /*
+         * If MAP_32BIT is set, print the address as a 32-bit value. This is
+         * consistent with strace output
+         */
+        if (mmap_flags & MAP_32BIT) {
+            qemu_log("0x" TARGET_ABI_FMT_x, (abi_uint)ret);
+        } else {
+            qemu_log("0x" TARGET_ABI_FMT_lx, ret);
+        }
+    }
+    qemu_log("\n");
+}
+
 #if 0 /* currently unused */
 static void
 print_syscall_ret_raw(struct syscallname *name, abi_long ret)
@@ -1196,8 +1217,11 @@ UNUSED static const struct flags mmap_flags[] = {
     FLAG_TARGET(MAP_POPULATE),
     FLAG_TARGET(MAP_STACK),
     FLAG_TARGET(MAP_SYNC),
-#if TARGET_MAP_UNINITIALIZED != 0
+#ifdef TARGET_MAP_UNINITIALIZED
     FLAG_TARGET(MAP_UNINITIALIZED),
+#endif
+#ifdef TARGET_MAP_32BIT
+    FLAG_TARGET(MAP_32BIT),
 #endif
     FLAG_END,
 };
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 51b5ead969..7a8d18ba96 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -602,10 +602,10 @@
 { TARGET_NR_mlockall, "mlockall" , NULL, print_mlockall, NULL },
 #endif
 #ifdef TARGET_NR_mmap
-{ TARGET_NR_mmap, "mmap" , NULL, print_mmap, print_syscall_ret_addr },
+{ TARGET_NR_mmap, "mmap" , NULL, print_mmap, print_mmap_ret },
 #endif
 #ifdef TARGET_NR_mmap2
-{ TARGET_NR_mmap2, "mmap2" , NULL, print_mmap2, print_syscall_ret_addr },
+{ TARGET_NR_mmap2, "mmap2" , NULL, print_mmap2, print_mmap_ret },
 #endif
 #ifdef TARGET_NR_modify_ldt
 { TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL },
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 2060e561a2..0bb56e7a8e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5896,32 +5896,6 @@ static const StructEntry struct_termios_def = {
 #define MAP_UNINITIALIZED 0
 #endif
 
-static const bitmask_transtbl mmap_flags_tbl[] = {
-    { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
-    { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
-      MAP_ANONYMOUS, MAP_ANONYMOUS },
-    { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
-      MAP_GROWSDOWN, MAP_GROWSDOWN },
-    { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
-      MAP_DENYWRITE, MAP_DENYWRITE },
-    { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
-      MAP_EXECUTABLE, MAP_EXECUTABLE },
-    { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
-    { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
-      MAP_NORESERVE, MAP_NORESERVE },
-    { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
-    /* MAP_STACK had been ignored by the kernel for quite some time.
-       Recognize it for the target insofar as we do not want to pass
-       it through to the host.  */
-    { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
-    { TARGET_MAP_NONBLOCK, TARGET_MAP_NONBLOCK, MAP_NONBLOCK, MAP_NONBLOCK },
-    { TARGET_MAP_POPULATE, TARGET_MAP_POPULATE, MAP_POPULATE, MAP_POPULATE },
-    { TARGET_MAP_FIXED_NOREPLACE, TARGET_MAP_FIXED_NOREPLACE,
-      MAP_FIXED_NOREPLACE, MAP_FIXED_NOREPLACE },
-    { TARGET_MAP_UNINITIALIZED, TARGET_MAP_UNINITIALIZED,
-      MAP_UNINITIALIZED, MAP_UNINITIALIZED },
-};
-
 /*
  * Arrange for legacy / undefined architecture specific flags to be
  * ignored by mmap handling code.
@@ -5936,6 +5910,30 @@ static const bitmask_transtbl mmap_flags_tbl[] = {
 #define TARGET_MAP_HUGE_1GB 0
 #endif
 
+static const bitmask_transtbl mmap_flags_tbl[] = {
+    BITMASK_BIT(TARGET_MAP_FIXED, MAP_FIXED),
+    BITMASK_BIT(TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS),
+    BITMASK_BIT(TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN),
+    BITMASK_BIT(TARGET_MAP_DENYWRITE, MAP_DENYWRITE),
+    BITMASK_BIT(TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE),
+    BITMASK_BIT(TARGET_MAP_LOCKED, MAP_LOCKED),
+    BITMASK_BIT(TARGET_MAP_NORESERVE, MAP_NORESERVE),
+    BITMASK_BIT(TARGET_MAP_HUGETLB, MAP_HUGETLB),
+    /*
+     * MAP_STACK had been ignored by the kernel for quite some time.
+     * Recognize it for the target insofar as we do not want to pass
+     * it through to the host.
+     */
+    BITMASK_BIT(TARGET_MAP_STACK, 0),
+    BITMASK_BIT(TARGET_MAP_NONBLOCK, MAP_NONBLOCK),
+    BITMASK_BIT(TARGET_MAP_POPULATE, MAP_POPULATE),
+    BITMASK_BIT(TARGET_MAP_FIXED_NOREPLACE, MAP_FIXED_NOREPLACE),
+    BITMASK_BIT(TARGET_MAP_UNINITIALIZED, MAP_UNINITIALIZED),
+#if TARGET_MAP_32BIT != 0
+    BITMASK_BIT(TARGET_MAP_32BIT, MAP_32BIT),
+#endif
+};
+
 static abi_long do_mmap(abi_ulong addr, abi_ulong len, int prot,
                         int target_flags, int fd, off_t offset)
 {
diff --git a/linux-user/x86_64/target_mman.h b/linux-user/x86_64/target_mman.h
index 48fbf20b42..14c29203f9 100644
--- a/linux-user/x86_64/target_mman.h
+++ b/linux-user/x86_64/target_mman.h
@@ -13,4 +13,7 @@
 /* arch/x86/include/asm/elf.h */
 #define ELF_ET_DYN_BASE       (TASK_UNMAPPED_BASE * 2)
 
+/* arch/x86/include/uapi/asm/mman.h */
+#define TARGET_MAP_32BIT 0x40
+
 #include "../generic/target_mman.h"
-- 
2.51.0


Reply via email to