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-2017 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_threadstate.h"
38 #include "pub_core_aspacemgr.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_machine.h"
43 #include "pub_core_options.h"
44 #include "pub_core_sigframe.h"
45 #include "pub_core_signals.h"
46 #include "pub_core_tooliface.h"
47 #include "pub_core_trampoline.h"
48 #include "priv_sigframe.h"
49 
50 struct vg_sig_private
51 {
52   UInt magicPI;
53   UInt sigNo_private;
54   VexGuestMIPS32State vex_shadow1;
55   VexGuestMIPS32State vex_shadow2;
56 };
57 
58 struct sigframe
59 {
60   UInt sf_ass[4];       /* argument save space for o32 */
61   UInt sf_pad[2];       /* Was: signal trampoline */
62   struct vki_sigcontext sf_sc;
63   vki_sigset_t sf_mask;
64   struct vg_sig_private priv;
65 };
66 
67 struct rt_sigframe
68 {
69   UInt rs_ass[4];		/* argument save space for o32 */
70   UInt rs_pad[2];		/* Was: signal trampoline */
71   vki_siginfo_t rs_info;
72   struct vki_ucontext rs_uc;
73   struct vg_sig_private priv;
74 };
75 
76 
77 static
setup_sigcontext2(ThreadState * tst,struct vki_sigcontext ** sc1,const vki_siginfo_t * si)78 void setup_sigcontext2 ( ThreadState* tst, struct vki_sigcontext **sc1,
79                          const vki_siginfo_t *si)
80 {
81 
82   struct vki_sigcontext *sc = *sc1;
83 
84   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
85            (Addr)sc, sizeof(unsigned long long)*34 );
86   sc->sc_regs[1] = tst->arch.vex.guest_r1;
87   sc->sc_regs[2] = tst->arch.vex.guest_r2;
88   sc->sc_regs[3] = tst->arch.vex.guest_r3;
89   sc->sc_regs[4] = tst->arch.vex.guest_r4;
90   sc->sc_regs[5] = tst->arch.vex.guest_r5;
91   sc->sc_regs[6] = tst->arch.vex.guest_r6;
92   sc->sc_regs[7] = tst->arch.vex.guest_r7;
93   sc->sc_regs[8] = tst->arch.vex.guest_r8;
94   sc->sc_regs[9] = tst->arch.vex.guest_r9;
95   sc->sc_regs[10] = tst->arch.vex.guest_r10;
96   sc->sc_regs[11] = tst->arch.vex.guest_r11;
97   sc->sc_regs[12] = tst->arch.vex.guest_r12;
98   sc->sc_regs[13] = tst->arch.vex.guest_r13;
99   sc->sc_regs[14] = tst->arch.vex.guest_r14;
100   sc->sc_regs[15] = tst->arch.vex.guest_r15;
101   sc->sc_regs[16] = tst->arch.vex.guest_r16;
102   sc->sc_regs[17] = tst->arch.vex.guest_r17;
103   sc->sc_regs[18] = tst->arch.vex.guest_r18;
104   sc->sc_regs[19] = tst->arch.vex.guest_r19;
105   sc->sc_regs[20] = tst->arch.vex.guest_r20;
106   sc->sc_regs[21] = tst->arch.vex.guest_r21;
107   sc->sc_regs[22] = tst->arch.vex.guest_r22;
108   sc->sc_regs[23] = tst->arch.vex.guest_r23;
109   sc->sc_regs[24] = tst->arch.vex.guest_r24;
110   sc->sc_regs[25] = tst->arch.vex.guest_r25;
111   sc->sc_regs[26] = tst->arch.vex.guest_r26;
112   sc->sc_regs[27] = tst->arch.vex.guest_r27;
113   sc->sc_regs[28] = tst->arch.vex.guest_r28;
114   sc->sc_regs[29] = tst->arch.vex.guest_r29;
115   sc->sc_regs[30] = tst->arch.vex.guest_r30;
116   sc->sc_regs[31] = tst->arch.vex.guest_r31;
117   sc->sc_pc = tst->arch.vex.guest_PC;
118   sc->sc_mdhi = tst->arch.vex.guest_HI;
119   sc->sc_mdlo = tst->arch.vex.guest_LO;
120 }
121 
122 /* EXPORTED */
VG_(sigframe_create)123 void VG_(sigframe_create)( ThreadId tid,
124                            Bool on_altstack,
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);
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);
151   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
152     return;
153 
154   vg_assert(VG_IS_8_ALIGNED(sp));
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 */
VG_(sigframe_destroy)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 %u): 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 /*--------------------------------------------------------------------*/
353