2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-x86-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_x86_freebsd)
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" /* find_segment */
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 */
50 /* This module creates and removes signal frames for signal deliveries
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 VexGuestX86State vex_shadow1
;
82 VexGuestX86State vex_shadow2
;
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 */
101 * The following 7 members are roughly the same as
102 * 'struct sigframe' in x86/sigframe.h
105 Addr psigInfo
; /* code or pointer to sigContext */
106 Addr puContext
; /* points to uContext */
107 Addr addr
; /* "secret" 4th argument */
108 Addr phandler
; /* "action" or "handler" */
110 /* pointed to by puContext */
111 struct vki_ucontext uContext
;
113 vki_siginfo_t sigInfo
;
115 struct _vki_fpstate fpstate
;
117 struct vg_sigframe vg
;
121 /*------------------------------------------------------------*/
122 /*--- Creating signal frames ---*/
123 /*------------------------------------------------------------*/
125 /* Create a plausible-looking sigcontext from the thread's
129 void synth_ucontext(ThreadId tid
, const vki_siginfo_t
*si
,
130 UWord trapno
, UWord err
, const vki_sigset_t
*set
,
131 struct vki_ucontext
*uc
, struct _vki_fpstate
*fpstate
)
133 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
134 struct vki_mcontext
*sc
= &uc
->uc_mcontext
;
136 VG_(memset
)(uc
, 0, sizeof(*uc
));
140 uc
->uc_sigmask
= *set
;
141 uc
->uc_stack
= tst
->altstack
;
142 VG_(memcpy
)(&sc
->fpstate
, fpstate
, sizeof(*fpstate
));
144 # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG
161 sc
->eflags
= LibVEX_GuestX86_get_eflags(&tst
->arch
.vex
);
165 // sc->addr = (UWord)si->si_addr;
166 sc
->fpformat
= VKI_FPFMT_NODEV
;
167 sc
->len
= sizeof(*sc
);
168 sc
->ownedfp
= VKI_FPOWNED_NONE
;
171 // sc->cr2 = (UInt)si->_sifields._sigfault._addr;
175 /* Extend the stack segment downwards if needed so as to ensure the
176 new signal frames are mapped to something. Return a Bool
177 indicating whether or not the operation was successful.
179 static Bool
extend ( ThreadState
*tst
, Addr addr
, SizeT size
)
181 ThreadId tid
= tst
->tid
;
182 NSegment
const* stackseg
= NULL
;
184 if (VG_(extend_stack
)(tid
, addr
)) {
185 stackseg
= VG_(am_find_nsegment
)(addr
);
187 VG_(printf
)("frame=%#lx seg=%#lx-%#lx\n",
188 addr
, stackseg
->start
, stackseg
->end
);
191 if (stackseg
== NULL
|| !stackseg
->hasR
|| !stackseg
->hasW
) {
194 "Can't extend stack to %#lx during signal delivery for thread %u:\n",
196 if (stackseg
== NULL
)
197 VG_(message
)(Vg_UserMsg
, " no stack segment\n");
199 VG_(message
)(Vg_UserMsg
, " too small or bad protection modes\n");
201 /* set SIGSEGV to default handler */
202 VG_(set_default_handler
)(VKI_SIGSEGV
);
203 VG_(synth_fault_mapping
)(tid
, addr
);
205 /* The whole process should be about to die, since the default
206 action of SIGSEGV to kill the whole process. */
210 /* For tracking memory events, indicate the entire frame has been
212 VG_TRACK( new_mem_stack_signal
, addr
- VG_STACK_REDZONE_SZB
,
213 size
+ VG_STACK_REDZONE_SZB
, tid
);
219 /* Build the Valgrind-specific part of a signal frame. */
221 static void build_vg_sigframe(struct vg_sigframe
*frame
,
223 const vki_sigset_t
*mask
,
227 frame
->sigNo_private
= sigNo
;
228 frame
->magicPI
= 0x31415927;
229 frame
->vex_shadow1
= tst
->arch
.vex_shadow1
;
230 frame
->vex_shadow2
= tst
->arch
.vex_shadow2
;
232 frame
->vex
= tst
->arch
.vex
;
234 frame
->mask
= tst
->sig_mask
;
235 frame
->handlerflags
= flags
;
236 frame
->magicE
= 0x27182818;
240 * According to the comments in lib/libc/i386/gen/signalcontext.c
241 * the stack sould look like this [where n = 4 = sizeof(int)]
243 * 2n+sizeof(struct sigframe) ucp
248 * Note that the 'struct sigframe' above is the one defined in FreeBSD.
249 * 5 word members + ucontext + siginfo
251 * 'struct sigframe' below is the one defined in this file:
254 * FreeBSD struct sigfame
259 static Addr
build_sigframe(ThreadState
*tst
,
260 Addr esp_top_of_frame
,
261 const vki_siginfo_t
*siginfo
,
262 const struct vki_ucontext
*siguc
,
263 void *handler
, UInt flags
,
264 const vki_sigset_t
*mask
,
267 struct sigframe
*frame
;
268 Addr esp
= esp_top_of_frame
;
269 Int sigNo
= siginfo
->si_signo
;
273 #if defined(__clang__)
275 esp
= VG_ROUNDDN(esp
, 16);
276 esp
-= sizeof(*frame
) + 4;
278 esp
-= sizeof(*frame
);
279 esp
= VG_ROUNDDN(esp
, 16);
282 frame
= (struct sigframe
*)esp
;
284 if (!extend(tst
, esp
, sizeof(*frame
)))
285 return esp_top_of_frame
;
287 /* retaddr, siginfo, uContext fields are to be written */
288 VG_TRACK( pre_mem_write
, Vg_CoreSignal
, tst
->tid
, "signal handler frame",
289 esp
, offsetof(struct sigframe
, vg
) );
291 frame
->sigNo
= sigNo
;
292 frame
->retaddr
= (Addr
)&VG_(x86_freebsd_SUBST_FOR_sigreturn
);
293 if ((flags
& VKI_SA_SIGINFO
) == 0)
294 frame
->psigInfo
= (Addr
)siginfo
->si_code
;
296 frame
->psigInfo
= (Addr
)&frame
->sigInfo
;
297 VG_(memcpy
)(&frame
->sigInfo
, siginfo
, sizeof(vki_siginfo_t
));
300 trapno
= siguc
->uc_mcontext
.trapno
;
301 err
= siguc
->uc_mcontext
.err
;
307 frame
->puContext
= (Addr
)&frame
->uContext
;
309 synth_ucontext(tst
->tid
, siginfo
, trapno
, err
, mask
,
310 &frame
->uContext
, &frame
->fpstate
);
312 if (sigNo
== VKI_SIGILL
&& siginfo
->si_code
> 0)
313 frame
->sigInfo
.si_addr
= (void*)tst
->arch
.vex
.guest_EIP
;
315 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
316 esp
, offsetof(struct sigframe
, vg
) );
318 build_vg_sigframe(&frame
->vg
, tst
, mask
, flags
, sigNo
);
324 void VG_(sigframe_create
)( ThreadId tid
,
326 Addr esp_top_of_frame
,
327 const vki_siginfo_t
*siginfo
,
328 const struct vki_ucontext
*siguc
,
331 const vki_sigset_t
*mask
,
335 struct sigframe
*frame
;
336 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
338 esp
= build_sigframe(tst
, esp_top_of_frame
, siginfo
, siguc
, handler
,
339 flags
, mask
, restorer
);
340 frame
= (struct sigframe
*)esp
;
342 /* Set the thread so it will next run the handler. */
343 /* tst->m_esp = esp; also notify the tool we've updated ESP */
344 VG_(set_SP
)(tid
, esp
);
345 VG_TRACK( post_reg_write
, Vg_CoreSignal
, tid
, VG_O_STACK_PTR
, sizeof(Addr
));
347 tst
->arch
.vex
.guest_EIP
= (Addr
) handler
;
348 tst
->arch
.vex
.guest_EDI
= (ULong
) siginfo
->si_signo
;
349 tst
->arch
.vex
.guest_ESI
= (Addr
) &frame
->sigInfo
;
350 tst
->arch
.vex
.guest_EDX
= (Addr
) &frame
->uContext
;
351 /* This thread needs to be marked runnable, but we leave that the
355 VG_(printf
)("pushed signal frame; %%ESP now = %#lx, "
356 "next %%EIP = %#x, status=%u\n",
357 esp
, tst
->arch
.vex
.guest_EIP
, tst
->status
);
361 /*------------------------------------------------------------*/
362 /*--- Destroying signal frames ---*/
363 /*------------------------------------------------------------*/
365 /* Return False and don't do anything, just set the client to take a
366 segfault, if it looks like the frame is corrupted. */
368 Bool
restore_vg_sigframe ( ThreadState
*tst
,
369 struct vg_sigframe
*frame
, Int
*sigNo
)
371 if (frame
->magicPI
!= 0x31415927 ||
372 frame
->magicE
!= 0x27182818) {
373 VG_(message
)(Vg_UserMsg
, "Thread %u return signal frame "
374 "corrupted. Killing process.", tst
->tid
);
375 VG_(set_default_handler
)(VKI_SIGSEGV
);
376 VG_(synth_fault
)(tst
->tid
);
377 *sigNo
= VKI_SIGSEGV
;
380 tst
->sig_mask
= frame
->mask
;
381 tst
->tmp_sig_mask
= frame
->mask
;
382 tst
->arch
.vex_shadow1
= frame
->vex_shadow1
;
383 tst
->arch
.vex_shadow2
= frame
->vex_shadow2
;
385 tst
->arch
.vex
= frame
->vex
;
387 *sigNo
= frame
->sigNo_private
;
392 void restore_sigcontext( ThreadState
*tst
,
393 struct vki_mcontext
*sc
,
394 struct _vki_fpstate
*fpstate
)
396 tst
->arch
.vex
.guest_EAX
= sc
->eax
;
397 tst
->arch
.vex
.guest_ECX
= sc
->ecx
;
398 tst
->arch
.vex
.guest_EDX
= sc
->edx
;
399 tst
->arch
.vex
.guest_EBX
= sc
->ebx
;
400 tst
->arch
.vex
.guest_EBP
= sc
->ebp
;
401 tst
->arch
.vex
.guest_ESP
= sc
->esp
;
402 tst
->arch
.vex
.guest_ESI
= sc
->esi
;
403 tst
->arch
.vex
.guest_EDI
= sc
->edi
;
404 //:: tst->arch.vex.guest_eflags = sc->eflags;
405 tst
->arch
.vex
.guest_EIP
= sc
->eip
;
406 tst
->arch
.vex
.guest_CS
= sc
->cs
;
407 tst
->arch
.vex
.guest_SS
= sc
->ss
;
408 tst
->arch
.vex
.guest_DS
= sc
->ds
;
409 tst
->arch
.vex
.guest_ES
= sc
->es
;
410 tst
->arch
.vex
.guest_FS
= sc
->fs
;
411 tst
->arch
.vex
.guest_GS
= sc
->gs
;
412 VG_(memcpy
)(fpstate
, &sc
->fpstate
, sizeof(*fpstate
));
417 SizeT
restore_sigframe ( ThreadState
*tst
,
418 struct sigframe
*frame
, Int
*sigNo
)
420 if (restore_vg_sigframe(tst
, &frame
->vg
, sigNo
))
421 restore_sigcontext(tst
, &frame
->uContext
.uc_mcontext
, &frame
->fpstate
);
423 return sizeof(*frame
);
427 void VG_(sigframe_destroy
)( ThreadId tid
)
434 tst
= VG_(get_ThreadState
)(tid
);
436 /* Correctly reestablish the frame base address. */
437 esp
= tst
->arch
.vex
.guest_ESP
;
438 esp
+= 8; /* Clean up stack from argument/ret passed to sigreturn(2) */
440 size
= restore_sigframe(tst
, (struct sigframe
*)esp
, &sigNo
);
442 VG_TRACK( die_mem_stack_signal
, esp
- VG_STACK_REDZONE_SZB
,
443 size
+ VG_STACK_REDZONE_SZB
);
445 if (VG_(clo_trace_signals
))
448 "VG_(sigframe_destroy) (thread %u): EIP=%#x\n",
449 tid
, tst
->arch
.vex
.guest_EIP
);
452 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
455 #endif // defined(VGP_x86_freebsd)
457 /*--------------------------------------------------------------------*/
459 /*--------------------------------------------------------------------*/