• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames.                       ---*/
4 /*---                                  sigframe-mips64-linux.c     ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright (C) 2010-2013 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_mips64_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    UInt magicPI;
53    UInt sigNo_private;
54    VexGuestMIPS64State vex_shadow1;
55    VexGuestMIPS64State vex_shadow2;
56 };
57 
58 struct sigframe {
59    UInt sf_ass[4];  /* argument save space for o32 */
60    UInt sf_pad[2];  /* Was: signal trampoline */
61    struct vki_sigcontext sf_sc;
62    vki_sigset_t sf_mask;
63    struct vg_sig_private priv;
64 };
65 
66 struct rt_sigframe {
67    UInt rs_ass[4];  /* argument save space for o32 */
68    UInt rs_pad[2];  /* Was: signal trampoline */
69    vki_siginfo_t rs_info;
70    struct vki_ucontext rs_uc;
71    struct vg_sig_private priv;
72 };
73 
74 /* Extend the stack segment downwards if needed so as to ensure the new signal
75    frames are mapped to something. Return a Bool indicating whether or not the
76    operation was successful.
77 */
extend(ThreadState * tst,Addr addr,SizeT size)78 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
79 {
80    ThreadId tid = tst->tid;
81    NSegment const* stackseg = NULL;
82 
83    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
84       stackseg = VG_(am_find_nsegment)(addr);
85    }
86 
87    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
88       VG_(message)(Vg_UserMsg,
89          "Can't extend stack to %#lx during signal delivery for thread %d:\n",
90          addr, tid);
91       if (stackseg == NULL)
92          VG_(message)(Vg_UserMsg, " no stack segment\n");
93       else
94          VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
95 
96       /* set SIGSEGV to default handler */
97       VG_(set_default_handler)(VKI_SIGSEGV);
98       VG_(synth_fault_mapping)(tid, addr);
99 
100       /* The whole process should be about to die, since the default
101          action of SIGSEGV to kill the whole process. */
102       return False;
103    }
104 
105    /* For tracking memory events, indicate the entire frame has been
106       allocated. */
107    VG_TRACK(new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
108             size + VG_STACK_REDZONE_SZB, tid);
109 
110    return True;
111 }
112 
setup_sigcontext(ThreadState * tst,struct vki_sigcontext ** sc1,const vki_siginfo_t * si)113 static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1,
114                                const vki_siginfo_t *si)
115 {
116    struct vki_sigcontext *sc = *sc1;
117 
118    VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
119             (Addr)sc, sizeof(unsigned long long)*34);
120    sc->sc_regs[1] = tst->arch.vex.guest_r1;
121    sc->sc_regs[2] = tst->arch.vex.guest_r2;
122    sc->sc_regs[3] = tst->arch.vex.guest_r3;
123    sc->sc_regs[4] = tst->arch.vex.guest_r4;
124    sc->sc_regs[5] = tst->arch.vex.guest_r5;
125    sc->sc_regs[6] = tst->arch.vex.guest_r6;
126    sc->sc_regs[7] = tst->arch.vex.guest_r7;
127    sc->sc_regs[8] = tst->arch.vex.guest_r8;
128    sc->sc_regs[9] = tst->arch.vex.guest_r9;
129    sc->sc_regs[10] = tst->arch.vex.guest_r10;
130    sc->sc_regs[11] = tst->arch.vex.guest_r11;
131    sc->sc_regs[12] = tst->arch.vex.guest_r12;
132    sc->sc_regs[13] = tst->arch.vex.guest_r13;
133    sc->sc_regs[14] = tst->arch.vex.guest_r14;
134    sc->sc_regs[15] = tst->arch.vex.guest_r15;
135    sc->sc_regs[16] = tst->arch.vex.guest_r16;
136    sc->sc_regs[17] = tst->arch.vex.guest_r17;
137    sc->sc_regs[18] = tst->arch.vex.guest_r18;
138    sc->sc_regs[19] = tst->arch.vex.guest_r19;
139    sc->sc_regs[20] = tst->arch.vex.guest_r20;
140    sc->sc_regs[21] = tst->arch.vex.guest_r21;
141    sc->sc_regs[22] = tst->arch.vex.guest_r22;
142    sc->sc_regs[23] = tst->arch.vex.guest_r23;
143    sc->sc_regs[24] = tst->arch.vex.guest_r24;
144    sc->sc_regs[25] = tst->arch.vex.guest_r25;
145    sc->sc_regs[26] = tst->arch.vex.guest_r26;
146    sc->sc_regs[27] = tst->arch.vex.guest_r27;
147    sc->sc_regs[28] = tst->arch.vex.guest_r28;
148    sc->sc_regs[29] = tst->arch.vex.guest_r29;
149    sc->sc_regs[30] = tst->arch.vex.guest_r30;
150    sc->sc_regs[31] = tst->arch.vex.guest_r31;
151    sc->sc_pc = tst->arch.vex.guest_PC;
152    sc->sc_mdhi = tst->arch.vex.guest_HI;
153    sc->sc_mdlo = tst->arch.vex.guest_LO;
154 }
155 
156 /* EXPORTED */
VG_(sigframe_create)157 void VG_(sigframe_create) ( ThreadId tid,
158                             Addr sp_top_of_frame,
159                             const vki_siginfo_t *siginfo,
160                             const struct vki_ucontext *siguc,
161                             void *handler,
162                             UInt flags,
163                             const vki_sigset_t *mask,
164                             void *restorer )
165 {
166    Addr sp;
167    ThreadState* tst = VG_(get_ThreadState)(tid);
168    Int sigNo = siginfo->si_signo;
169    struct vg_sig_private *priv;
170    /* Stack must be 16-byte aligned */
171    sp_top_of_frame &= ~0xf;
172 
173    sp = sp_top_of_frame - sizeof(struct rt_sigframe);
174 
175    tst = VG_(get_ThreadState)(tid);
176    if (!extend(tst, sp, sp_top_of_frame - sp))
177       return;
178 
179    sp = VG_ROUNDDN(sp, 16);
180 
181    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
182    struct vki_ucontext *ucp = &frame->rs_uc;
183    if (VG_(clo_trace_signals))
184       VG_(printf)("rt_sigframe\n");
185    /* Create siginfo. */
186    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
187             (Addr)&frame->rs_info, sizeof(frame->rs_info));
188 
189    VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
190 
191    VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
192             (Addr)&frame->rs_info, sizeof(frame->rs_info));
193 
194    /* Create the ucontext. */
195    VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
196             (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext));
197 
198    ucp->uc_flags = 0;
199    ucp->uc_link = 0;
200    ucp->uc_stack = tst->altstack;
201 
202    VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
203             offsetof(struct vki_ucontext, uc_mcontext));
204 
205    struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
206    setup_sigcontext(tst, &(scp), siginfo);
207    ucp->uc_sigmask = tst->sig_mask;
208    priv = &frame->priv;
209 
210    /* Arguments to signal handler:
211 
212       a0 = signal number
213       a1 = 0 (should be cause)
214       a2 = pointer to ucontext
215 
216       $25 and c0_epc point to the signal handler, $29 points to
217       the struct rt_sigframe. */
218 
219    tst->arch.vex.guest_r4 = siginfo->si_signo;
220    tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
221    tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
222    tst->arch.vex.guest_r29 = (Addr) frame;
223    tst->arch.vex.guest_r25 = (Addr) handler;
224 
225    if (flags & VKI_SA_RESTORER)
226       tst->arch.vex.guest_r31 = (Addr) restorer;
227    else
228       tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
229 
230    priv->magicPI       = 0x31415927;
231    priv->sigNo_private = sigNo;
232    priv->vex_shadow1   = tst->arch.vex_shadow1;
233    priv->vex_shadow2   = tst->arch.vex_shadow2;
234    /* Set the thread so it will next run the handler. */
235    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
236    if (VG_(clo_trace_signals))
237       VG_(printf)("handler = %p\n", handler);
238    tst->arch.vex.guest_PC = (Addr) handler;
239    /* This thread needs to be marked runnable, but we leave that
240       the caller to do. */
241 }
242 
243 /* EXPORTED */
VG_(sigframe_destroy)244 void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT )
245 {
246    ThreadState *tst;
247    struct vg_sig_private *priv1;
248    Addr sp;
249    UInt frame_size;
250    struct vki_sigcontext *mc;
251    Int sigNo;
252 
253    vg_assert(VG_(is_valid_tid)(tid));
254    tst = VG_(get_ThreadState)(tid);
255    sp   = tst->arch.vex.guest_r29;
256    struct rt_sigframe *frame = (struct rt_sigframe *)sp;
257    struct vki_ucontext *ucp = &frame->rs_uc;
258    frame_size = sizeof(*frame);
259    mc = &ucp->uc_mcontext;
260    tst->sig_mask = ucp->uc_sigmask;
261    tst->tmp_sig_mask = ucp->uc_sigmask;
262    priv1 = &frame->priv;
263    sigNo = priv1->sigNo_private;
264    vg_assert(priv1->magicPI == 0x31415927);
265    /* restore regs */
266    tst->arch.vex.guest_r1 = mc->sc_regs[1];
267    tst->arch.vex.guest_r2 = mc->sc_regs[2];
268    tst->arch.vex.guest_r3 = mc->sc_regs[3];
269    tst->arch.vex.guest_r4 = mc->sc_regs[4];
270    tst->arch.vex.guest_r5 = mc->sc_regs[5];
271    tst->arch.vex.guest_r6 = mc->sc_regs[6];
272    tst->arch.vex.guest_r7 = mc->sc_regs[7];
273    tst->arch.vex.guest_r8 = mc->sc_regs[8];
274    tst->arch.vex.guest_r9 = mc->sc_regs[9];
275    tst->arch.vex.guest_r10 = mc->sc_regs[10];
276    tst->arch.vex.guest_r11 = mc->sc_regs[11];
277    tst->arch.vex.guest_r12 = mc->sc_regs[12];
278    tst->arch.vex.guest_r13= mc->sc_regs[13];
279    tst->arch.vex.guest_r14 = mc->sc_regs[14];
280    tst->arch.vex.guest_r15 = mc->sc_regs[15];
281    tst->arch.vex.guest_r16 = mc->sc_regs[16];
282    tst->arch.vex.guest_r17 = mc->sc_regs[17];
283    tst->arch.vex.guest_r18 = mc->sc_regs[18];
284    tst->arch.vex.guest_r19 = mc->sc_regs[19];
285    tst->arch.vex.guest_r20 = mc->sc_regs[20];
286    tst->arch.vex.guest_r21 = mc->sc_regs[21];
287    tst->arch.vex.guest_r22 = mc->sc_regs[22];
288    tst->arch.vex.guest_r23 = mc->sc_regs[23];
289    tst->arch.vex.guest_r24 = mc->sc_regs[24];
290    tst->arch.vex.guest_r25 = mc->sc_regs[25];
291    tst->arch.vex.guest_r26 = mc->sc_regs[26];
292    tst->arch.vex.guest_r27 = mc->sc_regs[27];
293    tst->arch.vex.guest_r28 = mc->sc_regs[28];
294    tst->arch.vex.guest_r30 = mc->sc_regs[30];
295    tst->arch.vex.guest_PC = mc->sc_pc;
296    tst->arch.vex.guest_r31 = mc->sc_regs[31];
297    tst->arch.vex.guest_r29 = mc->sc_regs[29];
298 
299    tst->arch.vex.guest_HI = mc->sc_mdhi;
300    tst->arch.vex.guest_LO = mc->sc_mdlo;
301    tst->arch.vex_shadow1 = priv1->vex_shadow1;
302    tst->arch.vex_shadow2 = priv1->vex_shadow2;
303 
304    VG_TRACK(die_mem_stack_signal, sp, frame_size);
305    if (VG_(clo_trace_signals))
306       VG_(message)(Vg_DebugMsg,
307          "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n",
308          tid, isRT, tst->arch.vex.guest_PC);
309    /* tell the tools */
310    VG_TRACK( post_deliver_signal, tid, sigNo );
311 }
312 
313 #endif /* defined(VGP_mips64_linux) */
314 
315 /*--------------------------------------------------------------------*/
316 /*--- end                                  sigframe-mips64-linux.c ---*/
317 /*--------------------------------------------------------------------*/
318