diff options
author | WANG Xuerui <xen0n@gentoo.org> | 2022-03-20 13:22:59 +0800 |
---|---|---|
committer | Laurent Vivier <laurent@vivier.eu> | 2022-03-22 13:06:21 +0100 |
commit | 80f0fe3a854081e6d2e3a35275eeec1e2e9a7794 (patch) | |
tree | a86d8d3578afc2ae36a44f3c9aec28503ba6d850 | |
parent | 48fb0a826eea2e7b0135f49e7fa63e7efe2b7677 (diff) |
linux-user: Fix syscall parameter handling for MIPS n32
The MIPS n32 ABI is basically n64 with the address space (i.e. pointer
width) shrinked to 32 bits. Meanwhile the current code treats it as
o32-like based on TARGET_ABI_BITS, which causes problems with n32
syscalls utilizing 64-bit offsets, like pread64, affecting most (if not
all) recently built n32 binaries.
This partially solves issue #909 ("qemu-mipsn32(el) user mode emulator
fails to execute any recently built n32 binaries"); with this change
applied, the built qemu-mipsn32el is able to progress beyond the
pread64, and finish _dl_start_user for the "getting ld.so load libc.so"
case. The program later dies with SIGBUS, though, due to _dl_start_user
not maintaining stack alignment after removing ld.so itself from argv,
and qemu-user starting to enforce alignment recently, but that is
orthogonal to the issue here; the more common case of chrooting is
working, verified with my own-built Gentoo n32 sysroot. (Depending on
the exact ISA used, one may have to explicitly specify QEMU_CPU, which
is the case for my chroot.)
Buglink: https://gitlab.com/qemu-project/qemu/-/issues/909
Signed-off-by: WANG Xuerui <xen0n@gentoo.org>
Cc: Laurent Vivier <laurent@vivier.eu>
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Cc: Andreas K. Hüttel <dilfridge@gentoo.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20220320052259.1610883-1-xen0n@gentoo.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
-rw-r--r-- | linux-user/user-internals.h | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h index a8fdd6933b..ee152ccfaa 100644 --- a/linux-user/user-internals.h +++ b/linux-user/user-internals.h @@ -112,7 +112,7 @@ static inline int is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } -#if TARGET_ABI_BITS == 32 +#if (TARGET_ABI_BITS == 32) && !defined(TARGET_ABI_MIPSN32) static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) { #ifdef TARGET_WORDS_BIGENDIAN @@ -121,7 +121,7 @@ static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) return ((uint64_t)word1 << 32) | word0; #endif } -#else /* TARGET_ABI_BITS == 32 */ +#else /* TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32) */ static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) { return word0; @@ -136,7 +136,7 @@ static inline int regpairs_aligned(void *cpu_env, int num) { return ((((CPUARMState *)cpu_env)->eabi) == 1) ; } -#elif defined(TARGET_MIPS) && (TARGET_ABI_BITS == 32) +#elif defined(TARGET_MIPS) && defined(TARGET_ABI_MIPSO32) static inline int regpairs_aligned(void *cpu_env, int num) { return 1; } #elif defined(TARGET_PPC) && !defined(TARGET_PPC64) /* |