@samitouri / QOSamiQemu / commits / c3176e6457

linux-user/sh4: Fix target_ucontext tuc_link field type

tuc_link is declared as 'struct target_ucontext *', which is a HOST pointer. On a 64-bit host running a 32-bit SH4 target, this is 8 bytes instead of the 4 bytes the target expects, padding pushes tuc_mcontext 8 bytes past its correct offset. When a signal handler receives ucontext_t *, every field accessed through uc_mcontext (gregs[], pc, pr, ...) is read from the wrong address. In particular the saved PC comes back as a garbage stack value, which breaks any code that initialises a libunwind cursor from the signal context. Fix it by using abi_ulong, which is always sized to the target ABI (4 bytes for SH4), matching the layout the kernel and glibc agree on. This is the same pattern used by arm/signal.c. Also remove the (unsigned long *) cast from the __put_user that zeros tuc_link. The cast was harmless when tuc_link was pointer-sized (8 bytes matching unsigned long on a 64-bit host), but after the type change __put_user's sizeof dispatch would select stq_le_p (8-byte write) for a now-4-byte field, silently overwriting the start of tuc_stack. Neither this fix nor the companion setup_sigtramp fix is independently sufficient: this fix corrects register values read from the signal context but libunwind still cannot detect the frame without the correct trampoline pattern; that fix makes the frame detectable but register reads remain garbage without the correct ucontext layout. 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>

Matt Turner committed May 14, 2026 at 12:55 UTC c3176e645774fcb795bf99c1c6c40c67432232db
1 file changed +2 -2
linux-user/sh4/signal.c
+2 -2
@@ -57,7 +57,7 @@ struct target_sigframe
57
58 struct target_ucontext {
59 target_ulong tuc_flags;
60 - struct target_ucontext *tuc_link;
60 + abi_ulong tuc_link;
61 target_stack_t tuc_stack;
62 struct target_sigcontext tuc_mcontext;
63 target_sigset_t tuc_sigmask; /* mask last for extensibility */
@@ -237,7 +237,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
237
238 /* Create the ucontext. */
239 __put_user(0, &frame->uc.tuc_flags);
240 - __put_user(0, (unsigned long *)&frame->uc.tuc_link);
240 + __put_user(0, &frame->uc.tuc_link);
241 target_save_altstack(&frame->uc.tuc_stack, regs);
242 setup_sigcontext(&frame->uc.tuc_mcontext,
243 regs, set->sig[0]);