sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 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 | |
sewardj | 0f157dd | 2013-10-18 14:27:36 +0000 | [diff] [blame] | 11 | Copyright (C) 2010-2013 RT-RK |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 12 | mips-valgrind@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" |
florian | 01fcf6a | 2015-04-18 10:33:54 +0000 | [diff] [blame] | 49 | #include "priv_sigframe.h" |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 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 | |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 77 | |
| 78 | static |
petarj | 4df0bfc | 2013-02-27 23:17:33 +0000 | [diff] [blame] | 79 | void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, |
| 80 | const vki_siginfo_t *si) |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 81 | { |
| 82 | |
| 83 | struct vki_sigcontext *sc = *sc1; |
| 84 | |
| 85 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", |
| 86 | (Addr)sc, sizeof(unsigned long long)*34 ); |
| 87 | sc->sc_regs[1] = tst->arch.vex.guest_r1; |
| 88 | sc->sc_regs[2] = tst->arch.vex.guest_r2; |
| 89 | sc->sc_regs[3] = tst->arch.vex.guest_r3; |
| 90 | sc->sc_regs[4] = tst->arch.vex.guest_r4; |
| 91 | sc->sc_regs[5] = tst->arch.vex.guest_r5; |
| 92 | sc->sc_regs[6] = tst->arch.vex.guest_r6; |
| 93 | sc->sc_regs[7] = tst->arch.vex.guest_r7; |
| 94 | sc->sc_regs[8] = tst->arch.vex.guest_r8; |
| 95 | sc->sc_regs[9] = tst->arch.vex.guest_r9; |
| 96 | sc->sc_regs[10] = tst->arch.vex.guest_r10; |
| 97 | sc->sc_regs[11] = tst->arch.vex.guest_r11; |
| 98 | sc->sc_regs[12] = tst->arch.vex.guest_r12; |
| 99 | sc->sc_regs[13] = tst->arch.vex.guest_r13; |
| 100 | sc->sc_regs[14] = tst->arch.vex.guest_r14; |
| 101 | sc->sc_regs[15] = tst->arch.vex.guest_r15; |
| 102 | sc->sc_regs[16] = tst->arch.vex.guest_r16; |
| 103 | sc->sc_regs[17] = tst->arch.vex.guest_r17; |
| 104 | sc->sc_regs[18] = tst->arch.vex.guest_r18; |
| 105 | sc->sc_regs[19] = tst->arch.vex.guest_r19; |
| 106 | sc->sc_regs[20] = tst->arch.vex.guest_r20; |
| 107 | sc->sc_regs[21] = tst->arch.vex.guest_r21; |
| 108 | sc->sc_regs[22] = tst->arch.vex.guest_r22; |
| 109 | sc->sc_regs[23] = tst->arch.vex.guest_r23; |
| 110 | sc->sc_regs[24] = tst->arch.vex.guest_r24; |
| 111 | sc->sc_regs[25] = tst->arch.vex.guest_r25; |
| 112 | sc->sc_regs[26] = tst->arch.vex.guest_r26; |
| 113 | sc->sc_regs[27] = tst->arch.vex.guest_r27; |
| 114 | sc->sc_regs[28] = tst->arch.vex.guest_r28; |
| 115 | sc->sc_regs[29] = tst->arch.vex.guest_r29; |
| 116 | sc->sc_regs[30] = tst->arch.vex.guest_r30; |
| 117 | sc->sc_regs[31] = tst->arch.vex.guest_r31; |
| 118 | sc->sc_pc = tst->arch.vex.guest_PC; |
| 119 | sc->sc_mdhi = tst->arch.vex.guest_HI; |
| 120 | sc->sc_mdlo = tst->arch.vex.guest_LO; |
| 121 | } |
| 122 | |
| 123 | /* EXPORTED */ |
| 124 | void VG_(sigframe_create)( ThreadId tid, |
| 125 | Addr sp_top_of_frame, |
| 126 | const vki_siginfo_t *siginfo, |
| 127 | const struct vki_ucontext *siguc, |
| 128 | void *handler, |
| 129 | UInt flags, |
| 130 | const vki_sigset_t *mask, |
| 131 | void *restorer ) |
| 132 | { |
| 133 | Addr sp; |
| 134 | ThreadState* tst = VG_(get_ThreadState)(tid); |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 135 | Int sigNo = siginfo->si_signo; |
| 136 | struct vg_sig_private *priv; |
| 137 | |
| 138 | /* Stack must be 8-byte aligned */ |
| 139 | sp_top_of_frame &= ~0xf; |
| 140 | |
| 141 | if (flags & VKI_SA_SIGINFO) |
| 142 | { |
| 143 | sp = sp_top_of_frame - sizeof(struct rt_sigframe); |
| 144 | } |
| 145 | else |
| 146 | { |
| 147 | sp = sp_top_of_frame - sizeof(struct sigframe); |
| 148 | } |
| 149 | |
| 150 | tst = VG_(get_ThreadState)(tid); |
florian | 7d4a28b | 2015-04-23 15:20:00 +0000 | [diff] [blame^] | 151 | if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags)) |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 152 | return; |
| 153 | |
| 154 | vg_assert(VG_IS_8_ALIGNED(sp)); |
sewardj | c68994d | 2012-06-07 09:23:23 +0000 | [diff] [blame] | 155 | |
| 156 | if (flags & VKI_SA_SIGINFO) |
| 157 | { |
| 158 | struct rt_sigframe *frame = (struct rt_sigframe *) sp; |
| 159 | struct vki_ucontext *ucp = &frame->rs_uc; |
| 160 | if (VG_(clo_trace_signals)) |
| 161 | VG_(printf)("rt_sigframe\n"); |
| 162 | /* Create siginfo. */ |
| 163 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", |
| 164 | (Addr)&frame->rs_info, sizeof(frame->rs_info) ); |
| 165 | |
| 166 | VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo)); |
| 167 | |
| 168 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| 169 | (Addr)&frame->rs_info, sizeof(frame->rs_info) ); |
| 170 | |
| 171 | /* Create the ucontext. */ |
| 172 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", |
| 173 | (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext) ); |
| 174 | |
| 175 | ucp->uc_flags = 0; |
| 176 | ucp->uc_link = 0; |
| 177 | ucp->uc_stack = tst->altstack; |
| 178 | |
| 179 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, |
| 180 | offsetof(struct vki_ucontext, uc_mcontext) ); |
| 181 | |
| 182 | struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext); |
| 183 | setup_sigcontext2(tst, &(scp), siginfo); |
| 184 | |
| 185 | ucp->uc_sigmask = tst->sig_mask; |
| 186 | |
| 187 | priv = &frame->priv; |
| 188 | |
| 189 | /* |
| 190 | * Arguments to signal handler: |
| 191 | * |
| 192 | * a0 = signal number |
| 193 | * a1 = 0 (should be cause) |
| 194 | * a2 = pointer to ucontext |
| 195 | * |
| 196 | * $25 and c0_epc point to the signal handler, $29 points to |
| 197 | * the struct rt_sigframe. |
| 198 | */ |
| 199 | |
| 200 | tst->arch.vex.guest_r4 = siginfo->si_signo; |
| 201 | tst->arch.vex.guest_r5 = (Addr) &frame->rs_info; |
| 202 | tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc; |
| 203 | tst->arch.vex.guest_r29 = (Addr) frame; |
| 204 | tst->arch.vex.guest_r25 = (Addr) handler; |
| 205 | |
| 206 | if (flags & VKI_SA_RESTORER) |
| 207 | { |
| 208 | tst->arch.vex.guest_r31 = (Addr) restorer; |
| 209 | } |
| 210 | else |
| 211 | { |
| 212 | tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_rt_sigreturn); |
| 213 | } |
| 214 | |
| 215 | } |
| 216 | else |
| 217 | { |
| 218 | if (VG_(clo_trace_signals)) |
| 219 | VG_(printf)("sigframe\n"); |
| 220 | struct sigframe *frame = (struct sigframe *) sp; |
| 221 | struct vki_sigcontext *scp = &(frame->sf_sc); |
| 222 | setup_sigcontext2(tst, &(scp), siginfo); |
| 223 | frame->sf_mask = tst->sig_mask; |
| 224 | priv = &frame->priv; |
| 225 | /* |
| 226 | * Arguments to signal handler: |
| 227 | * |
| 228 | * a0 = signal number |
| 229 | * a1 = 0 (should be cause) |
| 230 | * a2 = pointer to struct sigcontext |
| 231 | * |
| 232 | * $25 and c0_epc point to the signal handler, $29 points to the |
| 233 | * struct sigframe. |
| 234 | */ |
| 235 | tst->arch.vex.guest_r4 = siginfo->si_signo; |
| 236 | tst->arch.vex.guest_r5 = 0; |
| 237 | tst->arch.vex.guest_r6 = (Addr) &frame->sf_sc; |
| 238 | tst->arch.vex.guest_r29 = (Addr) frame; |
| 239 | tst->arch.vex.guest_r25 = (Addr) handler; |
| 240 | |
| 241 | if (flags & VKI_SA_RESTORER) |
| 242 | { |
| 243 | tst->arch.vex.guest_r31 = (Addr) restorer; |
| 244 | } |
| 245 | else |
| 246 | { |
| 247 | tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_sigreturn); |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | priv->magicPI = 0x31415927; |
| 252 | priv->sigNo_private = sigNo; |
| 253 | priv->vex_shadow1 = tst->arch.vex_shadow1; |
| 254 | priv->vex_shadow2 = tst->arch.vex_shadow2; |
| 255 | /* Set the thread so it will next run the handler. */ |
| 256 | /* tst->m_sp = sp; also notify the tool we've updated SP */ |
| 257 | VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr)); |
| 258 | if (VG_(clo_trace_signals)) |
| 259 | VG_(printf)("handler = %p\n", handler); |
| 260 | tst->arch.vex.guest_PC = (Addr) handler; |
| 261 | /* This thread needs to be marked runnable, but we leave that the |
| 262 | caller to do. */ |
| 263 | } |
| 264 | |
| 265 | /* EXPORTED */ |
| 266 | void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) |
| 267 | { |
| 268 | ThreadState *tst; |
| 269 | struct vg_sig_private *priv1; |
| 270 | Addr sp; |
| 271 | UInt frame_size; |
| 272 | struct vki_sigcontext *mc; |
| 273 | Int sigNo; |
| 274 | Bool has_siginfo = isRT; |
| 275 | |
| 276 | vg_assert(VG_(is_valid_tid)(tid)); |
| 277 | tst = VG_(get_ThreadState)(tid); |
| 278 | sp = tst->arch.vex.guest_r29; |
| 279 | if (has_siginfo) |
| 280 | { |
| 281 | struct rt_sigframe *frame = (struct rt_sigframe *)sp; |
| 282 | struct vki_ucontext *ucp = &frame->rs_uc; |
| 283 | frame_size = sizeof(*frame); |
| 284 | mc = &ucp->uc_mcontext; |
| 285 | priv1 = &frame->priv; |
| 286 | vg_assert(priv1->magicPI == 0x31415927); |
| 287 | sigNo = priv1->sigNo_private; |
| 288 | } |
| 289 | else |
| 290 | { |
| 291 | struct sigframe *frame = (struct sigframe *)sp; |
| 292 | frame_size = sizeof(*frame); |
| 293 | mc = &(frame->sf_sc); |
| 294 | priv1 = &frame->priv; |
| 295 | vg_assert(priv1->magicPI == 0x31415927); |
| 296 | tst->sig_mask = frame->sf_mask; |
| 297 | tst->tmp_sig_mask = tst->sig_mask; |
| 298 | sigNo = priv1->sigNo_private; |
| 299 | } |
| 300 | //restore regs |
| 301 | tst->arch.vex.guest_r1 = mc->sc_regs[1]; |
| 302 | tst->arch.vex.guest_r2 = mc->sc_regs[2]; |
| 303 | tst->arch.vex.guest_r3 = mc->sc_regs[3]; |
| 304 | tst->arch.vex.guest_r4 = mc->sc_regs[4]; |
| 305 | tst->arch.vex.guest_r5 = mc->sc_regs[5]; |
| 306 | tst->arch.vex.guest_r6 = mc->sc_regs[6]; |
| 307 | tst->arch.vex.guest_r7 = mc->sc_regs[7]; |
| 308 | tst->arch.vex.guest_r8 = mc->sc_regs[8]; |
| 309 | tst->arch.vex.guest_r9 = mc->sc_regs[9]; |
| 310 | tst->arch.vex.guest_r10 = mc->sc_regs[10]; |
| 311 | tst->arch.vex.guest_r11 = mc->sc_regs[11]; |
| 312 | tst->arch.vex.guest_r12 = mc->sc_regs[12]; |
| 313 | tst->arch.vex.guest_r13= mc->sc_regs[13]; |
| 314 | tst->arch.vex.guest_r14 = mc->sc_regs[14]; |
| 315 | tst->arch.vex.guest_r15 = mc->sc_regs[15]; |
| 316 | tst->arch.vex.guest_r16 = mc->sc_regs[16]; |
| 317 | tst->arch.vex.guest_r17 = mc->sc_regs[17]; |
| 318 | tst->arch.vex.guest_r18 = mc->sc_regs[18]; |
| 319 | tst->arch.vex.guest_r19 = mc->sc_regs[19]; |
| 320 | tst->arch.vex.guest_r20 = mc->sc_regs[20]; |
| 321 | tst->arch.vex.guest_r21 = mc->sc_regs[21]; |
| 322 | tst->arch.vex.guest_r22 = mc->sc_regs[22]; |
| 323 | tst->arch.vex.guest_r23 = mc->sc_regs[23]; |
| 324 | tst->arch.vex.guest_r24 = mc->sc_regs[24]; |
| 325 | tst->arch.vex.guest_r25 = mc->sc_regs[25]; |
| 326 | tst->arch.vex.guest_r26 = mc->sc_regs[26]; |
| 327 | tst->arch.vex.guest_r27 = mc->sc_regs[27]; |
| 328 | tst->arch.vex.guest_r28 = mc->sc_regs[28]; |
| 329 | tst->arch.vex.guest_r30 = mc->sc_regs[30]; |
| 330 | tst->arch.vex.guest_PC = mc->sc_pc; |
| 331 | tst->arch.vex.guest_r31 = mc->sc_regs[31]; |
| 332 | tst->arch.vex.guest_r29 = mc->sc_regs[29]; |
| 333 | |
| 334 | tst->arch.vex.guest_HI = mc->sc_mdhi; |
| 335 | tst->arch.vex.guest_LO = mc->sc_mdlo; |
| 336 | tst->arch.vex_shadow1 = priv1->vex_shadow1; |
| 337 | tst->arch.vex_shadow2 = priv1->vex_shadow2; |
| 338 | |
| 339 | VG_TRACK(die_mem_stack_signal, sp, frame_size); |
| 340 | if (VG_(clo_trace_signals)) |
| 341 | VG_(message)( Vg_DebugMsg, |
| 342 | "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n", |
| 343 | tid, isRT, tst->arch.vex.guest_PC); |
| 344 | /* tell the tools */ |
| 345 | VG_TRACK( post_deliver_signal, tid, sigNo ); |
| 346 | } |
| 347 | |
| 348 | #endif // defined(VGP_mips32_linux) |
| 349 | |
| 350 | /*--------------------------------------------------------------------*/ |
| 351 | /*--- end sigframe-mips32-linux.c ---*/ |
| 352 | /*--------------------------------------------------------------------*/ |