1 2/*--------------------------------------------------------------------*/ 3/*--- Create/destroy signal delivery frames. ---*/ 4/*--- sigframe-ppc32-aix5.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2006-2010 OpenWorks LLP 12 info@open-works.co.uk 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 31 Neither the names of the U.S. Department of Energy nor the 32 University of California nor the names of its contributors may be 33 used to endorse or promote products derived from this software 34 without prior written permission. 35*/ 36 37#if defined(VGP_ppc32_aix5) 38 39#include "pub_core_basics.h" 40#include "pub_core_vki.h" 41#include "pub_core_vkiscnums.h" 42#include "pub_core_threadstate.h" 43#include "pub_core_aspacemgr.h" 44#include "pub_core_libcbase.h" 45#include "pub_core_libcassert.h" 46#include "pub_core_libcprint.h" 47#include "pub_core_machine.h" 48#include "pub_core_options.h" 49#include "pub_core_signals.h" 50#include "pub_core_tooliface.h" 51#include "pub_core_trampoline.h" 52#include "pub_core_transtab.h" // VG_(discard_translations) 53#include "pub_core_sigframe.h" /* self */ 54 55 56/* This module creates and removes signal frames for signal deliveries 57 on ppc32-aix5. Kludgey; the machine state ought to be saved in a 58 ucontext and retrieved from it later, so the handler can modify it 59 and return. However .. for now .. just stick the vex guest state 60 in the frame and snarf it again later. 61 62 Also, don't bother with creating siginfo and ucontext in the 63 handler, although do point them somewhere non-faulting. 64*/ 65struct hacky_sigframe { 66 UChar lower_guardzone[512]; // put nothing here 67 VexGuestPPC32State gst; 68 VexGuestPPC32State gshadow1; 69 VexGuestPPC32State gshadow2; 70 UInt magicPI; 71 UInt sigNo_private; 72 UInt tramp[2]; 73 UChar upper_guardzone[512]; // put nothing here 74}; 75 76 77/* Extend the stack segment downwards if needed so as to ensure the 78 new signal frames are mapped to something. Return a Bool 79 indicating whether or not the operation was successful. 80*/ 81static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 82{ 83 ThreadId tid = tst->tid; 84 /* For tracking memory events, indicate the entire frame has been 85 allocated. Except, don't mess with the area which 86 overlaps the previous frame's redzone. */ 87 /* XXX is the following call really right? compared with the 88 amd64-linux version, this doesn't appear to handle the redzone 89 in the same way. */ 90 VG_TRACK( new_mem_stack_signal, 91 addr, size - VG_STACK_REDZONE_SZB, tid ); 92 return True; 93} 94 95#define SET_SIGNAL_LR(zztst, zzval) \ 96 do { tst->arch.vex.guest_LR = (zzval); \ 97 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ 98 offsetof(VexGuestPPC32State,guest_LR), \ 99 sizeof(UWord) ); \ 100 } while (0) 101 102#define SET_SIGNAL_GPR(zztst, zzn, zzval) \ 103 do { tst->arch.vex.guest_GPR##zzn = (zzval); \ 104 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ 105 offsetof(VexGuestPPC32State,guest_GPR##zzn), \ 106 sizeof(UWord) ); \ 107 } while (0) 108 109 110/* Create a signal frame for thread 'tid'. */ 111void VG_(sigframe_create) ( ThreadId tid, 112 Addr sp_top_of_frame, 113 const vki_siginfo_t *siginfo, 114 const struct vki_ucontext *siguc, 115 void *handler, 116 UInt flags, 117 const vki_sigset_t *mask, 118 void *restorer ) 119{ 120 ThreadState* tst; 121 Addr sp; 122 struct hacky_sigframe* frame; 123 Int sigNo = siginfo->si_signo; 124 Int __NR_FAKE_SIGRETURN = __NR_AIX5_FAKE_SIGRETURN; 125 126 vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe))); 127 128 sp_top_of_frame &= ~0xf; 129 sp = sp_top_of_frame - sizeof(struct hacky_sigframe); 130 131 tst = VG_(get_ThreadState)(tid); 132 if (!extend(tst, sp, sp_top_of_frame - sp)) 133 return; 134 135 vg_assert(VG_IS_16_ALIGNED(sp)); 136 137 frame = (struct hacky_sigframe *) sp; 138 139 /* clear it (very conservatively) */ 140 VG_(memset)(&frame->lower_guardzone, 0, 512); 141 VG_(memset)(&frame->gst, 0, sizeof(VexGuestPPC32State)); 142 VG_(memset)(&frame->gshadow1, 0, sizeof(VexGuestPPC32State)); 143 VG_(memset)(&frame->gshadow2, 0, sizeof(VexGuestPPC32State)); 144 145 /* save stuff in frame */ 146 frame->gst = tst->arch.vex; 147 frame->gshadow1 = tst->arch.vex_shadow1; 148 frame->gshadow2 = tst->arch.vex_shadow2; 149 frame->sigNo_private = sigNo; 150 frame->magicPI = 0x31415927; 151 152 /* Set up stack frame pointer */ 153 sp += 256; 154 vg_assert(sp == (Addr)&frame->lower_guardzone[256]); 155 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", 156 sp, sizeof(UWord) ); 157 *(Addr*)sp = tst->arch.vex.guest_GPR1; 158 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 159 sp, sizeof(UWord) ); 160 161 /* Set regs for the handler */ 162 SET_SIGNAL_GPR(tid, 1, sp); 163 SET_SIGNAL_GPR(tid, 2, ((UWord*)handler)[1]); 164 SET_SIGNAL_GPR(tid, 3, sigNo); 165 SET_SIGNAL_GPR(tid, 4, 0); /* XXX: the siginfo* */ 166 SET_SIGNAL_GPR(tid, 5, 0); /* XXX: the ucontext* */ 167 tst->arch.vex.guest_CIA = ((UWord*)handler)[0]; 168 169 /* set up return trampoline */ 170 vg_assert(__NR_FAKE_SIGRETURN >= 10000); 171 vg_assert(__NR_FAKE_SIGRETURN <= 32767); 172 frame->tramp[0] = 0x38400000U 173 + __NR_FAKE_SIGRETURN; /* li 2,__NR_FAKE_SIGRETURN */ 174 frame->tramp[1] = 0x44000002U; /* sc */ 175 176 /* invalidate any translation of this area */ 177 VG_(discard_translations)( (Addr64)(Addr)&frame->tramp[0], 178 sizeof(frame->tramp), "sigframe tramp" ); 179 /* set the signal handler to return to the trampoline */ 180 SET_SIGNAL_LR(tst, (Addr) &frame->tramp[0]); 181 182 VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, 183 (Addr)&frame->tramp, sizeof(frame->tramp)); 184 185 if (0) { 186 VG_(printf)("pushed signal frame for sig %d; R1 now = %#lx, " 187 "next %%CIA = %#x, status=%d\n", 188 sigNo, 189 sp, tst->arch.vex.guest_CIA, tst->status); 190 VG_(printf)("trampoline is at %p\n", &frame->tramp[0]); 191 } 192} 193 194 195/* Remove a signal frame from thread 'tid's stack, and restore the CPU 196 state from it. Note, isRT is irrelevant here. */ 197void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) 198{ 199 ThreadState *tst; 200 Addr sp; 201 Int sigNo; 202 struct hacky_sigframe* frame; 203 204 vg_assert(VG_(is_valid_tid)(tid)); 205 tst = VG_(get_ThreadState)(tid); 206 207 /* Check that the stack frame looks valid */ 208 sp = tst->arch.vex.guest_GPR1; 209 vg_assert(VG_IS_16_ALIGNED(sp)); 210 211 frame = (struct hacky_sigframe*)(sp - 256); 212 vg_assert(frame->magicPI == 0x31415927); 213 214 /* restore the entire guest state, and shadows, from the 215 frame. Note, as per comments above, this is a kludge - should 216 restore it from saved ucontext. Oh well. */ 217 tst->arch.vex = frame->gst; 218 tst->arch.vex_shadow1 = frame->gshadow1; 219 tst->arch.vex_shadow2 = frame->gshadow2; 220 sigNo = frame->sigNo_private; 221 222 if (VG_(clo_trace_signals)) 223 VG_(message)(Vg_DebugMsg, 224 "vg_pop_signal_frame (thread %d): valid magic; CIA=%#x\n", 225 tid, tst->arch.vex.guest_CIA); 226 227 VG_TRACK( die_mem_stack_signal, 228 (Addr)frame, 229 sizeof(struct hacky_sigframe) - VG_STACK_REDZONE_SZB ); 230 231 /* tell the tools */ 232 VG_TRACK( post_deliver_signal, tid, sigNo ); 233} 234 235#endif // defined(VGP_ppc32_aix5) 236 237/*--------------------------------------------------------------------*/ 238/*--- end ---*/ 239/*--------------------------------------------------------------------*/ 240