Fix const signedness issue in VG_(show_open_fds)
[valgrind.git] / coregrind / m_sigframe / sigframe-x86-freebsd.c
blobeaa4df264a2181f7da5f1a16176a01fc8c79e3ca
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-x86-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_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
51 on x86-freebsd.
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 VexGuestX86State vex_shadow1;
82 VexGuestX86State vex_shadow2;
84 /* HACK ALERT */
85 VexGuestX86State 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;
101 * The following 7 members are roughly the same as
102 * 'struct sigframe' in x86/sigframe.h
104 Int sigNo;
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
126 Vex guest state.
128 static
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));
138 uc->uc_flags = 0;
139 uc->uc_link = 0;
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
145 SC2(gs,GS);
146 SC2(fs,FS);
147 SC2(es,ES);
148 SC2(ds,DS);
150 SC2(edi,EDI);
151 SC2(esi,ESI);
152 SC2(ebp,EBP);
153 SC2(esp,ESP);
154 SC2(ebx,EBX);
155 SC2(edx,EDX);
156 SC2(ecx,ECX);
157 SC2(eax,EAX);
159 SC2(eip,EIP);
160 SC2(cs,CS);
161 sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
162 SC2(ss,SS);
163 sc->trapno = trapno;
164 sc->err = err;
165 // sc->addr = (UWord)si->si_addr;
166 sc->fpformat = VKI_FPFMT_NODEV;
167 sc->len = sizeof(*sc);
168 sc->ownedfp = VKI_FPOWNED_NONE;
169 # undef SC2
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);
186 if (0 && stackseg)
187 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
188 addr, stackseg->start, stackseg->end);
191 if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
192 VG_(message)(
193 Vg_UserMsg,
194 "Can't extend stack to %#lx during signal delivery for thread %u:\n",
195 addr, tid);
196 if (stackseg == NULL)
197 VG_(message)(Vg_UserMsg, " no stack segment\n");
198 else
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. */
207 return False;
210 /* For tracking memory events, indicate the entire frame has been
211 allocated. */
212 VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
213 size + VG_STACK_REDZONE_SZB, tid );
215 return True;
219 /* Build the Valgrind-specific part of a signal frame. */
221 static void build_vg_sigframe(struct vg_sigframe *frame,
222 ThreadState *tst,
223 const vki_sigset_t *mask,
224 UInt flags,
225 Int sigNo)
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;
231 /* HACK ALERT */
232 frame->vex = tst->arch.vex;
233 /* end HACK ALERT */
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
244 * 2n struct sigframe
245 * 1n &func
246 * 0n &_ctx_start
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:
253 * Addr
254 * FreeBSD struct sigfame
255 * fpstate
256 * vg_sigframe
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,
265 void *restorer)
267 struct sigframe *frame;
268 Addr esp = esp_top_of_frame;
269 Int sigNo = siginfo->si_signo;
270 UWord trapno;
271 UWord err;
273 #if defined(__clang__)
274 esp -= 4;
275 esp = VG_ROUNDDN(esp, 16);
276 esp -= sizeof(*frame) + 4;
277 #else
278 esp -= sizeof(*frame);
279 esp = VG_ROUNDDN(esp, 16);
280 #endif
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;
295 else
296 frame->psigInfo = (Addr)&frame->sigInfo;
297 VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
299 if (siguc != NULL) {
300 trapno = siguc->uc_mcontext.trapno;
301 err = siguc->uc_mcontext.err;
302 } else {
303 trapno = 0;
304 err = 0;
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);
320 return esp;
323 /* EXPORTED */
324 void VG_(sigframe_create)( ThreadId tid,
325 Bool on_altstack,
326 Addr esp_top_of_frame,
327 const vki_siginfo_t *siginfo,
328 const struct vki_ucontext *siguc,
329 void *handler,
330 UInt flags,
331 const vki_sigset_t *mask,
332 void *restorer )
334 Addr esp;
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
352 caller to do. */
354 if (0)
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. */
367 static
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;
378 return False;
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;
384 /* HACK ALERT */
385 tst->arch.vex = frame->vex;
386 /* end HACK ALERT */
387 *sigNo = frame->sigNo_private;
388 return True;
391 static
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));
416 static
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);
426 /* EXPORTED */
427 void VG_(sigframe_destroy)( ThreadId tid )
429 Addr esp;
430 ThreadState* tst;
431 SizeT size;
432 Int sigNo;
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))
446 VG_(message)(
447 Vg_DebugMsg,
448 "VG_(sigframe_destroy) (thread %u): EIP=%#x\n",
449 tid, tst->arch.vex.guest_EIP);
451 /* tell the tools */
452 VG_TRACK( post_deliver_signal, tid, sigNo );
455 #endif // defined(VGP_x86_freebsd)
457 /*--------------------------------------------------------------------*/
458 /*--- end ---*/
459 /*--------------------------------------------------------------------*/