2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-amd64-freebsd.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2009 Nicholas Nethercote
13 Copyright (C) 2018-2021 Paul Floyd
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
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 */
70 /* Sanity check word. */
73 UInt handlerflags
; /* flags for signal handler */
76 /* Safely-saved version of sigNo, as described above. */
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
;
85 VexGuestAMD64State vex
;
88 /* saved signal mask to be restored when handler returns */
91 /* Sanity check word. Is the highest-addressed word; do not
97 /* Sig handler's return address */
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
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
));
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
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
);
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
);
181 VG_(printf
)("frame=%#lx seg=%#lx-%#lx\n",
182 addr
, stackseg
->start
, stackseg
->end
);
186 if (stackseg
== NULL
|| !stackseg
->hasR
|| !stackseg
->hasW
) {
189 "Can't extend stack to %#lx during signal delivery for thread %u:\n",
191 if (stackseg
== NULL
) {
192 VG_(message
)(Vg_UserMsg
, " no stack segment\n");
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. */
206 /* For tracking memory events, indicate the entire frame has been
208 VG_TRACK( new_mem_stack_signal
, addr
- VG_STACK_REDZONE_SZB
,
209 size
+ VG_STACK_REDZONE_SZB
, tid
);
215 /* Build the Valgrind-specific part of a signal frame. */
217 static void build_vg_sigframe(struct vg_sigframe
*frame
,
219 const vki_sigset_t
*mask
,
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
;
228 frame
->vex
= tst
->arch
.vex
;
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
,
243 struct sigframe
*frame
;
244 Addr rsp
= rsp_top_of_frame
;
245 Int sigNo
= siginfo
->si_signo
;
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
);
264 trapno
= siguc
->uc_mcontext
.trapno
;
265 err
= siguc
->uc_mcontext
.err
;
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
);
289 void VG_(sigframe_create
)( ThreadId tid
,
291 Addr rsp_top_of_frame
,
292 const vki_siginfo_t
*siginfo
,
293 const struct vki_ucontext
*siguc
,
296 const vki_sigset_t
*mask
,
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
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. */
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",
347 VG_(set_default_handler
)(VKI_SIGSEGV
);
348 VG_(synth_fault
)(tst
->tid
);
349 *sigNo
= VKI_SIGSEGV
;
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
;
357 tst
->arch
.vex
= frame
->vex
;
359 *sigNo
= frame
->sigNo_private
;
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
;
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
));
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
)
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
)) {
428 "VG_(sigframe_destroy) (thread %u): valid magic; RIP=%#llx\n",
429 tid
, tst
->arch
.vex
.guest_RIP
);
433 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
436 #endif // defined(VGP_amd64_freebsd)
438 /*--------------------------------------------------------------------*/
440 /*--------------------------------------------------------------------*/