1 2 /*--------------------------------------------------------------------*/ 3 /*--- Create/destroy signal delivery frames. ---*/ 4 /*--- sigframe-ppc64-linux.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2000-2013 Nicholas Nethercote 12 njn (at) valgrind.org 13 Copyright (C) 2004-2013 Paul Mackerras 14 paulus (at) samba.org 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 */ 33 34 #if defined(VGP_ppc64_linux) 35 36 #include "pub_core_basics.h" 37 #include "pub_core_vki.h" 38 #include "pub_core_vkiscnums.h" 39 #include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 40 #include "pub_core_threadstate.h" 41 #include "pub_core_aspacemgr.h" 42 #include "pub_core_libcbase.h" 43 #include "pub_core_libcassert.h" 44 #include "pub_core_libcprint.h" 45 #include "pub_core_machine.h" 46 #include "pub_core_options.h" 47 #include "pub_core_sigframe.h" 48 #include "pub_core_signals.h" 49 #include "pub_core_tooliface.h" 50 #include "pub_core_trampoline.h" 51 #include "pub_core_transtab.h" // VG_(discard_translations) 52 53 54 /* This module creates and removes signal frames for signal deliveries 55 on ppc64-linux. 56 57 Note, this file contains kernel-specific knowledge in the form of 58 'struct sigframe' and 'struct rt_sigframe'. How does that relate 59 to the vki kernel interface stuff? 60 61 Either a 'struct sigframe' or a 'struct rtsigframe' is pushed 62 onto the client's stack. This contains a subsidiary 63 vki_ucontext. That holds the vcpu's state across the signal, 64 so that the sighandler can mess with the vcpu state if it 65 really wants. 66 67 FIXME: sigcontexting is basically broken for the moment. When 68 delivering a signal, the integer registers and %eflags are 69 correctly written into the sigcontext, however the FP and SSE state 70 is not. When returning from a signal, only the integer registers 71 are restored from the sigcontext; the rest of the CPU state is 72 restored to what it was before the signal. 73 74 This will be fixed. 75 */ 76 77 78 /*------------------------------------------------------------*/ 79 /*--- Signal frame layouts ---*/ 80 /*------------------------------------------------------------*/ 81 82 // A structure in which to save the application's registers 83 // during the execution of signal handlers. 84 85 // On ppc64-linux, rt_sigframe is used for all signals. 86 87 // In theory, so long as we get the arguments to the handler function 88 // right, it doesn't matter what the exact layout of the rest of the 89 // frame is. Unfortunately, things like gcc's exception unwinding 90 // make assumptions about the locations of various parts of the frame, 91 // so we need to duplicate it exactly. 92 93 /* Many of these byzantine details derived from 94 linux-2.6.13/arch/ppc64/kernel/signal.c */ 95 96 #define TRAMP_SIZE 6 /* who knows why - it only needs to be 2. */ 97 98 /* Structure containing bits of information that we want to save 99 on signal delivery. */ 100 struct vg_sig_private { 101 UInt magicPI; 102 UInt sigNo_private; 103 ULong _unused; /* makes the struct size be zero % 16 */ 104 VexGuestPPC64State vex_shadow1; 105 VexGuestPPC64State vex_shadow2; 106 }; 107 108 /* Structure put on stack for all signal handlers. */ 109 struct rt_sigframe { 110 struct vki_ucontext uc; 111 ULong _unused[2]; 112 UInt tramp[TRAMP_SIZE]; 113 struct vki_siginfo* pinfo; 114 void* puc; 115 vki_siginfo_t info; 116 struct vg_sig_private priv; 117 UChar abigap[288]; 118 }; 119 120 #define SET_SIGNAL_LR(zztst, zzval) \ 121 do { tst->arch.vex.guest_LR = (zzval); \ 122 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ 123 offsetof(VexGuestPPC64State,guest_LR), \ 124 sizeof(UWord) ); \ 125 } while (0) 126 127 #define SET_SIGNAL_GPR(zztst, zzn, zzval) \ 128 do { tst->arch.vex.guest_GPR##zzn = (zzval); \ 129 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ 130 offsetof(VexGuestPPC64State,guest_GPR##zzn), \ 131 sizeof(UWord) ); \ 132 } while (0) 133 134 135 /* Extend the stack segment downwards if needed so as to ensure the 136 new signal frames are mapped to something. Return a Bool 137 indicating whether or not the operation was successful. 138 */ 139 static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 140 { 141 ThreadId tid = tst->tid; 142 NSegment const* stackseg = NULL; 143 144 if (VG_(extend_stack)(addr, tst->client_stack_szB)) { 145 stackseg = VG_(am_find_nsegment)(addr); 146 if (0 && stackseg) 147 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n", 148 addr, stackseg->start, stackseg->end); 149 } 150 151 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { 152 VG_(message)( 153 Vg_UserMsg, 154 "Can't extend stack to %#lx during signal delivery for thread %d:\n", 155 addr, tid); 156 if (stackseg == NULL) 157 VG_(message)(Vg_UserMsg, " no stack segment\n"); 158 else 159 VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); 160 161 /* set SIGSEGV to default handler */ 162 VG_(set_default_handler)(VKI_SIGSEGV); 163 VG_(synth_fault_mapping)(tid, addr); 164 165 /* The whole process should be about to die, since the default 166 action of SIGSEGV to kill the whole process. */ 167 return False; 168 } 169 170 /* For tracking memory events, indicate the entire frame has been 171 allocated. */ 172 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, 173 size + VG_STACK_REDZONE_SZB, tid ); 174 175 return True; 176 } 177 178 179 /* EXPORTED */ 180 void VG_(sigframe_create)( ThreadId tid, 181 Addr sp_top_of_frame, 182 const vki_siginfo_t *siginfo, 183 const struct vki_ucontext *siguc, 184 void *handler, 185 UInt flags, 186 const vki_sigset_t *mask, 187 void *restorer ) 188 { 189 struct vg_sig_private* priv; 190 Addr sp; 191 ThreadState* tst; 192 Int sigNo = siginfo->si_signo; 193 /* Addr faultaddr; */ /* UNUSED */ 194 struct rt_sigframe* frame; 195 196 /* Stack must be 16-byte aligned */ 197 vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private))); 198 vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe))); 199 200 sp_top_of_frame &= ~0xf; 201 sp = sp_top_of_frame - sizeof(struct rt_sigframe); 202 203 tst = VG_(get_ThreadState)(tid); 204 if (!extend(tst, sp, sp_top_of_frame - sp)) 205 return; 206 207 vg_assert(VG_IS_16_ALIGNED(sp)); 208 209 frame = (struct rt_sigframe *) sp; 210 211 /* clear it (conservatively) */ 212 VG_(memset)(frame, 0, sizeof(*frame)); 213 214 ///////// 215 frame->pinfo = &frame->info; 216 frame->puc = &frame->uc; 217 218 frame->uc.uc_flags = 0; 219 frame->uc.uc_link = 0; 220 ///////// 221 222 /* Set up the stack chain pointer */ 223 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", 224 sp, sizeof(UWord) ); 225 *(Addr *)sp = tst->arch.vex.guest_GPR1; 226 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 227 sp, sizeof(UWord) ); 228 229 /* UNUSED: 230 faultaddr = (Addr)siginfo->_sifields._sigfault._addr; 231 if (sigNo == VKI_SIGILL && siginfo->si_code > 0) 232 faultaddr = tst->arch.vex.guest_CIA; 233 */ 234 235 VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo)); 236 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 237 (Addr)&frame->info, sizeof(frame->info) ); 238 239 frame->uc.uc_flags = 0; 240 frame->uc.uc_link = 0; 241 frame->uc.uc_stack = tst->altstack; 242 frame->uc.uc_sigmask = tst->sig_mask; 243 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 244 (Addr)(&frame->uc), sizeof(frame->uc) ); 245 246 # define DO(gpr) frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \ 247 = tst->arch.vex.guest_GPR##gpr 248 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 249 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 250 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 251 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 252 # undef DO 253 254 frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; 255 frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ 256 frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; 257 frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; 258 frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK] = tst->arch.vex.guest_LR; 259 frame->uc.uc_mcontext.gp_regs[VKI_PT_XER] = LibVEX_GuestPPC64_get_XER( 260 &tst->arch.vex); 261 frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR] = LibVEX_GuestPPC64_get_CR( 262 &tst->arch.vex); 263 //mc->mc_gregs[VKI_PT_MQ] = 0; 264 //mc->mc_gregs[VKI_PT_TRAP] = 0; 265 //mc->mc_gregs[VKI_PT_DAR] = fault_addr; 266 //mc->mc_gregs[VKI_PT_DSISR] = 0; 267 //mc->mc_gregs[VKI_PT_RESULT] = 0; 268 269 /* XXX should do FP and vector regs */ 270 271 /* set up signal return trampoline */ 272 /* NB. 5 Sept 07. mc->mc_pad[0..1] used to contain a the code to 273 which the signal handler returns, and it just did sys_sigreturn 274 or sys_rt_sigreturn. But this doesn't work if the stack is 275 non-executable, and it isn't consistent with the x86-linux and 276 amd64-linux scheme for removing the stack frame. So instead be 277 consistent and use a stub in m_trampoline. Then it doesn't 278 matter whether or not the (guest) stack is executable. This 279 fixes #149519 and #145837. */ 280 frame->tramp[0] = 0; /* invalid */ 281 frame->tramp[1] = 0; /* invalid */ 282 VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid, 283 (Addr)&frame->tramp, sizeof(frame->tramp)); 284 285 /* invalidate any translation of this area */ 286 VG_(discard_translations)( (Addr64)&frame->tramp[0], 287 sizeof(frame->tramp), "stack_mcontext" ); 288 289 /* set the signal handler to return to the trampoline */ 290 SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)); 291 292 /* Stack pointer for the handler .. (note, back chain set 293 earlier) */ 294 SET_SIGNAL_GPR(tid, 1, sp); 295 296 /* Args for the handler .. */ 297 SET_SIGNAL_GPR(tid, 3, sigNo); 298 SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info); 299 SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc); 300 /* the kernel sets this, though it doesn't seem to be in the ABI */ 301 SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info); 302 303 /* Handler is in fact a standard ppc64-linux function descriptor, 304 so extract the function entry point and also the toc ptr to use. */ 305 SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]); 306 tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0]; 307 308 priv = &frame->priv; 309 priv->magicPI = 0x31415927; 310 priv->sigNo_private = sigNo; 311 priv->vex_shadow1 = tst->arch.vex_shadow1; 312 priv->vex_shadow2 = tst->arch.vex_shadow2; 313 314 if (0) 315 VG_(printf)("pushed signal frame; %%R1 now = %#lx, " 316 "next %%CIA = %#llx, status=%d\n", 317 sp, tst->arch.vex.guest_CIA, tst->status); 318 } 319 320 321 /*------------------------------------------------------------*/ 322 /*--- Destroying signal frames ---*/ 323 /*------------------------------------------------------------*/ 324 325 /* EXPORTED */ 326 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) 327 { 328 ThreadState *tst; 329 struct vg_sig_private *priv; 330 Addr sp; 331 UInt frame_size; 332 struct rt_sigframe *frame; 333 Int sigNo; 334 Bool has_siginfo = isRT; 335 336 vg_assert(VG_(is_valid_tid)(tid)); 337 tst = VG_(get_ThreadState)(tid); 338 339 /* Check that the stack frame looks valid */ 340 sp = tst->arch.vex.guest_GPR1; 341 vg_assert(VG_IS_16_ALIGNED(sp)); 342 /* JRS 17 Nov 05: This code used to check that *sp -- which should 343 have been set by the stwu at the start of the handler -- points 344 to just above the frame (ie, the previous frame). However, that 345 isn't valid when delivering signals on alt stacks. So I removed 346 it. The frame is still sanity-checked using the priv->magicPI 347 field. */ 348 349 frame = (struct rt_sigframe *)sp; 350 frame_size = sizeof(*frame); 351 priv = &frame->priv; 352 vg_assert(priv->magicPI == 0x31415927); 353 tst->sig_mask = frame->uc.uc_sigmask; 354 tst->tmp_sig_mask = tst->sig_mask; 355 356 sigNo = priv->sigNo_private; 357 358 # define DO(gpr) tst->arch.vex.guest_GPR##gpr \ 359 = frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] 360 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 361 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 362 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 363 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 364 # undef DO 365 366 tst->arch.vex.guest_CIA = frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP]; 367 368 LibVEX_GuestPPC64_put_CR( frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR], 369 &tst->arch.vex ); 370 371 tst->arch.vex.guest_LR = frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK]; 372 tst->arch.vex.guest_CTR = frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR]; 373 LibVEX_GuestPPC64_put_XER( frame->uc.uc_mcontext.gp_regs[VKI_PT_XER], 374 &tst->arch.vex ); 375 376 tst->arch.vex_shadow1 = priv->vex_shadow1; 377 tst->arch.vex_shadow2 = priv->vex_shadow2; 378 379 VG_TRACK(die_mem_stack_signal, sp, frame_size); 380 381 if (VG_(clo_trace_signals)) 382 VG_(message)(Vg_DebugMsg, 383 "vg_pop_signal_frame (thread %d): isRT=%d " 384 "valid magic; EIP=%#llx\n", 385 tid, has_siginfo, tst->arch.vex.guest_CIA); 386 387 /* tell the tools */ 388 VG_TRACK( post_deliver_signal, tid, sigNo ); 389 } 390 391 #endif // defined(VGP_ppc64_linux) 392 393 /*--------------------------------------------------------------------*/ 394 /*--- end ---*/ 395 /*--------------------------------------------------------------------*/ 396