Re: [PATCH 1/2] linux-user/sh4: Fix target_ucontext tuc_link field type

2026-05-19 Thread Helge Deller

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 
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



Re: [PATCH 1/2] linux-user/sh4: Fix target_ucontext tuc_link field type

2026-05-16 Thread Richard Henderson

On 5/14/26 09: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 
Cc: [email protected]
---
  linux-user/sh4/signal.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git ./linux-user/sh4/signal.c ./linux-user/sh4/signal.c
index 9ecc026fae..20d2bc8b2c 100644
--- ./linux-user/sh4/signal.c
+++ ./linux-user/sh4/signal.c
@@ -57,7 +57,7 @@ struct target_sigframe
  
  struct target_ucontext {

  target_ulong tuc_flags;
-struct target_ucontext *tuc_link;
+abi_ulong tuc_link;


abi_ptr.

Otherwise,
Reviewed-by: Richard Henderson 

r~


  target_stack_t tuc_stack;
  struct target_sigcontext tuc_mcontext;
  target_sigset_t tuc_sigmask;/* mask last for extensibility */
@@ -237,7 +237,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
  
  /* Create the ucontext.  */

  __put_user(0, &frame->uc.tuc_flags);
-__put_user(0, (unsigned long *)&frame->uc.tuc_link);
+__put_user(0, &frame->uc.tuc_link);
  target_save_altstack(&frame->uc.tuc_stack, regs);
  setup_sigcontext(&frame->uc.tuc_mcontext,
   regs, set->sig[0]);





[PATCH 1/2] linux-user/sh4: Fix target_ucontext tuc_link field type

2026-05-14 Thread Matt Turner
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 
Cc: [email protected]
---
 linux-user/sh4/signal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git ./linux-user/sh4/signal.c ./linux-user/sh4/signal.c
index 9ecc026fae..20d2bc8b2c 100644
--- ./linux-user/sh4/signal.c
+++ ./linux-user/sh4/signal.c
@@ -57,7 +57,7 @@ struct target_sigframe
 
 struct target_ucontext {
 target_ulong tuc_flags;
-struct target_ucontext *tuc_link;
+abi_ulong tuc_link;
 target_stack_t tuc_stack;
 struct target_sigcontext tuc_mcontext;
 target_sigset_t tuc_sigmask;/* mask last for extensibility */
@@ -237,7 +237,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
 /* Create the ucontext.  */
 __put_user(0, &frame->uc.tuc_flags);
-__put_user(0, (unsigned long *)&frame->uc.tuc_link);
+__put_user(0, &frame->uc.tuc_link);
 target_save_altstack(&frame->uc.tuc_stack, regs);
 setup_sigcontext(&frame->uc.tuc_mcontext,
  regs, set->sig[0]);
-- 
2.52.0