Bug 444488 - Use glibc.pthread.stack_cache_size tunable
[valgrind.git] / coregrind / m_syswrap / syswrap-amd64-freebsd.c
blob3b2f9397d1508c3ad5754918b15f1a9b6b7a72d9
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 POST_MEM_WRITE( ARG2, sizeof(void *) );
182 break;
183 case VKI_AMD64_GET_XFPUSTATE:
184 POST_MEM_WRITE( ARG2, sizeof(void *) );
185 break;
186 default:
187 break;
191 // freebsd6_pread 173
192 #if (FREEBSD_VERS <= FREEBSD_10)
193 PRE(sys_freebsd6_pread)
195 *flags |= SfMayBlock;
196 PRINT("sys_freebsd6_pread ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %lu, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4, ARG5);
197 PRE_REG_READ5(ssize_t, "read",
198 unsigned int, fd, char *, buf, vki_size_t, count,
199 int, pad, unsigned long, off);
201 if (!ML_(fd_allowed)(ARG1, "freebsd6_pread", tid, False))
202 SET_STATUS_Failure( VKI_EBADF );
203 else
204 PRE_MEM_WRITE( "freebsd6_pread(buf)", ARG2, ARG3 );
207 POST(sys_freebsd6_pread)
209 vg_assert(SUCCESS);
210 POST_MEM_WRITE( ARG2, RES );
212 #endif
214 // freebsd6_pwrite 174
215 #if (FREEBSD_VERS <= FREEBSD_10)
216 PRE(sys_freebsd6_pwrite)
218 Bool ok;
219 *flags |= SfMayBlock;
220 PRINT("sys_freebsd6_pwrite ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", SARG1, ARG2, ARG3, ARG4, ARG5);
221 PRE_REG_READ5(ssize_t, "write",
222 unsigned int, fd, const char *, buf, vki_size_t, count,
223 int, pad, unsigned long, off);
224 /* check to see if it is allowed. If not, try for an exemption from
225 --sim-hints=enable-outer (used for self hosting). */
226 ok = ML_(fd_allowed)(ARG1, "freebsd6_pwrite", tid, False);
227 if (!ok && ARG1 == 2/*stderr*/
228 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
229 ok = True;
230 if (!ok)
231 SET_STATUS_Failure( VKI_EBADF );
232 else
233 PRE_MEM_READ( "freebsd6_pwrite(buf)", ARG2, ARG3 );
235 #endif
237 // SYS_freebsd6_mmap 197
238 #if (FREEBSD_VERS <= FREEBSD_10)
239 /* This is here because on x86 the off_t is passed in 2 regs. Don't ask about pad. */
241 /* caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); */
242 /* ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 */
244 PRE(sys_freebsd6_mmap)
246 SysRes r;
248 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)",
249 ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6, ARG7 );
250 PRE_REG_READ7(long, "mmap",
251 char *, addr, unsigned long, len, int, prot, int, flags,
252 int, fd, int, pad, unsigned long, pos);
254 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG7 );
255 SET_STATUS_from_SysRes(r);
257 #endif
259 // freebsd6_lseek 199
260 #if (FREEBSD_VERS <= FREEBSD_10)
261 PRE(sys_freebsd6_lseek)
263 PRINT("sys_freebsd6_lseek ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3,ARG4);
264 PRE_REG_READ4(long, "lseek",
265 unsigned int, fd, int, pad, unsigned long, offset,
266 unsigned int, whence);
268 #endif
270 // freebsd6_truncate 200
271 #if (FREEBSD_VERS <= FREEBSD_10)
272 PRE(sys_freebsd6_truncate)
274 *flags |= SfMayBlock;
275 PRINT("sys_truncate ( %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u )", ARG1,(char *)ARG1,ARG3);
276 PRE_REG_READ3(long, "truncate",
277 const char *, path, int, pad, unsigned int, length);
278 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
280 #endif
282 // freebsd6_ftruncate 201
283 #if (FREEBSD_VERS <= FREEBSD_10)
284 PRE(sys_freebsd6_ftruncate)
286 *flags |= SfMayBlock;
287 PRINT("sys_ftruncate ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1,ARG3);
288 PRE_REG_READ3(long, "ftruncate", unsigned int, fd, int, pad,
289 unsigned int, length);
291 #endif
293 // SYS_clock_getcpuclockid2 247
294 // no manpage for this, from syscalls.master
295 // int clock_getcpuclockid2(id_t id, int which, _Out_ clockid_t *clock_id);
296 PRE(sys_clock_getcpuclockid2)
298 PRINT("sys_clock_getcpuclockid2( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
299 SARG1,SARG2,ARG3);
300 PRE_REG_READ3(int, "clock_getcpuclockid2",
301 id_t, id, int, len, clockid_t *, clock_id);
302 PRE_MEM_WRITE("clock_getcpuclockid2(clock_id)", ARG3, sizeof(vki_clockid_t));
305 // SYS_rfork 251
306 // pid_t rfork(int flags);
307 PRE(sys_rfork)
309 PRINT("sys_rfork ( %#" FMT_REGWORD "x )", ARG1 );
310 PRE_REG_READ1(long, "rfork", int, flags);
312 VG_(message)(Vg_UserMsg, "rfork() not implemented");
313 VG_(unimplemented)("Valgrind does not support rfork().");
315 SET_STATUS_Failure(VKI_ENOSYS);
318 // SYS_preadv 289
319 // ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
320 PRE(sys_preadv)
322 Int i;
323 struct vki_iovec * vec;
324 char buf[sizeof("preadv(iov[])") + 11];
325 *flags |= SfMayBlock;
326 PRINT("sys_preadv ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
327 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
328 PRE_REG_READ4(ssize_t, "preadv",
329 int, fd, const struct iovec *, iov,
330 int, iovcnt, vki_off_t, offset);
331 if (!ML_(fd_allowed)(ARG1, "preadv", tid, False)) {
332 SET_STATUS_Failure( VKI_EBADF );
333 } else {
334 if ((Int)ARG3 > 0)
335 PRE_MEM_READ( "preadv(iov)", ARG2, ARG3 * sizeof(struct vki_iovec) );
337 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
338 vec = (struct vki_iovec *)(Addr)ARG2;
339 for (i = 0; i < (Int)ARG3; i++) {
340 VG_(sprintf)(buf, "preadv(iov[%d])", i);
341 PRE_MEM_WRITE(buf, (Addr)vec[i].iov_base, vec[i].iov_len);
347 POST(sys_preadv)
349 vg_assert(SUCCESS);
350 if (RES > 0) {
351 Int i;
352 struct vki_iovec * vec = (struct vki_iovec *)(Addr)ARG2;
353 Int remains = RES;
355 /* RES holds the number of bytes read. */
356 for (i = 0; i < (Int)ARG3; i++) {
357 Int nReadThisBuf = vec[i].iov_len;
358 if (nReadThisBuf > remains) nReadThisBuf = remains;
359 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
360 remains -= nReadThisBuf;
361 if (remains < 0) VG_(core_panic)("preadv: remains < 0");
366 // SYS_pwritev 290
367 // ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
368 PRE(sys_pwritev)
370 Int i;
371 struct vki_iovec * vec;
372 char buf[sizeof("pwritev(iov[])") + 11];
373 *flags |= SfMayBlock;
374 PRINT("sys_pwritev ( %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %"
375 FMT_REGWORD "d, %" FMT_REGWORD "d )", SARG1, ARG2, SARG3, SARG4);
377 PRE_REG_READ4(ssize_t, "pwritev",
378 int, fd, const struct iovec *, iov,
379 int, iovcnt,
380 vki_off_t, offset);
381 if (!ML_(fd_allowed)(ARG1, "pwritev", tid, False)) {
382 SET_STATUS_Failure( VKI_EBADF );
383 } else {
384 if ((Int)ARG3 >= 0)
385 PRE_MEM_READ( "pwritev(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
386 if (ML_(safe_to_deref)((struct vki_iovec *)ARG2, ARG3 * sizeof(struct vki_iovec))) {
387 vec = (struct vki_iovec *)(Addr)ARG2;
388 for (i = 0; i < (Int)ARG3; i++) {
389 VG_(sprintf)(buf, "pwritev(iov[%d])", i);
390 PRE_MEM_READ(buf, (Addr)vec[i].iov_base, vec[i].iov_len );
396 // SYS_sendfile 393
397 // int sendfile(int fd, int s, off_t offset, size_t nbytes,
398 // struct sf_hdtr *hdtr, off_t *sbytes, int flags);
399 PRE(sys_sendfile)
401 *flags |= SfMayBlock;
403 PRINT("sys_sendfile ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %lu, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
404 SARG1,SARG2,ARG3,ARG4,ARG5,ARG6,SARG7);
405 PRE_REG_READ7(int, "sendfile",
406 int, fd, int, s, vki_off_t, offset, size_t, nbytes,
407 void *, hdtr, vki_off_t *, sbytes, int, flags);
409 if (ARG5 != 0)
410 PRE_MEM_READ("sendfile(hdtr)", ARG5, sizeof(struct vki_sf_hdtr));
412 if (ARG6 != 0)
413 PRE_MEM_WRITE( "sendfile(sbytes)", ARG6, sizeof(vki_off_t) );
416 POST(sys_sendfile)
418 if (ARG6 != 0 ) {
419 POST_MEM_WRITE( ARG6, sizeof( vki_off_t ) );
423 // SYS_sigreturn 417
424 // int sigreturn(const ucontext_t *scp);
425 PRE(sys_sigreturn)
427 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
428 PRE_REG_READ1(int, "sigreturn",
429 struct vki_ucontext *, scp);
431 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
432 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
435 static void restore_mcontext(ThreadState *tst, struct vki_mcontext *sc)
437 tst->arch.vex.guest_RAX = sc->rax;
438 tst->arch.vex.guest_RCX = sc->rcx;
439 tst->arch.vex.guest_RDX = sc->rdx;
440 tst->arch.vex.guest_RBX = sc->rbx;
441 tst->arch.vex.guest_RBP = sc->rbp;
442 tst->arch.vex.guest_RSP = sc->rsp;
443 tst->arch.vex.guest_RSI = sc->rsi;
444 tst->arch.vex.guest_RDI = sc->rdi;
445 tst->arch.vex.guest_R8 = sc->r8;
446 tst->arch.vex.guest_R9 = sc->r9;
447 tst->arch.vex.guest_R10 = sc->r10;
448 tst->arch.vex.guest_R11 = sc->r11;
449 tst->arch.vex.guest_R12 = sc->r12;
450 tst->arch.vex.guest_R13 = sc->r13;
451 tst->arch.vex.guest_R14 = sc->r14;
452 tst->arch.vex.guest_R15 = sc->r15;
453 tst->arch.vex.guest_RIP = sc->rip;
455 * XXX: missing support for other flags.
457 if (sc->rflags & 0x0001)
458 LibVEX_GuestAMD64_put_rflag_c(1, &tst->arch.vex);
459 else
460 LibVEX_GuestAMD64_put_rflag_c(0, &tst->arch.vex);
463 static void fill_mcontext(ThreadState *tst, struct vki_mcontext *sc)
465 sc->rax = tst->arch.vex.guest_RAX;
466 sc->rcx = tst->arch.vex.guest_RCX;
467 sc->rdx = tst->arch.vex.guest_RDX;
468 sc->rbx = tst->arch.vex.guest_RBX;
469 sc->rbp = tst->arch.vex.guest_RBP;
470 sc->rsp = tst->arch.vex.guest_RSP;
471 sc->rsi = tst->arch.vex.guest_RSI;
472 sc->rdi = tst->arch.vex.guest_RDI;
473 sc->r8 = tst->arch.vex.guest_R8;
474 sc->r9 = tst->arch.vex.guest_R9;
475 sc->r10 = tst->arch.vex.guest_R10;
476 sc->r11 = tst->arch.vex.guest_R11;
477 sc->r12 = tst->arch.vex.guest_R12;
478 sc->r13 = tst->arch.vex.guest_R13;
479 sc->r14 = tst->arch.vex.guest_R14;
480 sc->r15 = tst->arch.vex.guest_R15;
481 sc->rip = tst->arch.vex.guest_RIP;
483 Not supported by VEX.
484 sc->cs = tst->arch.vex.guest_CS;
485 sc->ss = tst->arch.vex.guest_SS;
486 sc->ds = tst->arch.vex.guest_DS;
487 sc->es = tst->arch.vex.guest_ES;
488 sc->fs = tst->arch.vex.guest_FS;
489 sc->gs = tst->arch.vex.guest_GS;
491 sc->rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
493 not yet.
494 VG_(memcpy)(&sc->fpstate, fpstate, sizeof(*fpstate));
496 sc->fpformat = VKI_FPFMT_NODEV;
497 sc->ownedfp = VKI_FPOWNED_NONE;
498 sc->len = sizeof(*sc);
499 VG_(memset)(sc->spare2, 0, sizeof(sc->spare2));
502 // SYS_getcontext 421
503 // int getcontext(ucontext_t *ucp);
504 PRE(sys_getcontext)
506 ThreadState* tst;
507 struct vki_ucontext *uc;
509 PRINT("sys_getcontext ( %#" FMT_REGWORD "x )", ARG1);
510 PRE_REG_READ1(int, "getcontext",
511 struct vki_ucontext *, ucp);
512 PRE_MEM_WRITE( "getcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
513 uc = (struct vki_ucontext *)ARG1;
514 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext))) {
515 SET_STATUS_Failure(VKI_EFAULT);
516 return;
518 tst = VG_(get_ThreadState)(tid);
519 fill_mcontext(tst, &uc->uc_mcontext);
520 uc->uc_mcontext.rax = 0;
521 uc->uc_mcontext.rdx = 0;
522 uc->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
523 uc->uc_sigmask = tst->sig_mask;
524 VG_(memset)(uc->__spare__, 0, sizeof(uc->__spare__));
525 SET_STATUS_Success(0);
528 // SYS_setcontext 422
529 // int setcontext(const ucontext_t *ucp);
530 PRE(sys_setcontext)
532 ThreadState* tst;
533 struct vki_ucontext *uc;
535 PRINT("sys_setcontext ( %#" FMT_REGWORD "x )", ARG1);
536 PRE_REG_READ1(long, "setcontext",
537 struct vki_ucontext *, ucp);
539 PRE_MEM_READ( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
540 PRE_MEM_WRITE( "setcontext(ucp)", ARG1, sizeof(struct vki_ucontext) );
542 vg_assert(VG_(is_valid_tid)(tid));
543 vg_assert(tid >= 1 && tid < VG_N_THREADS);
544 vg_assert(VG_(is_running_thread)(tid));
546 tst = VG_(get_ThreadState)(tid);
547 uc = (struct vki_ucontext *)ARG1;
548 if (!ML_(safe_to_deref)(uc, sizeof(struct vki_ucontext)) || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
549 SET_STATUS_Failure(VKI_EFAULT);
550 return;
553 restore_mcontext(tst, &uc->uc_mcontext);
554 tst->sig_mask = uc->uc_sigmask;
555 tst->tmp_sig_mask = uc->uc_sigmask;
557 /* Tell the driver not to update the guest state with the "result",
558 and set a bogus result to keep it happy. */
559 *flags |= SfNoWriteResult;
560 SET_STATUS_Success(0);
562 /* Check to see if some any signals arose as a result of this. */
563 *flags |= SfPollAfter;
566 // SYS_swapcontext 423
567 // int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
568 PRE(sys_swapcontext)
570 struct vki_ucontext *ucp, *oucp;
571 ThreadState* tst;
573 PRINT("sys_swapcontext ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )", ARG1, ARG2);
574 PRE_REG_READ2(long, "swapcontext",
575 struct vki_ucontext *, oucp, struct vki_ucontext *, ucp);
577 PRE_MEM_READ( "swapcontext(ucp)", ARG2, sizeof(struct vki_ucontext) );
578 PRE_MEM_WRITE( "swapcontext(oucp)", ARG1, sizeof(struct vki_ucontext) );
580 oucp = (struct vki_ucontext *)ARG1;
581 ucp = (struct vki_ucontext *)ARG2;
582 if (!ML_(safe_to_deref)(oucp, sizeof(struct vki_ucontext)) ||
583 !ML_(safe_to_deref)(ucp, sizeof(struct vki_ucontext)) ||
584 ucp->uc_mcontext.len != sizeof(ucp->uc_mcontext)) {
585 SET_STATUS_Failure(VKI_EINVAL);
586 return;
588 tst = VG_(get_ThreadState)(tid);
591 * Save the context.
593 fill_mcontext(tst, &oucp->uc_mcontext);
594 oucp->uc_mcontext.rax = 0;
595 oucp->uc_mcontext.rdx = 0;
596 oucp->uc_mcontext.rflags &= ~0x0001; /* PSL_C */
597 oucp->uc_sigmask = tst->sig_mask;
598 VG_(memset)(oucp->__spare__, 0, sizeof(oucp->__spare__));
601 * Switch to new one.
603 restore_mcontext(tst, &ucp->uc_mcontext);
604 tst->sig_mask = ucp->uc_sigmask;
605 tst->tmp_sig_mask = ucp->uc_sigmask;
607 /* Tell the driver not to update the guest state with the "result",
608 and set a bogus result to keep it happy. */
609 *flags |= SfNoWriteResult;
610 SET_STATUS_Success(0);
612 /* Check to see if some any signals arose as a result of this. */
613 *flags |= SfPollAfter;
616 // SYS_thr_new 455
617 // int thr_new(struct thr_param *param, int param_size);
618 PRE(sys_thr_new)
620 static const Bool debug = False;
622 ThreadId ctid = VG_(alloc_ThreadState)();
623 ThreadState* ptst = VG_(get_ThreadState)(tid);
624 ThreadState* ctst = VG_(get_ThreadState)(ctid);
625 SysRes res;
626 vki_sigset_t blockall, savedmask;
627 struct vki_thr_param tp;
628 Addr stk;
630 PRINT("thr_new ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u )",ARG1,ARG2);
631 PRE_REG_READ2(int, "thr_new",
632 struct thr_param *, param,
633 int, param_size);
635 PRE_MEM_READ( "thr_new(param)", ARG1, offsetof(struct vki_thr_param, spare));
636 if (!ML_(safe_to_deref)( (void*)ARG1, offsetof(struct vki_thr_param, spare))) {
637 SET_STATUS_Failure( VKI_EFAULT );
638 return;
640 VG_(memset)(&tp, 0, sizeof(tp));
641 VG_(memcpy)(&tp, (void *)ARG1, offsetof(struct vki_thr_param, spare));
642 PRE_MEM_WRITE("thr_new(parent_tidptr)", (Addr)tp.parent_tid, sizeof(long));
643 PRE_MEM_WRITE("thr_new(child_tidptr)", (Addr)tp.child_tid, sizeof(long));
645 VG_(sigfillset)(&blockall);
647 vg_assert(VG_(is_running_thread)(tid));
648 vg_assert(VG_(is_valid_tid)(ctid));
650 /* Copy register state
652 On linux, both parent and child return to the same place, and the code
653 following the clone syscall works out which is which, so we
654 don't need to worry about it.
655 On FreeBSD, thr_new arranges a direct call. We don't actually need any
656 of this gunk.
658 The parent gets the child's new tid returned from clone, but the
659 child gets 0.
661 If the clone call specifies a NULL rsp for the new thread, then
662 it actually gets a copy of the parent's rsp.
664 /* We inherit our parent's guest state. */
665 ctst->arch.vex = ptst->arch.vex;
666 ctst->arch.vex_shadow1 = ptst->arch.vex_shadow1;
667 ctst->arch.vex_shadow2 = ptst->arch.vex_shadow2;
669 /* Make thr_new appear to have returned Success(0) in the
670 child. */
671 ctst->arch.vex.guest_RAX = 0;
672 ctst->arch.vex.guest_RDX = 0;
673 LibVEX_GuestAMD64_put_rflag_c(0, &ctst->arch.vex);
675 ctst->os_state.parent = tid;
677 /* inherit signal mask */
678 ctst->sig_mask = ptst->sig_mask;
679 ctst->tmp_sig_mask = ptst->sig_mask;
681 /* Linux has to guess, we don't */
682 ctst->client_stack_highest_byte = (Addr)tp.stack_base + tp.stack_size;
683 ctst->client_stack_szB = tp.stack_size;
684 ctst->os_state.stk_id = VG_(register_stack)((Addr)tp.stack_base, (Addr)tp.stack_base + tp.stack_size);
686 /* Assume the thr_new will succeed, and tell any tool that wants to
687 know that this thread has come into existence. If the thr_new
688 fails, we'll send out a ll_exit notification for it at the out:
689 label below, to clean up. */
690 VG_TRACK ( pre_thread_ll_create, tid, ctid );
692 if (debug)
693 VG_(printf)("clone child has SETTLS: tls at %#lx\n", (Addr)tp.tls_base);
694 ctst->arch.vex.guest_FS_CONST = (UWord)tp.tls_base;
695 tp.tls_base = 0; /* Don't have the kernel do it too */
697 /* start the thread with everything blocked */
698 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
700 /* Set the client state for scheduler to run libthr's trampoline */
701 ctst->arch.vex.guest_RDI = (Addr)tp.arg;
702 /* XXX: align on 16-byte boundary? */
703 ctst->arch.vex.guest_RSP = (Addr)tp.stack_base + tp.stack_size - 8;
704 ctst->arch.vex.guest_RIP = (Addr)tp.start_func;
706 /* But this is for thr_new() to run valgrind's trampoline */
707 tp.start_func = (void *)ML_(start_thread_NORETURN);
708 tp.arg = &VG_(threads)[ctid];
710 /* And valgrind's trampoline on its own stack */
711 stk = ML_(allocstack)(ctid);
712 if (stk == (Addr)NULL) {
713 res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
714 goto fail;
716 tp.stack_base = (void *)ctst->os_state.valgrind_stack_base;
717 tp.stack_size = (Addr)stk - (Addr)tp.stack_base;
719 /* Create the new thread */
720 res = VG_(do_syscall2)(__NR_thr_new, (UWord)&tp, sizeof(tp));
722 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
724 fail:
725 if (sr_isError(res)) {
726 /* thr_new failed */
727 VG_(cleanup_thread)(&ctst->arch);
728 ctst->status = VgTs_Empty;
729 /* oops. Better tell the tool the thread exited in a hurry :-) */
730 VG_TRACK( pre_thread_ll_exit, ctid );
731 } else {
733 POST_MEM_WRITE((Addr)tp.parent_tid, sizeof(long));
734 POST_MEM_WRITE((Addr)tp.child_tid, sizeof(long));
736 /* Thread creation was successful; let the child have the chance
737 to run */
738 *flags |= SfYieldAfter;
741 /* "Complete" the syscall so that the wrapper doesn't call the kernel again. */
742 SET_STATUS_from_SysRes(res);
745 // SYS_pread 475
746 // ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset);
747 PRE(sys_pread)
749 *flags |= SfMayBlock;
750 PRINT("sys_pread ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
751 PRE_REG_READ4(ssize_t, "pread",
752 unsigned int, fd, char *, buf, vki_size_t, count,
753 unsigned long, off);
755 if (!ML_(fd_allowed)(ARG1, "read", tid, False))
756 SET_STATUS_Failure( VKI_EBADF );
757 else
758 PRE_MEM_WRITE( "pread(buf)", ARG2, ARG3 );
761 POST(sys_pread)
763 vg_assert(SUCCESS);
764 POST_MEM_WRITE( ARG2, RES );
767 // SYS_pwrite 476
768 // ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);
769 PRE(sys_pwrite)
771 Bool ok;
772 *flags |= SfMayBlock;
773 PRINT("sys_pwrite ( %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3, ARG4);
774 PRE_REG_READ4(ssize_t, "pwrite",
775 int, fd, const char *, buf, vki_size_t, nbytes,
776 vki_off_t, offset);
777 /* check to see if it is allowed. If not, try for an exemption from
778 --sim-hints=enable-outer (used for self hosting). */
779 ok = ML_(fd_allowed)(ARG1, "pwrite", tid, False);
780 if (!ok && ARG1 == 2/*stderr*/
781 && SimHintiS(SimHint_enable_outer, VG_(clo_sim_hints)))
782 ok = True;
783 if (!ok)
784 SET_STATUS_Failure( VKI_EBADF );
785 else
786 PRE_MEM_READ( "pwrite(buf)", ARG2, ARG3 );
789 // SYS_mmap 477
790 /* FreeBSD-7 introduces a "regular" version of mmap etc. */
791 // void * mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
792 PRE(sys_mmap)
794 SysRes r;
796 PRINT("sys_mmap ( %#" FMT_REGWORD "x, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x)",
797 ARG1, (UWord)ARG2, ARG3, ARG4, ARG5, ARG6 );
798 PRE_REG_READ6(void *, "mmap",
799 void *, addr, size_t, len, int, prot, int, flags,
800 int, fd, off_t, offset);
802 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
803 SET_STATUS_from_SysRes(r);
806 // SYS_lseek 478
807 // off_t lseek(int fildes, off_t offset, int whence);
808 PRE(sys_lseek)
810 PRINT("sys_lseek ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %" FMT_REGWORD "u )", ARG1,ARG2,ARG3);
811 PRE_REG_READ3(long, "lseek",
812 unsigned int, fd, unsigned long, offset,
813 unsigned int, whence);
816 // SYS_truncate 479
817 // int truncate(const char *path, off_t length);
818 PRE(sys_truncate)
820 *flags |= SfMayBlock;
821 PRINT("sys_truncate ( %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u )", ARG1,(char *)ARG1,ARG2);
822 PRE_REG_READ2(long, "truncate",
823 const char *, path, unsigned long, length);
824 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
827 // SYS_ftruncate 480
828 // int ftruncate(int fd, off_t length);
829 PRE(sys_ftruncate)
831 *flags |= SfMayBlock;
832 PRINT("sys_ftruncate ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1,ARG2);
833 PRE_REG_READ2(long, "ftruncate", unsigned int, fd,
834 unsigned long, length);
837 // SYS_cpuset_setid 485
838 // int cpuset_setid(cpuwhich_t which, id_t id, cpusetid_t setid);
839 PRE(sys_cpuset_setid)
841 PRINT("sys_cpuset_setid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
842 SARG1, SARG2, ARG3);
843 PRE_REG_READ3(int, "cpuset_setid", vki_cpuwhich_t, which, vki_id_t, id,
844 vki_cpusetid_t *,setid);
847 // SYS_cpuset_getid 486
848 // int cpuset_getid(cpulevel_t level, cpuwhich_t which, id_t id,
849 // cpusetid_t *setid);
850 PRE(sys_cpuset_getid)
852 PRINT("sys_cpuset_getid ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x )",
853 SARG1, SARG2, SARG3, ARG4);
854 PRE_REG_READ4(int, "cpuset_getid", vki_cpulevel_t, level,
855 vki_cpuwhich_t, which, vki_id_t, id,
856 vki_cpusetid_t, setid);
857 PRE_MEM_WRITE("cpuset_getid(setid)", ARG4, sizeof(vki_cpusetid_t));
860 POST(sys_cpuset_getid)
862 POST_MEM_WRITE(ARG4, sizeof(vki_cpusetid_t));
865 // SYS_cpuset_getaffinity 487
866 // int cpuset_getaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
867 // size_t setsize, cpuset_t *mask);
868 PRE(sys_cpuset_getaffinity)
870 PRINT("sys_cpuset_getaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
871 ARG1, ARG2, SARG3, ARG4, ARG5);
872 PRE_REG_READ5(int, "cpuset_getaffinity",
873 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
874 size_t, setsize, void *, mask);
875 PRE_MEM_WRITE("cpuset_getaffinity", ARG5, ARG4);
878 POST(sys_cpuset_getaffinity)
880 vg_assert(SUCCESS);
881 if (RES == 0)
882 POST_MEM_WRITE( ARG5, ARG4 );
885 // SYS_cpuset_setaffinity 488
886 // int cpuset_setaffinity(cpulevel_t level, cpuwhich_t which, id_t id,
887 // size_t setsize, const cpuset_t *mask);
888 PRE(sys_cpuset_setaffinity)
891 PRINT("sys_cpuset_setaffinity ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x )",
892 ARG1, ARG2, SARG3, ARG4, ARG5);
893 PRE_REG_READ5(int, "cpuset_setaffinity",
894 vki_cpulevel_t, level, vki_cpuwhich_t, which, vki_id_t, id,
895 size_t, setsize, void *, mask);
896 PRE_MEM_READ("cpuset_setaffinity", ARG5, ARG4);
899 // SYS_posix_fallocate 530
900 // int posix_fallocate(int fd, off_t offset, off_t len);
901 PRE(sys_posix_fallocate)
903 PRINT("sys_posix_fallocate ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u )",
904 SARG1, ARG2, ARG3);
905 PRE_REG_READ3(long, "posix_fallocate",
906 int, fd, vki_off_t, offset,
907 vki_off_t, len);
910 // SYS_posix_fadvise 531
911 // int posix_fadvise(int fd, off_t offset, off_t len, int advice);
912 PRE(sys_posix_fadvise)
914 PRINT("sys_posix_fadvise ( %" FMT_REGWORD "d, %" FMT_REGWORD "u, %" FMT_REGWORD "u, %" FMT_REGWORD "d )",
915 SARG1, ARG2, ARG3, SARG4);
916 PRE_REG_READ4(long, "posix_fadvise",
917 int, fd, off_t, offset,
918 off_t, len,
919 int, advice);
920 // @todo PJF advice can be 0 to 5 inclusive
923 // SYS_wait6 532
924 // pid_t wait6(idtype_t idtype, id_t id, int *status, int options,
925 // struct __wrusage *wrusage, siginfo_t *infop);
926 PRE(sys_wait6)
928 PRINT("sys_wait6 ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %" FMT_REGWORD "d, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
929 SARG1, SARG2, ARG3, SARG4, ARG5, ARG6);
930 PRE_REG_READ6(pid_t, "wait6", vki_idtype_t, idtype, vki_id_t, id, int *, status, int, options,
931 struct vki___wrusage *, wrusage, vki_siginfo_t *,infop);
932 PRE_MEM_WRITE("wait6(status)", ARG3, sizeof(int));
933 if (ARG5) {
934 PRE_MEM_WRITE("wait6(wrusage)", ARG5, sizeof(struct vki___wrusage));
936 if (ARG6) {
937 PRE_MEM_WRITE("wait6(infop)", ARG6, sizeof(vki_siginfo_t));
941 POST(sys_wait6)
943 POST_MEM_WRITE(ARG3, sizeof(int));
944 if (ARG5) {
945 POST_MEM_WRITE(ARG5, sizeof(struct vki___wrusage));
948 if (ARG6) {
949 POST_MEM_WRITE(ARG5, sizeof(vki_siginfo_t));
953 // the man page is inconsistent for the last argument
954 // See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=247386
955 // will stick to 'arg' for simplicity
957 // SYS_procctl 544
958 // int procctl(idtype_t idtype, id_t id, int cmd, void *arg);
959 PRE(sys_procctl)
961 PRINT("sys_procctl ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD"d, %#" FMT_REGWORD "x )",
962 SARG1, SARG2, SARG3, ARG4);
963 PRE_REG_READ4(int, "procctl", vki_idtype_t, idtype, vki_id_t, id, int, cmd, void *, arg);
964 switch (ARG3) {
965 case VKI_PROC_ASLR_CTL:
966 case VKI_PROC_SPROTECT:
967 case VKI_PROC_TRACE_CTL:
968 case VKI_PROC_TRAPCAP_CTL:
969 case VKI_PROC_PDEATHSIG_CTL:
970 case VKI_PROC_STACKGAP_CTL:
971 case VKI_PROC_NO_NEW_PRIVS_CTL:
972 case VKI_PROC_WXMAP_CTL:
973 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(int));
974 break;
975 case VKI_PROC_REAP_STATUS:
976 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(struct vki_procctl_reaper_status));
977 break;
978 case VKI_PROC_REAP_GETPIDS:
979 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(struct vki_procctl_reaper_pids));
980 break;
981 case VKI_PROC_REAP_KILL:
982 /* The first three fields are reads
983 * int rk_sig;
984 * u_int rk_flags;
985 * pid_t rk_subtree;
987 * The last two fields are writes
988 * u_int rk_killed;
989 * pid_t rk_fpid;
991 * There is also a pad field
993 PRE_MEM_READ("procctl(arg)", ARG4, sizeof(int) + sizeof(u_int) + sizeof(vki_pid_t));
994 PRE_MEM_WRITE("procctl(arg)", ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
995 break;
996 case VKI_PROC_ASLR_STATUS:
997 case VKI_PROC_PDEATHSIG_STATUS:
998 case VKI_PROC_STACKGAP_STATUS:
999 case VKI_PROC_TRAPCAP_STATUS:
1000 case VKI_PROC_TRACE_STATUS:
1001 case VKI_PROC_NO_NEW_PRIVS_STATUS:
1002 case VKI_PROC_WXMAP_STATUS:
1003 PRE_MEM_WRITE("procctl(arg)", ARG4, sizeof(int));
1004 case VKI_PROC_REAP_ACQUIRE:
1005 case VKI_PROC_REAP_RELEASE:
1006 default:
1007 break;
1011 POST(sys_procctl)
1013 switch (ARG3) {
1014 case VKI_PROC_REAP_KILL:
1015 POST_MEM_WRITE(ARG4+offsetof(struct vki_procctl_reaper_kill, rk_killed), sizeof(u_int) + sizeof(vki_pid_t));
1016 break;
1017 case VKI_PROC_ASLR_STATUS:
1018 case VKI_PROC_PDEATHSIG_STATUS:
1019 case VKI_PROC_STACKGAP_STATUS:
1020 case VKI_PROC_TRAPCAP_STATUS:
1021 case VKI_PROC_TRACE_STATUS:
1022 case VKI_PROC_NO_NEW_PRIVS_STATUS:
1023 case VKI_PROC_WXMAP_STATUS:
1024 POST_MEM_WRITE(ARG4, sizeof(int));
1025 default:
1026 break;
1030 #if (FREEBSD_VERS >= FREEBSD_12)
1032 // SYS_cpuset_getdomain 561
1033 // int cpuset_getdomain(cpulevel_t level, cpuwhich_t which, id_t id,
1034 // size_t setsize, domainset_t *mask, int *policy);
1035 PRE(sys_cpuset_getdomain)
1037 PRINT("sys_cpuset_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
1038 SARG1, SARG2, SARG3, ARG4, ARG5, ARG6);
1039 PRE_REG_READ6(int, "cpuset_getdomain",
1040 cpulevel_t, level, cpuwhich_t, which, id_t, id,
1041 size_t, setsize, vki_domainset_t *, mask, int *, policy);
1042 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
1043 PRE_MEM_WRITE( "cpuset_getdomain(mask)", ARG5, ARG4 );
1044 PRE_MEM_WRITE( "cpuset_getdomain(policy)", ARG6, sizeof(int) );
1047 POST(sys_cpuset_getdomain)
1049 POST_MEM_WRITE(ARG5, ARG4 );
1050 POST_MEM_WRITE(ARG6, sizeof(int) );
1053 // SYS_cpuset_setdomain 562
1054 // int cuset_setdomain(cpulevel_t level, cpuwhich_t which, id_t id,
1055 // size_t setsize, const domainset_t *mask, int policy);
1056 PRE(sys_cpuset_setdomain)
1058 PRINT("sys_cpuget_getdomain ( %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "d, %" FMT_REGWORD "u, %#" FMT_REGWORD "x, %" FMT_REGWORD "d )",
1059 SARG1, SARG2, SARG3, ARG4, ARG5, SARG6);
1060 PRE_REG_READ6(int, "cpuset_getdomain",
1061 cpulevel_t, level, cpuwhich_t, which, id_t, id,
1062 size_t, setsize, vki_domainset_t *, mask, int, policy);
1063 // man page says that setsize (ARG4) "is usually provided by calling sizeof(mask)"
1064 PRE_MEM_READ( "cpuset_getdomain(mask)", ARG5, ARG4 );
1067 #endif
1069 PRE(sys_fake_sigreturn)
1071 ThreadState* tst;
1072 struct vki_ucontext *uc;
1073 int rflags;
1075 PRINT("sys_sigreturn ( %#" FMT_REGWORD "x )", ARG1);
1076 PRE_REG_READ1(long, "sigreturn",
1077 struct vki_ucontext *, scp);
1079 PRE_MEM_READ( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1080 PRE_MEM_WRITE( "sigreturn(scp)", ARG1, sizeof(struct vki_ucontext) );
1082 vg_assert(VG_(is_valid_tid)(tid));
1083 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1084 vg_assert(VG_(is_running_thread)(tid));
1086 /* Adjust esp to point to start of frame; skip back up over handler
1087 ret addr */
1088 tst = VG_(get_ThreadState)(tid);
1089 tst->arch.vex.guest_RSP -= sizeof(Addr);
1091 uc = (struct vki_ucontext *)ARG1;
1092 if (uc == NULL || uc->uc_mcontext.len != sizeof(uc->uc_mcontext)) {
1093 SET_STATUS_Failure(VKI_EINVAL);
1094 return;
1097 /* This is only so that the EIP is (might be) useful to report if
1098 something goes wrong in the sigreturn */
1099 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
1101 VG_(sigframe_destroy)(tid);
1103 /* For unclear reasons, it appears we need the syscall to return
1104 without changing %RAX. Since %RAX is the return value, and can
1105 denote either success or failure, we must set up so that the
1106 driver logic copies it back unchanged. Also, note %RAX is of
1107 the guest registers written by VG_(sigframe_destroy). */
1108 rflags = LibVEX_GuestAMD64_get_rflags(&tst->arch.vex);
1109 SET_STATUS_from_SysRes( VG_(mk_SysRes_amd64_freebsd)( tst->arch.vex.guest_RAX,
1110 tst->arch.vex.guest_RDX, (rflags & 1) != 0 ? True : False) );
1113 * Signal handler might have changed the signal mask. Respect that.
1115 tst->sig_mask = uc->uc_sigmask;
1116 tst->tmp_sig_mask = uc->uc_sigmask;
1118 /* Tell the driver not to update the guest state with the "result",
1119 and set a bogus result to keep it happy. */
1120 *flags |= SfNoWriteResult;
1121 SET_STATUS_Success(0);
1123 /* Check to see if some any signals arose as a result of this. */
1124 *flags |= SfPollAfter;
1128 #undef PRE
1129 #undef POST
1131 #endif /* defined(VGP_amd64_freebsd) */
1133 /*--------------------------------------------------------------------*/
1134 /*--- end ---*/
1135 /*--------------------------------------------------------------------*/