From: Julian Seward Date: Mon, 10 Sep 2007 16:28:38 +0000 (+0000) Subject: ppc32-linux signal handling: don't place the sigframe return stub on X-Git-Tag: svn/VALGRIND_3_3_0~220 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd13fc1af8649553c43942a513f8d8920ce9d645;p=thirdparty%2Fvalgrind.git 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. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6813 --- diff --git a/coregrind/m_sigframe/sigframe-ppc32-linux.c b/coregrind/m_sigframe/sigframe-ppc32-linux.c index 5a828f816e..aa364269a5 100644 --- a/coregrind/m_sigframe/sigframe-ppc32-linux.c +++ b/coregrind/m_sigframe/sigframe-ppc32-linux.c @@ -133,7 +133,7 @@ struct rt_sigframe { 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 @@ void stack_mcontext ( struct vki_mcontext *mc, /* 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 @@ void stack_mcontext ( struct vki_mcontext *mc, 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 @@ void VG_(sigframe_create)( ThreadId tid, (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 @@ void VG_(sigframe_create)( ThreadId tid, 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); diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index 40a96bcc47..10d5ec4036 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -242,6 +242,18 @@ VG_(trampoline_stuff_end): .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.) diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c index 0d796a817a..eec5e8f749 100644 --- a/coregrind/m_translate.c +++ b/coregrind/m_translate.c @@ -1164,8 +1164,8 @@ Bool VG_(translate) ( ThreadId tid, 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 */ diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 86a077a114..da9ff416ec 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -69,6 +69,8 @@ extern void VG_(amd64_linux_REDIR_FOR_vtime); #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 );