1
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-amd64-dragonfly.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2000-2009 Nicholas Nethercote
12 njn@valgrind.org
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_amd64_dragonfly)
33
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
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_signals.h"
45 #include "pub_core_tooliface.h"
46 #include "pub_core_trampoline.h"
47 #include "pub_core_sigframe.h" /* self */
48
49 /* This module creates and removes signal frames for signal deliveries
50 on amd64-dragonfly.
51 */
52
53
54 /*------------------------------------------------------------*/
55 /*--- Signal frame layouts ---*/
56 /*------------------------------------------------------------*/
57
58 // A structure in which to save the application's registers
59 // during the execution of signal handlers.
60
61 // In theory, so long as we get the arguments to the handler function
62 // right, it doesn't matter what the exact layout of the rest of the
63 // frame is. Unfortunately, things like gcc's exception unwinding
64 // make assumptions about the locations of various parts of the frame,
65 // so we need to duplicate it exactly.
66
67 /* Valgrind-specific parts of the signal frame */
68 struct vg_sigframe
69 {
70 /* Sanity check word. */
71 UInt magicPI;
72
73 UInt handlerflags; /* flags for signal handler */
74
75
76 /* Safely-saved version of sigNo, as described above. */
77 Int sigNo_private;
78
79 /* XXX This is wrong. Surely we should store the shadow values
80 into the shadow memory behind the actual values? */
81 VexGuestAMD64State vex_shadow1;
82 VexGuestAMD64State vex_shadow2;
83
84 /* HACK ALERT */
85 VexGuestAMD64State vex;
86 /* end HACK ALERT */
87
88 /* saved signal mask to be restored when handler returns */
89 vki_sigset_t mask;
90
91 /* Sanity check word. Is the highest-addressed word; do not
92 move!*/
93 UInt magicE;
94 };
95
96 struct sigframe
97 {
98 /* Sig handler's return address */
99 Addr retaddr;
100
101 Int sigNo;
102 Addr psigInfo; /* code or pointer to sigContext */
103 Addr puContext; /* points to uContext */
104 Addr addr; /* "secret" 4th argument */
105 Addr phandler; /* "action" or "handler" */
106
107 /* pointed to by puContext */
108 struct vki_ucontext uContext;
109
110 vki_siginfo_t sigInfo;
111
112 struct _vki_fpstate fpstate;
113
114 struct vg_sigframe vg;
115 };
116
117 /*------------------------------------------------------------*/
118 /*--- Creating signal frames ---*/
119 /*------------------------------------------------------------*/
120
121 /* Create a plausible-looking sigcontext from the thread's
122 Vex guest state.
123 */
124 static
synth_ucontext(ThreadId tid,const vki_siginfo_t * si,UWord trapno,UWord err,const vki_sigset_t * set,struct vki_ucontext * uc,struct _vki_fpstate * fpstate)125 void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
126 UWord trapno, UWord err, const vki_sigset_t *set,
127 struct vki_ucontext *uc, struct _vki_fpstate *fpstate)
128 {
129 ThreadState *tst = VG_(get_ThreadState)(tid);
130 struct vki_mcontext *sc = &uc->uc_mcontext;
131
132 VG_(memset)(uc, 0, sizeof(*uc));
133
134 uc->uc_flags = 0;
135 uc->uc_link = 0;
136 uc->uc_sigmask = *set;
137 uc->uc_stack = tst->altstack;
138 VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
139
140 # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG
141 SC2(r8,R8);
142 SC2(r9,R9);
143 SC2(r10,R10);
144 SC2(r11,R11);
145 SC2(r12,R12);
146 SC2(r13,R13);
147 SC2(r14,R14);
148 SC2(r15,R15);
149 SC2(rdi,RDI);
150 SC2(rsi,RSI);
151 SC2(rbp,RBP);
152 SC2(rbx,RBX);
153 SC2(rdx,RDX);
154 SC2(rax,RAX);
155 SC2(rcx,RCX);
156 SC2(rsp,RSP);
157 /*
158 SC2(cs,CS);
159 SC2(gs,SS);
160 XXX
161 */
162 SC2(rip,RIP);
163 sc->addr = (UWord)si->si_addr;
164 sc->err = err;
165 sc->fpformat = VKI_FPFMT_NODEV;
166 sc->len = sizeof(*sc);
167 sc->ownedfp = VKI_FPOWNED_NONE;
168 sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
169 sc->trapno = trapno;
170 # undef SC2
171 }
172
173
174 /* Extend the stack segment downwards if needed so as to ensure the
175 new signal frames are mapped to something. Return a Bool
176 indicating whether or not the operation was successful.
177 */
extend(ThreadState * tst,Addr addr,SizeT size)178 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
179 {
180 ThreadId tid = tst->tid;
181 NSegment const* stackseg = NULL;
182
183 if (VG_(extend_stack)(tid, addr)) {
184 stackseg = VG_(am_find_nsegment)(addr);
185 if (0 && stackseg)
186 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
187 addr, stackseg->start, stackseg->end);
188 }
189
190 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
191 VG_(message)(
192 Vg_UserMsg,
193 "Can't extend stack to %#lx during signal delivery for thread %d:\n",
194 addr, tid);
195 if (stackseg == NULL)
196 VG_(message)(Vg_UserMsg, " no stack segment\n");
197 else
198 VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
199
200 /* set SIGSEGV to default handler */
201 VG_(set_default_handler)(VKI_SIGSEGV);
202 VG_(synth_fault_mapping)(tid, addr);
203
204 /* The whole process should be about to die, since the default
205 action of SIGSEGV to kill the whole process. */
206 return False;
207 }
208
209 /* For tracking memory events, indicate the entire frame has been
210 allocated. */
211 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
212 size + VG_STACK_REDZONE_SZB, tid );
213
214 return True;
215 }
216
217
218 /* Build the Valgrind-specific part of a signal frame. */
219
build_vg_sigframe(struct vg_sigframe * frame,ThreadState * tst,const vki_sigset_t * mask,UInt flags,Int sigNo)220 static void build_vg_sigframe(struct vg_sigframe *frame,
221 ThreadState *tst,
222 const vki_sigset_t *mask,
223 UInt flags,
224 Int sigNo)
225 {
226 frame->sigNo_private = sigNo;
227 frame->magicPI = 0x31415927;
228 frame->vex_shadow1 = tst->arch.vex_shadow1;
229 frame->vex_shadow2 = tst->arch.vex_shadow2;
230 /* HACK ALERT */
231 frame->vex = tst->arch.vex;
232 /* end HACK ALERT */
233 frame->mask = tst->sig_mask;
234 frame->handlerflags = flags;
235 frame->magicE = 0x27182818;
236 }
237
build_sigframe(ThreadState * tst,Addr rsp_top_of_frame,const vki_siginfo_t * siginfo,const struct vki_ucontext * siguc,void * handler,UInt flags,const vki_sigset_t * mask,void * restorer)238 static Addr build_sigframe(ThreadState *tst,
239 Addr rsp_top_of_frame,
240 const vki_siginfo_t *siginfo,
241 const struct vki_ucontext *siguc,
242 void *handler, UInt flags,
243 const vki_sigset_t *mask,
244 void *restorer)
245 {
246 struct sigframe *frame;
247 Addr rsp = rsp_top_of_frame;
248 Int sigNo = siginfo->si_signo;
249 UWord trapno;
250 UWord err;
251
252 rsp -= sizeof(*frame);
253 rsp = VG_ROUNDDN(rsp, 16) - 8;
254 frame = (struct sigframe *)rsp;
255
256 if (!extend(tst, rsp, sizeof(*frame)))
257 return rsp_top_of_frame;
258
259 /* retaddr, siginfo, uContext fields are to be written */
260 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
261 rsp, offsetof(struct sigframe, vg) );
262
263 frame->sigNo = sigNo;
264 frame->retaddr = (Addr)&VG_(amd64_dragonfly_SUBST_FOR_sigreturn);
265 if ((flags & VKI_SA_SIGINFO) == 0)
266 frame->psigInfo = (Addr)siginfo->si_code;
267 else
268 frame->psigInfo = (Addr)&frame->sigInfo;
269 VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
270
271 if (siguc != NULL) {
272 trapno = siguc->uc_mcontext.trapno;
273 err = siguc->uc_mcontext.err;
274 } else {
275 trapno = 0;
276 err = 0;
277 }
278
279 synth_ucontext(tst->tid, siginfo, trapno, err, mask,
280 &frame->uContext, &frame->fpstate);
281
282 if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
283 frame->sigInfo.si_addr = (void*)tst->arch.vex.guest_RIP;
284
285 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
286 rsp, offsetof(struct sigframe, vg) );
287
288 build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo);
289
290 return rsp;
291 }
292
293
VG_(sigframe_create)294 void VG_(sigframe_create)( ThreadId tid,
295 Bool on_altstack,
296 Addr rsp_top_of_frame,
297 const vki_siginfo_t *siginfo,
298 const struct vki_ucontext *siguc,
299 void *handler,
300 UInt flags,
301 const vki_sigset_t *mask,
302 void *restorer )
303 {
304 Addr rsp;
305 struct sigframe *frame;
306 ThreadState* tst = VG_(get_ThreadState)(tid);
307
308 rsp = build_sigframe(tst, rsp_top_of_frame, siginfo, siguc, handler,
309 flags, mask, restorer);
310 frame = (struct sigframe *)rsp;
311
312 /* Set the thread so it will next run the handler. */
313 /* tst->m_rsp = rsp; also notify the tool we've updated RSP */
314 VG_(set_SP)(tid, rsp);
315 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
316
317 //VG_(printf)("handler = %p\n", handler);
318 tst->arch.vex.guest_RIP = (Addr) handler;
319 tst->arch.vex.guest_RDI = (ULong) siginfo->si_signo;
320 tst->arch.vex.guest_RSI = (Addr) &frame->sigInfo;
321 tst->arch.vex.guest_RDX = (Addr) &frame->uContext;
322 /* This thread needs to be marked runnable, but we leave that the
323 caller to do. */
324 }
325
326
327 /*------------------------------------------------------------*/
328 /*--- Destroying signal frames ---*/
329 /*------------------------------------------------------------*/
330
331 /* Return False and don't do anything, just set the client to take a
332 segfault, if it looks like the frame is corrupted. */
333 static
restore_vg_sigframe(ThreadState * tst,struct vg_sigframe * frame,Int * sigNo)334 Bool restore_vg_sigframe ( ThreadState *tst,
335 struct vg_sigframe *frame, Int *sigNo )
336 {
337 if (frame->magicPI != 0x31415927 ||
338 frame->magicE != 0x27182818) {
339 VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
340 "corrupted. Killing process.\n",
341 tst->tid);
342 VG_(set_default_handler)(VKI_SIGSEGV);
343 VG_(synth_fault)(tst->tid);
344 *sigNo = VKI_SIGSEGV;
345 return False;
346 }
347 tst->sig_mask = frame->mask;
348 tst->tmp_sig_mask = frame->mask;
349 tst->arch.vex_shadow1 = frame->vex_shadow1;
350 tst->arch.vex_shadow2 = frame->vex_shadow2;
351 /* HACK ALERT */
352 tst->arch.vex = frame->vex;
353 /* end HACK ALERT */
354 *sigNo = frame->sigNo_private;
355 return True;
356 }
357
358 static
restore_sigcontext(ThreadState * tst,struct vki_mcontext * sc,struct _vki_fpstate * fpstate)359 void restore_sigcontext( ThreadState *tst,
360 struct vki_mcontext *sc,
361 struct _vki_fpstate *fpstate )
362 {
363 tst->arch.vex.guest_RAX = sc->rax;
364 tst->arch.vex.guest_RCX = sc->rcx;
365 tst->arch.vex.guest_RDX = sc->rdx;
366 tst->arch.vex.guest_RBX = sc->rbx;
367 tst->arch.vex.guest_RBP = sc->rbp;
368 tst->arch.vex.guest_RSP = sc->rsp;
369 tst->arch.vex.guest_RSI = sc->rsi;
370 tst->arch.vex.guest_RDI = sc->rdi;
371 tst->arch.vex.guest_R8 = sc->r8;
372 tst->arch.vex.guest_R9 = sc->r9;
373 tst->arch.vex.guest_R10 = sc->r10;
374 tst->arch.vex.guest_R11 = sc->r11;
375 tst->arch.vex.guest_R12 = sc->r12;
376 tst->arch.vex.guest_R13 = sc->r13;
377 tst->arch.vex.guest_R14 = sc->r14;
378 tst->arch.vex.guest_R15 = sc->r15;
379 /*
380 XXX:
381 tst->arch.vex.guest_rflags = sc->rflags;
382 */
383 tst->arch.vex.guest_RIP = sc->rip;
384 /*
385 XXX
386 tst->arch.vex.guest_CS = sc->cs;
387 tst->arch.vex.guest_SS = sc->ss;
388 */
389 VG_(memcpy)(fpstate, &sc->fpstate, sizeof(*fpstate));
390 }
391
392 static
restore_sigframe(ThreadState * tst,struct sigframe * frame,Int * sigNo)393 SizeT restore_sigframe ( ThreadState *tst,
394 struct sigframe *frame, Int *sigNo )
395 {
396 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
397 restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
398
399 return sizeof(*frame);
400 }
401
VG_(sigframe_destroy)402 void VG_(sigframe_destroy)( ThreadId tid )
403 {
404 Addr rsp;
405 ThreadState* tst;
406 SizeT size;
407 Int sigNo;
408
409 tst = VG_(get_ThreadState)(tid);
410
411 /* Correctly reestablish the frame base address. */
412 rsp = tst->arch.vex.guest_RSP;
413
414 size = restore_sigframe(tst, (struct sigframe *)rsp, &sigNo);
415
416 VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB,
417 size + VG_STACK_REDZONE_SZB );
418
419 if (VG_(clo_trace_signals))
420 VG_(message)(
421 Vg_DebugMsg,
422 "VG_(signal_return) (thread %d): valid magic; RIP=%#llx\n",
423 tid, tst->arch.vex.guest_RIP);
424
425 /* tell the tools */
426 VG_TRACK( post_deliver_signal, tid, sigNo );
427 }
428
429 #endif // defined(VGP_amd64_dragonfly)
430
431 /*--------------------------------------------------------------------*/
432 /*--- end ---*/
433 /*--------------------------------------------------------------------*/
434