|
From: <sv...@va...> - 2006-10-17 01:05:11
|
Author: sewardj
Date: 2006-10-17 02:05:09 +0100 (Tue, 17 Oct 2006)
New Revision: 6246
Log:
Merge r6095:
A minimal sigframe implementation for AIX5. Works but does not
provide valid siginfo or ucontext to handlers.
Added:
trunk/coregrind/m_sigframe/sigframe-ppc32-aix5.c
trunk/coregrind/m_sigframe/sigframe-ppc64-aix5.c
Added: trunk/coregrind/m_sigframe/sigframe-ppc32-aix5.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-aix5.c =
(rev 0)
+++ trunk/coregrind/m_sigframe/sigframe-ppc32-aix5.c 2006-10-17 01:05:09 =
UTC (rev 6246)
@@ -0,0 +1,220 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames. ---*/
+/*--- sigframe-ppc32-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+#include "pub_core_transtab.h" // VG_(discard_translations)
+#include "pub_core_sigframe.h" /* self */
+
+
+/* This module creates and removes signal frames for signal deliveries
+ on ppc32-aix5. Kludgey; the machine state ought to be saved in a
+ ucontext and retrieved from it later, so the handler can modify it
+ and return. However .. for now .. just stick the vex guest state
+ in the frame and snarf it again later.
+
+ Also, don't bother with creating siginfo and ucontext in the
+ handler, although do point them somewhere non-faulting.
+*/
+struct hacky_sigframe {
+ UChar lower_guardzone[512]; // put nothing here
+ VexGuestPPC32State gst;
+ VexGuestPPC32State gshadow;
+ UInt magicPI;
+ UInt sigNo_private;
+ UInt tramp[2];
+ UChar upper_guardzone[512]; // put nothing here
+};
+
+
+/* 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 )
+{
+ /* For tracking memory events, indicate the entire frame has been
+ allocated. Except, don't mess with the area which
+ overlaps the previous frame's redzone. */
+ VG_TRACK( new_mem_stack_signal, addr, size - VG_STACK_REDZONE_SZB );
+ return True;
+}
+
+#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)
+
+#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)
+
+
+/* Create a signal frame for thread 'tid'. */
+void VG_(sigframe_create) ( ThreadId tid,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t *siginfo,
+ void *handler,
+ UInt flags,
+ const vki_sigset_t *mask,
+ void *restorer )
+{
+ ThreadState* tst;
+ Addr sp;
+ struct hacky_sigframe* frame;
+ Int sigNo =3D siginfo->si_signo;
+ Int __NR_FAKE_SIGRETURN =3D __NR_AIX5_FAKE_SIGRETURN;
+
+ vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
+
+ sp_top_of_frame &=3D ~0xf;
+ sp =3D sp_top_of_frame - sizeof(struct hacky_sigframe);
+
+ tst =3D VG_(get_ThreadState)(tid);
+ if (!extend(tst, sp, sp_top_of_frame - sp))
+ return;
+
+ vg_assert(VG_IS_16_ALIGNED(sp));
+
+ frame =3D (struct hacky_sigframe *) sp;
+
+ /* clear it (very conservatively) */
+ VG_(memset)(&frame->lower_guardzone, 0, 512);
+ VG_(memset)(&frame->gst, 0, sizeof(VexGuestPPC32State));
+ VG_(memset)(&frame->gshadow, 0, sizeof(VexGuestPPC32State));
+
+ /* save stuff in frame */
+ frame->gst =3D tst->arch.vex;
+ frame->gshadow =3D tst->arch.vex_shadow;
+ frame->sigNo_private =3D sigNo;
+ frame->magicPI =3D 0x31415927;
+
+ /* Set up stack frame pointer */
+ sp +=3D 256;
+ vg_assert(sp =3D=3D (Addr)&frame->lower_guardzone[256]);
+ 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,
+ sp, sizeof(UWord) );
+
+ /* Set regs for the handler */
+ SET_SIGNAL_GPR(tid, 1, sp);
+ SET_SIGNAL_GPR(tid, 2, ((UWord*)handler)[1]);
+ SET_SIGNAL_GPR(tid, 3, sigNo);
+ SET_SIGNAL_GPR(tid, 4, 0); /* XXX: the siginfo* */
+ SET_SIGNAL_GPR(tid, 5, 0); /* XXX: the ucontext* */
+ tst->arch.vex.guest_CIA =3D ((UWord*)handler)[0];
+
+ /* set up return trampoline */
+ vg_assert(__NR_FAKE_SIGRETURN >=3D 10000);
+ vg_assert(__NR_FAKE_SIGRETURN <=3D 32767);
+ frame->tramp[0] =3D 0x38400000U=20
+ + __NR_FAKE_SIGRETURN; /* li 2,__NR_FAKE_SIGRETURN =
*/
+ frame->tramp[1] =3D 0x44000002U; /* sc */
+
+ /* invalidate any translation of this area */
+ VG_(discard_translations)( (Addr64)(Addr)&frame->tramp[0],=20
+ sizeof(frame->tramp), "sigframe tramp" ); =
=20
+ /* set the signal handler to return to the trampoline */
+ SET_SIGNAL_LR(tst, (Addr) &frame->tramp[0]);
+
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
+ (Addr)&frame->tramp, sizeof(frame->tramp));
+
+ if (0) {
+ VG_(printf)("pushed signal frame for sig %d; R1 now =3D %p, "
+ "next %%CIA =3D %p, status=3D%d\n",=20
+ sigNo,
+ sp, tst->arch.vex.guest_CIA, tst->status);
+ VG_(printf)("trampoline is at %p\n", &frame->tramp[0]);
+ }
+}
+
+
+/* Remove a signal frame from thread 'tid's stack, and restore the CPU
+ state from it. Note, isRT is irrelevant here. */
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
+ ThreadState *tst;
+ Addr sp;
+ Int sigNo;
+ struct hacky_sigframe* frame;
+=20
+ 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 =3D (struct hacky_sigframe*)(sp - 256);
+ vg_assert(frame->magicPI =3D=3D 0x31415927);
+
+ /* restore the entire guest state, and shadow, from the
+ frame. Note, as per comments above, this is a kludge - should
+ restore it from saved ucontext. Oh well. */
+ tst->arch.vex =3D frame->gst;
+ tst->arch.vex_shadow =3D frame->gshadow;
+ sigNo =3D frame->sigNo_private;
+
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg,
+ "vg_pop_signal_frame (thread %d): valid magic; CIA=3D=
%p",
+ tid, tst->arch.vex.guest_CIA);
+
+ VG_TRACK( die_mem_stack_signal,=20
+ (Addr)frame,=20
+ sizeof(struct hacky_sigframe) - VG_STACK_REDZONE_SZB );
+
+ /* tell the tools */
+ VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end sigframe-ppc32-linux.c ---*/
+/*--------------------------------------------------------------------*/
Added: trunk/coregrind/m_sigframe/sigframe-ppc64-aix5.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-ppc64-aix5.c =
(rev 0)
+++ trunk/coregrind/m_sigframe/sigframe-ppc64-aix5.c 2006-10-17 01:05:09 =
UTC (rev 6246)
@@ -0,0 +1,254 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames. ---*/
+/*--- sigframe-ppc64-aix5.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2006-2006 OpenWorks LLP
+ in...@op...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+#include "pub_core_transtab.h" // VG_(discard_translations)
+#include "pub_core_sigframe.h" /* self */
+
+
+/* This module creates and removes signal frames for signal deliveries
+ on ppc64-aix5. Kludgey; the machine state ought to be saved in a
+ ucontext and retrieved from it later, so the handler can modify it
+ and return. However .. for now .. just stick the vex guest state
+ in the frame and snarf it again later.
+
+ Also, don't bother with creating siginfo and ucontext in the
+ handler, although do point them somewhere non-faulting.
+*/
+struct hacky_sigframe {
+ UChar lower_guardzone[1024]; // put nothing here
+ VexGuestPPC64State gst;
+ VexGuestPPC64State gshadow;
+ UInt magicPI;
+ UInt sigNo_private;
+ UInt tramp[2];
+ UChar upper_guardzone[1024]; // put nothing here
+};
+
+
+/* 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 )
+{
+ /* For tracking memory events, indicate the entire frame has been
+ allocated. Except, don't mess with the area which
+ overlaps the previous frame's redzone. */
+ VG_TRACK( new_mem_stack_signal, addr, size - VG_STACK_REDZONE_SZB );
+ return True;
+}
+
+#define SET_SIGNAL_LR(zztst, zzval) \
+ do { tst->arch.vex.guest_LR =3D (zzval); \
+ VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \
+ offsetof(VexGuestPPC64State,guest_LR), \
+ sizeof(UWord) ); \
+ } while (0)
+
+#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(VexGuestPPC64State,guest_GPR##zzn), \
+ sizeof(UWord) ); \
+ } while (0)
+
+
+/* Create a signal frame for thread 'tid'. */
+void VG_(sigframe_create) ( ThreadId tid,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t *siginfo,
+ void *handler,
+ UInt flags,
+ const vki_sigset_t *mask,
+ void *restorer )
+{
+ ThreadState* tst;
+ Addr sp;
+ struct hacky_sigframe* frame;
+ Int sigNo =3D siginfo->si_signo;
+ Int __NR_FAKE_SIGRETURN =3D __NR_AIX5_FAKE_SIGRETURN;
+
+ vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
+
+ sp_top_of_frame &=3D ~0xf;
+ sp =3D sp_top_of_frame - sizeof(struct hacky_sigframe);
+
+ tst =3D VG_(get_ThreadState)(tid);
+ if (!extend(tst, sp, sp_top_of_frame - sp))
+ return;
+
+ vg_assert(VG_IS_16_ALIGNED(sp));
+
+ frame =3D (struct hacky_sigframe *) sp;
+
+ /* clear it (very conservatively) */
+ VG_(memset)(&frame->lower_guardzone, 0, 1024);
+ VG_(memset)(&frame->gst, 0, sizeof(VexGuestPPC64State));
+ VG_(memset)(&frame->gshadow, 0, sizeof(VexGuestPPC64State));
+
+ /* save stuff in frame */
+ frame->gst =3D tst->arch.vex;
+ frame->gshadow =3D tst->arch.vex_shadow;
+ frame->sigNo_private =3D sigNo;
+ frame->magicPI =3D 0x31415927;
+
+ /* Set up stack frame pointer */
+ sp +=3D 512;
+ vg_assert(sp =3D=3D (Addr)&frame->lower_guardzone[512]);
+ 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,
+ sp, sizeof(UWord) );
+
+ /* Set regs for the handler */
+ SET_SIGNAL_GPR(tid, 1, sp);
+ SET_SIGNAL_GPR(tid, 2, ((UWord*)handler)[1]);
+ SET_SIGNAL_GPR(tid, 3, sigNo);
+ SET_SIGNAL_GPR(tid, 4, 0); /* XXX: the siginfo* */
+ SET_SIGNAL_GPR(tid, 5, 0); /* XXX: the ucontext* */
+ tst->arch.vex.guest_CIA =3D ((UWord*)handler)[0];
+
+ /* set up return trampoline */
+ vg_assert(__NR_FAKE_SIGRETURN >=3D 10000);
+ vg_assert(__NR_FAKE_SIGRETURN <=3D 32767);
+ frame->tramp[0] =3D 0x38400000U=20
+ + __NR_FAKE_SIGRETURN; /* li 2,__NR_FAKE_SIGRETURN =
*/
+ frame->tramp[1] =3D 0x44000002U; /* sc */
+
+ /* invalidate any translation of this area */
+ VG_(discard_translations)( (Addr64)(Addr)&frame->tramp[0],=20
+ sizeof(frame->tramp), "sigframe tramp" ); =
=20
+ /* set the signal handler to return to the trampoline */
+ SET_SIGNAL_LR(tst, (Addr) &frame->tramp[0]);
+
+ VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
+ (Addr)&frame->tramp, sizeof(frame->tramp));
+
+ if (0) {
+ VG_(printf)("pushed signal frame for sig %d; R1 now =3D %p, "
+ "next %%CIA =3D %p, status=3D%d\n",=20
+ sigNo,
+ sp, tst->arch.vex.guest_CIA, tst->status);
+ VG_(printf)("trampoline is at %p\n", &frame->tramp[0]);
+ }
+}
+
+
+/* Remove a signal frame from thread 'tid's stack, and restore the CPU
+ state from it. Note, isRT is irrelevant here. */
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
+ ThreadState *tst;
+ Addr sp, sp_max;
+ const UWord one_meg =3D 1048576;
+ UWord scannable_bytes;
+
+ Int sigNo, i;
+ struct hacky_sigframe* frame;
+=20
+ 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));
+
+ /* If the frame is being cleared by some mechanism other than our
+ fake sigreturn, sp may not be as it was after the frame was
+ constructed. If so, scan back up the stack looking for the most
+ recently pushed frame and assume that's the right one to use.
+ Urk. */
+ sp_max =3D tst->client_stack_highest_word;
+ scannable_bytes =3D 0;
+ if (sp_max > sp)
+ scannable_bytes =3D sp_max - sp;
+ if (scannable_bytes > one_meg)
+ scannable_bytes =3D one_meg;
+ if (scannable_bytes < (sizeof(struct hacky_sigframe)-512))=20
+ scannable_bytes =3D 0;
+ else
+ scannable_bytes -=3D (sizeof(struct hacky_sigframe)-512);
+
+ vg_assert(scannable_bytes <=3D one_meg);
+
+ frame =3D (struct hacky_sigframe*)(sp - 512);
+ if (frame->magicPI !=3D 0x31415927) {
+ if (!VG_(clo_xml))
+ VG_(message)(Vg_DebugMsg,=20
+ "WARNING: dubious signal return: searching %ld bytes for fra=
me",=20
+ scannable_bytes);
+ for (i =3D 0; i < scannable_bytes/4; i++) {
+ if (frame->magicPI =3D=3D 0x31415927)
+ break;
+ frame =3D (struct hacky_sigframe*)(((Addr)frame)+4);
+ }
+ }
+
+ /* If we haven't found the frame by now, we're hosed. */
+ vg_assert(frame->magicPI =3D=3D 0x31415927);
+
+ /* restore the entire guest state, and shadow, from the
+ frame. Note, as per comments above, this is a kludge - should
+ restore it from saved ucontext. Oh well. */
+ tst->arch.vex =3D frame->gst;
+ tst->arch.vex_shadow =3D frame->gshadow;
+ sigNo =3D frame->sigNo_private;
+
+ if (VG_(clo_trace_signals))
+ VG_(message)(Vg_DebugMsg,
+ "vg_pop_signal_frame (thread %d): valid magic; CIA=3D=
%p",
+ tid, tst->arch.vex.guest_CIA);
+
+ VG_TRACK( die_mem_stack_signal,=20
+ (Addr)frame,=20
+ sizeof(struct hacky_sigframe) - VG_STACK_REDZONE_SZB );
+
+ /* tell the tools */
+ VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end sigframe-ppc64-linux.c ---*/
+/*--------------------------------------------------------------------*/
|