FreeBSD Helgrind: turn off check for locks held on exit for FreeBSD 14.2
[valgrind.git] / coregrind / m_syswrap / syswrap-amd64-freebsd.c
bloba58698532249486160528d109c6f3e8d3a2fb0e0
2 /*--------------------------------------------------------------------*/
3 /*--- Platform-specific syscalls stuff. syswrap-amd64-freebsd.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2005 Nicholas Nethercote
11 njn@valgrind.org
12 Copyright (C) 2018-2021 Paul Floyd
13 pjfloyd@wanadoo.fr
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, see <http://www.gnu.org/licenses/>.
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGP_amd64_freebsd)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_vkiscnums.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_debuglog.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_libcproc.h"
43 #include "pub_core_libcsignal.h"
44 #include "pub_core_machine.h"
45 #include "pub_core_options.h"
46 #include "pub_core_scheduler.h"
47 #include "pub_core_sigframe.h"
48 #include "pub_core_signals.h"
49 #include "pub_core_syscall.h"
50 #include "pub_core_syswrap.h"
51 #include "pub_core_tooliface.h"
52 #include "pub_core_stacks.h" // VG_(register_stack)
54 #include "priv_types_n_macros.h"
55 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
56 #include "priv_syswrap-freebsd.h" /* for decls of freebsd-ish wrappers */
57 #include "priv_syswrap-main.h"
59 /* ---------------------------------------------------------------------
60 clone() handling
61 ------------------------------------------------------------------ */
63 /* Call f(arg1), but first switch stacks, using 'stack' as the new
64 stack, and use 'retaddr' as f's return-to address. Also, clear all
65 the integer registers before entering f. */
66 __attribute__((noreturn))
67 void ML_(call_on_new_stack_0_1) ( Addr stack,
68 Addr retaddr,
69 void (*f)(Word),
70 Word arg1 );
71 // %rdi == stack
72 // %rsi == retaddr
73 // %rdx == f
74 // %rcx == arg1
75 __asm__(
76 ".text\n"
77 ".globl vgModuleLocal_call_on_new_stack_0_1\n"
78 "vgModuleLocal_call_on_new_stack_0_1:\n"
79 " movq %rdi, %rsp\n" // set stack
80 " pushq %rsi\n" // retaddr to stack
81 " pushq %rdx\n" // f to stack
82 " pushq %rcx\n" // arg1 to stack
83 " movq $0, %rax\n" // zero all GP regs
84 " movq $0, %rbx\n"
85 " movq $0, %rcx\n"
86 " movq $0, %rdx\n"
87 " movq $0, %rsi\n"
88 " movq $0, %rdi\n"
89 " movq $0, %rbp\n"
90 " movq $0, %r8\n"
91 " movq $0, %r9\n"
92 " movq $0, %r10\n"
93 " movq $0, %r11\n"
94 " movq $0, %r12\n"
95 " movq $0, %r13\n"
96 " movq $0, %r14\n"
97 " movq $0, %r15\n"
98 " popq %rdi\n" // arg1 to correct arg reg
99 " ret\n" // jump to f
100 " ud2\n" // should never get here
101 ".previous\n"
105 /* ---------------------------------------------------------------------
106 More thread stuff
107 ------------------------------------------------------------------ */
109 void VG_(cleanup_thread) ( ThreadArchState *arch )
113 /* ---------------------------------------------------------------------
114 PRE/POST wrappers for amd64/FreeBSD-specific syscalls
115 ------------------------------------------------------------------ */
117 #define PRE(name) DEFN_PRE_TEMPLATE(freebsd, name)
118 #define POST(name) DEFN_POST_TEMPLATE(freebsd, name)
120 // SYS_sysarch 165
121 // int sysarch(int number, void *args);
122 PRE(sys_sysarch)
124 ThreadState *tst;
125 void **p;
127 PRINT("sys_sysarch ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x )", ARG1, ARG2);
128 PRE_REG_READ2(int, "sysarch", int, number, void *, args);
129 switch (ARG1) {
130 case VKI_AMD64_SET_FSBASE:
131 PRINT("sys_amd64_set_fsbase ( %#lx )", ARG2);
133 if (ML_(safe_to_deref)((void**)ARG2, sizeof(void*))) {
134 /* On FreeBSD, the syscall loads the %gs selector for us, so do it now. */
135 tst = VG_(get_ThreadState)(tid);
136 p = (void**)ARG2;
137 tst->arch.vex.guest_FS_CONST = (UWord)*p;
138 /* "do" the syscall ourselves; the kernel never sees it */
139 SET_STATUS_Success2((ULong)*p, tst->arch.vex.guest_RDX );
140 } else {
141 // ????
142 SET_STATUS_Failure( VKI_EINVAL );
145 break;
146 case VKI_AMD64_GET_FSBASE:
147 PRINT("sys_amd64_get_fsbase ( %#lx )", ARG2);
148 PRE_MEM_WRITE( "amd64_get_fsbase(basep)", ARG2, sizeof(void *) );
149 if (ML_(safe_to_deref)((void**)ARG2, sizeof(void*))) {
150 /* "do" the syscall ourselves; the kernel never sees it */
151 tst = VG_(get_ThreadState)(tid);
152 SET_STATUS_Success2( tst->arch.vex.guest_FS_CONST, tst->arch.vex.guest_RDX );
153 } else {
154 SET_STATUS_Failure( VKI_EINVAL );
156 break;
157 case VKI_AMD64_GET_XFPUSTATE:
158 PRINT("sys_amd64_get_xfpustate ( %#lx )", ARG2);
159 PRE_MEM_WRITE( "amd64_get_xfpustate(basep)", ARG2, sizeof(void *) );
161 // @todo PJF need a test for this
162 // I think that it will fail in the POST if ARG2 is not a valid pointer
164 /* "do" the syscall ourselves; the kernel never sees it */
165 tst = VG_(get_ThreadState)(tid);
166 SET_STATUS_Success2( tst->arch.vex.guest_FPTAG[0], tst->arch.vex.guest_FPTAG[0] );
167 break;
168 default:
169 VG_(message) (Vg_UserMsg, "unhandled sysarch cmd %lu", ARG1);
170 VG_(unimplemented) ("unhandled sysarch cmd");
171 break;
175 POST(sys_sysarch)
177 switch (ARG1) {
178 case VKI_AMD64_SET_FSBASE:
179 break;
180 case VKI_AMD64_GET_FSBASE:
181 case VKI_AMD64_GET_XFPUSTATE:
182 POST_MEM_WRITE( ARG2, sizeof(void *) );
183 break;
184 default:
185 break;
189 // freebsd6_pread 173
190 // removed
192 // freebsd6_pwrite 174
193 // removed
195 // SYS_freebsd6_mmap 197
196 // removed
198 // freebsd6_lseek 199
199 // removed
201 // freebsd6_truncate 200
202 // removed
204 // freebsd6_ftruncate 201
205 // removed
207 // SYS_clock_getcpuclockid2 247
208 // no manpage for this, from syscalls.master
209 // int clock_getcpuclockid2(id_t id, int which, _Out_ clockid_t *clock_id);
210 PRE(sys_clock_getcpuclockid2)
212 PRINT("sys_clock_getcpuclockid2( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
213 SARG1,SARG2,ARG3);
214 PRE_REG_READ3(int, "clock_getcpuclockid2",
215 id_t, id, int, len, clockid_t *, clock_id);
216 PRE_MEM_WRITE("clock_getcpuclockid2(clock_id)", ARG3, sizeof(vki_clockid_t));
219 // SYS_rfork 251
220 // pid_t rfork(int flags);
221 PRE(sys_rfork)
223 PRINT("sys_rfork ( %#" FMT_REGWORD "x )", ARG1 );
224 PRE_REG_READ1(pid_t, "rfork", int, flags);
226 VG_(message)(Vg_UserMsg, "warning: rfork() not implemented\n");
228 if ((UInt)ARG1 == VKI_RFSPAWN) {
229 // posix_spawn uses RFSPAWN and it will fall back to vfork
230 // if it sees EINVAL
231 SET_STATUS_Failure(VKI_EINVAL);
232 } else {
233 SET_STATUS_Failure(VKI_ENOSYS);
237 // SYS_preadv 289
238 // ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
239 PRE(sys_preadv)
241 Int i;
242 struct vki_iovec * vec;
243 char buf[sizeof("preadv(iov[])") + 11];
244 *flags |= SfMayBlock;
245 PRINT("sys_preadv ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
246 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
247 PRE_REG_READ4(ssize_t, "preadv",
248 int, fd, const struct iovec *, iov,
249 int, iovcnt, vki_off_t, offset);
250 if (!ML_(fd_allowed)(ARG1, "preadv", tid, False)) {
251 SET_STATUS_Failure( VKI_EBADF );
252 } else {
253 if ((Int)ARG3 > 0) {
254 PRE_MEM_READ( "preadv(iov)", ARG2, ARG3 * sizeof(struct vki_iovec) );
257 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
258 vec = (struct vki_iovec *)(Addr)ARG2;
259 for (i = 0; i < (Int)ARG3; i++) {
260 VG_(sprintf)(buf, "preadv(iov[%d])", i);
261 PRE_MEM_WRITE(buf, (Addr)vec[i].iov_base, vec[i].iov_len);
267 POST(sys_preadv)
269 vg_assert(SUCCESS);
270 if (RES > 0) {
271 Int i;
272 struct vki_iovec * vec = (struct vki_iovec *)(Addr)ARG2;
273 Int remains = RES;
275 /* RES holds the number of bytes read. */
276 for (i = 0; i < (Int)ARG3; i++) {
277 Int nReadThisBuf = vec[i].iov_len;
278 if (nReadThisBuf > remains) {
279 nReadThisBuf = remains;
281 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
282 remains -= nReadThisBuf;
283 if (remains < 0) {
284 VG_(core_panic)("preadv: remains < 0");
290 // SYS_pwritev 290
291 // ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
292 PRE(sys_pwritev)
294 Int i;
295 struct vki_iovec * vec;
296 char buf[sizeof("pwritev(iov[])") + 11];
297 *flags |= SfMayBlock;
298 PRINT("sys_pwritev ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
299 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
301 PRE_REG_READ4(ssize_t, "pwritev",
302 int, fd, const struct iovec *, iov,
303 int, iovcnt,
304 vki_off_t, offset);
305 if (!ML_(fd_allowed)(ARG1, "pwritev", tid, False)) {
306 SET_STATUS_Failure( VKI_EBADF );
307 } else {
308 if ((Int)ARG3 >= 0) {
309 PRE_MEM_READ( "pwritev(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
311 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
312 vec = (struct vki_iovec *)(Addr)ARG2;
313 for (i = 0; i < (Int)ARG3; i++) {
314 VG_(sprintf)(buf, "pwritev(iov[%d])", i);
315 PRE_MEM_READ(buf, (Addr)vec[i].iov_base, vec[i].iov_len );
321 // SYS_sendfile 393
322 // int sendfile(int fd, int s, off_t offset, size_t nbytes,
323 // struct sf_hdtr *hdtr, off_t *sbytes, int flags);
324 PRE(sys_sendfile)
326 *flags |= SfMayBlock;
328 PRINT("sys_sendfile ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %lu, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
329 SARG1,SARG2,ARG3,ARG4,ARG5,ARG6,SARG7);
330 PRE_REG_READ7(int, "sendfile",
331 int, fd, int, s, vki_off_t, offset, size_t, nbytes,
332 void *, hdtr, vki_off_t *, sbytes, int, flags);
334 if (ARG5 != 0) {
335 PRE_MEM_READ("sendfile(hdtr)", ARG5, sizeof(struct vki_sf_hdtr));
338 if (ARG6 != 0) {
339 PRE_MEM_WRITE( "sendfile(sbytes)", ARG6, sizeof(vki_off_t) );
343 POST(sys_sendfile)
345 if (ARG6 != 0 ) {
346 POST_MEM_WRITE( ARG6, sizeof( vki_off_t ) );
350 // SYS_sigreturn 417
351 // int sigreturn(const ucontext_t *scp);
352 PRE(sys_sigreturn)
354 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
355 PRE_REG_READ1(int, "sigreturn",
356 struct vki_ucontext *, scp);
358 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
359 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
362 static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc)
364 tst->arch.vex.guest_RAX = sc->rax;
365 tst->arch.vex.guest_RCX = sc->rcx;
366 tst->arch.vex.guest_RDX = sc->rdx;
367 tst->arch.vex.guest_RBX = sc->rbx;
368 tst->arch.vex.guest_RBP = sc->rbp;
369 tst->arch.vex.guest_RSP = sc->rsp;
370 tst->arch.vex.guest_RSI = sc->rsi;
371 tst->arch.vex.guest_RDI = sc->rdi;
372 tst->arch.vex.guest_R8 = sc->r8;
373 tst->arch.vex.guest_R9 = sc->r9;
374 tst->arch.vex.guest_R10 = sc->r10;
375 tst->arch.vex.guest_R11 = sc->r11;
376 tst->arch.vex.guest_R12 = sc->r12;
377 tst->arch.vex.guest_R13 = sc->r13;
378 tst->arch.vex.guest_R14 = sc->r14;
379 tst->arch.vex.guest_R15 = sc->r15;
380 tst->arch.vex.guest_RIP = sc->rip;
382 * XXX: missing support for other flags.
384 if (sc->rflags & 0x0001)
385 LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex);
386 else
387 LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex);
390 static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc)
392 sc->rax = tst->arch.vex.guest_RAX;
393 sc->rcx = tst->arch.vex.guest_RCX;
394 sc->rdx = tst->arch.vex.guest_RDX;
395 sc->rbx = tst->arch.vex.guest_RBX;
396 sc->rbp = tst->arch.vex.guest_RBP;
397 sc->rsp = tst->arch.vex.guest_RSP;
398 sc->rsi = tst->arch.vex.guest_RSI;
399 sc->rdi = tst->arch.vex.guest_RDI;
400 sc->r8 = tst->arch.vex.guest_R8;
401 sc->r9 = tst->arch.vex.guest_R9;
402 sc->r10 = tst->arch.vex.guest_R10;
403 sc->r11 = tst->arch.vex.guest_R11;
404 sc->r12 = tst->arch.vex.guest_R12;
405 sc->r13 = tst->arch.vex.guest_R13;
406 sc->r14 = tst->arch.vex.guest_R14;
407 sc->r15 = tst->arch.vex.guest_R15;
408 sc->rip = tst->arch.vex.guest_RIP;
410 Not supported by VEX.
411 sc->cs = tst->arch.vex.guest_CS;
412 sc->ss = tst->arch.vex.guest_SS;
413 sc->ds = tst->arch.vex.guest_DS;
414 sc->es = tst->arch.vex.guest_ES;
415 sc->fs = tst->arch.vex.guest_FS;
416 sc->gs = tst->arch.vex.guest_GS;
418 sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
420 not yet.
421 VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
423 sc->fpformat = VKI_FPFMT_NODEV;
424 sc->ownedfp = VKI_FPOWNED_NONE;
425 sc->len = sizeof(*sc);
426 VG_(memset)(sc->spare2, 0, sizeof(sc->spare2));
429 // SYS_getcontext 421
430 // int getcontext(ucontext_t *ucp);
431 PRE(sys_getcontext)
433 ThreadState* tst;
434 struct vki_ucontext *uc;
436 PRINT("sys_getcontext ( %#" FMT_REGWORD "x )", ARG1);
437 PRE_REG_READ1(int, "getcontext",
438 struct vki_ucontext *, ucp);
439 PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
440 uc = (struct vki_ucontext *)ARG1;
441 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext))) {
442 SET_STATUS_Failure(VKI_EFAULT);
443 return;
445 tst = VG_(get_ThreadState)(tid);
446 fill_mcontext(tst, &uc->uc_mcontext);
447 uc->uc_mcontext.rax = 0;
448 uc->uc_mcontext.rdx = 0;
449 uc->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
450 uc->uc_sigmask = tst->sig_mask;
451 VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__));
452 SET_STATUS_Success(0);
455 // SYS_setcontext 422
456 // int setcontext(const ucontext_t *ucp);
457 PRE(sys_setcontext)
459 ThreadState* tst;
460 struct vki_ucontext *uc;
462 PRINT("sys_setcontext ( %#" FMT_REGWORD "x )", ARG1);
463 PRE_REG_READ1(int, "setcontext",
464 struct vki_ucontext *, ucp);
466 PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
468 vg_assert(VG_(is_valid_tid)(tid));
469 vg_assert(tid >= 1 && tid < VG_N_THREADS);
470 vg_assert(VG_(is_running_thread)(tid));
472 tst = VG_(get_ThreadState)(tid);
473 uc = (struct vki_ucontext *)ARG1;
474 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext)) || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
475 SET_STATUS_Failure(VKI_EFAULT);
476 return;
479 restore_mcontext(tst, &uc->uc_mcontext);
480 tst->sig_mask = uc->uc_sigmask;
481 tst->tmp_sig_mask = uc->uc_sigmask;
483 /* Tell the driver not to update the guest state with the "result",
484 and set a bogus result to keep it happy. */
485 *flags |= SfNoWriteResult;
486 SET_STATUS_Success(0);
488 /* Check to see if some any signals arose as a result of this. */
489 *flags |= SfPollAfter;
492 // SYS_swapcontext 423
493 // int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
494 PRE(sys_swapcontext)
496 struct vki_ucontext *ucp;
497 struct vki_ucontext *oucp;
498 ThreadState* tst;
500 PRINT("sys_swapcontext ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )", ARG1, ARG2);
501 PRE_REG_READ2(long, "swapcontext",
502 struct vki_ucontext *, oucp, struct vki_ucontext *, ucp);
504 PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) );
505 PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) );
507 oucp = (struct vki_ucontext *)ARG1;
508 ucp = (struct vki_ucontext *)ARG2;
509 if (!ML_(safe_to_deref)(oucp, sizeof(struct vki_ucontext)) ||
510 !ML_(safe_to_deref)(ucp, sizeof(struct vki_ucontext)) ||
511 ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) {
512 SET_STATUS_Failure(VKI_EINVAL);
513 return;
515 tst = VG_(get_ThreadState)(tid);
518 * Save the context.
520 fill_mcontext(tst, &oucp->uc_mcontext);
521 oucp->uc_mcontext.rax = 0;
522 oucp->uc_mcontext.rdx = 0;
523 oucp->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
524 oucp->uc_sigmask = tst->sig_mask;
525 VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__));
528 * Switch to new one.
530 restore_mcontext(tst, &ucp->uc_mcontext);
531 tst->sig_mask = ucp->uc_sigmask;
532 tst->tmp_sig_mask = ucp->uc_sigmask;
534 /* Tell the driver not to update the guest state with the "result",
535 and set a bogus result to keep it happy. */
536 *flags |= SfNoWriteResult;
537 SET_STATUS_Success(0);
539 /* Check to see if some any signals arose as a result of this. */
540 *flags |= SfPollAfter;
543 // SYS_thr_new 455
544 // int thr_new(struct thr_param *param, int param_size);
545 PRE(sys_thr_new)
547 static const Bool debug = False;
549 ThreadId ctid = VG_(alloc_ThreadState)();
550 ThreadState* ptst = VG_(get_ThreadState)(tid);
551 ThreadState* ctst = VG_(get_ThreadState)(ctid);
552 SysRes res;
553 vki_sigset_t blockall;
554 vki_sigset_t savedmask;
555 struct vki_thr_param tp;
556 Addr stk;
558 PRINT("thr_new ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u )",ARG1,ARG2);
559 PRE_REG_READ2(int, "thr_new",
560 struct thr_param *, param,
561 int, param_size);
563 PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare));
564 if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) {
565 SET_STATUS_Failure( VKI_EFAULT );
566 return;
568 VG_(memset)(&tp, 0, sizeof(tp));
569 VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare));
570 PRE_MEM_WRITE("thr_new(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long));
571 PRE_MEM_WRITE("thr_new(child_tidptr)", (Addr)tp.child_tid, sizeof(long));
573 VG_(sigfillset)(&blockall);
575 vg_assert(VG_(is_running_thread)(tid));
576 vg_assert(VG_(is_valid_tid)(ctid));
578 /* Copy register state
580 On linux, both parent and child return to the same place, and the code
581 following the clone syscall works out which is which, so we
582 don't need to worry about it.
583 On FreeBSD, thr_new arranges a direct call. We don't actually need any
584 of this gunk.
586 The parent gets the child's new tid returned from clone, but the
587 child gets 0.
589 If the clone call specifies a NULL rsp for the new thread, then
590 it actually gets a copy of the parent's rsp.
592 /* We inherit our parent's guest state. */
593 ctst->arch.vex = ptst->arch.vex;
594 ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
595 ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
597 /* Make thr_new appear to have returned Success(0) in the
598 child. */
599 ctst->arch.vex.guest_RAX = 0;
600 ctst->arch.vex.guest_RDX = 0;
601 LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex);
603 ctst->os_state.parent = tid;
605 /* inherit signal mask */
606 ctst->sig_mask = ptst->sig_mask;
607 ctst->tmp_sig_mask = ptst->sig_mask;
609 /* Linux has to guess, we don't */
610 ctst->client_stack_highest_byte = (Addr)tp.stack_base + tp.stack_size;
611 ctst->client_stack_szB = tp.stack_size;
612 ctst->os_state.stk_id = VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size);
614 /* Assume the thr_new will succeed, and tell any tool that wants to
615 know that this thread has come into existence. If the thr_new
616 fails, we'll send out a ll_exit notification for it at the out:
617 label below, to clean up. */
618 VG_TRACK ( pre_thread_ll_create, tid, ctid );
620 if (debug) {
621 VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
623 ctst->arch.vex.guest_FS_CONST = (UWord)tp.tls_base;
624 tp.tls_base = 0; /* Don't have the kernel do it too */
626 /* start the thread with everything blocked */
627 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
629 /* Set the client state for scheduler to run libthr's trampoline */
630 ctst->arch.vex.guest_RDI = (Addr)tp.arg;
631 /* XXX: align on 16-byte boundary? */
632 ctst->arch.vex.guest_RSP = (Addr)tp.stack_base + tp.stack_size - 8;
633 ctst->arch.vex.guest_RIP = (Addr)tp.start_func;
635 /* But this is for thr_new() to run valgrind's trampoline */
636 tp.start_func = (void *)ML_(start_thread_NORETURN);
637 tp.arg = &VG_(threads)[ctid];
639 /* And valgrind's trampoline on its own stack */
640 stk = ML_(allocstack)(ctid);
641 if (stk == (Addr)NULL) {
642 res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
643 goto fail;
645 tp.stack_base = (void *)ctst->os_state.valgrind_stack_base;
646 tp.stack_size = (Addr)stk - (Addr)tp.stack_base;
648 /* Create the new thread */
649 res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp));
651 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
653 fail:
654 if (sr_isError(res)) {
655 /* thr_new failed */
656 VG_(cleanup_thread)(&ctst->arch);
657 ctst->status = VgTs_Empty;
658 /* oops. Better tell the tool the thread exited in a hurry :-) */
659 VG_TRACK( pre_thread_ll_exit, ctid );
660 } else {
662 POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long));
663 POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long));
665 /* Thread creation was successful; let the child have the chance
666 to run */
667 *flags |= SfYieldAfter;
670 /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */
671 SET_STATUS_from_SysRes(res);
674 // SYS_pread 475
675 // ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
676 PRE(sys_pread)
678 *flags |= SfMayBlock;
679 PRINT("sys_pread ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
680 PRE_REG_READ4(ssize_t, "pread",
681 unsigned int, fd, char *, buf, vki_size_t, count,
682 unsigned long, off);
684 if (!ML_(fd_allowed)(ARG1, "read", tid, False)) {
685 SET_STATUS_Failure( VKI_EBADF );
686 } else {
687 PRE_MEM_WRITE( "pread(buf)", ARG2, ARG3 );
691 POST(sys_pread)
693 vg_assert(SUCCESS);
694 POST_MEM_WRITE( ARG2, RES );
697 // SYS_pwrite 476
698 // ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
699 PRE(sys_pwrite)
701 Bool ok;
702 *flags |= SfMayBlock;
703 PRINT("sys_pwrite ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
704 PRE_REG_READ4(ssize_t, "pwrite",
705 int, fd, const char *, buf, vki_size_t, nbytes,
706 vki_off_t, offset);
707 /* check to see if it is allowed. If not, try for an exemption from
708 --sim-hints=enable-outer (used for self hosting). */
709 ok = ML_(fd_allowed)(ARG1, "pwrite", tid, False);
710 if (!ok && ARG1 == 2/*stderr*/
711 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
712 ok = True;
713 if (!ok) {
714 SET_STATUS_Failure( VKI_EBADF );
715 } else {
716 PRE_MEM_READ( "pwrite(buf)", ARG2, ARG3 );
720 // SYS_mmap 477
721 /* FreeBSD-7 introduces a "regular" version of mmap etc. */
722 // void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
723 PRE(sys_mmap)
725 SysRes r;
727 PRINT("sys_mmap ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x)",
728 ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
729 PRE_REG_READ6(void *, "mmap",
730 void *, addr, size_t, len, int, prot, int, flags,
731 int, fd, off_t, offset);
733 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
734 SET_STATUS_from_SysRes(r);
737 // SYS_lseek 478
738 // off_t lseek(int fildes, off_t offset, int whence);
739 PRE(sys_lseek)
741 PRINT("sys_lseek ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3);
742 PRE_REG_READ3(long, "lseek",
743 unsigned int, fd, unsigned long, offset,
744 unsigned int, whence);
747 // SYS_truncate 479
748 // int truncate(const char *path, off_t length);
749 PRE(sys_truncate)
751 *flags |= SfMayBlock;
752 PRINT("sys_truncate ( %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u )", ARG1,(char *)ARG1,ARG2);
753 PRE_REG_READ2(long, "truncate",
754 const char *, path, unsigned long, length);
755 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
758 // SYS_ftruncate 480
759 // int ftruncate(int fd, off_t length);
760 PRE(sys_ftruncate)
762 *flags |= SfMayBlock;
763 PRINT("sys_ftruncate ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1,ARG2);
764 PRE_REG_READ2(long, "ftruncate", unsigned int, fd,
765 unsigned long, length);
768 // SYS_cpuset_setid 485
769 // int cpuset_setid(cpuwhich_t which, id_t id, cpusetid_t setid);
770 PRE(sys_cpuset_setid)
772 PRINT("sys_cpuset_setid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
773 SARG1, SARG2, ARG3);
774 PRE_REG_READ3(int, "cpuset_setid", vki_cpuwhich_t, which, vki_id_t, id,
775 vki_cpusetid_t *,setid);
778 // SYS_cpuset_getid 486
779 // int cpuset_getid(cpulevel_t level, cpuwhich_t which, id_t id,
780 // cpusetid_t *setid);
781 PRE(sys_cpuset_getid)
783 PRINT("sys_cpuset_getid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
784 SARG1, SARG2, SARG3, ARG4);
785 PRE_REG_READ4(int, "cpuset_getid", vki_cpulevel_t, level,
786 vki_cpuwhich_t, which, vki_id_t, id,
787 vki_cpusetid_t, setid);
788 PRE_MEM_WRITE("cpuset_getid(setid)", ARG4, sizeof(vki_cpusetid_t));
791 POST(sys_cpuset_getid)
793 POST_MEM_WRITE(ARG4, sizeof(vki_cpusetid_t));
796 // SYS_cpuset_getaffinity 487
797 // int cpuset_getaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
798 // size_t setsize, cpuset_t *mask);
799 PRE(sys_cpuset_getaffinity)
801 PRINT("sys_cpuset_getaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
802 ARG1, ARG2, SARG3, ARG4, ARG5);
803 PRE_REG_READ5(int, "cpuset_getaffinity",
804 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
805 size_t, setsize, void *, mask);
806 PRE_MEM_WRITE("cpuset_getaffinity", ARG5, ARG4);
809 POST(sys_cpuset_getaffinity)
811 vg_assert(SUCCESS);
812 if (RES == 0)
813 POST_MEM_WRITE( ARG5, ARG4 );
816 // SYS_cpuset_setaffinity 488
817 // int cpuset_setaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
818 // size_t setsize, const cpuset_t *mask);
819 PRE(sys_cpuset_setaffinity)
822 PRINT("sys_cpuset_setaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
823 ARG1, ARG2, SARG3, ARG4, ARG5);
824 PRE_REG_READ5(int, "cpuset_setaffinity",
825 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
826 size_t, setsize, void *, mask);
827 PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4);
830 // SYS_posix_fallocate 530
831 // int posix_fallocate(int fd, off_t offset, off_t len);
832 PRE(sys_posix_fallocate)
834 PRINT("sys_posix_fallocate ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",
835 SARG1, ARG2, ARG3);
836 PRE_REG_READ3(long, "posix_fallocate",
837 int, fd, vki_off_t, offset,
838 vki_off_t, len);
841 // SYS_posix_fadvise 531
842 // int posix_fadvise(int fd, off_t offset, off_t len, int advice);
843 PRE(sys_posix_fadvise)
845 PRINT("sys_posix_fadvise ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d )",
846 SARG1, ARG2, ARG3, SARG4);
847 PRE_REG_READ4(long, "posix_fadvise",
848 int, fd, off_t, offset,
849 off_t, len,
850 int, advice);
851 // @todo PJF advice can be 0 to 5 inclusive
854 // SYS_wait6 532
855 // pid_t wait6(idtype_t idtype, id_t id, int *status, int options,
856 // struct __wrusage *wrusage, siginfo_t *infop);
857 PRE(sys_wait6)
859 PRINT("sys_wait6 ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
860 SARG1, SARG2, ARG3, SARG4, ARG5, ARG6);
861 PRE_REG_READ6(pid_t, "wait6", vki_idtype_t, idtype, vki_id_t, id, int *, status, int, options,
862 struct vki___wrusage *, wrusage, vki_siginfo_t *,infop);
863 PRE_MEM_WRITE("wait6(status)", ARG3, sizeof(int));
864 if (ARG5) {
865 PRE_MEM_WRITE("wait6(wrusage)", ARG5, sizeof(struct vki___wrusage));
867 if (ARG6) {
868 PRE_MEM_WRITE("wait6(infop)", ARG6, sizeof(vki_siginfo_t));
872 POST(sys_wait6)
874 POST_MEM_WRITE(ARG3, sizeof(int));
875 if (ARG5) {
876 POST_MEM_WRITE(ARG5, sizeof(struct vki___wrusage));
879 if (ARG6) {
880 POST_MEM_WRITE(ARG6, sizeof(vki_siginfo_t));
884 // SYS_procctl 544
885 // int procctl(idtype_t idtype, id_t id, int cmd, void *data);
886 PRE(sys_procctl)
888 PRINT("sys_procctl ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD"d, %#" FMT_REGWORD "x )",
889 SARG1, SARG2, SARG3, ARG4);
890 PRE_REG_READ4(int, "procctl", vki_idtype_t, idtype, vki_id_t, id, int, cmd, void *, data);
891 switch (ARG3) {
892 case VKI_PROC_ASLR_CTL:
893 case VKI_PROC_SPROTECT:
894 case VKI_PROC_TRACE_CTL:
895 case VKI_PROC_TRAPCAP_CTL:
896 case VKI_PROC_PDEATHSIG_CTL:
897 case VKI_PROC_STACKGAP_CTL:
898 case VKI_PROC_NO_NEW_PRIVS_CTL:
899 case VKI_PROC_WXMAP_CTL:
900 PRE_MEM_READ("procctl(data)", ARG4, sizeof(int));
901 break;
902 case VKI_PROC_REAP_STATUS:
903 PRE_MEM_READ("procctl(data)", ARG4, sizeof(struct vki_procctl_reaper_status));
904 break;
905 case VKI_PROC_REAP_GETPIDS:
906 PRE_MEM_READ("procctl(data)", ARG4, sizeof(struct vki_procctl_reaper_pids));
907 break;
908 case VKI_PROC_REAP_KILL:
909 /* The first three fields are reads
910 * int rk_sig;
911 * u_int rk_flags;
912 * pid_t rk_subtree;
914 * The last two fields are writes
915 * u_int rk_killed;
916 * pid_t rk_fpid;
918 * There is also a pad field
920 PRE_MEM_READ("procctl(data)", ARG4, sizeof(int) + sizeof(u_int) + sizeof(vki_pid_t));
921 PRE_MEM_WRITE("procctl(data)", ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
922 break;
923 case VKI_PROC_ASLR_STATUS:
924 case VKI_PROC_PDEATHSIG_STATUS:
925 case VKI_PROC_STACKGAP_STATUS:
926 case VKI_PROC_TRAPCAP_STATUS:
927 case VKI_PROC_TRACE_STATUS:
928 case VKI_PROC_NO_NEW_PRIVS_STATUS:
929 case VKI_PROC_WXMAP_STATUS:
930 PRE_MEM_WRITE("procctl(data)", ARG4, sizeof(int));
931 case VKI_PROC_REAP_ACQUIRE:
932 case VKI_PROC_REAP_RELEASE:
933 default:
934 break;
938 POST(sys_procctl)
940 switch (ARG3) {
941 case VKI_PROC_REAP_KILL:
942 POST_MEM_WRITE(ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
943 break;
944 case VKI_PROC_ASLR_STATUS:
945 case VKI_PROC_PDEATHSIG_STATUS:
946 case VKI_PROC_STACKGAP_STATUS:
947 case VKI_PROC_TRAPCAP_STATUS:
948 case VKI_PROC_TRACE_STATUS:
949 case VKI_PROC_NO_NEW_PRIVS_STATUS:
950 case VKI_PROC_WXMAP_STATUS:
951 POST_MEM_WRITE(ARG4, sizeof(int));
952 default:
953 break;
957 // SYS_mknodat 559
958 // int mknodat(int fd, const char *path, mode_t mode, dev_t dev);
959 PRE(sys_mknodat)
961 PRINT("sys_mknodat ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x(%s), 0x%" FMT_REGWORD "x, 0x%" FMT_REGWORD "x )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4 );
962 PRE_REG_READ4(long, "mknodat",
963 int, fd, const char *, path, vki_mode_t, mode, vki_dev_t, dev);
964 PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 );
967 // SYS_cpuset_getdomain 561
968 // int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id,
969 // size_t setsize, domainset_t *mask, int *policy);
970 PRE(sys_cpuset_getdomain)
972 PRINT("sys_cpuset_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
973 SARG1, SARG2, SARG3, ARG4, ARG5, ARG6);
974 PRE_REG_READ6(int, "cpuset_getdomain",
975 cpulevel_t, level, cpuwhich_t, which, id_t, id,
976 size_t, setsize, vki_domainset_t *, mask, int *, policy);
977 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
978 PRE_MEM_WRITE( "cpuset_getdomain(mask)", ARG5, ARG4 );
979 PRE_MEM_WRITE( "cpuset_getdomain(policy)", ARG6, sizeof(int) );
982 POST(sys_cpuset_getdomain)
984 POST_MEM_WRITE(ARG5, ARG4 );
985 POST_MEM_WRITE(ARG6, sizeof(int) );
988 // SYS_cpuset_setdomain 562
989 // int cuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id,
990 // size_t setsize, const domainset_t *mask, int policy);
991 PRE(sys_cpuset_setdomain)
993 PRINT("sys_cpuget_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
994 SARG1, SARG2, SARG3, ARG4, ARG5, SARG6);
995 PRE_REG_READ6(int, "cpuset_getdomain",
996 cpulevel_t, level, cpuwhich_t, which, id_t, id,
997 size_t, setsize, vki_domainset_t *, mask, int, policy);
998 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
999 PRE_MEM_READ( "cpuset_getdomain(mask)", ARG5, ARG4 );
1002 PRE(sys_fake_sigreturn)
1004 ThreadState* tst;
1005 struct vki_ucontext *uc;
1006 ULong rflags;
1008 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
1009 PRE_REG_READ1(long, "sigreturn",
1010 struct vki_ucontext *, scp);
1012 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1013 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1015 vg_assert(VG_(is_valid_tid)(tid));
1016 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1017 vg_assert(VG_(is_running_thread)(tid));
1019 /* Adjust esp to point to start of frame; skip back up over handler
1020 ret addr */
1021 tst = VG_(get_ThreadState)(tid);
1022 tst->arch.vex.guest_RSP -= sizeof(Addr);
1024 uc = (struct vki_ucontext *)ARG1;
1025 if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
1026 SET_STATUS_Failure(VKI_EINVAL);
1027 return;
1030 /* This is only so that the EIP is (might be) useful to report if
1031 something goes wrong in the sigreturn */
1032 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
1034 VG_(sigframe_destroy)(tid);
1036 /* For unclear reasons, it appears we need the syscall to return
1037 without changing %RAX. Since %RAX is the return value, and can
1038 denote either success or failure, we must set up so that the
1039 driver logic copies it back unchanged. Also, note %RAX is of
1040 the guest registers written by VG_(sigframe_destroy). */
1041 rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
1042 SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_freebsd)( tst->arch.vex.guest_RAX,
1043 tst->arch.vex.guest_RDX, (rflags & 1U) != 0U ? True : False) );
1046 * Signal handler might have changed the signal mask. Respect that.
1048 tst->sig_mask = uc->uc_sigmask;
1049 tst->tmp_sig_mask = uc->uc_sigmask;
1051 /* Tell the driver not to update the guest state with the "result",
1052 and set a bogus result to keep it happy. */
1053 *flags |= SfNoWriteResult;
1054 SET_STATUS_Success(0);
1056 /* Check to see if some any signals arose as a result of this. */
1057 *flags |= SfPollAfter;
1061 #undef PRE
1062 #undef POST
1064 #endif /* defined(VGP_amd64_freebsd) */
1066 /*--------------------------------------------------------------------*/
1067 /*--- end ---*/
1068 /*--------------------------------------------------------------------*/