2 /*--------------------------------------------------------------------*/
3 /*--- Platform-specific syscalls stuff. syswrap-amd64-freebsd.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2005 Nicholas Nethercote
12 Copyright (C) 2018-2021 Paul Floyd
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 /* ---------------------------------------------------------------------
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
,
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
98 " popq %rdi\n" // arg1 to correct arg reg
100 " ud2\n" // should never get here
105 /* ---------------------------------------------------------------------
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)
121 // int sysarch(int number, void *args);
127 PRINT("sys_sysarch ( %" FMT_REGWORD
"u, %#" FMT_REGWORD
"x )", ARG1
, ARG2
);
128 PRE_REG_READ2(int, "sysarch", int, number
, void *, args
);
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
);
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
);
142 SET_STATUS_Failure( VKI_EINVAL
);
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
);
154 SET_STATUS_Failure( VKI_EINVAL
);
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] );
169 VG_(message
) (Vg_UserMsg
, "unhandled sysarch cmd %lu", ARG1
);
170 VG_(unimplemented
) ("unhandled sysarch cmd");
178 case VKI_AMD64_SET_FSBASE
:
180 case VKI_AMD64_GET_FSBASE
:
181 case VKI_AMD64_GET_XFPUSTATE
:
182 POST_MEM_WRITE( ARG2
, sizeof(void *) );
189 // freebsd6_pread 173
192 // freebsd6_pwrite 174
195 // SYS_freebsd6_mmap 197
198 // freebsd6_lseek 199
201 // freebsd6_truncate 200
204 // freebsd6_ftruncate 201
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 )",
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
));
220 // pid_t rfork(int flags);
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
231 SET_STATUS_Failure(VKI_EINVAL
);
233 SET_STATUS_Failure(VKI_ENOSYS
);
238 // ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
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
);
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
);
272 struct vki_iovec
* vec
= (struct vki_iovec
*)(Addr
)ARG2
;
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
;
284 VG_(core_panic
)("preadv: remains < 0");
291 // ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
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
,
305 if (!ML_(fd_allowed
)(ARG1
, "pwritev", tid
, False
)) {
306 SET_STATUS_Failure( VKI_EBADF
);
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
);
322 // int sendfile(int fd, int s, off_t offset, size_t nbytes,
323 // struct sf_hdtr *hdtr, off_t *sbytes, int flags);
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
);
335 PRE_MEM_READ("sendfile(hdtr)", ARG5
, sizeof(struct vki_sf_hdtr
));
339 PRE_MEM_WRITE( "sendfile(sbytes)", ARG6
, sizeof(vki_off_t
) );
346 POST_MEM_WRITE( ARG6
, sizeof( vki_off_t
) );
351 // int sigreturn(const ucontext_t *scp);
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
);
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
);
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);
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
);
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);
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
);
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);
496 struct vki_ucontext
*ucp
;
497 struct vki_ucontext
*oucp
;
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
);
515 tst
= VG_(get_ThreadState
)(tid
);
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__
));
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
;
544 // int thr_new(struct thr_param *param, int param_size);
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
);
553 vki_sigset_t blockall
;
554 vki_sigset_t savedmask
;
555 struct vki_thr_param tp
;
558 PRINT("thr_new ( %#" FMT_REGWORD
"x, %" FMT_REGWORD
"u )",ARG1
,ARG2
);
559 PRE_REG_READ2(int, "thr_new",
560 struct thr_param
*, param
,
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
);
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
586 The parent gets the child's new tid returned from clone, but the
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
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
);
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
);
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
);
654 if (sr_isError(res
)) {
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
);
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
667 *flags
|= SfYieldAfter
;
670 /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */
671 SET_STATUS_from_SysRes(res
);
675 // ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
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
,
684 if (!ML_(fd_allowed
)(ARG1
, "read", tid
, False
)) {
685 SET_STATUS_Failure( VKI_EBADF
);
687 PRE_MEM_WRITE( "pread(buf)", ARG2
, ARG3
);
694 POST_MEM_WRITE( ARG2
, RES
);
698 // ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
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
,
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
)))
714 SET_STATUS_Failure( VKI_EBADF
);
716 PRE_MEM_READ( "pwrite(buf)", ARG2
, ARG3
);
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);
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
);
738 // off_t lseek(int fildes, off_t offset, int whence);
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
);
748 // int truncate(const char *path, off_t length);
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
);
759 // int ftruncate(int fd, off_t length);
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 )",
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
)
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 )",
836 PRE_REG_READ3(long, "posix_fallocate",
837 int, fd
, vki_off_t
, offset
,
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
,
851 // @todo PJF advice can be 0 to 5 inclusive
855 // pid_t wait6(idtype_t idtype, id_t id, int *status, int options,
856 // struct __wrusage *wrusage, siginfo_t *infop);
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));
865 PRE_MEM_WRITE("wait6(wrusage)", ARG5
, sizeof(struct vki___wrusage
));
868 PRE_MEM_WRITE("wait6(infop)", ARG6
, sizeof(vki_siginfo_t
));
874 POST_MEM_WRITE(ARG3
, sizeof(int));
876 POST_MEM_WRITE(ARG5
, sizeof(struct vki___wrusage
));
880 POST_MEM_WRITE(ARG6
, sizeof(vki_siginfo_t
));
885 // int procctl(idtype_t idtype, id_t id, int cmd, void *data);
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
);
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));
902 case VKI_PROC_REAP_STATUS
:
903 PRE_MEM_READ("procctl(data)", ARG4
, sizeof(struct vki_procctl_reaper_status
));
905 case VKI_PROC_REAP_GETPIDS
:
906 PRE_MEM_READ("procctl(data)", ARG4
, sizeof(struct vki_procctl_reaper_pids
));
908 case VKI_PROC_REAP_KILL
:
909 /* The first three fields are reads
914 * The last two fields are writes
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
));
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
:
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
));
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));
958 // int mknodat(int fd, const char *path, mode_t mode, dev_t dev);
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
)
1005 struct vki_ucontext
*uc
;
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
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
);
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
;
1064 #endif /* defined(VGP_amd64_freebsd) */
1066 /*--------------------------------------------------------------------*/
1068 /*--------------------------------------------------------------------*/