mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-08-26 22:23:12 -04:00
QEMU used MOVW(2) (0x9300), which loads the syscall number from PC+4,
instead of the kernel's MOVW(7) (0x9305), which loads from PC+14. The
kernel uses five "or r0,r0" nop pads between TRAP_NOARG and the syscall
number word to reach that offset. libunwind's unw_is_signal_frame checks
for the exact kernel byte pattern 0xc3109305 at the frame PC, so QEMU's
compact layout was not detected, breaking unwinding through signal frames.
Expand each trampoline from 6 to 16 bytes matching the kernel layout
defined in arch/sh/kernel/signal_32.c:
#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */
#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
__put_user(MOVW(7), &frame->retcode[0]); /* 0x9305 */
__put_user(TRAP_NOARG, &frame->retcode[1]); /* 0xc310 */
__put_user(OR_R0_R0, &frame->retcode[2]); /* 0x200b */
__put_user(OR_R0_R0, &frame->retcode[3]); /* 0x200b */
__put_user(OR_R0_R0, &frame->retcode[4]); /* 0x200b */
__put_user(OR_R0_R0, &frame->retcode[5]); /* 0x200b */
__put_user(OR_R0_R0, &frame->retcode[6]); /* 0x200b */
__put_user((__NR_sigreturn), &frame->retcode[7]);
The first two halfwords (MOVW(7) || TRAP_NOARG = 0xc3109305) form the
32-bit value libunwind checks at the frame PC, followed by two
OR_R0_R0 halfwords (0x200b200b) at PC+4. The same layout applies to
the rt_sigreturn trampoline (lines 366-373 of signal_32.c).
Neither this fix nor the companion tuc_link fix is independently
sufficient: this fix makes signal frames detectable but register reads
remain garbage without the correct ucontext layout; that fix corrects the
ucontext layout but libunwind still cannot detect the frame without the
correct trampoline pattern. Together they fix the following libunwind
tests on a 64-bit host:
Gtest-sig-context, Gtest-trace, Ltest-init-local-signal,
Ltest-sig-context, Ltest-trace
Signed-off-by: Matt Turner <mattst88@gmail.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Helge Deller <deller@gmx.de>
(cherry picked from commit
|
||
|---|---|---|
| .. | ||
| aarch64 | ||
| alpha | ||
| arm | ||
| generic | ||
| hexagon | ||
| hppa | ||
| i386 | ||
| include | ||
| loongarch64 | ||
| m68k | ||
| microblaze | ||
| mips | ||
| mips64 | ||
| openrisc | ||
| ppc | ||
| riscv | ||
| s390x | ||
| sh4 | ||
| sparc | ||
| x86_64 | ||
| xtensa | ||
| elfload.c | ||
| errnos.c.inc | ||
| exit.c | ||
| fd-trans.c | ||
| fd-trans.h | ||
| flat.h | ||
| flatload.c | ||
| gen-vdso-elfn.c.inc | ||
| gen-vdso.c | ||
| ioctls.h | ||
| linux_loop.h | ||
| linuxload.c | ||
| loader.h | ||
| main.c | ||
| meson.build | ||
| mmap.c | ||
| plugin-api.c | ||
| qemu.h | ||
| semihost.c | ||
| signal-common.h | ||
| signal.c | ||
| socket.h | ||
| strace.c | ||
| strace.h | ||
| strace.list | ||
| syscall.c | ||
| syscall_defs.h | ||
| syscall_types.h | ||
| thunk.c | ||
| trace-events | ||
| trace.h | ||
| uaccess.c | ||
| uname.c | ||
| uname.h | ||
| user-internals.h | ||
| user-mmap.h | ||
| vm86.c | ||