static
void stack_mcontext ( struct vki_mcontext *mc,
ThreadState* tst,
- Int ret,
+ Bool use_rt_sigreturn,
UInt fault_addr )
{
VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
/* XXX should do FP and vector regs */
/* set up signal return trampoline */
+ /* NB. 5 Sept 07. mc->mc_pad[0..1] used to contain a the code to
+ which the signal handler returns, and it just did sys_sigreturn
+ or sys_rt_sigreturn. But this doesn't work if the stack is
+ non-executable, and it isn't consistent with the x86-linux and
+ amd64-linux scheme for removing the stack frame. So instead be
+ consistent and use a stub in m_trampoline. Then it doesn't
+ matter whether or not the (guest) stack is executable. This
+ fixes #149519 and #145837. */
VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
(Addr)&mc->mc_pad, sizeof(mc->mc_pad));
- mc->mc_pad[0] = 0x38000000U + ret; /* li 0,ret */
- mc->mc_pad[1] = 0x44000002U; /* sc */
+ mc->mc_pad[0] = 0; /* invalid */
+ mc->mc_pad[1] = 0; /* invalid */
VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
(Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
/* invalidate any translation of this area */
sizeof(mc->mc_pad), "stack_mcontext" );
/* set the signal handler to return to the trampoline */
- SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
+ SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn
+ ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
+ : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn)
+ ));
}
//:: /* Valgrind-specific parts of the signal frame */
(Addr)&ucp->uc_regs,
sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
- stack_mcontext(&ucp->uc_mcontext, tst, __NR_rt_sigreturn, faultaddr);
+ stack_mcontext(&ucp->uc_mcontext, tst, True/*use_rt_sigreturn*/, faultaddr);
priv = &frame->priv;
SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
(Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
- stack_mcontext(&frame->mcontext, tst, __NR_sigreturn, faultaddr);
+ stack_mcontext(&frame->mcontext, tst, False/*!use_rt_sigreturn*/, faultaddr);
priv = &frame->priv;
SET_SIGNAL_GPR(tid, 4, (Addr) scp);
.global VG_(trampoline_stuff_start)
VG_(trampoline_stuff_start):
+.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
+VG_(ppc32_linux_SUBST_FOR_sigreturn):
+ li 0,__NR_sigreturn
+ sc
+ .long 0 /*illegal insn*/
+
+.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
+VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
+ li 0,__NR_rt_sigreturn
+ sc
+ .long 0 /*illegal insn*/
+
/* There's no particular reason that this needs to be handwritten
assembly, but since that's what this file contains, here's a
simple strlen implementation (written in C and compiled by gcc.)
if ( (!translations_allowable_from_seg(seg))
|| addr == TRANSTAB_BOGUS_GUEST_ADDR ) {
if (VG_(clo_trace_signals))
- VG_(message)(Vg_DebugMsg, "translations not allowed here "
- "- throwing SEGV");
+ VG_(message)(Vg_DebugMsg, "translations not allowed here (0x%llx)"
+ " - throwing SEGV", addr);
/* U R busted, sonny. Place your hands on your head and step
away from the orig_addr. */
/* Code address is bad - deliver a signal instead */