vgdb: Handle EAGAIN in read_buf
[valgrind.git] / coregrind / m_syswrap / syswrap-amd64-freebsd.c
blob00c353ae417a7ed4f69b708eb17734f2c78871fa
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 #if (FREEBSD_VERS <= FREEBSD_10)
191 PRE(sys_freebsd6_pread)
193 *flags |= SfMayBlock;
194 PRINT("sys_freebsd6_pread ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %lu, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4, ARG5);
195 PRE_REG_READ5(ssize_t, "read",
196 unsigned int, fd, char *, buf, vki_size_t, count,
197 int, pad, unsigned long, off);
199 if (!ML_(fd_allowed)(ARG1, "freebsd6_pread", tid, False))
200 SET_STATUS_Failure( VKI_EBADF );
201 else
202 PRE_MEM_WRITE( "freebsd6_pread(buf)", ARG2, ARG3 );
205 POST(sys_freebsd6_pread)
207 vg_assert(SUCCESS);
208 POST_MEM_WRITE( ARG2, RES );
210 #endif
212 // freebsd6_pwrite 174
213 #if (FREEBSD_VERS <= FREEBSD_10)
214 PRE(sys_freebsd6_pwrite)
216 Bool ok;
217 *flags |= SfMayBlock;
218 PRINT("sys_freebsd6_pwrite ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", SARG1, ARG2, ARG3, ARG4, ARG5);
219 PRE_REG_READ5(ssize_t, "write",
220 unsigned int, fd, const char *, buf, vki_size_t, count,
221 int, pad, unsigned long, off);
222 /* check to see if it is allowed. If not, try for an exemption from
223 --sim-hints=enable-outer (used for self hosting). */
224 ok = ML_(fd_allowed)(ARG1, "freebsd6_pwrite", tid, False);
225 if (!ok && ARG1 == 2/*stderr*/
226 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
227 ok = True;
228 if (!ok)
229 SET_STATUS_Failure( VKI_EBADF );
230 else
231 PRE_MEM_READ( "freebsd6_pwrite(buf)", ARG2, ARG3 );
233 #endif
235 // SYS_freebsd6_mmap 197
236 #if (FREEBSD_VERS <= FREEBSD_10)
237 /* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */
239 /* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */
240 /* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 */
242 PRE(sys_freebsd6_mmap)
244 SysRes r;
246 PRINT("sys_mmap ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, pad%" FMT_REGWORD "u, 0x%" FMT_REGWORD "x)",
247 ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 );
248 PRE_REG_READ7(long, "mmap",
249 char *, addr, unsigned long, len, int, prot, int, flags,
250 int, fd, int, pad, unsigned long, pos);
252 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 );
253 SET_STATUS_from_SysRes(r);
255 #endif
257 // freebsd6_lseek 199
258 #if (FREEBSD_VERS <= FREEBSD_10)
259 PRE(sys_freebsd6_lseek)
261 PRINT("sys_freebsd6_lseek ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3,ARG4);
262 PRE_REG_READ4(long, "lseek",
263 unsigned int, fd, int, pad, unsigned long, offset,
264 unsigned int, whence);
266 #endif
268 // freebsd6_truncate 200
269 #if (FREEBSD_VERS <= FREEBSD_10)
270 PRE(sys_freebsd6_truncate)
272 *flags |= SfMayBlock;
273 PRINT("sys_truncate ( %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u )", ARG1,(char *)ARG1,ARG3);
274 PRE_REG_READ3(long, "truncate",
275 const char *, path, int, pad, unsigned int, length);
276 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
278 #endif
280 // freebsd6_ftruncate 201
281 #if (FREEBSD_VERS <= FREEBSD_10)
282 PRE(sys_freebsd6_ftruncate)
284 *flags |= SfMayBlock;
285 PRINT("sys_ftruncate ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1,ARG3);
286 PRE_REG_READ3(long, "ftruncate", unsigned int, fd, int, pad,
287 unsigned int, length);
289 #endif
291 // SYS_clock_getcpuclockid2 247
292 // no manpage for this, from syscalls.master
293 // int clock_getcpuclockid2(id_t id, int which, _Out_ clockid_t *clock_id);
294 PRE(sys_clock_getcpuclockid2)
296 PRINT("sys_clock_getcpuclockid2( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
297 SARG1,SARG2,ARG3);
298 PRE_REG_READ3(int, "clock_getcpuclockid2",
299 id_t, id, int, len, clockid_t *, clock_id);
300 PRE_MEM_WRITE("clock_getcpuclockid2(clock_id)", ARG3, sizeof(vki_clockid_t));
303 // SYS_rfork 251
304 // pid_t rfork(int flags);
305 PRE(sys_rfork)
307 PRINT("sys_rfork ( %#" FMT_REGWORD "x )", ARG1 );
308 PRE_REG_READ1(pid_t, "rfork", int, flags);
310 VG_(message)(Vg_UserMsg, "warning: rfork() not implemented\n");
312 if ((UInt)ARG1 == VKI_RFSPAWN) {
313 // posix_spawn uses RFSPAWN and it will fall back to vfork
314 // if it sees EINVAL
315 SET_STATUS_Failure(VKI_EINVAL);
316 } else {
317 SET_STATUS_Failure(VKI_ENOSYS);
321 // SYS_preadv 289
322 // ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
323 PRE(sys_preadv)
325 Int i;
326 struct vki_iovec * vec;
327 char buf[sizeof("preadv(iov[])") + 11];
328 *flags |= SfMayBlock;
329 PRINT("sys_preadv ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
330 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
331 PRE_REG_READ4(ssize_t, "preadv",
332 int, fd, const struct iovec *, iov,
333 int, iovcnt, vki_off_t, offset);
334 if (!ML_(fd_allowed)(ARG1, "preadv", tid, False)) {
335 SET_STATUS_Failure( VKI_EBADF );
336 } else {
337 if ((Int)ARG3 > 0) {
338 PRE_MEM_READ( "preadv(iov)", ARG2, ARG3 * sizeof(struct vki_iovec) );
341 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
342 vec = (struct vki_iovec *)(Addr)ARG2;
343 for (i = 0; i < (Int)ARG3; i++) {
344 VG_(sprintf)(buf, "preadv(iov[%d])", i);
345 PRE_MEM_WRITE(buf, (Addr)vec[i].iov_base, vec[i].iov_len);
351 POST(sys_preadv)
353 vg_assert(SUCCESS);
354 if (RES > 0) {
355 Int i;
356 struct vki_iovec * vec = (struct vki_iovec *)(Addr)ARG2;
357 Int remains = RES;
359 /* RES holds the number of bytes read. */
360 for (i = 0; i < (Int)ARG3; i++) {
361 Int nReadThisBuf = vec[i].iov_len;
362 if (nReadThisBuf > remains) {
363 nReadThisBuf = remains;
365 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
366 remains -= nReadThisBuf;
367 if (remains < 0) {
368 VG_(core_panic)("preadv: remains < 0");
374 // SYS_pwritev 290
375 // ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
376 PRE(sys_pwritev)
378 Int i;
379 struct vki_iovec * vec;
380 char buf[sizeof("pwritev(iov[])") + 11];
381 *flags |= SfMayBlock;
382 PRINT("sys_pwritev ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
383 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
385 PRE_REG_READ4(ssize_t, "pwritev",
386 int, fd, const struct iovec *, iov,
387 int, iovcnt,
388 vki_off_t, offset);
389 if (!ML_(fd_allowed)(ARG1, "pwritev", tid, False)) {
390 SET_STATUS_Failure( VKI_EBADF );
391 } else {
392 if ((Int)ARG3 >= 0) {
393 PRE_MEM_READ( "pwritev(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
395 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
396 vec = (struct vki_iovec *)(Addr)ARG2;
397 for (i = 0; i < (Int)ARG3; i++) {
398 VG_(sprintf)(buf, "pwritev(iov[%d])", i);
399 PRE_MEM_READ(buf, (Addr)vec[i].iov_base, vec[i].iov_len );
405 // SYS_sendfile 393
406 // int sendfile(int fd, int s, off_t offset, size_t nbytes,
407 // struct sf_hdtr *hdtr, off_t *sbytes, int flags);
408 PRE(sys_sendfile)
410 *flags |= SfMayBlock;
412 PRINT("sys_sendfile ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %lu, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
413 SARG1,SARG2,ARG3,ARG4,ARG5,ARG6,SARG7);
414 PRE_REG_READ7(int, "sendfile",
415 int, fd, int, s, vki_off_t, offset, size_t, nbytes,
416 void *, hdtr, vki_off_t *, sbytes, int, flags);
418 if (ARG5 != 0) {
419 PRE_MEM_READ("sendfile(hdtr)", ARG5, sizeof(struct vki_sf_hdtr));
422 if (ARG6 != 0) {
423 PRE_MEM_WRITE( "sendfile(sbytes)", ARG6, sizeof(vki_off_t) );
427 POST(sys_sendfile)
429 if (ARG6 != 0 ) {
430 POST_MEM_WRITE( ARG6, sizeof( vki_off_t ) );
434 // SYS_sigreturn 417
435 // int sigreturn(const ucontext_t *scp);
436 PRE(sys_sigreturn)
438 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
439 PRE_REG_READ1(int, "sigreturn",
440 struct vki_ucontext *, scp);
442 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
443 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
446 static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc)
448 tst->arch.vex.guest_RAX = sc->rax;
449 tst->arch.vex.guest_RCX = sc->rcx;
450 tst->arch.vex.guest_RDX = sc->rdx;
451 tst->arch.vex.guest_RBX = sc->rbx;
452 tst->arch.vex.guest_RBP = sc->rbp;
453 tst->arch.vex.guest_RSP = sc->rsp;
454 tst->arch.vex.guest_RSI = sc->rsi;
455 tst->arch.vex.guest_RDI = sc->rdi;
456 tst->arch.vex.guest_R8 = sc->r8;
457 tst->arch.vex.guest_R9 = sc->r9;
458 tst->arch.vex.guest_R10 = sc->r10;
459 tst->arch.vex.guest_R11 = sc->r11;
460 tst->arch.vex.guest_R12 = sc->r12;
461 tst->arch.vex.guest_R13 = sc->r13;
462 tst->arch.vex.guest_R14 = sc->r14;
463 tst->arch.vex.guest_R15 = sc->r15;
464 tst->arch.vex.guest_RIP = sc->rip;
466 * XXX: missing support for other flags.
468 if (sc->rflags & 0x0001)
469 LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex);
470 else
471 LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex);
474 static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc)
476 sc->rax = tst->arch.vex.guest_RAX;
477 sc->rcx = tst->arch.vex.guest_RCX;
478 sc->rdx = tst->arch.vex.guest_RDX;
479 sc->rbx = tst->arch.vex.guest_RBX;
480 sc->rbp = tst->arch.vex.guest_RBP;
481 sc->rsp = tst->arch.vex.guest_RSP;
482 sc->rsi = tst->arch.vex.guest_RSI;
483 sc->rdi = tst->arch.vex.guest_RDI;
484 sc->r8 = tst->arch.vex.guest_R8;
485 sc->r9 = tst->arch.vex.guest_R9;
486 sc->r10 = tst->arch.vex.guest_R10;
487 sc->r11 = tst->arch.vex.guest_R11;
488 sc->r12 = tst->arch.vex.guest_R12;
489 sc->r13 = tst->arch.vex.guest_R13;
490 sc->r14 = tst->arch.vex.guest_R14;
491 sc->r15 = tst->arch.vex.guest_R15;
492 sc->rip = tst->arch.vex.guest_RIP;
494 Not supported by VEX.
495 sc->cs = tst->arch.vex.guest_CS;
496 sc->ss = tst->arch.vex.guest_SS;
497 sc->ds = tst->arch.vex.guest_DS;
498 sc->es = tst->arch.vex.guest_ES;
499 sc->fs = tst->arch.vex.guest_FS;
500 sc->gs = tst->arch.vex.guest_GS;
502 sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
504 not yet.
505 VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
507 sc->fpformat = VKI_FPFMT_NODEV;
508 sc->ownedfp = VKI_FPOWNED_NONE;
509 sc->len = sizeof(*sc);
510 VG_(memset)(sc->spare2, 0, sizeof(sc->spare2));
513 // SYS_getcontext 421
514 // int getcontext(ucontext_t *ucp);
515 PRE(sys_getcontext)
517 ThreadState* tst;
518 struct vki_ucontext *uc;
520 PRINT("sys_getcontext ( %#" FMT_REGWORD "x )", ARG1);
521 PRE_REG_READ1(int, "getcontext",
522 struct vki_ucontext *, ucp);
523 PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
524 uc = (struct vki_ucontext *)ARG1;
525 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext))) {
526 SET_STATUS_Failure(VKI_EFAULT);
527 return;
529 tst = VG_(get_ThreadState)(tid);
530 fill_mcontext(tst, &uc->uc_mcontext);
531 uc->uc_mcontext.rax = 0;
532 uc->uc_mcontext.rdx = 0;
533 uc->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
534 uc->uc_sigmask = tst->sig_mask;
535 VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__));
536 SET_STATUS_Success(0);
539 // SYS_setcontext 422
540 // int setcontext(const ucontext_t *ucp);
541 PRE(sys_setcontext)
543 ThreadState* tst;
544 struct vki_ucontext *uc;
546 PRINT("sys_setcontext ( %#" FMT_REGWORD "x )", ARG1);
547 PRE_REG_READ1(long, "setcontext",
548 struct vki_ucontext *, ucp);
550 PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
551 PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
553 vg_assert(VG_(is_valid_tid)(tid));
554 vg_assert(tid >= 1 && tid < VG_N_THREADS);
555 vg_assert(VG_(is_running_thread)(tid));
557 tst = VG_(get_ThreadState)(tid);
558 uc = (struct vki_ucontext *)ARG1;
559 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext)) || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
560 SET_STATUS_Failure(VKI_EFAULT);
561 return;
564 restore_mcontext(tst, &uc->uc_mcontext);
565 tst->sig_mask = uc->uc_sigmask;
566 tst->tmp_sig_mask = uc->uc_sigmask;
568 /* Tell the driver not to update the guest state with the "result",
569 and set a bogus result to keep it happy. */
570 *flags |= SfNoWriteResult;
571 SET_STATUS_Success(0);
573 /* Check to see if some any signals arose as a result of this. */
574 *flags |= SfPollAfter;
577 // SYS_swapcontext 423
578 // int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
579 PRE(sys_swapcontext)
581 struct vki_ucontext *ucp;
582 struct vki_ucontext *oucp;
583 ThreadState* tst;
585 PRINT("sys_swapcontext ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )", ARG1, ARG2);
586 PRE_REG_READ2(long, "swapcontext",
587 struct vki_ucontext *, oucp, struct vki_ucontext *, ucp);
589 PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) );
590 PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) );
592 oucp = (struct vki_ucontext *)ARG1;
593 ucp = (struct vki_ucontext *)ARG2;
594 if (!ML_(safe_to_deref)(oucp, sizeof(struct vki_ucontext)) ||
595 !ML_(safe_to_deref)(ucp, sizeof(struct vki_ucontext)) ||
596 ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) {
597 SET_STATUS_Failure(VKI_EINVAL);
598 return;
600 tst = VG_(get_ThreadState)(tid);
603 * Save the context.
605 fill_mcontext(tst, &oucp->uc_mcontext);
606 oucp->uc_mcontext.rax = 0;
607 oucp->uc_mcontext.rdx = 0;
608 oucp->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
609 oucp->uc_sigmask = tst->sig_mask;
610 VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__));
613 * Switch to new one.
615 restore_mcontext(tst, &ucp->uc_mcontext);
616 tst->sig_mask = ucp->uc_sigmask;
617 tst->tmp_sig_mask = ucp->uc_sigmask;
619 /* Tell the driver not to update the guest state with the "result",
620 and set a bogus result to keep it happy. */
621 *flags |= SfNoWriteResult;
622 SET_STATUS_Success(0);
624 /* Check to see if some any signals arose as a result of this. */
625 *flags |= SfPollAfter;
628 // SYS_thr_new 455
629 // int thr_new(struct thr_param *param, int param_size);
630 PRE(sys_thr_new)
632 static const Bool debug = False;
634 ThreadId ctid = VG_(alloc_ThreadState)();
635 ThreadState* ptst = VG_(get_ThreadState)(tid);
636 ThreadState* ctst = VG_(get_ThreadState)(ctid);
637 SysRes res;
638 vki_sigset_t blockall;
639 vki_sigset_t savedmask;
640 struct vki_thr_param tp;
641 Addr stk;
643 PRINT("thr_new ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u )",ARG1,ARG2);
644 PRE_REG_READ2(int, "thr_new",
645 struct thr_param *, param,
646 int, param_size);
648 PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare));
649 if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) {
650 SET_STATUS_Failure( VKI_EFAULT );
651 return;
653 VG_(memset)(&tp, 0, sizeof(tp));
654 VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare));
655 PRE_MEM_WRITE("thr_new(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long));
656 PRE_MEM_WRITE("thr_new(child_tidptr)", (Addr)tp.child_tid, sizeof(long));
658 VG_(sigfillset)(&blockall);
660 vg_assert(VG_(is_running_thread)(tid));
661 vg_assert(VG_(is_valid_tid)(ctid));
663 /* Copy register state
665 On linux, both parent and child return to the same place, and the code
666 following the clone syscall works out which is which, so we
667 don't need to worry about it.
668 On FreeBSD, thr_new arranges a direct call. We don't actually need any
669 of this gunk.
671 The parent gets the child's new tid returned from clone, but the
672 child gets 0.
674 If the clone call specifies a NULL rsp for the new thread, then
675 it actually gets a copy of the parent's rsp.
677 /* We inherit our parent's guest state. */
678 ctst->arch.vex = ptst->arch.vex;
679 ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
680 ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
682 /* Make thr_new appear to have returned Success(0) in the
683 child. */
684 ctst->arch.vex.guest_RAX = 0;
685 ctst->arch.vex.guest_RDX = 0;
686 LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex);
688 ctst->os_state.parent = tid;
690 /* inherit signal mask */
691 ctst->sig_mask = ptst->sig_mask;
692 ctst->tmp_sig_mask = ptst->sig_mask;
694 /* Linux has to guess, we don't */
695 ctst->client_stack_highest_byte = (Addr)tp.stack_base + tp.stack_size;
696 ctst->client_stack_szB = tp.stack_size;
697 ctst->os_state.stk_id = VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size);
699 /* Assume the thr_new will succeed, and tell any tool that wants to
700 know that this thread has come into existence. If the thr_new
701 fails, we'll send out a ll_exit notification for it at the out:
702 label below, to clean up. */
703 VG_TRACK ( pre_thread_ll_create, tid, ctid );
705 if (debug) {
706 VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
708 ctst->arch.vex.guest_FS_CONST = (UWord)tp.tls_base;
709 tp.tls_base = 0; /* Don't have the kernel do it too */
711 /* start the thread with everything blocked */
712 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
714 /* Set the client state for scheduler to run libthr's trampoline */
715 ctst->arch.vex.guest_RDI = (Addr)tp.arg;
716 /* XXX: align on 16-byte boundary? */
717 ctst->arch.vex.guest_RSP = (Addr)tp.stack_base + tp.stack_size - 8;
718 ctst->arch.vex.guest_RIP = (Addr)tp.start_func;
720 /* But this is for thr_new() to run valgrind's trampoline */
721 tp.start_func = (void *)ML_(start_thread_NORETURN);
722 tp.arg = &VG_(threads)[ctid];
724 /* And valgrind's trampoline on its own stack */
725 stk = ML_(allocstack)(ctid);
726 if (stk == (Addr)NULL) {
727 res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
728 goto fail;
730 tp.stack_base = (void *)ctst->os_state.valgrind_stack_base;
731 tp.stack_size = (Addr)stk - (Addr)tp.stack_base;
733 /* Create the new thread */
734 res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp));
736 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
738 fail:
739 if (sr_isError(res)) {
740 /* thr_new failed */
741 VG_(cleanup_thread)(&ctst->arch);
742 ctst->status = VgTs_Empty;
743 /* oops. Better tell the tool the thread exited in a hurry :-) */
744 VG_TRACK( pre_thread_ll_exit, ctid );
745 } else {
747 POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long));
748 POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long));
750 /* Thread creation was successful; let the child have the chance
751 to run */
752 *flags |= SfYieldAfter;
755 /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */
756 SET_STATUS_from_SysRes(res);
759 // SYS_pread 475
760 // ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
761 PRE(sys_pread)
763 *flags |= SfMayBlock;
764 PRINT("sys_pread ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
765 PRE_REG_READ4(ssize_t, "pread",
766 unsigned int, fd, char *, buf, vki_size_t, count,
767 unsigned long, off);
769 if (!ML_(fd_allowed)(ARG1, "read", tid, False)) {
770 SET_STATUS_Failure( VKI_EBADF );
771 } else {
772 PRE_MEM_WRITE( "pread(buf)", ARG2, ARG3 );
776 POST(sys_pread)
778 vg_assert(SUCCESS);
779 POST_MEM_WRITE( ARG2, RES );
782 // SYS_pwrite 476
783 // ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
784 PRE(sys_pwrite)
786 Bool ok;
787 *flags |= SfMayBlock;
788 PRINT("sys_pwrite ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
789 PRE_REG_READ4(ssize_t, "pwrite",
790 int, fd, const char *, buf, vki_size_t, nbytes,
791 vki_off_t, offset);
792 /* check to see if it is allowed. If not, try for an exemption from
793 --sim-hints=enable-outer (used for self hosting). */
794 ok = ML_(fd_allowed)(ARG1, "pwrite", tid, False);
795 if (!ok && ARG1 == 2/*stderr*/
796 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
797 ok = True;
798 if (!ok) {
799 SET_STATUS_Failure( VKI_EBADF );
800 } else {
801 PRE_MEM_READ( "pwrite(buf)", ARG2, ARG3 );
805 // SYS_mmap 477
806 /* FreeBSD-7 introduces a "regular" version of mmap etc. */
807 // void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
808 PRE(sys_mmap)
810 SysRes r;
812 PRINT("sys_mmap ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x)",
813 ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
814 PRE_REG_READ6(void *, "mmap",
815 void *, addr, size_t, len, int, prot, int, flags,
816 int, fd, off_t, offset);
818 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
819 SET_STATUS_from_SysRes(r);
822 // SYS_lseek 478
823 // off_t lseek(int fildes, off_t offset, int whence);
824 PRE(sys_lseek)
826 PRINT("sys_lseek ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3);
827 PRE_REG_READ3(long, "lseek",
828 unsigned int, fd, unsigned long, offset,
829 unsigned int, whence);
832 // SYS_truncate 479
833 // int truncate(const char *path, off_t length);
834 PRE(sys_truncate)
836 *flags |= SfMayBlock;
837 PRINT("sys_truncate ( %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u )", ARG1,(char *)ARG1,ARG2);
838 PRE_REG_READ2(long, "truncate",
839 const char *, path, unsigned long, length);
840 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
843 // SYS_ftruncate 480
844 // int ftruncate(int fd, off_t length);
845 PRE(sys_ftruncate)
847 *flags |= SfMayBlock;
848 PRINT("sys_ftruncate ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1,ARG2);
849 PRE_REG_READ2(long, "ftruncate", unsigned int, fd,
850 unsigned long, length);
853 // SYS_cpuset_setid 485
854 // int cpuset_setid(cpuwhich_t which, id_t id, cpusetid_t setid);
855 PRE(sys_cpuset_setid)
857 PRINT("sys_cpuset_setid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
858 SARG1, SARG2, ARG3);
859 PRE_REG_READ3(int, "cpuset_setid", vki_cpuwhich_t, which, vki_id_t, id,
860 vki_cpusetid_t *,setid);
863 // SYS_cpuset_getid 486
864 // int cpuset_getid(cpulevel_t level, cpuwhich_t which, id_t id,
865 // cpusetid_t *setid);
866 PRE(sys_cpuset_getid)
868 PRINT("sys_cpuset_getid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
869 SARG1, SARG2, SARG3, ARG4);
870 PRE_REG_READ4(int, "cpuset_getid", vki_cpulevel_t, level,
871 vki_cpuwhich_t, which, vki_id_t, id,
872 vki_cpusetid_t, setid);
873 PRE_MEM_WRITE("cpuset_getid(setid)", ARG4, sizeof(vki_cpusetid_t));
876 POST(sys_cpuset_getid)
878 POST_MEM_WRITE(ARG4, sizeof(vki_cpusetid_t));
881 // SYS_cpuset_getaffinity 487
882 // int cpuset_getaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
883 // size_t setsize, cpuset_t *mask);
884 PRE(sys_cpuset_getaffinity)
886 PRINT("sys_cpuset_getaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
887 ARG1, ARG2, SARG3, ARG4, ARG5);
888 PRE_REG_READ5(int, "cpuset_getaffinity",
889 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
890 size_t, setsize, void *, mask);
891 PRE_MEM_WRITE("cpuset_getaffinity", ARG5, ARG4);
894 POST(sys_cpuset_getaffinity)
896 vg_assert(SUCCESS);
897 if (RES == 0)
898 POST_MEM_WRITE( ARG5, ARG4 );
901 // SYS_cpuset_setaffinity 488
902 // int cpuset_setaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
903 // size_t setsize, const cpuset_t *mask);
904 PRE(sys_cpuset_setaffinity)
907 PRINT("sys_cpuset_setaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
908 ARG1, ARG2, SARG3, ARG4, ARG5);
909 PRE_REG_READ5(int, "cpuset_setaffinity",
910 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
911 size_t, setsize, void *, mask);
912 PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4);
915 // SYS_posix_fallocate 530
916 // int posix_fallocate(int fd, off_t offset, off_t len);
917 PRE(sys_posix_fallocate)
919 PRINT("sys_posix_fallocate ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",
920 SARG1, ARG2, ARG3);
921 PRE_REG_READ3(long, "posix_fallocate",
922 int, fd, vki_off_t, offset,
923 vki_off_t, len);
926 // SYS_posix_fadvise 531
927 // int posix_fadvise(int fd, off_t offset, off_t len, int advice);
928 PRE(sys_posix_fadvise)
930 PRINT("sys_posix_fadvise ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d )",
931 SARG1, ARG2, ARG3, SARG4);
932 PRE_REG_READ4(long, "posix_fadvise",
933 int, fd, off_t, offset,
934 off_t, len,
935 int, advice);
936 // @todo PJF advice can be 0 to 5 inclusive
939 // SYS_wait6 532
940 // pid_t wait6(idtype_t idtype, id_t id, int *status, int options,
941 // struct __wrusage *wrusage, siginfo_t *infop);
942 PRE(sys_wait6)
944 PRINT("sys_wait6 ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
945 SARG1, SARG2, ARG3, SARG4, ARG5, ARG6);
946 PRE_REG_READ6(pid_t, "wait6", vki_idtype_t, idtype, vki_id_t, id, int *, status, int, options,
947 struct vki___wrusage *, wrusage, vki_siginfo_t *,infop);
948 PRE_MEM_WRITE("wait6(status)", ARG3, sizeof(int));
949 if (ARG5) {
950 PRE_MEM_WRITE("wait6(wrusage)", ARG5, sizeof(struct vki___wrusage));
952 if (ARG6) {
953 PRE_MEM_WRITE("wait6(infop)", ARG6, sizeof(vki_siginfo_t));
957 POST(sys_wait6)
959 POST_MEM_WRITE(ARG3, sizeof(int));
960 if (ARG5) {
961 POST_MEM_WRITE(ARG5, sizeof(struct vki___wrusage));
964 if (ARG6) {
965 POST_MEM_WRITE(ARG6, sizeof(vki_siginfo_t));
969 // the man page is inconsistent for the last argument
970 // See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=247386
971 // will stick to 'arg' for simplicity
973 // SYS_procctl 544
974 // int procctl(idtype_t idtype, id_t id, int cmd, void *arg);
975 PRE(sys_procctl)
977 PRINT("sys_procctl ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD"d, %#" FMT_REGWORD "x )",
978 SARG1, SARG2, SARG3, ARG4);
979 PRE_REG_READ4(int, "procctl", vki_idtype_t, idtype, vki_id_t, id, int, cmd, void *, arg);
980 switch (ARG3) {
981 case VKI_PROC_ASLR_CTL:
982 case VKI_PROC_SPROTECT:
983 case VKI_PROC_TRACE_CTL:
984 case VKI_PROC_TRAPCAP_CTL:
985 case VKI_PROC_PDEATHSIG_CTL:
986 case VKI_PROC_STACKGAP_CTL:
987 case VKI_PROC_NO_NEW_PRIVS_CTL:
988 case VKI_PROC_WXMAP_CTL:
989 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(int));
990 break;
991 case VKI_PROC_REAP_STATUS:
992 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(struct vki_procctl_reaper_status));
993 break;
994 case VKI_PROC_REAP_GETPIDS:
995 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(struct vki_procctl_reaper_pids));
996 break;
997 case VKI_PROC_REAP_KILL:
998 /* The first three fields are reads
999 * int rk_sig;
1000 * u_int rk_flags;
1001 * pid_t rk_subtree;
1003 * The last two fields are writes
1004 * u_int rk_killed;
1005 * pid_t rk_fpid;
1007 * There is also a pad field
1009 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(int) + sizeof(u_int) + sizeof(vki_pid_t));
1010 PRE_MEM_WRITE("procctl(arg)", ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
1011 break;
1012 case VKI_PROC_ASLR_STATUS:
1013 case VKI_PROC_PDEATHSIG_STATUS:
1014 case VKI_PROC_STACKGAP_STATUS:
1015 case VKI_PROC_TRAPCAP_STATUS:
1016 case VKI_PROC_TRACE_STATUS:
1017 case VKI_PROC_NO_NEW_PRIVS_STATUS:
1018 case VKI_PROC_WXMAP_STATUS:
1019 PRE_MEM_WRITE("procctl(arg)", ARG4, sizeof(int));
1020 case VKI_PROC_REAP_ACQUIRE:
1021 case VKI_PROC_REAP_RELEASE:
1022 default:
1023 break;
1027 POST(sys_procctl)
1029 switch (ARG3) {
1030 case VKI_PROC_REAP_KILL:
1031 POST_MEM_WRITE(ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
1032 break;
1033 case VKI_PROC_ASLR_STATUS:
1034 case VKI_PROC_PDEATHSIG_STATUS:
1035 case VKI_PROC_STACKGAP_STATUS:
1036 case VKI_PROC_TRAPCAP_STATUS:
1037 case VKI_PROC_TRACE_STATUS:
1038 case VKI_PROC_NO_NEW_PRIVS_STATUS:
1039 case VKI_PROC_WXMAP_STATUS:
1040 POST_MEM_WRITE(ARG4, sizeof(int));
1041 default:
1042 break;
1046 // SYS_mknodat 559
1047 // int mknodat(int fd, const char *path, mode_t mode, dev_t dev);
1048 PRE(sys_mknodat)
1050 PRINT("sys_mknodat ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x(%s), 0x%" FMT_REGWORD "x, 0x%" FMT_REGWORD "x )", ARG1,ARG2,(char*)ARG2,ARG3,ARG4 );
1051 PRE_REG_READ4(long, "mknodat",
1052 int, fd, const char *, path, vki_mode_t, mode, vki_dev_t, dev);
1053 PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 );
1056 #if (FREEBSD_VERS >= FREEBSD_12)
1058 // SYS_cpuset_getdomain 561
1059 // int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id,
1060 // size_t setsize, domainset_t *mask, int *policy);
1061 PRE(sys_cpuset_getdomain)
1063 PRINT("sys_cpuset_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
1064 SARG1, SARG2, SARG3, ARG4, ARG5, ARG6);
1065 PRE_REG_READ6(int, "cpuset_getdomain",
1066 cpulevel_t, level, cpuwhich_t, which, id_t, id,
1067 size_t, setsize, vki_domainset_t *, mask, int *, policy);
1068 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
1069 PRE_MEM_WRITE( "cpuset_getdomain(mask)", ARG5, ARG4 );
1070 PRE_MEM_WRITE( "cpuset_getdomain(policy)", ARG6, sizeof(int) );
1073 POST(sys_cpuset_getdomain)
1075 POST_MEM_WRITE(ARG5, ARG4 );
1076 POST_MEM_WRITE(ARG6, sizeof(int) );
1079 // SYS_cpuset_setdomain 562
1080 // int cuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id,
1081 // size_t setsize, const domainset_t *mask, int policy);
1082 PRE(sys_cpuset_setdomain)
1084 PRINT("sys_cpuget_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
1085 SARG1, SARG2, SARG3, ARG4, ARG5, SARG6);
1086 PRE_REG_READ6(int, "cpuset_getdomain",
1087 cpulevel_t, level, cpuwhich_t, which, id_t, id,
1088 size_t, setsize, vki_domainset_t *, mask, int, policy);
1089 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
1090 PRE_MEM_READ( "cpuset_getdomain(mask)", ARG5, ARG4 );
1093 #endif
1095 PRE(sys_fake_sigreturn)
1097 ThreadState* tst;
1098 struct vki_ucontext *uc;
1099 ULong rflags;
1101 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
1102 PRE_REG_READ1(long, "sigreturn",
1103 struct vki_ucontext *, scp);
1105 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1106 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1108 vg_assert(VG_(is_valid_tid)(tid));
1109 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1110 vg_assert(VG_(is_running_thread)(tid));
1112 /* Adjust esp to point to start of frame; skip back up over handler
1113 ret addr */
1114 tst = VG_(get_ThreadState)(tid);
1115 tst->arch.vex.guest_RSP -= sizeof(Addr);
1117 uc = (struct vki_ucontext *)ARG1;
1118 if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
1119 SET_STATUS_Failure(VKI_EINVAL);
1120 return;
1123 /* This is only so that the EIP is (might be) useful to report if
1124 something goes wrong in the sigreturn */
1125 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
1127 VG_(sigframe_destroy)(tid);
1129 /* For unclear reasons, it appears we need the syscall to return
1130 without changing %RAX. Since %RAX is the return value, and can
1131 denote either success or failure, we must set up so that the
1132 driver logic copies it back unchanged. Also, note %RAX is of
1133 the guest registers written by VG_(sigframe_destroy). */
1134 rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
1135 SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_freebsd)( tst->arch.vex.guest_RAX,
1136 tst->arch.vex.guest_RDX, (rflags & 1U) != 0U ? True : False) );
1139 * Signal handler might have changed the signal mask. Respect that.
1141 tst->sig_mask = uc->uc_sigmask;
1142 tst->tmp_sig_mask = uc->uc_sigmask;
1144 /* Tell the driver not to update the guest state with the "result",
1145 and set a bogus result to keep it happy. */
1146 *flags |= SfNoWriteResult;
1147 SET_STATUS_Success(0);
1149 /* Check to see if some any signals arose as a result of this. */
1150 *flags |= SfPollAfter;
1154 #undef PRE
1155 #undef POST
1157 #endif /* defined(VGP_amd64_freebsd) */
1159 /*--------------------------------------------------------------------*/
1160 /*--- end ---*/
1161 /*--------------------------------------------------------------------*/