1 2 /*--------------------------------------------------------------------*/ 3 /*--- Create/destroy signal delivery frames. ---*/ 4 /*--- sigframe-mips64-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_mips64_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 UInt magicPI; 53 UInt sigNo_private; 54 VexGuestMIPS64State vex_shadow1; 55 VexGuestMIPS64State vex_shadow2; 56 }; 57 58 struct sigframe { 59 UInt sf_ass[4]; /* argument save space for o32 */ 60 UInt sf_pad[2]; /* Was: signal trampoline */ 61 struct vki_sigcontext sf_sc; 62 vki_sigset_t sf_mask; 63 struct vg_sig_private priv; 64 }; 65 66 struct rt_sigframe { 67 UInt rs_ass[4]; /* argument save space for o32 */ 68 UInt rs_pad[2]; /* Was: signal trampoline */ 69 vki_siginfo_t rs_info; 70 struct vki_ucontext rs_uc; 71 struct vg_sig_private priv; 72 }; 73 74 /* Extend the stack segment downwards if needed so as to ensure the new signal 75 frames are mapped to something. Return a Bool indicating whether or not the 76 operation was successful. 77 */ 78 static Bool extend ( ThreadState *tst, Addr addr, SizeT size ) 79 { 80 ThreadId tid = tst->tid; 81 NSegment const* stackseg = NULL; 82 83 if (VG_(extend_stack)(addr, tst->client_stack_szB)) { 84 stackseg = VG_(am_find_nsegment)(addr); 85 } 86 87 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) { 88 VG_(message)(Vg_UserMsg, 89 "Can't extend stack to %#lx during signal delivery for thread %d:\n", 90 addr, tid); 91 if (stackseg == NULL) 92 VG_(message)(Vg_UserMsg, " no stack segment\n"); 93 else 94 VG_(message)(Vg_UserMsg, " too small or bad protection modes\n"); 95 96 /* set SIGSEGV to default handler */ 97 VG_(set_default_handler)(VKI_SIGSEGV); 98 VG_(synth_fault_mapping)(tid, addr); 99 100 /* The whole process should be about to die, since the default 101 action of SIGSEGV to kill the whole process. */ 102 return False; 103 } 104 105 /* For tracking memory events, indicate the entire frame has been 106 allocated. */ 107 VG_TRACK(new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB, 108 size + VG_STACK_REDZONE_SZB, tid); 109 110 return True; 111 } 112 113 static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1, 114 const vki_siginfo_t *si) 115 { 116 struct vki_sigcontext *sc = *sc1; 117 118 VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", 119 (Addr)sc, sizeof(unsigned long long)*34); 120 sc->sc_regs[1] = tst->arch.vex.guest_r1; 121 sc->sc_regs[2] = tst->arch.vex.guest_r2; 122 sc->sc_regs[3] = tst->arch.vex.guest_r3; 123 sc->sc_regs[4] = tst->arch.vex.guest_r4; 124 sc->sc_regs[5] = tst->arch.vex.guest_r5; 125 sc->sc_regs[6] = tst->arch.vex.guest_r6; 126 sc->sc_regs[7] = tst->arch.vex.guest_r7; 127 sc->sc_regs[8] = tst->arch.vex.guest_r8; 128 sc->sc_regs[9] = tst->arch.vex.guest_r9; 129 sc->sc_regs[10] = tst->arch.vex.guest_r10; 130 sc->sc_regs[11] = tst->arch.vex.guest_r11; 131 sc->sc_regs[12] = tst->arch.vex.guest_r12; 132 sc->sc_regs[13] = tst->arch.vex.guest_r13; 133 sc->sc_regs[14] = tst->arch.vex.guest_r14; 134 sc->sc_regs[15] = tst->arch.vex.guest_r15; 135 sc->sc_regs[16] = tst->arch.vex.guest_r16; 136 sc->sc_regs[17] = tst->arch.vex.guest_r17; 137 sc->sc_regs[18] = tst->arch.vex.guest_r18; 138 sc->sc_regs[19] = tst->arch.vex.guest_r19; 139 sc->sc_regs[20] = tst->arch.vex.guest_r20; 140 sc->sc_regs[21] = tst->arch.vex.guest_r21; 141 sc->sc_regs[22] = tst->arch.vex.guest_r22; 142 sc->sc_regs[23] = tst->arch.vex.guest_r23; 143 sc->sc_regs[24] = tst->arch.vex.guest_r24; 144 sc->sc_regs[25] = tst->arch.vex.guest_r25; 145 sc->sc_regs[26] = tst->arch.vex.guest_r26; 146 sc->sc_regs[27] = tst->arch.vex.guest_r27; 147 sc->sc_regs[28] = tst->arch.vex.guest_r28; 148 sc->sc_regs[29] = tst->arch.vex.guest_r29; 149 sc->sc_regs[30] = tst->arch.vex.guest_r30; 150 sc->sc_regs[31] = tst->arch.vex.guest_r31; 151 sc->sc_pc = tst->arch.vex.guest_PC; 152 sc->sc_mdhi = tst->arch.vex.guest_HI; 153 sc->sc_mdlo = tst->arch.vex.guest_LO; 154 } 155 156 /* EXPORTED */ 157 void VG_(sigframe_create) ( ThreadId tid, 158 Addr sp_top_of_frame, 159 const vki_siginfo_t *siginfo, 160 const struct vki_ucontext *siguc, 161 void *handler, 162 UInt flags, 163 const vki_sigset_t *mask, 164 void *restorer ) 165 { 166 Addr sp; 167 ThreadState* tst = VG_(get_ThreadState)(tid); 168 Int sigNo = siginfo->si_signo; 169 struct vg_sig_private *priv; 170 /* Stack must be 16-byte aligned */ 171 sp_top_of_frame &= ~0xf; 172 173 sp = sp_top_of_frame - sizeof(struct rt_sigframe); 174 175 tst = VG_(get_ThreadState)(tid); 176 if (!extend(tst, sp, sp_top_of_frame - sp)) 177 return; 178 179 sp = VG_ROUNDDN(sp, 16); 180 181 struct rt_sigframe *frame = (struct rt_sigframe *)sp; 182 struct vki_ucontext *ucp = &frame->rs_uc; 183 if (VG_(clo_trace_signals)) 184 VG_(printf)("rt_sigframe\n"); 185 /* Create siginfo. */ 186 VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", 187 (Addr)&frame->rs_info, sizeof(frame->rs_info)); 188 189 VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo)); 190 191 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, 192 (Addr)&frame->rs_info, sizeof(frame->rs_info)); 193 194 /* Create the ucontext. */ 195 VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", 196 (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext)); 197 198 ucp->uc_flags = 0; 199 ucp->uc_link = 0; 200 ucp->uc_stack = tst->altstack; 201 202 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, 203 offsetof(struct vki_ucontext, uc_mcontext)); 204 205 struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext); 206 setup_sigcontext(tst, &(scp), siginfo); 207 ucp->uc_sigmask = tst->sig_mask; 208 priv = &frame->priv; 209 210 /* Arguments to signal handler: 211 212 a0 = signal number 213 a1 = 0 (should be cause) 214 a2 = pointer to ucontext 215 216 $25 and c0_epc point to the signal handler, $29 points to 217 the struct rt_sigframe. */ 218 219 tst->arch.vex.guest_r4 = siginfo->si_signo; 220 tst->arch.vex.guest_r5 = (Addr) &frame->rs_info; 221 tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc; 222 tst->arch.vex.guest_r29 = (Addr) frame; 223 tst->arch.vex.guest_r25 = (Addr) handler; 224 225 if (flags & VKI_SA_RESTORER) 226 tst->arch.vex.guest_r31 = (Addr) restorer; 227 else 228 tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn); 229 230 priv->magicPI = 0x31415927; 231 priv->sigNo_private = sigNo; 232 priv->vex_shadow1 = tst->arch.vex_shadow1; 233 priv->vex_shadow2 = tst->arch.vex_shadow2; 234 /* Set the thread so it will next run the handler. */ 235 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); 236 if (VG_(clo_trace_signals)) 237 VG_(printf)("handler = %p\n", handler); 238 tst->arch.vex.guest_PC = (Addr) handler; 239 /* This thread needs to be marked runnable, but we leave that 240 the caller to do. */ 241 } 242 243 /* EXPORTED */ 244 void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT ) 245 { 246 ThreadState *tst; 247 struct vg_sig_private *priv1; 248 Addr sp; 249 UInt frame_size; 250 struct vki_sigcontext *mc; 251 Int sigNo; 252 253 vg_assert(VG_(is_valid_tid)(tid)); 254 tst = VG_(get_ThreadState)(tid); 255 sp = tst->arch.vex.guest_r29; 256 struct rt_sigframe *frame = (struct rt_sigframe *)sp; 257 struct vki_ucontext *ucp = &frame->rs_uc; 258 frame_size = sizeof(*frame); 259 mc = &ucp->uc_mcontext; 260 tst->sig_mask = ucp->uc_sigmask; 261 tst->tmp_sig_mask = ucp->uc_sigmask; 262 priv1 = &frame->priv; 263 sigNo = priv1->sigNo_private; 264 vg_assert(priv1->magicPI == 0x31415927); 265 /* restore regs */ 266 tst->arch.vex.guest_r1 = mc->sc_regs[1]; 267 tst->arch.vex.guest_r2 = mc->sc_regs[2]; 268 tst->arch.vex.guest_r3 = mc->sc_regs[3]; 269 tst->arch.vex.guest_r4 = mc->sc_regs[4]; 270 tst->arch.vex.guest_r5 = mc->sc_regs[5]; 271 tst->arch.vex.guest_r6 = mc->sc_regs[6]; 272 tst->arch.vex.guest_r7 = mc->sc_regs[7]; 273 tst->arch.vex.guest_r8 = mc->sc_regs[8]; 274 tst->arch.vex.guest_r9 = mc->sc_regs[9]; 275 tst->arch.vex.guest_r10 = mc->sc_regs[10]; 276 tst->arch.vex.guest_r11 = mc->sc_regs[11]; 277 tst->arch.vex.guest_r12 = mc->sc_regs[12]; 278 tst->arch.vex.guest_r13= mc->sc_regs[13]; 279 tst->arch.vex.guest_r14 = mc->sc_regs[14]; 280 tst->arch.vex.guest_r15 = mc->sc_regs[15]; 281 tst->arch.vex.guest_r16 = mc->sc_regs[16]; 282 tst->arch.vex.guest_r17 = mc->sc_regs[17]; 283 tst->arch.vex.guest_r18 = mc->sc_regs[18]; 284 tst->arch.vex.guest_r19 = mc->sc_regs[19]; 285 tst->arch.vex.guest_r20 = mc->sc_regs[20]; 286 tst->arch.vex.guest_r21 = mc->sc_regs[21]; 287 tst->arch.vex.guest_r22 = mc->sc_regs[22]; 288 tst->arch.vex.guest_r23 = mc->sc_regs[23]; 289 tst->arch.vex.guest_r24 = mc->sc_regs[24]; 290 tst->arch.vex.guest_r25 = mc->sc_regs[25]; 291 tst->arch.vex.guest_r26 = mc->sc_regs[26]; 292 tst->arch.vex.guest_r27 = mc->sc_regs[27]; 293 tst->arch.vex.guest_r28 = mc->sc_regs[28]; 294 tst->arch.vex.guest_r30 = mc->sc_regs[30]; 295 tst->arch.vex.guest_PC = mc->sc_pc; 296 tst->arch.vex.guest_r31 = mc->sc_regs[31]; 297 tst->arch.vex.guest_r29 = mc->sc_regs[29]; 298 299 tst->arch.vex.guest_HI = mc->sc_mdhi; 300 tst->arch.vex.guest_LO = mc->sc_mdlo; 301 tst->arch.vex_shadow1 = priv1->vex_shadow1; 302 tst->arch.vex_shadow2 = priv1->vex_shadow2; 303 304 VG_TRACK(die_mem_stack_signal, sp, frame_size); 305 if (VG_(clo_trace_signals)) 306 VG_(message)(Vg_DebugMsg, 307 "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n", 308 tid, isRT, tst->arch.vex.guest_PC); 309 /* tell the tools */ 310 VG_TRACK( post_deliver_signal, tid, sigNo ); 311 } 312 313 #endif /* defined(VGP_mips64_linux) */ 314 315 /*--------------------------------------------------------------------*/ 316 /*--- end sigframe-mips64-linux.c ---*/ 317 /*--------------------------------------------------------------------*/ 318