• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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