Bug499183 - FreeBSD: differences in avx-vmovq output
[valgrind.git] / coregrind / m_sigframe / sigframe-amd64-freebsd.c
blob1377c2baebe07b588057300bafaf31d7253f4713
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-amd64-freebsd.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2009 Nicholas Nethercote
12 njn@valgrind.org
13 Copyright (C) 2018-2021 Paul Floyd
14 pjfloyd@wanadoo.fr
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, see <http://www.gnu.org/licenses/>.
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGP_amd64_freebsd)
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_machine.h"
42 #include "pub_core_options.h"
43 #include "pub_core_signals.h"
44 #include "pub_core_tooliface.h"
45 #include "pub_core_trampoline.h"
46 #include "pub_core_sigframe.h" /* self */
48 /* This module creates and removes signal frames for signal deliveries
49 on amd64-freebsd.
52 const UInt MAGIC_PI = 0x31415927U;
53 const UInt MAGIC_E = 0x27182818U;
55 /*------------------------------------------------------------*/
56 /*--- Signal frame layouts ---*/
57 /*------------------------------------------------------------*/
59 // A structure in which to save the application's registers
60 // during the execution of signal handlers.
62 // In theory, so long as we get the arguments to the handler function
63 // right, it doesn't matter what the exact layout of the rest of the
64 // frame is. Unfortunately, things like gcc's exception unwinding
65 // make assumptions about the locations of various parts of the frame,
66 // so we need to duplicate it exactly.
68 /* Valgrind-specific parts of the signal frame */
69 struct vg_sigframe {
70 /* Sanity check word. */
71 UInt magicPI;
73 UInt handlerflags; /* flags for signal handler */
76 /* Safely-saved version of sigNo, as described above. */
77 Int sigNo_private;
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;
84 /* HACK ALERT */
85 VexGuestAMD64State vex;
86 /* end HACK ALERT */
88 /* saved signal mask to be restored when handler returns */
89 vki_sigset_t mask;
91 /* Sanity check word. Is the highest-addressed word; do not
92 move!*/
93 UInt magicE;
96 struct sigframe {
97 /* Sig handler's return address */
98 Addr retaddr;
100 Addr phandler; /* "action" or "handler" */
102 /* pointed to by puContext */
103 struct vki_ucontext uContext;
105 vki_siginfo_t sigInfo;
107 struct _vki_fpstate fpstate;
109 struct vg_sigframe vg;
112 /*------------------------------------------------------------*/
113 /*--- Creating signal frames ---*/
114 /*------------------------------------------------------------*/
116 /* Create a plausible-looking sigcontext from the thread's
117 Vex guest state.
119 static
120 void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
121 UWord trapno, UWord err, const vki_sigset_t *set,
122 struct vki_ucontext *ucp, struct _vki_fpstate *fpstate)
124 ThreadState *tst = VG_(get_ThreadState)(tid);
125 struct vki_mcontext *sc = &ucp->uc_mcontext;
127 VG_(memset)(ucp, 0, sizeof(*ucp));
129 ucp->uc_flags = 0;
130 ucp->uc_link = 0;
131 ucp->uc_sigmask = *set;
132 ucp->uc_stack = tst->altstack;
133 VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
135 # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG
136 SC2(r8,R8);
137 SC2(r9,R9);
138 SC2(r10,R10);
139 SC2(r11,R11);
140 SC2(r12,R12);
141 SC2(r13,R13);
142 SC2(r14,R14);
143 SC2(r15,R15);
144 SC2(rdi,RDI);
145 SC2(rsi,RSI);
146 SC2(rbp,RBP);
147 SC2(rbx,RBX);
148 SC2(rdx,RDX);
149 SC2(rax,RAX);
150 SC2(rcx,RCX);
151 SC2(rsp,RSP);
153 SC2(cs,CS);
154 SC2(gs,SS);
157 SC2(rip,RIP);
158 sc->addr = (vki_register_t)si->si_addr;
159 sc->err = (vki_register_t)err;
160 sc->fpformat = VKI_FPFMT_NODEV;
161 sc->ownedfp = VKI_FPOWNED_NONE;
162 sc->len = sizeof(*sc);
163 sc->rflags = (vki_register_t)LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
164 sc->trapno = trapno;
165 # undef SC2
169 /* Extend the stack segment downwards if needed so as to ensure the
170 new signal frames are mapped to something. Return a Bool
171 indicating whether or not the operation was successful.
173 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
175 ThreadId tid = tst->tid;
176 NSegment const* stackseg = NULL;
178 if (VG_(extend_stack)(tid, addr)) {
179 stackseg = VG_(am_find_nsegment)(addr);
180 if (0 && stackseg) {
181 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
182 addr, stackseg->start, stackseg->end);
186 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
187 VG_(message)(
188 Vg_UserMsg,
189 "Can't extend stack to %#lx during signal delivery for thread %u:\n",
190 addr, tid);
191 if (stackseg == NULL) {
192 VG_(message)(Vg_UserMsg, " no stack segment\n");
193 } else {
194 VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
197 /* set SIGSEGV to default handler */
198 VG_(set_default_handler)(VKI_SIGSEGV);
199 VG_(synth_fault_mapping)(tid, addr);
201 /* The whole process should be about to die, since the default
202 action of SIGSEGV to kill the whole process. */
203 return False;
206 /* For tracking memory events, indicate the entire frame has been
207 allocated. */
208 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
209 size + VG_STACK_REDZONE_SZB, tid );
211 return True;
215 /* Build the Valgrind-specific part of a signal frame. */
217 static void build_vg_sigframe(struct vg_sigframe *frame,
218 ThreadState *tst,
219 const vki_sigset_t *mask,
220 UInt flags,
221 Int sigNo)
223 frame->sigNo_private = sigNo;
224 frame->magicPI = MAGIC_PI;
225 frame->vex_shadow1 = tst->arch.vex_shadow1;
226 frame->vex_shadow2 = tst->arch.vex_shadow2;
227 /* HACK ALERT */
228 frame->vex = tst->arch.vex;
229 /* end HACK ALERT */
230 frame->mask = tst->sig_mask;
231 frame->handlerflags = flags;
232 frame->magicE = MAGIC_E;
235 static Addr build_sigframe(ThreadState *tst,
236 Addr rsp_top_of_frame,
237 const vki_siginfo_t *siginfo,
238 const struct vki_ucontext *siguc,
239 void *handler, UInt flags,
240 const vki_sigset_t *mask,
241 void *restorer)
243 struct sigframe *frame;
244 Addr rsp = rsp_top_of_frame;
245 Int sigNo = siginfo->si_signo;
246 UWord trapno;
247 UWord err;
249 rsp -= sizeof(*frame);
250 rsp = VG_ROUNDDN(rsp, 16) - 8;
251 frame = (struct sigframe *)rsp;
253 if (!extend(tst, rsp, sizeof(*frame))) {
254 return rsp_top_of_frame;
257 /* retaddr, siginfo, uContext fields are to be written */
258 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
259 rsp, offsetof(struct sigframe, vg) );
261 frame->retaddr = (Addr)VG_(amd64_freebsd_SUBST_FOR_sigreturn);
263 if (siguc) {
264 trapno = siguc->uc_mcontext.trapno;
265 err = siguc->uc_mcontext.err;
266 } else {
267 trapno = 0;
268 err = 0;
271 VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
273 if (sigNo == VKI_SIGILL && siginfo->si_code > 0) {
274 frame->sigInfo.si_addr = (void*)tst->arch.vex.guest_RIP;
277 synth_ucontext(tst->tid, siginfo, trapno, err, mask,
278 &frame->uContext, &frame->fpstate);
280 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
281 rsp, offsetof(struct sigframe, vg) );
283 build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo);
285 return rsp;
289 void VG_(sigframe_create)( ThreadId tid,
290 Bool on_altstack,
291 Addr rsp_top_of_frame,
292 const vki_siginfo_t *siginfo,
293 const struct vki_ucontext *siguc,
294 void *handler,
295 UInt flags,
296 const vki_sigset_t *mask,
297 void *restorer )
299 Addr rsp;
300 struct sigframe *frame;
301 ThreadState* tst = VG_(get_ThreadState)(tid);
303 rsp = build_sigframe(tst, rsp_top_of_frame, siginfo, siguc, handler,
304 flags, mask, restorer);
305 frame = (struct sigframe *)rsp;
307 /* Set the thread so it will next run the handler. */
308 /* tst->m_rsp = rsp; also notify the tool we've updated RSP */
309 VG_(set_SP)(tid, rsp);
310 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
312 //VG_(printf)("handler = %p\n", handler);
313 tst->arch.vex.guest_RIP = (Addr) handler;
314 tst->arch.vex.guest_RDI = (ULong) siginfo->si_signo;
315 tst->arch.vex.guest_RSI = (Addr) &frame->sigInfo;
316 tst->arch.vex.guest_RDX = (Addr) &frame->uContext;
317 /* And tell the tool that these registers have been written. */
318 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,
319 offsetof(VexGuestAMD64State,guest_RIP), sizeof(UWord) );
320 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,
321 offsetof(VexGuestAMD64State,guest_RDI), sizeof(UWord) );
322 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,
323 offsetof(VexGuestAMD64State,guest_RSI), sizeof(UWord) );
324 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid,
325 offsetof(VexGuestAMD64State,guest_RDX), sizeof(UWord) );
327 /* This thread needs to be marked runnable, but we leave that the
328 caller to do. */
332 /*------------------------------------------------------------*/
333 /*--- Destroying signal frames ---*/
334 /*------------------------------------------------------------*/
336 /* Return False and don't do anything, just set the client to take a
337 segfault, if it looks like the frame is corrupted. */
338 static
339 Bool restore_vg_sigframe ( ThreadState *tst,
340 struct vg_sigframe *frame, Int *sigNo )
342 if (frame->magicPI != MAGIC_PI ||
343 frame->magicE != MAGIC_E) {
344 VG_(message)(Vg_UserMsg, "Thread %u return signal frame "
345 "corrupted. Killing process.\n",
346 tst->tid);
347 VG_(set_default_handler)(VKI_SIGSEGV);
348 VG_(synth_fault)(tst->tid);
349 *sigNo = VKI_SIGSEGV;
350 return False;
352 tst->sig_mask = frame->mask;
353 tst->tmp_sig_mask = frame->mask;
354 tst->arch.vex_shadow1 = frame->vex_shadow1;
355 tst->arch.vex_shadow2 = frame->vex_shadow2;
356 /* HACK ALERT */
357 tst->arch.vex = frame->vex;
358 /* end HACK ALERT */
359 *sigNo = frame->sigNo_private;
360 return True;
363 static
364 void restore_sigcontext( ThreadState *tst,
365 struct vki_mcontext *sc,
366 struct _vki_fpstate *fpstate )
368 tst->arch.vex.guest_RAX = sc->rax;
369 tst->arch.vex.guest_RCX = sc->rcx;
370 tst->arch.vex.guest_RDX = sc->rdx;
371 tst->arch.vex.guest_RBX = sc->rbx;
372 tst->arch.vex.guest_RBP = sc->rbp;
373 tst->arch.vex.guest_RSP = sc->rsp;
374 tst->arch.vex.guest_RSI = sc->rsi;
375 tst->arch.vex.guest_RDI = sc->rdi;
376 tst->arch.vex.guest_R8 = sc->r8;
377 tst->arch.vex.guest_R9 = sc->r9;
378 tst->arch.vex.guest_R10 = sc->r10;
379 tst->arch.vex.guest_R11 = sc->r11;
380 tst->arch.vex.guest_R12 = sc->r12;
381 tst->arch.vex.guest_R13 = sc->r13;
382 tst->arch.vex.guest_R14 = sc->r14;
383 tst->arch.vex.guest_R15 = sc->r15;
385 XXX:
386 tst->arch.vex.guest_rflags = sc->rflags;
388 tst->arch.vex.guest_RIP = sc->rip;
391 tst->arch.vex.guest_CS = sc->cs;
392 tst->arch.vex.guest_SS = sc->ss;
394 VG_(memcpy)(fpstate, &sc->fpstate, sizeof(*fpstate));
397 static
398 SizeT restore_sigframe ( ThreadState *tst,
399 struct sigframe *frame, Int *sigNo )
401 if (restore_vg_sigframe(tst, &frame->vg, sigNo)) {
402 restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
405 return sizeof(*frame);
408 void VG_(sigframe_destroy)( ThreadId tid )
410 Addr rsp;
411 ThreadState* tst;
412 SizeT size;
413 Int sigNo;
415 tst = VG_(get_ThreadState)(tid);
417 /* Correctly reestablish the frame base address. */
418 rsp = tst->arch.vex.guest_RSP;
420 size = restore_sigframe(tst, (struct sigframe *)rsp, &sigNo);
422 VG_TRACK( die_mem_stack_signal, rsp - VG_STACK_REDZONE_SZB,
423 size + VG_STACK_REDZONE_SZB );
425 if (VG_(clo_trace_signals)) {
426 VG_(message)(
427 Vg_DebugMsg,
428 "VG_(sigframe_destroy) (thread %u): valid magic; RIP=%#llx\n",
429 tid, tst->arch.vex.guest_RIP);
432 /* tell the tools */
433 VG_TRACK( post_deliver_signal, tid, sigNo );
436 #endif // defined(VGP_amd64_freebsd)
438 /*--------------------------------------------------------------------*/
439 /*--- end ---*/
440 /*--------------------------------------------------------------------*/