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(-)
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 <jean.christian.cirstea@gmail.com>
---
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
On 12/27/25 07:31, Jean-Christian CÎRSTEA wrote: > 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<jean.christian.cirstea@gmail.com> > --- > 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(-) You can't just pass along MAP_32BIT to the host, even if it does support it. You need to take guest_base into account, which may well place the low 4GB of the guest space well above the low 4GB of the host address space. Emulating this requires full control of the guest address space, which we don't usually do. Though, see reserved_va. r~
© 2016 - 2026 Red Hat, Inc.