On 5/14/26 18:55, Matt Turner wrote:
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 <[email protected]>
Cc: [email protected]
---
linux-user/sh4/signal.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
patch series applied to linux-user-next git tree.
Thanks!
Helge