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-2015 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
50struct vg_sig_private
51{
52  UInt magicPI;
53  UInt sigNo_private;
54  VexGuestMIPS32State vex_shadow1;
55  VexGuestMIPS32State vex_shadow2;
56};
57
58struct 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
67struct 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
77static
78void 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 */
123void 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 */
266void 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