|
From: <sv...@va...> - 2005-07-08 18:28:44
|
Author: sewardj
Date: 2005-07-08 19:28:40 +0100 (Fri, 08 Jul 2005)
New Revision: 4138
Log:
Import sigframe stuff from Paul's tree. With this and the other changes=20
today, it's possible to run bash on ppc32-linux.
Modified:
trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c
Modified: trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c 2005-07-08 18:27:22=
UTC (rev 4137)
+++ trunk/coregrind/m_sigframe/sigframe-ppc32-linux.c 2005-07-08 18:28:40=
UTC (rev 4138)
@@ -8,8 +8,10 @@
This file is part of Valgrind, a dynamic binary instrumentation
framework.
=20
- Copyright (C) 2005 Nicholas Nethercote
- nj...@ca...
+ Copyright (C) 2000-2005 Nicholas Nethercote
+ nj...@va...
+ Copyright (C) 2004-2005 Paul Mackerras
+ pa...@sa...
=20
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -42,6 +44,8 @@
#include "pub_core_signals.h"
#include "pub_core_tooliface.h"
#include "pub_core_trampoline.h"
+#include "pub_core_transtab.h" // VG_(discard_translations)
+#include "vki_unistd-ppc32-linux.h" // __NR_rt_sigreturn
=20
=20
/* This module creates and removes signal frames for signal deliveries
@@ -85,68 +89,157 @@
// make assumptions about the locations of various parts of the frame,
// so we need to duplicate it exactly.
=20
-/* Valgrind-specific parts of the signal frame */
-struct vg_sigframe
-{
- /* Sanity check word. */
+/* Structure containing bits of information that we want to save
+ on signal delivery. */
+struct vg_sig_private {
UInt magicPI;
+ UInt sigNo_private;
+ VexGuestPPC32State shadow;
+};
=20
- UInt handlerflags; /* flags for signal handler */
+/* Structure put on stack for signal handlers with SA_SIGINFO clear. */
+struct nonrt_sigframe {
+ UInt gap1[16];
+ struct vki_sigcontext sigcontext;
+ struct vki_mcontext mcontext;
+ struct vg_sig_private priv;
+ unsigned char abigap[224];
+};
=20
+/* Structure put on stack for signal handlers with SA_SIGINFO set. */
+struct rt_sigframe {
+ UInt gap1[20];
+ vki_siginfo_t siginfo;
+ struct vki_ucontext ucontext;
+ struct vg_sig_private priv;
+ unsigned char abigap[224];
+};
=20
- /* Safely-saved version of sigNo, as described above. */
- Int sigNo_private;
+#define SET_SIGNAL_LR(zztst, zzval) \
+ do { tst->arch.vex.guest_LR =3D (zzval); \
+ VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \
+ offsetof(VexGuestPPC32State,guest_LR), \
+ sizeof(UWord) ); \
+ } while (0)
=20
- /* XXX This is wrong. Surely we should store the shadow values
- into the shadow memory behind the actual values? */
- VexGuestPPC32State vex_shadow;
+#define SET_SIGNAL_GPR(zztst, zzn, zzval) \
+ do { tst->arch.vex.guest_GPR##zzn =3D (zzval); \
+ VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \
+ offsetof(VexGuestPPC32State,guest_GPR##zzn), \
+ sizeof(UWord) ); \
+ } while (0)
=20
- /* HACK ALERT */
- VexGuestPPC32State vex;
- /* end HACK ALERT */
=20
- /* saved signal mask to be restored when handler returns */
- vki_sigset_t mask;
-
- /* Sanity check word. Is the highest-addressed word; do not
- move!*/
- UInt magicE;
-};
-
-struct sigframe
+static=20
+void stack_mcontext ( struct vki_mcontext *mc,=20
+ ThreadState* tst,=20
+ Int ret,
+ UInt fault_addr )
{
- /* Sig handler's return address */
- Addr retaddr;
- Int sigNo;
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcont=
ext",
+ (Addr)mc, sizeof(struct vki_pt_regs) );
=20
- struct vki_sigcontext sigContext;
-//.. struct _vki_fpstate fpstate;
+# define DO(gpr) mc->mc_gregs[VKI_PT_R0+gpr] =3D tst->arch.vex.guest_G=
PR##gpr
+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+ DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+ DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+# undef DO
=20
- struct vg_sigframe vg;
-};
+ mc->mc_gregs[VKI_PT_NIP] =3D tst->arch.vex.guest_CIA;
+ mc->mc_gregs[VKI_PT_MSR] =3D 0xf032; /* pretty arbitrary */
+ mc->mc_gregs[VKI_PT_ORIG_R3] =3D tst->arch.vex.guest_GPR3;
+ mc->mc_gregs[VKI_PT_CTR] =3D tst->arch.vex.guest_CTR;
+ mc->mc_gregs[VKI_PT_LNK] =3D tst->arch.vex.guest_LR;
+ mc->mc_gregs[VKI_PT_XER] =3D tst->arch.vex.guest_XER;
+ mc->mc_gregs[VKI_PT_CCR] =3D LibVEX_GuestPPC32_get_cr(&tst->arch.=
vex);
+ mc->mc_gregs[VKI_PT_MQ] =3D 0;
+ mc->mc_gregs[VKI_PT_TRAP] =3D 0;
+ mc->mc_gregs[VKI_PT_DAR] =3D fault_addr;
+ mc->mc_gregs[VKI_PT_DSISR] =3D 0;
+ mc->mc_gregs[VKI_PT_RESULT] =3D 0;
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,=20
+ (Addr)mc, sizeof(struct vki_pt_regs) );
=20
-struct rt_sigframe
-{
- /* Sig handler's return address */
- Addr retaddr;
- Int sigNo;
+ /* XXX should do FP and vector regs */
=20
- /* ptr to siginfo_t. */
- Addr psigInfo;
+ /* set up signal return trampoline */
+ VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mconte=
xt",
+ (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
+ mc->mc_pad[0] =3D 0x38000000U + ret; /* li 0,ret */
+ mc->mc_pad[1] =3D 0x44000002U; /* sc */
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,=20
+ (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
+ /* invalidate any translation of this area */
+ VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad,=20
+ sizeof(mc->mc_pad) ); =20
=20
- /* ptr to ucontext */
- Addr puContext;
- /* pointed to by psigInfo */
- vki_siginfo_t sigInfo;
+ /* set the signal handler to return to the trampoline */
+ SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
+}
=20
- /* pointed to by puContext */
- struct vki_ucontext uContext;
-//.. struct _vki_fpstate fpstate;
+//:: /* Valgrind-specific parts of the signal frame */
+//:: struct vg_sigframe
+//:: {
+//:: /* Sanity check word. */
+//:: UInt magicPI;
+//::=20
+//:: UInt handlerflags; /* flags for signal handler */
+//::=20
+//::=20
+//:: /* Safely-saved version of sigNo, as described above. */
+//:: Int sigNo_private;
+//::=20
+//:: /* XXX This is wrong. Surely we should store the shadow values
+//:: into the shadow memory behind the actual values? */
+//:: VexGuestPPC32State vex_shadow;
+//::=20
+//:: /* HACK ALERT */
+//:: VexGuestPPC32State vex;
+//:: /* end HACK ALERT */
+//::=20
+//:: /* saved signal mask to be restored when handler returns */
+//:: vki_sigset_t mask;
+//::=20
+//:: /* Sanity check word. Is the highest-addressed word; do not
+//:: move!*/
+//:: UInt magicE;
+//:: };
+//::=20
+//:: struct sigframe
+//:: {
+//:: /* Sig handler's return address */
+//:: Addr retaddr;
+//:: Int sigNo;
+//::=20
+//:: struct vki_sigcontext sigContext;
+//:: //.. struct _vki_fpstate fpstate;
+//::=20
+//:: struct vg_sigframe vg;
+//:: };
+//::=20
+//:: struct rt_sigframe
+//:: {
+//:: /* Sig handler's return address */
+//:: Addr retaddr;
+//:: Int sigNo;
+//::=20
+//:: /* ptr to siginfo_t. */
+//:: Addr psigInfo;
+//::=20
+//:: /* ptr to ucontext */
+//:: Addr puContext;
+//:: /* pointed to by psigInfo */
+//:: vki_siginfo_t sigInfo;
+//::=20
+//:: /* pointed to by puContext */
+//:: struct vki_ucontext uContext;
+//:: //.. struct _vki_fpstate fpstate;
+//::=20
+//:: struct vg_sigframe vg;
+//:: };
=20
- struct vg_sigframe vg;
-};
=20
-
//:: /*------------------------------------------------------------*/
//:: /*--- Signal operations ---*/
//:: /*------------------------------------------------------------*/
@@ -393,50 +486,51 @@
//.. SET_THREAD_REG(zztid, zzval, STACK_PTR, post_reg_write, \
//.. Vg_CoreSignal, zztid, VG_O_STACK_PTR, sizeof(Addr=
))
*/
-//.. /* Extend the stack segment downwards if needed so as to ensure the
-//.. new signal frames are mapped to something. Return a Bool
-//.. indicating whether or not the operation was successful.
-//.. */
-//.. static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
-//.. {
-//.. ThreadId tid =3D tst->tid;
-//.. Segment *stackseg =3D NULL;
-//..=20
-//.. if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
-//.. stackseg =3D VG_(find_segment)(addr);
-//.. if (0 && stackseg)
-//.. VG_(printf)("frame=3D%p seg=3D%p-%p\n",
-//.. addr, stackseg->addr, stackseg->addr+stackseg->len);
-//.. }
-//..=20
-//.. if (stackseg =3D=3D NULL=20
-//.. || (stackseg->prot & (VKI_PROT_READ|VKI_PROT_WRITE)) =3D=3D =
0) {
-//.. VG_(message)(
-//.. Vg_UserMsg,
-//.. "Can't extend stack to %p during signal delivery for threa=
d %d:",
-//.. addr, tid);
-//.. if (stackseg =3D=3D NULL)
-//.. VG_(message)(Vg_UserMsg, " no stack segment");
-//.. else
-//.. VG_(message)(Vg_UserMsg, " too small or bad protection mo=
des");
-//..=20
-//.. /* set SIGSEGV to default handler */
-//.. VG_(set_default_handler)(VKI_SIGSEGV);
-//.. VG_(synth_fault_mapping)(tid, addr);
-//..=20
-//.. /* The whole process should be about to die, since the defaul=
t
-//.. action of SIGSEGV to kill the whole process. */
-//.. return False;
-//.. }
-//..=20
-//.. /* For tracking memory events, indicate the entire frame has bee=
n
-//.. allocated. */
-//.. VG_TRACK( new_mem_stack_signal, addr, size );
-//..=20
-//.. return True;
-//.. }
=20
+/* Extend the stack segment downwards if needed so as to ensure the
+ new signal frames are mapped to something. Return a Bool
+ indicating whether or not the operation was successful.
+*/
+static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
+{
+ ThreadId tid =3D tst->tid;
+ Segment *stackseg =3D NULL;
=20
+ if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
+ stackseg =3D VG_(find_segment)(addr);
+ if (0 && stackseg)
+ VG_(printf)("frame=3D%p seg=3D%p-%p\n",
+ addr, stackseg->addr, stackseg->addr+stackseg->len);
+ }
+
+ if (stackseg =3D=3D NULL=20
+ || (stackseg->prot & (VKI_PROT_READ|VKI_PROT_WRITE)) =3D=3D 0) {
+ VG_(message)(
+ Vg_UserMsg,
+ "Can't extend stack to %p during signal delivery for thread %d:=
",
+ addr, tid);
+ if (stackseg =3D=3D NULL)
+ VG_(message)(Vg_UserMsg, " no stack segment");
+ else
+ VG_(message)(Vg_UserMsg, " too small or bad protection modes")=
;
+
+ /* set SIGSEGV to default handler */
+ VG_(set_default_handler)(VKI_SIGSEGV);
+ VG_(synth_fault_mapping)(tid, addr);
+
+ /* The whole process should be about to die, since the default
+ action of SIGSEGV to kill the whole process. */
+ return False;
+ }
+
+ /* For tracking memory events, indicate the entire frame has been
+ allocated. */
+ VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
+ size + VG_STACK_REDZONE_SZB );
+
+ return True;
+}
+
//.. /* Build the Valgrind-specific part of a signal frame. */
//..=20
//.. static void build_vg_sigframe(struct vg_sigframe *frame,
@@ -566,8 +660,102 @@
const vki_sigset_t *mask,
void *restorer )
{
- I_die_here;
+ struct vg_sig_private *priv;
+ Addr sp;
+ ThreadState *tst;
+ Int sigNo =3D siginfo->si_signo;
+ Addr faultaddr;
=20
+ /* Stack must be 16-byte aligned */
+ sp_top_of_frame &=3D ~0xf;
+
+ if (flags & VKI_SA_SIGINFO) {
+ sp =3D sp_top_of_frame - sizeof(struct rt_sigframe);
+ } else {
+ sp =3D sp_top_of_frame - sizeof(struct nonrt_sigframe);
+ }
+
+ tst =3D VG_(get_ThreadState)(tid);
+
+ if (!extend(tst, sp, sp_top_of_frame - sp))
+ return;
+
+ vg_assert(VG_IS_16_ALIGNED(sp));
+
+ /* Set up the stack chain pointer */
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
+ sp, sizeof(UWord) );
+ *(Addr *)sp =3D tst->arch.vex.guest_GPR1;
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tid,=20
+ sp, sizeof(UWord) );
+
+ faultaddr =3D (Addr)siginfo->_sifields._sigfault._addr;
+ if (sigNo =3D=3D VKI_SIGILL && siginfo->si_code > 0)
+ faultaddr =3D tst->arch.vex.guest_CIA;
+
+ if (flags & VKI_SA_SIGINFO) {
+ struct rt_sigframe *frame =3D (struct rt_sigframe *) sp;
+ struct vki_ucontext *ucp =3D &frame->ucontext;
+
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo=
",
+ (Addr)&frame->siginfo, sizeof(frame->siginfo) );
+ VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo));
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tid,=20
+ (Addr)&frame->siginfo, sizeof(frame->siginfo) );
+
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontex=
t",
+ (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) );
+ ucp->uc_flags =3D 0;
+ ucp->uc_link =3D 0;
+ ucp->uc_stack =3D tst->altstack;
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
+ offsetof(struct vki_ucontext, uc_pad) );
+
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontex=
t",
+ (Addr)&ucp->uc_regs,
+ sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
+ ucp->uc_regs =3D &ucp->uc_mcontext;
+ ucp->uc_sigmask =3D tst->sig_mask;
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tid,=20
+ (Addr)&ucp->uc_regs,
+ sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
+
+ stack_mcontext(&ucp->uc_mcontext, tst, __NR_rt_sigreturn, faultadd=
r);
+ priv =3D &frame->priv;
+
+ SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
+ SET_SIGNAL_GPR(tid, 5, (Addr) ucp);
+ /* the kernel sets this, though it doesn't seem to be in the ABI *=
/
+ SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo);
+
+ } else {
+ /* non-RT signal delivery */
+ struct nonrt_sigframe *frame =3D (struct nonrt_sigframe *) sp;
+ struct vki_sigcontext *scp =3D &frame->sigcontext;
+
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame sigcont=
ext",
+ (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) =
);
+ scp->signal =3D sigNo;
+ scp->handler =3D (Addr) handler;
+ scp->oldmask =3D tst->sig_mask.sig[0];
+ scp->_unused[3] =3D tst->sig_mask.sig[1];
+ 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);
+ priv =3D &frame->priv;
+
+ SET_SIGNAL_GPR(tid, 4, (Addr) scp);
+ }
+
+ priv->magicPI =3D 0x31415927;
+ priv->sigNo_private =3D sigNo;
+ priv->shadow =3D tst->arch.vex_shadow;
+
+ SET_SIGNAL_GPR(tid, 1, sp);
+ SET_SIGNAL_GPR(tid, 3, sigNo);
+ tst->arch.vex.guest_CIA =3D (Addr) handler;
+
//.. Addr esp;
//.. ThreadState* tst =3D VG_(get_ThreadState)(tid);
//..=20
@@ -586,13 +774,14 @@
//.. tst->arch.vex.guest_CIA =3D (Addr) handler;
//.. /* This thread needs to be marked runnable, but we leave that th=
e
//.. caller to do. */
-//..=20
-//.. if (0)
-//.. VG_(printf)("pushed signal frame; %%ESP now =3D %p, "
-//.. "next %%EIP =3D %p, status=3D%d\n",=20
-//.. esp, tst->arch.vex.guest_CIA, tst->status);
+
+ if (0)
+ VG_(printf)("pushed signal frame; %R1 now =3D %p, "
+ "next %%CIA =3D %p, status=3D%d\n",=20
+ sp, tst->arch.vex.guest_CIA, tst->status);
}
=20
+
/*------------------------------------------------------------*/
/*--- Destroying signal frames ---*/
/*------------------------------------------------------------*/
@@ -669,9 +858,75 @@
//.. }
=20
=20
-//.. /* EXPORTED */
-//.. void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
-//.. {
+/* EXPORTED */
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
+ ThreadState *tst;
+ struct vg_sig_private *priv;
+ Addr sp;
+ UInt frame_size;
+ struct vki_mcontext *mc;
+ Int sigNo;
+ Bool has_siginfo =3D isRT;
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ tst =3D VG_(get_ThreadState)(tid);
+
+ /* Check that the stack frame looks valid */
+ sp =3D tst->arch.vex.guest_GPR1;
+ vg_assert(VG_IS_16_ALIGNED(sp));
+ frame_size =3D *(Addr *)sp - sp;
+
+ if (has_siginfo) {
+ struct rt_sigframe *frame =3D (struct rt_sigframe *)sp;
+ vg_assert(frame_size =3D=3D sizeof(*frame));
+ mc =3D &frame->ucontext.uc_mcontext;
+ priv =3D &frame->priv;
+ tst->sig_mask =3D frame->ucontext.uc_sigmask;
+ } else {
+ struct nonrt_sigframe *frame =3D (struct nonrt_sigframe *)sp;
+ vg_assert(frame_size =3D=3D sizeof(*frame));
+ mc =3D &frame->mcontext;
+ priv =3D &frame->priv;
+ tst->sig_mask.sig[0] =3D frame->sigcontext.oldmask;
+ tst->sig_mask.sig[1] =3D frame->sigcontext._unused[3];
+ }
+ tst->tmp_sig_mask =3D tst->sig_mask;
+
+ vg_assert(priv->magicPI =3D=3D 0x31415927);
+ sigNo =3D priv->sigNo_private;
+
+# define DO(gpr) tst->arch.vex.guest_GPR##gpr =3D mc->mc_gregs[VKI_PT_=
R0+gpr]
+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+ DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
+ DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
+# undef DO
+
+ tst->arch.vex.guest_CIA =3D mc->mc_gregs[VKI_PT_NIP];
+
+ // Umm ... ? (jrs 2005 July 8)
+ // tst->arch.m_orig_gpr3 =3D mc->mc_gregs[VKI_PT_ORIG_R3];
+
+ //tst->arch.m_cr =3D mc->mc_gregs[VKI_PT_CCR];
+ LibVEX_GuestPPC32_put_cr( mc->mc_gregs[VKI_PT_CCR], &tst->arch.vex );
+
+ tst->arch.vex.guest_LR =3D mc->mc_gregs[VKI_PT_LNK];
+ tst->arch.vex.guest_CTR =3D mc->mc_gregs[VKI_PT_CTR];
+ tst->arch.vex.guest_XER =3D mc->mc_gregs[VKI_PT_XER];
+
+ tst->arch.vex_shadow =3D priv->shadow;
+
+ VG_TRACK(die_mem_stack_signal, sp, frame_size);
+
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg,
+ "vg_pop_signal_frame (thread %d): isRT=3D%d valid mag=
ic; EIP=3D%p",
+ tid, has_siginfo, tst->arch.vex.guest_CIA);
+
+ /* tell the tools */
+ VG_TRACK( post_deliver_signal, tid, sigNo );
+
//.. Addr esp;
//.. ThreadState* tst;
//.. SizeT size;
@@ -697,7 +952,7 @@
//..=20
//.. /* tell the tools */
//.. VG_TRACK( post_deliver_signal, tid, sigNo );
-//.. }
+}
=20
//:: /*------------------------------------------------------------*/
//:: /*--- Making coredumps ---*/
|