aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorWANG Xuerui <xen0n@gentoo.org>2022-03-20 13:22:59 +0800
committerLaurent Vivier <laurent@vivier.eu>2022-03-22 13:06:21 +0100
commit80f0fe3a854081e6d2e3a35275eeec1e2e9a7794 (patch)
treea86d8d3578afc2ae36a44f3c9aec28503ba6d850 /linux-user
parent48fb0a826eea2e7b0135f49e7fa63e7efe2b7677 (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>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/user-internals.h6
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)
/*