1 2 /*--------------------------------------------------------------------*/ 3 /*--- Create/destroy signal delivery frames. ---*/ 4 /*--- sigframe-mips32-linux.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2010-2013 RT-RK 12 mips-valgrind (at) rt-rk.com 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 32 #if defined(VGP_mips32_linux) 33 34 #include "pub_core_basics.h" 35 #include "pub_core_vki.h" 36 #include "pub_core_vkiscnums.h" 37 #include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 38 #include "pub_core_threadstate.h" 39 #include "pub_core_aspacemgr.h" 40 #include "pub_core_libcbase.h" 41 #include "pub_core_libcassert.h" 42 #include "pub_core_libcprint.h" 43 #include "pub_core_machine.h" 44 #include "pub_core_options.h" 45 #include "pub_core_sigframe.h" 46 #include "pub_core_signals.h" 47 #include "pub_core_tooliface.h" 48 #include "pub_core_trampoline.h" 49 #include "pub_core_transtab.h" // VG_(discard_translations) 50 51 struct vg_sig_private 52 { 53 UInt magicPI; 54 UInt sigNo_private; 55 VexGuestMIPS32State vex_shadow1; 56 VexGuestMIPS32State vex_shadow2; 57 }; 58 59 struct sigframe 60 { 61 UInt sf_ass[4]; /* argument save space for o32 */ 62 UInt sf_pad[2]; /* Was: signal trampoline */ 63 struct vki_sigcontext sf_sc; 64 vki_sigset_t sf_mask; 65 struct vg_sig_private priv; 66 }; 67 68 struct rt_sigframe 69 { 70 UInt rs_ass[4]; /* argument save space for o32 */ 71 UInt rs_pad[2]; /* Was: signal trampoline */ 72 vki_siginfo_t rs_info; 73 struct vki_ucontext rs_uc; 74 struct vg_sig_private priv; 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 */ 81 static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 82 { 83 ThreadId tid = tst->tid; 84 NSegment const* stackseg = NULL; 85 86 if (VG_(extend_stack)(addr, tst->client_stack_szB)) 87 { 88 stackseg = VG_(am_find_nsegment)(addr); 89 } 90 91 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) 92 { 93 VG_(message)(Vg_UserMsg, 94 "Can't extend stack to %#lx during signal delivery for thread %d:\n", 95 addr, tid ); 96 if (stackseg == NULL) 97 VG_(message)( Vg_UserMsg, " no stack segment\n" ); 98 else 99 VG_(message)( Vg_UserMsg, " too small or bad protection modes\n" ); 100 101 /* set SIGSEGV to default handler */ 102 VG_(set_default_handler)( VKI_SIGSEGV ); 103 VG_(synth_fault_mapping)( tid, addr ); 104 105 /* The whole process should be about to die, since the default 106 action of SIGSEGV to kill the whole process. */ 107 return False; 108 } 109 110 /* For tracking memory events, indicate the entire frame has been 111 allocated. */ 112 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, 113 size + VG_STACK_REDZONE_SZB, tid ); 114 115 return True; 116 } 117 118 static 119 void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, 120 const vki_siginfo_t *si) 121 { 122 123 struct vki_sigcontext *sc = *sc1; 124 125 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", 126 (Addr)sc, sizeof(unsigned long long)*34 ); 127 sc->sc_regs[1] = tst->arch.vex.guest_r1; 128 sc->sc_regs[2] = tst->arch.vex.guest_r2; 129 sc->sc_regs[3] = tst->arch.vex.guest_r3; 130 sc->sc_regs[4] = tst->arch.vex.guest_r4; 131 sc->sc_regs[5] = tst->arch.vex.guest_r5; 132 sc->sc_regs[6] = tst->arch.vex.guest_r6; 133 sc->sc_regs[7] = tst->arch.vex.guest_r7; 134 sc->sc_regs[8] = tst->arch.vex.guest_r8; 135 sc->sc_regs[9] = tst->arch.vex.guest_r9; 136 sc->sc_regs[10] = tst->arch.vex.guest_r10; 137 sc->sc_regs[11] = tst->arch.vex.guest_r11; 138 sc->sc_regs[12] = tst->arch.vex.guest_r12; 139 sc->sc_regs[13] = tst->arch.vex.guest_r13; 140 sc->sc_regs[14] = tst->arch.vex.guest_r14; 141 sc->sc_regs[15] = tst->arch.vex.guest_r15; 142 sc->sc_regs[16] = tst->arch.vex.guest_r16; 143 sc->sc_regs[17] = tst->arch.vex.guest_r17; 144 sc->sc_regs[18] = tst->arch.vex.guest_r18; 145 sc->sc_regs[19] = tst->arch.vex.guest_r19; 146 sc->sc_regs[20] = tst->arch.vex.guest_r20; 147 sc->sc_regs[21] = tst->arch.vex.guest_r21; 148 sc->sc_regs[22] = tst->arch.vex.guest_r22; 149 sc->sc_regs[23] = tst->arch.vex.guest_r23; 150 sc->sc_regs[24] = tst->arch.vex.guest_r24; 151 sc->sc_regs[25] = tst->arch.vex.guest_r25; 152 sc->sc_regs[26] = tst->arch.vex.guest_r26; 153 sc->sc_regs[27] = tst->arch.vex.guest_r27; 154 sc->sc_regs[28] = tst->arch.vex.guest_r28; 155 sc->sc_regs[29] = tst->arch.vex.guest_r29; 156 sc->sc_regs[30] = tst->arch.vex.guest_r30; 157 sc->sc_regs[31] = tst->arch.vex.guest_r31; 158 sc->sc_pc = tst->arch.vex.guest_PC; 159 sc->sc_mdhi = tst->arch.vex.guest_HI; 160 sc->sc_mdlo = tst->arch.vex.guest_LO; 161 } 162 163 /* EXPORTED */ 164 void VG_(sigframe_create)( ThreadId tid, 165 Addr sp_top_of_frame, 166 const vki_siginfo_t *siginfo, 167 const struct vki_ucontext *siguc, 168 void *handler, 169 UInt flags, 170 const vki_sigset_t *mask, 171 void *restorer ) 172 { 173 Addr sp; 174 ThreadState* tst = VG_(get_ThreadState)(tid); 175 Int sigNo = siginfo->si_signo; 176 struct vg_sig_private *priv; 177 178 /* Stack must be 8-byte aligned */ 179 sp_top_of_frame &= ~0xf; 180 181 if (flags & VKI_SA_SIGINFO) 182 { 183 sp = sp_top_of_frame - sizeof(struct rt_sigframe); 184 } 185 else 186 { 187 sp = sp_top_of_frame - sizeof(struct sigframe); 188 } 189 190 tst = VG_(get_ThreadState)(tid); 191 if (!extend(tst, sp, sp_top_of_frame - sp)) 192 return; 193 194 vg_assert(VG_IS_8_ALIGNED(sp)); 195 196 if (flags & VKI_SA_SIGINFO) 197 { 198 struct rt_sigframe *frame = (struct rt_sigframe *) sp; 199 struct vki_ucontext *ucp = &frame->rs_uc; 200 if (VG_(clo_trace_signals)) 201 VG_(printf)("rt_sigframe\n"); 202 /* Create siginfo. */ 203 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", 204 (Addr)&frame->rs_info, sizeof(frame->rs_info) ); 205 206 VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo)); 207 208 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 209 (Addr)&frame->rs_info, sizeof(frame->rs_info) ); 210 211 /* Create the ucontext. */ 212 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", 213 (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext) ); 214 215 ucp->uc_flags = 0; 216 ucp->uc_link = 0; 217 ucp->uc_stack = tst->altstack; 218 219 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, 220 offsetof(struct vki_ucontext, uc_mcontext) ); 221 222 struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext); 223 setup_sigcontext2(tst, &(scp), siginfo); 224 225 ucp->uc_sigmask = tst->sig_mask; 226 227 priv = &frame->priv; 228 229 /* 230 * Arguments to signal handler: 231 * 232 * a0 = signal number 233 * a1 = 0 (should be cause) 234 * a2 = pointer to ucontext 235 * 236 * $25 and c0_epc point to the signal handler, $29 points to 237 * the struct rt_sigframe. 238 */ 239 240 tst->arch.vex.guest_r4 = siginfo->si_signo; 241 tst->arch.vex.guest_r5 = (Addr) &frame->rs_info; 242 tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc; 243 tst->arch.vex.guest_r29 = (Addr) frame; 244 tst->arch.vex.guest_r25 = (Addr) handler; 245 246 if (flags & VKI_SA_RESTORER) 247 { 248 tst->arch.vex.guest_r31 = (Addr) restorer; 249 } 250 else 251 { 252 tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_rt_sigreturn); 253 } 254 255 } 256 else 257 { 258 if (VG_(clo_trace_signals)) 259 VG_(printf)("sigframe\n"); 260 struct sigframe *frame = (struct sigframe *) sp; 261 struct vki_sigcontext *scp = &(frame->sf_sc); 262 setup_sigcontext2(tst, &(scp), siginfo); 263 frame->sf_mask = tst->sig_mask; 264 priv = &frame->priv; 265 /* 266 * Arguments to signal handler: 267 * 268 * a0 = signal number 269 * a1 = 0 (should be cause) 270 * a2 = pointer to struct sigcontext 271 * 272 * $25 and c0_epc point to the signal handler, $29 points to the 273 * struct sigframe. 274 */ 275 tst->arch.vex.guest_r4 = siginfo->si_signo; 276 tst->arch.vex.guest_r5 = 0; 277 tst->arch.vex.guest_r6 = (Addr) &frame->sf_sc; 278 tst->arch.vex.guest_r29 = (Addr) frame; 279 tst->arch.vex.guest_r25 = (Addr) handler; 280 281 if (flags & VKI_SA_RESTORER) 282 { 283 tst->arch.vex.guest_r31 = (Addr) restorer; 284 } 285 else 286 { 287 tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_sigreturn); 288 } 289 } 290 291 priv->magicPI = 0x31415927; 292 priv->sigNo_private = sigNo; 293 priv->vex_shadow1 = tst->arch.vex_shadow1; 294 priv->vex_shadow2 = tst->arch.vex_shadow2; 295 /* Set the thread so it will next run the handler. */ 296 /* tst->m_sp = sp; also notify the tool we've updated SP */ 297 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); 298 if (VG_(clo_trace_signals)) 299 VG_(printf)("handler = %p\n", handler); 300 tst->arch.vex.guest_PC = (Addr) handler; 301 /* This thread needs to be marked runnable, but we leave that the 302 caller to do. */ 303 } 304 305 /* EXPORTED */ 306 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) 307 { 308 ThreadState *tst; 309 struct vg_sig_private *priv1; 310 Addr sp; 311 UInt frame_size; 312 struct vki_sigcontext *mc; 313 Int sigNo; 314 Bool has_siginfo = isRT; 315 316 vg_assert(VG_(is_valid_tid)(tid)); 317 tst = VG_(get_ThreadState)(tid); 318 sp = tst->arch.vex.guest_r29; 319 if (has_siginfo) 320 { 321 struct rt_sigframe *frame = (struct rt_sigframe *)sp; 322 struct vki_ucontext *ucp = &frame->rs_uc; 323 frame_size = sizeof(*frame); 324 mc = &ucp->uc_mcontext; 325 priv1 = &frame->priv; 326 vg_assert(priv1->magicPI == 0x31415927); 327 sigNo = priv1->sigNo_private; 328 } 329 else 330 { 331 struct sigframe *frame = (struct sigframe *)sp; 332 frame_size = sizeof(*frame); 333 mc = &(frame->sf_sc); 334 priv1 = &frame->priv; 335 vg_assert(priv1->magicPI == 0x31415927); 336 tst->sig_mask = frame->sf_mask; 337 tst->tmp_sig_mask = tst->sig_mask; 338 sigNo = priv1->sigNo_private; 339 } 340 //restore regs 341 tst->arch.vex.guest_r1 = mc->sc_regs[1]; 342 tst->arch.vex.guest_r2 = mc->sc_regs[2]; 343 tst->arch.vex.guest_r3 = mc->sc_regs[3]; 344 tst->arch.vex.guest_r4 = mc->sc_regs[4]; 345 tst->arch.vex.guest_r5 = mc->sc_regs[5]; 346 tst->arch.vex.guest_r6 = mc->sc_regs[6]; 347 tst->arch.vex.guest_r7 = mc->sc_regs[7]; 348 tst->arch.vex.guest_r8 = mc->sc_regs[8]; 349 tst->arch.vex.guest_r9 = mc->sc_regs[9]; 350 tst->arch.vex.guest_r10 = mc->sc_regs[10]; 351 tst->arch.vex.guest_r11 = mc->sc_regs[11]; 352 tst->arch.vex.guest_r12 = mc->sc_regs[12]; 353 tst->arch.vex.guest_r13= mc->sc_regs[13]; 354 tst->arch.vex.guest_r14 = mc->sc_regs[14]; 355 tst->arch.vex.guest_r15 = mc->sc_regs[15]; 356 tst->arch.vex.guest_r16 = mc->sc_regs[16]; 357 tst->arch.vex.guest_r17 = mc->sc_regs[17]; 358 tst->arch.vex.guest_r18 = mc->sc_regs[18]; 359 tst->arch.vex.guest_r19 = mc->sc_regs[19]; 360 tst->arch.vex.guest_r20 = mc->sc_regs[20]; 361 tst->arch.vex.guest_r21 = mc->sc_regs[21]; 362 tst->arch.vex.guest_r22 = mc->sc_regs[22]; 363 tst->arch.vex.guest_r23 = mc->sc_regs[23]; 364 tst->arch.vex.guest_r24 = mc->sc_regs[24]; 365 tst->arch.vex.guest_r25 = mc->sc_regs[25]; 366 tst->arch.vex.guest_r26 = mc->sc_regs[26]; 367 tst->arch.vex.guest_r27 = mc->sc_regs[27]; 368 tst->arch.vex.guest_r28 = mc->sc_regs[28]; 369 tst->arch.vex.guest_r30 = mc->sc_regs[30]; 370 tst->arch.vex.guest_PC = mc->sc_pc; 371 tst->arch.vex.guest_r31 = mc->sc_regs[31]; 372 tst->arch.vex.guest_r29 = mc->sc_regs[29]; 373 374 tst->arch.vex.guest_HI = mc->sc_mdhi; 375 tst->arch.vex.guest_LO = mc->sc_mdlo; 376 tst->arch.vex_shadow1 = priv1->vex_shadow1; 377 tst->arch.vex_shadow2 = priv1->vex_shadow2; 378 379 VG_TRACK(die_mem_stack_signal, sp, frame_size); 380 if (VG_(clo_trace_signals)) 381 VG_(message)( Vg_DebugMsg, 382 "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n", 383 tid, isRT, tst->arch.vex.guest_PC); 384 /* tell the tools */ 385 VG_TRACK( post_deliver_signal, tid, sigNo ); 386 } 387 388 #endif // defined(VGP_mips32_linux) 389 390 /*--------------------------------------------------------------------*/ 391 /*--- end sigframe-mips32-linux.c ---*/ 392 /*--------------------------------------------------------------------*/ 393