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
51struct vg_sig_private
52{
53  UInt magicPI;
54  UInt sigNo_private;
55  VexGuestMIPS32State vex_shadow1;
56  VexGuestMIPS32State vex_shadow2;
57};
58
59struct 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
68struct 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*/
81static 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
118static
119void 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 */
163void 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 */
312void 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