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-2012 RT-RK
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"
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 */
extend(ThreadState * tst,Addr addr,SizeT size)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
setup_sigcontext2(ThreadState * tst,struct vki_sigcontext ** sc1,const vki_siginfo_t * si)119 void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1, const vki_siginfo_t *si)
120 {
121
122 struct vki_sigcontext *sc = *sc1;
123
124 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
125 (Addr)sc, sizeof(unsigned long long)*34 );
126 sc->sc_regs[1] = tst->arch.vex.guest_r1;
127 sc->sc_regs[2] = tst->arch.vex.guest_r2;
128 sc->sc_regs[3] = tst->arch.vex.guest_r3;
129 sc->sc_regs[4] = tst->arch.vex.guest_r4;
130 sc->sc_regs[5] = tst->arch.vex.guest_r5;
131 sc->sc_regs[6] = tst->arch.vex.guest_r6;
132 sc->sc_regs[7] = tst->arch.vex.guest_r7;
133 sc->sc_regs[8] = tst->arch.vex.guest_r8;
134 sc->sc_regs[9] = tst->arch.vex.guest_r9;
135 sc->sc_regs[10] = tst->arch.vex.guest_r10;
136 sc->sc_regs[11] = tst->arch.vex.guest_r11;
137 sc->sc_regs[12] = tst->arch.vex.guest_r12;
138 sc->sc_regs[13] = tst->arch.vex.guest_r13;
139 sc->sc_regs[14] = tst->arch.vex.guest_r14;
140 sc->sc_regs[15] = tst->arch.vex.guest_r15;
141 sc->sc_regs[16] = tst->arch.vex.guest_r16;
142 sc->sc_regs[17] = tst->arch.vex.guest_r17;
143 sc->sc_regs[18] = tst->arch.vex.guest_r18;
144 sc->sc_regs[19] = tst->arch.vex.guest_r19;
145 sc->sc_regs[20] = tst->arch.vex.guest_r20;
146 sc->sc_regs[21] = tst->arch.vex.guest_r21;
147 sc->sc_regs[22] = tst->arch.vex.guest_r22;
148 sc->sc_regs[23] = tst->arch.vex.guest_r23;
149 sc->sc_regs[24] = tst->arch.vex.guest_r24;
150 sc->sc_regs[25] = tst->arch.vex.guest_r25;
151 sc->sc_regs[26] = tst->arch.vex.guest_r26;
152 sc->sc_regs[27] = tst->arch.vex.guest_r27;
153 sc->sc_regs[28] = tst->arch.vex.guest_r28;
154 sc->sc_regs[29] = tst->arch.vex.guest_r29;
155 sc->sc_regs[30] = tst->arch.vex.guest_r30;
156 sc->sc_regs[31] = tst->arch.vex.guest_r31;
157 sc->sc_pc = tst->arch.vex.guest_PC;
158 sc->sc_mdhi = tst->arch.vex.guest_HI;
159 sc->sc_mdlo = tst->arch.vex.guest_LO;
160 }
161
162 /* EXPORTED */
VG_(sigframe_create)163 void VG_(sigframe_create)( ThreadId tid,
164 Addr sp_top_of_frame,
165 const vki_siginfo_t *siginfo,
166 const struct vki_ucontext *siguc,
167 void *handler,
168 UInt flags,
169 const vki_sigset_t *mask,
170 void *restorer )
171 {
172 Addr sp;
173 ThreadState* tst = VG_(get_ThreadState)(tid);
174 Addr faultaddr;
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 /* SIGILL defines addr to be the faulting address */
197
198 faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
199 if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
200 faultaddr = tst->arch.vex.guest_PC;
201
202 if (flags & VKI_SA_SIGINFO)
203 {
204 struct rt_sigframe *frame = (struct rt_sigframe *) sp;
205 struct vki_ucontext *ucp = &frame->rs_uc;
206 if (VG_(clo_trace_signals))
207 VG_(printf)("rt_sigframe\n");
208 /* Create siginfo. */
209 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
210 (Addr)&frame->rs_info, sizeof(frame->rs_info) );
211
212 VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
213
214 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
215 (Addr)&frame->rs_info, sizeof(frame->rs_info) );
216
217 /* Create the ucontext. */
218 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
219 (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext) );
220
221 ucp->uc_flags = 0;
222 ucp->uc_link = 0;
223 ucp->uc_stack = tst->altstack;
224
225 VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
226 offsetof(struct vki_ucontext, uc_mcontext) );
227
228 struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
229 setup_sigcontext2(tst, &(scp), siginfo);
230
231 ucp->uc_sigmask = tst->sig_mask;
232
233 priv = &frame->priv;
234
235 /*
236 * Arguments to signal handler:
237 *
238 * a0 = signal number
239 * a1 = 0 (should be cause)
240 * a2 = pointer to ucontext
241 *
242 * $25 and c0_epc point to the signal handler, $29 points to
243 * the struct rt_sigframe.
244 */
245
246 tst->arch.vex.guest_r4 = siginfo->si_signo;
247 tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
248 tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
249 tst->arch.vex.guest_r29 = (Addr) frame;
250 tst->arch.vex.guest_r25 = (Addr) handler;
251
252 if (flags & VKI_SA_RESTORER)
253 {
254 tst->arch.vex.guest_r31 = (Addr) restorer;
255 }
256 else
257 {
258 tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_rt_sigreturn);
259 }
260
261 }
262 else
263 {
264 if (VG_(clo_trace_signals))
265 VG_(printf)("sigframe\n");
266 struct sigframe *frame = (struct sigframe *) sp;
267 struct vki_sigcontext *scp = &(frame->sf_sc);
268 setup_sigcontext2(tst, &(scp), siginfo);
269 frame->sf_mask = tst->sig_mask;
270 priv = &frame->priv;
271 /*
272 * Arguments to signal handler:
273 *
274 * a0 = signal number
275 * a1 = 0 (should be cause)
276 * a2 = pointer to struct sigcontext
277 *
278 * $25 and c0_epc point to the signal handler, $29 points to the
279 * struct sigframe.
280 */
281 tst->arch.vex.guest_r4 = siginfo->si_signo;
282 tst->arch.vex.guest_r5 = 0;
283 tst->arch.vex.guest_r6 = (Addr) &frame->sf_sc;
284 tst->arch.vex.guest_r29 = (Addr) frame;
285 tst->arch.vex.guest_r25 = (Addr) handler;
286
287 if (flags & VKI_SA_RESTORER)
288 {
289 tst->arch.vex.guest_r31 = (Addr) restorer;
290 }
291 else
292 {
293 tst->arch.vex.guest_r31 = (Addr)&VG_(mips32_linux_SUBST_FOR_sigreturn);
294 }
295 }
296
297 priv->magicPI = 0x31415927;
298 priv->sigNo_private = sigNo;
299 priv->vex_shadow1 = tst->arch.vex_shadow1;
300 priv->vex_shadow2 = tst->arch.vex_shadow2;
301 /* Set the thread so it will next run the handler. */
302 /* tst->m_sp = sp; also notify the tool we've updated SP */
303 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
304 if (VG_(clo_trace_signals))
305 VG_(printf)("handler = %p\n", handler);
306 tst->arch.vex.guest_PC = (Addr) handler;
307 /* This thread needs to be marked runnable, but we leave that the
308 caller to do. */
309 }
310
311 /* EXPORTED */
VG_(sigframe_destroy)312 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
313 {
314 ThreadState *tst;
315 struct vg_sig_private *priv1;
316 Addr sp;
317 UInt frame_size;
318 struct vki_sigcontext *mc;
319 Int sigNo;
320 Bool has_siginfo = isRT;
321
322 vg_assert(VG_(is_valid_tid)(tid));
323 tst = VG_(get_ThreadState)(tid);
324 sp = tst->arch.vex.guest_r29;
325 if (has_siginfo)
326 {
327 struct rt_sigframe *frame = (struct rt_sigframe *)sp;
328 struct vki_ucontext *ucp = &frame->rs_uc;
329 frame_size = sizeof(*frame);
330 mc = &ucp->uc_mcontext;
331 priv1 = &frame->priv;
332 vg_assert(priv1->magicPI == 0x31415927);
333 sigNo = priv1->sigNo_private;
334 }
335 else
336 {
337 struct sigframe *frame = (struct sigframe *)sp;
338 frame_size = sizeof(*frame);
339 mc = &(frame->sf_sc);
340 priv1 = &frame->priv;
341 vg_assert(priv1->magicPI == 0x31415927);
342 tst->sig_mask = frame->sf_mask;
343 tst->tmp_sig_mask = tst->sig_mask;
344 sigNo = priv1->sigNo_private;
345 }
346 //restore regs
347 tst->arch.vex.guest_r1 = mc->sc_regs[1];
348 tst->arch.vex.guest_r2 = mc->sc_regs[2];
349 tst->arch.vex.guest_r3 = mc->sc_regs[3];
350 tst->arch.vex.guest_r4 = mc->sc_regs[4];
351 tst->arch.vex.guest_r5 = mc->sc_regs[5];
352 tst->arch.vex.guest_r6 = mc->sc_regs[6];
353 tst->arch.vex.guest_r7 = mc->sc_regs[7];
354 tst->arch.vex.guest_r8 = mc->sc_regs[8];
355 tst->arch.vex.guest_r9 = mc->sc_regs[9];
356 tst->arch.vex.guest_r10 = mc->sc_regs[10];
357 tst->arch.vex.guest_r11 = mc->sc_regs[11];
358 tst->arch.vex.guest_r12 = mc->sc_regs[12];
359 tst->arch.vex.guest_r13= mc->sc_regs[13];
360 tst->arch.vex.guest_r14 = mc->sc_regs[14];
361 tst->arch.vex.guest_r15 = mc->sc_regs[15];
362 tst->arch.vex.guest_r16 = mc->sc_regs[16];
363 tst->arch.vex.guest_r17 = mc->sc_regs[17];
364 tst->arch.vex.guest_r18 = mc->sc_regs[18];
365 tst->arch.vex.guest_r19 = mc->sc_regs[19];
366 tst->arch.vex.guest_r20 = mc->sc_regs[20];
367 tst->arch.vex.guest_r21 = mc->sc_regs[21];
368 tst->arch.vex.guest_r22 = mc->sc_regs[22];
369 tst->arch.vex.guest_r23 = mc->sc_regs[23];
370 tst->arch.vex.guest_r24 = mc->sc_regs[24];
371 tst->arch.vex.guest_r25 = mc->sc_regs[25];
372 tst->arch.vex.guest_r26 = mc->sc_regs[26];
373 tst->arch.vex.guest_r27 = mc->sc_regs[27];
374 tst->arch.vex.guest_r28 = mc->sc_regs[28];
375 tst->arch.vex.guest_r30 = mc->sc_regs[30];
376 tst->arch.vex.guest_PC = mc->sc_pc;
377 tst->arch.vex.guest_r31 = mc->sc_regs[31];
378 tst->arch.vex.guest_r29 = mc->sc_regs[29];
379
380 tst->arch.vex.guest_HI = mc->sc_mdhi;
381 tst->arch.vex.guest_LO = mc->sc_mdlo;
382 tst->arch.vex_shadow1 = priv1->vex_shadow1;
383 tst->arch.vex_shadow2 = priv1->vex_shadow2;
384
385 VG_TRACK(die_mem_stack_signal, sp, frame_size);
386 if (VG_(clo_trace_signals))
387 VG_(message)( Vg_DebugMsg,
388 "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n",
389 tid, isRT, tst->arch.vex.guest_PC);
390 /* tell the tools */
391 VG_TRACK( post_deliver_signal, tid, sigNo );
392 }
393
394 #endif // defined(VGP_mips32_linux)
395
396 /*--------------------------------------------------------------------*/
397 /*--- end sigframe-mips32-linux.c ---*/
398 /*--------------------------------------------------------------------*/
399