|
From: <sv...@va...> - 2007-09-10 16:28:39
|
Author: sewardj
Date: 2007-09-10 17:28:38 +0100 (Mon, 10 Sep 2007)
New Revision: 6813
Log:
ppc32-linux signal handling: don't place the sigframe return stub on
the stack; instead use a stub in m_trampoline.S. This makes it
possible to deliver signals on non-executable stacks, and makes the
behaviour consistent with x86-linux and amd64-linux.
Modified:
trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c
trunk/coregrind/m_trampoline.S
trunk/coregrind/m_translate.c
trunk/coregrind/pub_core_trampoline.h
Modified: trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c
===================================================================
--- trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c 2007-09-10 14:06:40 UTC (rev 6812)
+++ trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c 2007-09-10 16:28:38 UTC (rev 6813)
@@ -133,7 +133,7 @@
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",
@@ -164,10 +164,18 @@
/* 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 */
@@ -175,7 +183,10 @@
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 */
@@ -719,7 +730,7 @@
(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);
@@ -741,7 +752,7 @@
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);
Modified: trunk/coregrind/m_trampoline.S
===================================================================
--- trunk/coregrind/m_trampoline.S 2007-09-10 14:06:40 UTC (rev 6812)
+++ trunk/coregrind/m_trampoline.S 2007-09-10 16:28:38 UTC (rev 6813)
@@ -242,6 +242,18 @@
.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.)
Modified: trunk/coregrind/m_translate.c
===================================================================
--- trunk/coregrind/m_translate.c 2007-09-10 14:06:40 UTC (rev 6812)
+++ trunk/coregrind/m_translate.c 2007-09-10 16:28:38 UTC (rev 6813)
@@ -1164,8 +1164,8 @@
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 */
Modified: trunk/coregrind/pub_core_trampoline.h
===================================================================
--- trunk/coregrind/pub_core_trampoline.h 2007-09-10 14:06:40 UTC (rev 6812)
+++ trunk/coregrind/pub_core_trampoline.h 2007-09-10 16:28:38 UTC (rev 6813)
@@ -69,6 +69,8 @@
#endif
#if defined(VGP_ppc32_linux)
+extern void VG_(ppc32_linux_SUBST_FOR_sigreturn);
+extern void VG_(ppc32_linux_SUBST_FOR_rt_sigreturn);
extern UInt VG_(ppc32_linux_REDIR_FOR_strlen)( void* );
extern UInt VG_(ppc32_linux_REDIR_FOR_strcmp)( void*, void* );
extern void* VG_(ppc32_linux_REDIR_FOR_strchr)( void*, Int );
|