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