2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2005-2010 Apple Inc.
11 Greg Parker gparker@apple.com
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGO_darwin)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_vkiscnums.h"
36 #include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy
37 #include "pub_core_threadstate.h"
38 #include "pub_core_aspacemgr.h"
39 #include "pub_core_xarray.h"
40 #include "pub_core_clientstate.h"
41 #include "pub_core_debuglog.h"
42 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
43 #include "pub_core_transtab.h" // VG_(discard_translations)
44 #include "pub_tool_gdbserver.h" // VG_(gdbserver)
45 #include "pub_core_libcbase.h"
46 #include "pub_core_libcassert.h"
47 #include "pub_core_libcfile.h"
48 #include "pub_core_libcprint.h"
49 #include "pub_core_libcproc.h"
50 #include "pub_core_libcsignal.h"
51 #include "pub_core_machine.h" // VG_(get_SP)
52 #include "pub_core_mallocfree.h"
53 #include "pub_core_options.h"
54 #include "pub_core_oset.h"
55 #include "pub_core_scheduler.h"
56 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
57 #include "pub_core_signals.h"
58 #include "pub_core_syscall.h"
59 #include "pub_core_syswrap.h"
60 #include "pub_core_tooliface.h"
62 #include "priv_types_n_macros.h"
63 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
64 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
65 #include "priv_syswrap-main.h"
67 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
68 #include <mach/mach.h>
69 #include <mach/mach_vm.h>
70 #include <semaphore.h>
71 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
73 #define msgh_request_port msgh_remote_port
74 #define msgh_reply_port msgh_local_port
75 #define BOOTSTRAP_MAX_NAME_LEN 128
76 typedef char name_t[BOOTSTRAP_MAX_NAME_LEN];
78 typedef uint64_t mig_addr_t;
82 static mach_port_t vg_host_port = 0;
83 static mach_port_t vg_task_port = 0;
84 static mach_port_t vg_bootstrap_port = 0;
86 // Run a thread from beginning to end and return the thread's
87 // scheduler-return-code.
88 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
90 VgSchedReturnCode ret;
91 ThreadId tid = (ThreadId)tidW;
92 ThreadState* tst = VG_(get_ThreadState)(tid);
94 VG_(debugLog)(1, "syswrap-darwin",
95 "thread_wrapper(tid=%lld): entry\n",
98 vg_assert(tst->status == VgTs_Init);
100 /* make sure we get the CPU lock before doing anything significant */
101 VG_(acquire_BigLock)(tid, "thread_wrapper");
104 VG_(printf)("thread tid %d started: stack = %p\n",
107 VG_TRACK(pre_thread_first_insn, tid);
109 tst->os_state.lwpid = VG_(gettid)();
110 tst->os_state.threadgroup = VG_(getpid)();
112 /* Thread created with all signals blocked; scheduler will set the
115 ret = VG_(scheduler)(tid);
117 vg_assert(VG_(is_exiting)(tid));
119 vg_assert(tst->status == VgTs_Runnable);
120 vg_assert(VG_(is_running_thread)(tid));
122 VG_(debugLog)(1, "syswrap-darwin",
123 "thread_wrapper(tid=%lld): done\n",
126 /* Return to caller, still holding the lock. */
132 /* Allocate a stack for this thread, if it doesn't already have one.
133 Returns the initial stack pointer value to use, or 0 if allocation
136 Addr allocstack ( ThreadId tid )
138 ThreadState* tst = VG_(get_ThreadState)(tid);
142 /* Either the stack_base and stack_init_SP are both zero (in which
143 case a stack hasn't been allocated) or they are both non-zero,
144 in which case it has. */
146 if (tst->os_state.valgrind_stack_base == 0)
147 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
149 if (tst->os_state.valgrind_stack_base != 0)
150 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
152 /* If no stack is present, allocate one. */
154 if (tst->os_state.valgrind_stack_base == 0) {
155 stack = VG_(am_alloc_VgStack)( &initial_SP );
157 tst->os_state.valgrind_stack_base = (Addr)stack;
158 tst->os_state.valgrind_stack_init_SP = initial_SP;
162 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
164 (void*)tst->os_state.valgrind_stack_base,
165 (void*)tst->os_state.valgrind_stack_init_SP );
167 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
169 return tst->os_state.valgrind_stack_init_SP;
173 void find_stack_segment(ThreadId tid, Addr sp)
175 /* We don't really know where the client stack is, because it's
176 allocated by the client. The best we can do is look at the
177 memory mappings and try to derive some useful information. We
178 assume that esp starts near its highest possible value, and can
179 only go down to the start of the mmaped segment. */
180 ThreadState *tst = VG_(get_ThreadState)(tid);
181 const NSegment *seg = VG_(am_find_nsegment)(sp);
182 if (seg && seg->kind != SkResvn) {
183 tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
184 tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
187 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
188 tid, seg->start, VG_PGROUNDUP(sp));
190 VG_(printf)("couldn't find user stack\n");
191 VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
193 tst->client_stack_szB = 0;
198 /* Run a thread all the way to the end, then do appropriate exit actions
199 (this is the last-one-out-turn-off-the-lights bit).
201 static void run_a_thread_NORETURN ( Word tidW )
204 VgSchedReturnCode src;
205 ThreadId tid = (ThreadId)tidW;
207 VG_(debugLog)(1, "syswrap-darwin",
208 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
211 /* Run the thread all the way through. */
212 src = thread_wrapper(tid);
214 VG_(debugLog)(1, "syswrap-darwin",
215 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
218 c = VG_(count_living_threads)();
219 vg_assert(c >= 1); /* stay sane */
221 // Tell the tool this thread is exiting
222 VG_TRACK( pre_thread_ll_exit, tid );
226 VG_(debugLog)(1, "syswrap-darwin",
227 "run_a_thread_NORETURN(tid=%lld): "
228 "last one standing\n",
231 /* We are the last one standing. Keep hold of the lock and
232 carry on to show final tool results, then exit the entire system.
233 Use the continuation pointer set at startup in m_main. */
234 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
239 mach_msg_header_t msg;
241 VG_(debugLog)(1, "syswrap-darwin",
242 "run_a_thread_NORETURN(tid=%lld): "
243 "not last one standing\n",
246 /* OK, thread is dead, but others still exist. Just exit. */
247 tst = VG_(get_ThreadState)(tid);
249 /* This releases the run lock */
250 VG_(exit_thread)(tid);
251 vg_assert(tst->status == VgTs_Zombie);
253 /* tid is now invalid. */
255 // GrP fixme exit race
256 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
257 msg.msgh_request_port = VG_(gettid)();
258 msg.msgh_reply_port = 0;
259 msg.msgh_id = 3600; // thread_terminate
261 tst->status = VgTs_Empty;
262 // GrP fixme race here! new thread may claim this V thread stack
263 // before we get out here!
264 // GrP fixme use bsdthread_terminate for safe cleanup?
265 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
266 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
268 // DDD: This is reached sometimes on none/tests/manythreads, maybe
269 // because of the race above.
270 VG_(core_panic)("Thread exit failed?\n");
278 /* Allocate a stack for the main thread, and run it all the way to the
279 end. Although we already have a working VgStack
280 (VG_(interim_stack)) it's better to allocate a new one, so that
281 overflow detection works uniformly for all threads.
283 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
286 VG_(debugLog)(1, "syswrap-darwin",
287 "entering VG_(main_thread_wrapper_NORETURN)\n");
289 sp = allocstack(tid);
291 /* If we can't even allocate the first thread's stack, we're hosed.
293 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
295 /* shouldn't be any other threads around yet */
296 vg_assert( VG_(count_living_threads)() == 1 );
298 call_on_new_stack_0_1(
299 (Addr)sp, /* stack */
300 0, /*bogus return address*/
301 run_a_thread_NORETURN, /* fn to call */
302 (Word)tid /* arg to give it */
310 void start_thread_NORETURN ( Word arg )
312 ThreadState* tst = (ThreadState*)arg;
313 ThreadId tid = tst->tid;
315 run_a_thread_NORETURN ( (Word)tid );
321 void VG_(cleanup_thread) ( ThreadArchState* arch )
326 /* ---------------------------------------------------------------------
327 Mach port tracking (based on syswrap-generic's fd tracker)
328 ------------------------------------------------------------------ */
330 /* One of these is allocated for each open port. */
331 typedef struct OpenPort
334 mach_port_type_t type; /* right type(s) */
335 Int send_count; /* number of send rights */
336 Char *name; /* bootstrap name or NULL */
337 ExeContext *where; /* first allocation only */
338 struct OpenPort *next, *prev;
341 // strlen("0x12345678")
342 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
344 /* List of allocated ports. */
345 static OpenPort *allocated_ports;
347 /* Count of open ports. */
348 static Int allocated_port_count = 0;
351 __attribute__((unused))
352 static Bool port_exists(mach_port_t port)
356 /* Check to see if this port is already open. */
359 if (i->port == port) {
368 static OpenPort *info_for_port(mach_port_t port)
371 if (!port) return NULL;
375 if (i->port == port) {
385 // Give a port a name, without changing its refcount
386 // GrP fixme don't override name if it already has a specific one
387 __private_extern__ void assign_port_name(mach_port_t port, const char *name)
393 i = info_for_port(port);
396 if (i->name) VG_(arena_free)(VG_AR_CORE, i->name);
398 VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name",
399 VG_(strlen)(name) + PORT_STRLEN + 1);
400 VG_(sprintf)(i->name, name, port);
404 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
405 static const char *name_for_port(mach_port_t port)
407 static char buf[8 + PORT_STRLEN + 1];
411 if (port == VG_(gettid)()) return "mach_thread_self()";
412 if (port == 0) return "NULL";
416 if (i->port == port) {
422 VG_(sprintf)(buf, "NONPORT-%#x", port);
426 /* Note the fact that a port was just deallocated. */
429 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
431 OpenPort *i = allocated_ports;
435 if(i->port == port) {
436 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
437 if (right & MACH_PORT_TYPE_SEND) {
438 // send rights are refcounted
439 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
440 i->send_count += delta;
441 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
442 else i->type &= ~MACH_PORT_TYPE_SEND;
444 right = right & ~MACH_PORT_TYPE_SEND;
446 // other rights are not refcounted
449 } else if (delta < 0) {
454 if (i->type != 0) return;
456 // Port has no rights left. Kill it.
457 // VG_(printf)("deleting port %p %s", i->port, i->name);
459 i->prev->next = i->next;
461 allocated_ports = i->next;
463 i->next->prev = i->prev;
465 VG_(arena_free) (VG_AR_CORE, i->name);
466 VG_(arena_free) (VG_AR_CORE, i);
467 allocated_port_count--;
473 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
477 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
480 case MACH_MSG_TYPE_PORT_NAME:
481 // this task has no rights for the name
483 case MACH_MSG_TYPE_PORT_RECEIVE:
484 // this task gets receive rights
485 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
487 case MACH_MSG_TYPE_PORT_SEND:
488 // this task gets a send right
489 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
491 case MACH_MSG_TYPE_PORT_SEND_ONCE:
492 // this task gets send-once rights
493 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
502 void record_port_dealloc(mach_port_t port)
504 // deletes 1 send or send-once right (port can't have both)
505 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
509 void record_port_destroy(mach_port_t port)
511 // deletes all rights to port
512 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
516 /* Note the fact that a Mach port was just allocated or transferred.
517 If the port is already known, increment its reference count. */
518 void record_named_port(ThreadId tid, mach_port_t port,
519 mach_port_right_t right, const char *name)
524 /* Check to see if this port is already open. */
527 if (i->port == port) {
528 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
534 /* Not already one: allocate an OpenPort */
536 i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port",
540 i->next = allocated_ports;
541 if(allocated_ports) allocated_ports->prev = i;
543 allocated_port_count++;
546 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
549 i->type = MACH_PORT_TYPE(right);
550 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
556 assign_port_name(port, name);
561 // Record opening of a nameless port.
562 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
564 record_named_port(tid, port, right, "unnamed-%p");
568 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
569 void VG_(show_open_ports)(void)
573 VG_(message)(Vg_UserMsg,
574 "MACH PORTS: %d open at exit.", allocated_port_count);
576 for (i = allocated_ports; i; i = i->next) {
578 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name);
580 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port);
584 VG_(pp_ExeContext)(i->where);
585 VG_(message)(Vg_UserMsg, "");
589 VG_(message)(Vg_UserMsg, "");
593 /* ---------------------------------------------------------------------
595 ------------------------------------------------------------------ */
597 void ML_(sync_mappings)(const HChar *when, const HChar *where, Int num)
599 // Usually the number of segments added/removed in a single calls is very
600 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
601 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
602 // because we can't do dynamic allocation within VG_(get_changed_segments),
603 // because it's in m_aspacemgr.
604 ChangedSeg* css = NULL;
610 if (VG_(clo_trace_syscalls)) {
611 VG_(debugLog)(0, "syswrap-darwin",
612 "sync_mappings(\"%s\", \"%s\", %d)\n",
616 // 16 is enough for most cases, but small enough that overflow happens
617 // occasionally and thus the overflow path gets some test coverage.
621 VG_(free)(css); // css is NULL on first iteration; that's ok.
622 css = VG_(malloc)("sys_wrap.sync_mappings", css_size*sizeof(ChangedSeg));
623 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
627 // Now add/remove them.
628 for (i = 0; i < css_used; i++) {
629 ChangedSeg* cs = &css[i];
632 ML_(notify_core_and_tool_of_mmap)(
633 cs->start, cs->end - cs->start + 1,
634 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
635 // should this call VG_(di_notify_mmap) also?
639 ML_(notify_core_and_tool_of_munmap)(
640 cs->start, cs->end - cs->start + 1);
643 if (VG_(clo_trace_syscalls)) {
644 VG_(debugLog)(0, "syswrap-darwin",
645 " %s region 0x%010lx..0x%010lx at %s (%s)\n",
646 action, cs->start, cs->end + 1, where, when);
653 /* ---------------------------------------------------------------------
655 ------------------------------------------------------------------ */
657 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
658 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
660 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
661 #define POST_FN(name) vgSysWrap_darwin_##name##_after
663 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
664 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
667 // Combine two 32-bit values into a 64-bit value
668 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
669 # if defined(VGA_x86)
670 # define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
672 # error unknown architecture
676 // Retrieve the current Mach thread
677 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
679 // Set the POST handler for a mach_msg derivative
680 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
682 // Set or get values saved from Mach messages
683 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
684 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
685 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
687 /* ---------------------------------------------------------------------
689 ------------------------------------------------------------------ */
693 *flags |= SfMayBlock;
695 /* Handle ioctls that don't take an arg first */
696 switch (ARG2 /* request */) {
699 case VKI_TIOCPTYGRANT:
700 case VKI_TIOCPTYUNLK:
701 case VKI_DTRACEHIOC_REMOVE:
702 PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
703 PRE_REG_READ2(long, "ioctl",
704 unsigned int, fd, unsigned int, request);
707 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
708 PRE_REG_READ3(long, "ioctl",
709 unsigned int, fd, unsigned int, request, unsigned long, arg);
712 switch (ARG2 /* request */) {
714 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
717 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
720 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
723 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
726 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
729 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
732 /* Get process group ID for foreground processing group. */
733 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
736 /* Set a process group ID? */
737 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
740 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
743 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
745 case VKI_FIONREAD: /* identical to SIOCINQ */
746 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
750 /* These all use struct ifreq AFAIK */
751 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
752 case VKI_SIOCGIFFLAGS: /* get flags */
753 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
754 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
755 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
757 case VKI_SIOCGIFMTU: /* get MTU size */
758 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
759 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
760 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
762 case VKI_SIOCGIFADDR: /* get PA address */
763 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
764 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
765 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
767 case VKI_SIOCGIFNETMASK: /* get network PA mask */
768 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
769 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
770 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
772 case VKI_SIOCGIFMETRIC: /* get metric */
773 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
774 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
775 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
777 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
778 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
779 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
780 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
782 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
783 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
784 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
785 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
787 case VKI_SIOCGIFCONF: /* get iface list */
789 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
790 KERNEL_DO_SYSCALL(tid,RES);
791 if (!VG_(is_kerror)(RES) && RES == 0)
792 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
794 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
795 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
796 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
797 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
798 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
799 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
801 // TODO len must be readable and writable
802 // buf pointer only needs to be readable
803 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
804 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
805 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
809 case VKI_SIOCSIFFLAGS: /* set flags */
810 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
811 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
812 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
813 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
814 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
816 case VKI_SIOCSIFADDR: /* set PA address */
817 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
818 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
819 case VKI_SIOCSIFNETMASK: /* set network PA mask */
820 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
821 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
822 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
823 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
824 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
826 case VKI_SIOCSIFMETRIC: /* set metric */
827 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
828 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
829 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
830 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
831 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
833 case VKI_SIOCSIFMTU: /* set MTU size */
834 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
835 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
836 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
837 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
838 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
840 /* Routing table calls. */
842 case VKI_SIOCADDRT: /* add routing table entry */
843 case VKI_SIOCDELRT: /* delete routing table entry */
844 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
845 sizeof(struct vki_rtentry));
850 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
853 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
854 //tst->sys_flags &= ~SfMayBlock;
858 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
861 case VKI_DTRACEHIOC_ADDDOF:
866 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
869 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
872 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
875 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
877 case VKI_TIOCPTYGNAME:
878 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
882 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
891 switch (ARG2 /* request */) {
893 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
901 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
904 /* Get process group ID for foreground processing group. */
905 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
908 /* Set a process group ID? */
909 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
917 case VKI_FIONREAD: /* identical to SIOCINQ */
918 POST_MEM_WRITE( ARG3, sizeof(int) );
921 /* These all use struct ifreq AFAIK */
922 case VKI_SIOCGIFFLAGS: /* get flags */
923 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
924 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
926 case VKI_SIOCGIFMTU: /* get MTU size */
927 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
928 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
930 case VKI_SIOCGIFADDR: /* get PA address */
931 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
932 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
933 case VKI_SIOCGIFNETMASK: /* get network PA mask */
935 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
936 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
938 case VKI_SIOCGIFMETRIC: /* get metric */
940 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
941 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
943 case VKI_SIOCGIFCONF: /* get iface list */
945 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
946 KERNEL_DO_SYSCALL(tid,RES);
947 if (!VG_(is_kerror)(RES) && RES == 0)
948 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
950 if (RES == 0 && ARG3 ) {
951 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
952 if (ifc->vki_ifc_buf != NULL)
953 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
957 case VKI_SIOCSIFFLAGS: /* set flags */
958 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
959 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
960 case VKI_SIOCSIFNETMASK: /* set network PA mask */
961 case VKI_SIOCSIFMETRIC: /* set metric */
962 case VKI_SIOCSIFADDR: /* set PA address */
963 case VKI_SIOCSIFMTU: /* set MTU size */
967 /* Routing table calls. */
968 case VKI_SIOCADDRT: /* add routing table entry */
969 case VKI_SIOCDELRT: /* delete routing table entry */
974 POST_MEM_WRITE(ARG3, sizeof(int));
980 POST_MEM_WRITE( ARG3, sizeof(int) );
983 case VKI_DTRACEHIOC_REMOVE:
984 case VKI_DTRACEHIOC_ADDDOF:
989 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
994 POST_MEM_WRITE( ARG3, sizeof(int) );
998 case VKI_TIOCPTYGNAME:
999 POST_MEM_WRITE( ARG3, 128);
1001 case VKI_TIOCPTYGRANT:
1002 case VKI_TIOCPTYUNLK:
1011 /* ---------------------------------------------------------------------
1012 darwin fcntl wrapper
1013 ------------------------------------------------------------------ */
1014 static const char *name_for_fcntl(UWord cmd) {
1015 #define F(n) case VKI_##n: return #n
1023 F(F_GLOBAL_NOCACHE);
1028 F(F_WRITEBOOTSTRAP);
1042 // These ones ignore ARG3.
1046 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1047 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1050 // These ones use ARG3 as "arg".
1055 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1056 PRE_REG_READ3(long, "fcntl",
1057 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1060 // These ones use ARG3 as "lock".
1064 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1065 PRE_REG_READ3(long, "fcntl",
1066 unsigned int, fd, unsigned int, cmd,
1067 struct flock64 *, lock);
1068 // GrP fixme mem read sizeof(flock64)
1069 if (ARG2 == VKI_F_SETLKW)
1070 *flags |= SfMayBlock;
1074 case VKI_F_CHKCLEAN:
1077 case VKI_F_FULLFSYNC:
1078 case VKI_F_FREEZE_FS:
1080 case VKI_F_GLOBAL_NOCACHE:
1081 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1082 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1086 case VKI_F_PREALLOCATE:
1087 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1088 PRE_REG_READ3(long, "fcntl",
1089 unsigned int, fd, unsigned int, cmd,
1090 struct fstore *, fstore);
1092 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1093 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1094 fstore->fst_flags );
1095 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1096 fstore->fst_posmode );
1097 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1098 fstore->fst_offset );
1099 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1100 fstore->fst_length );
1101 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1102 fstore->fst_bytesalloc);
1108 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1109 PRE_REG_READ3(long, "fcntl",
1110 unsigned int, fd, unsigned int, cmd,
1111 vki_off_t *, offset);
1115 case VKI_F_RDADVISE:
1116 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1117 PRE_REG_READ3(long, "fcntl",
1118 unsigned int, fd, unsigned int, cmd,
1119 struct vki_radvisory *, radvisory);
1121 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1122 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1123 radvisory->ra_offset );
1124 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1125 radvisory->ra_count );
1129 // struct fbootstraptransfer
1130 case VKI_F_READBOOTSTRAP:
1131 case VKI_F_WRITEBOOTSTRAP:
1132 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1133 PRE_REG_READ3(long, "fcntl",
1134 unsigned int, fd, unsigned int, cmd,
1135 struct fbootstraptransfer *, bootstrap);
1136 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1137 ARG3, sizeof(struct vki_fbootstraptransfer) );
1140 // struct log2phys (out)
1141 case VKI_F_LOG2PHYS:
1142 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1143 PRE_REG_READ3(long, "fcntl",
1144 unsigned int, fd, unsigned int, cmd,
1145 struct log2phys *, l2p);
1146 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1147 ARG3, sizeof(struct vki_log2phys) );
1150 // char[maxpathlen] (out)
1152 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1153 PRE_REG_READ3(long, "fcntl",
1154 unsigned int, fd, unsigned int, cmd,
1156 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1157 ARG3, VKI_MAXPATHLEN );
1160 // char[maxpathlen] (in)
1161 case VKI_F_PATHPKG_CHECK:
1162 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1164 PRE_REG_READ3(long, "fcntl",
1165 unsigned int, fd, unsigned int, cmd,
1167 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1170 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1171 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1172 PRE_REG_READ3(long, "fcntl",
1173 unsigned int, fd, unsigned int, cmd,
1174 vki_fsignatures_t *, sigs);
1177 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1178 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1179 fsigs->fs_blob_start);
1180 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1181 fsigs->fs_blob_size);
1183 if (fsigs->fs_blob_start)
1184 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1185 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1190 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1191 VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
1201 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1203 SET_STATUS_Failure( VKI_EMFILE );
1205 if (VG_(clo_track_fds))
1206 ML_(record_fd_open_named)(tid, RES);
1221 case VKI_F_PREALLOCATE:
1223 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1224 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1228 case VKI_F_LOG2PHYS:
1229 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1233 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1234 PRINT("\"%s\"", (char*)ARG3);
1238 // DDD: ugh, missing lots of cases here, not nice
1243 /* ---------------------------------------------------------------------
1245 ------------------------------------------------------------------ */
1249 PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
1250 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1251 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1252 SET_STATUS_Failure( VKI_EBADF );
1253 } else if (ARG2 != 0) {
1254 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1255 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1261 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1262 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1267 *flags |= SfMayBlock;
1268 PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
1269 PRE_REG_READ3(long, "semop",
1270 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1271 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1279 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1280 PRE_REG_READ4(long, "semctl",
1281 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1285 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1286 PRE_REG_READ4(long, "semctl",
1287 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1290 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1291 PRE_REG_READ4(long, "semctl",
1292 int, semid, int, semnum, int, cmd, int, arg);
1295 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1296 PRE_REG_READ3(long, "semctl",
1297 int, semid, int, semnum, int, cmd);
1300 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1304 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1309 if (ARG2 & VKI_O_CREAT) {
1311 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1312 ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1313 PRE_REG_READ4(vki_sem_t *, "sem_open",
1314 const char *, name, int, oflag, vki_mode_t, mode,
1315 unsigned int, value);
1318 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1319 PRE_REG_READ2(vki_sem_t *, "sem_open",
1320 const char *, name, int, oflag);
1322 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1324 /* Otherwise handle normally */
1325 *flags |= SfMayBlock;
1330 PRINT("sem_close( %#lx )", ARG1);
1331 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1336 PRINT("sem_unlink( %#lx(%s) )", ARG1,(char*)ARG1);
1337 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1338 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1343 PRINT("sem_post( %#lx )", ARG1);
1344 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1345 *flags |= SfMayBlock;
1350 PRINT("sem_destroy( %#lx )", ARG1);
1351 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1352 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1357 PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
1358 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1359 int, pshared, unsigned int, value);
1360 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1365 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1370 PRINT("sem_wait( %#lx )", ARG1);
1371 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1372 *flags |= SfMayBlock;
1377 PRINT("sem_trywait( %#lx )", ARG1);
1378 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1379 *flags |= SfMayBlock;
1389 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1391 SET_STATUS_Failure( VKI_EMFILE );
1393 if (VG_(clo_track_fds)) {
1394 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1401 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1402 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1403 PRE_REG_READ6(int,"kevent", int,kq,
1404 const struct vki_kevent *,changelist, int,nchanges,
1405 struct vki_kevent *,eventlist, int,nevents,
1406 const struct vki_timespec *,timeout);
1408 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
1409 ARG2, ARG3 * sizeof(struct vki_kevent));
1410 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
1411 ARG4, ARG5 * sizeof(struct vki_kevent));
1412 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
1413 ARG6, sizeof(struct vki_timespec));
1415 *flags |= SfMayBlock;
1420 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
1421 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
1425 Addr pthread_starter = 0;
1426 Addr wqthread_starter = 0;
1427 SizeT pthread_structsize = 0;
1429 PRE(bsdthread_register)
1431 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
1432 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
1433 void *,"wqthread", size_t,"pthsize");
1435 pthread_starter = ARG1;
1436 wqthread_starter = ARG2;
1437 pthread_structsize = ARG3;
1438 ARG1 = (Word)&pthread_hijack_asm;
1439 ARG2 = (Word)&wqthread_hijack_asm;
1444 PRINT("workq_open()");
1445 PRE_REG_READ0(int, "workq_open");
1447 // This creates lots of threads and thread stacks under the covers,
1448 // but we ignore them all until some work item starts running on it.
1451 static const char *workqop_name(int op)
1454 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
1455 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
1456 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
1457 default: return "?";
1464 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
1466 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
1470 case VKI_WQOPS_QUEUE_ADD:
1471 case VKI_WQOPS_QUEUE_REMOVE:
1472 // GrP fixme need anything here?
1473 // GrP fixme may block?
1476 case VKI_WQOPS_THREAD_RETURN: {
1477 // The interesting case. The kernel will do one of two things:
1478 // 1. Return normally. We continue; libc proceeds to stop the thread.
1479 // V does nothing special here.
1480 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
1481 // new work item, and never returns from workq_ops.
1482 // V handles this by longjmp() from wqthread_hijack back to the
1483 // scheduler, which continues at the new client SP/IP/state.
1484 // This works something like V's signal handling.
1485 // To the tool, this looks like workq_ops() sometimes returns
1486 // to a strange address.
1487 ThreadState *tst = VG_(get_ThreadState)(tid);
1488 tst->os_state.wq_jmpbuf_valid = True;
1489 *flags |= SfMayBlock; // GrP fixme true?
1494 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
1500 ThreadState *tst = VG_(get_ThreadState)(tid);
1501 tst->os_state.wq_jmpbuf_valid = False;
1508 PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
1509 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
1510 int,"call", void *,"arg");
1512 // GrP fixme check call's arg?
1513 // GrP fixme check policy?
1517 /* Not like syswrap-generic's sys_exit, which exits only one thread.
1518 More like syswrap-generic's sys_exit_group. */
1524 PRINT("darwin exit( %ld )", ARG1);
1525 PRE_REG_READ1(void, "exit", int, status);
1527 tst = VG_(get_ThreadState)(tid);
1529 /* A little complex; find all the threads with the same threadgroup
1530 as this one (including this one), and mark them to exit */
1531 for (t = 1; t < VG_N_THREADS; t++) {
1532 if ( /* not alive */
1533 VG_(threads)[t].status == VgTs_Empty
1534 /* GrP fixme zombie? */
1538 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
1539 VG_(threads)[t].os_state.exitcode = ARG1;
1542 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
1545 /* We have to claim the syscall already succeeded. */
1546 SET_STATUS_Success(0);
1552 PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
1553 PRE_REG_READ3(long, "sigaction",
1554 int, signum, vki_sigaction_toK_t *, act,
1555 vki_sigaction_fromK_t *, oldact);
1558 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
1559 PRE_MEM_READ( "sigaction(act->sa_handler)",
1560 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1561 PRE_MEM_READ( "sigaction(act->sa_mask)",
1562 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1563 PRE_MEM_READ( "sigaction(act->sa_flags)",
1564 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
1567 PRE_MEM_WRITE( "sigaction(oldact)",
1568 ARG3, sizeof(vki_sigaction_fromK_t));
1570 SET_STATUS_from_SysRes(
1571 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
1572 (vki_sigaction_fromK_t *)ARG3)
1578 if (RES == 0 && ARG3 != 0)
1579 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
1585 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
1586 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
1590 PRE(__pthread_sigmask)
1593 // JRS: arguments are identical to sigprocmask
1594 // (how, sigset_t*, sigset_t*). Perhaps behave identically?
1597 VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. "
1598 "This warning will not be repeated.\n");
1601 SET_STATUS_Success( 0 );
1605 PRE(__pthread_canceled)
1607 *flags |= SfMayBlock; /* might kill this thread??? */
1608 /* I don't think so -- I think it just changes the cancellation
1609 state. But taking no chances. */
1610 PRINT("__pthread_canceled ( %ld )", ARG1);
1611 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
1615 PRE(__pthread_markcancel)
1617 *flags |= SfMayBlock; /* might kill this thread??? */
1618 PRINT("__pthread_markcancel ( %#lx )", ARG1);
1619 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
1620 /* Just let it go through. No idea if this is correct. */
1624 PRE(__disable_threadsignal)
1627 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
1628 /* I don't think this really looks at its arguments. So don't
1629 bother to check them. */
1631 VG_(sigfillset)( &set );
1632 SET_STATUS_from_SysRes(
1633 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
1636 /* We don't expect that blocking all signals for this thread could
1637 cause any more to be delivered (how could it?), but just in case
1640 *flags |= SfPollAfter;
1646 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
1647 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1649 Don't check anything - some clients pass fewer arguments.
1650 PRE_REG_READ6(long, "kdebug_trace",
1651 int,"code", int,"arg1", int,"arg2",
1652 int,"arg3", int,"arg4", int,"arg5");
1659 PRINT("seteuid(%ld)", ARG1);
1660 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
1666 PRINT("setegid(%ld)", ARG1);
1667 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
1672 PRINT("settid(%ld, %ld)", ARG1, ARG2);
1673 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
1676 /* XXX need to check whether we need POST operations for
1677 * waitevent, watchevent, modwatch -- jpeach
1681 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
1682 PRE_REG_READ2(long, "watchevent",
1683 vki_eventreq *, "event", unsigned int, "eventmask");
1685 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
1686 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
1687 *flags |= SfMayBlock;
1690 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
1693 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
1694 PRE_REG_READ2(long, "waitevent",
1695 vki_eventreq *, "event", struct timeval *, "timeout");
1696 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
1698 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
1699 PRE_timeval_READ("waitevent(timeout)", ARG2);
1702 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
1703 *flags |= SfMayBlock;
1708 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
1713 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
1714 PRE_REG_READ2(long, "modwatch",
1715 vki_eventreq *, "event", unsigned int, "eventmask");
1717 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
1718 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
1723 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
1724 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1726 PRE_REG_READ6(vki_ssize_t, "getxattr",
1727 const char *, path, char *, name, void *, value,
1728 vki_size_t, size, uint32_t, position, int, options);
1729 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
1730 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1731 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1736 vg_assert((vki_ssize_t)RES >= 0);
1737 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1742 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
1743 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1745 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
1746 int, fd, char *, name, void *, value,
1747 vki_size_t, size, uint32_t, position, int, options);
1748 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1749 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1754 vg_assert((vki_ssize_t)RES >= 0);
1755 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1760 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
1761 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1762 PRE_REG_READ6(int, "setxattr",
1763 const char *,"path", char *,"name", void *,"value",
1764 vki_size_t,"size", uint32_t,"position", int,"options" );
1766 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
1767 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
1768 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
1774 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
1775 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1776 PRE_REG_READ6(int, "fsetxattr",
1777 int,"fd", char *,"name", void *,"value",
1778 vki_size_t,"size", uint32_t,"position", int,"options" );
1780 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
1781 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
1787 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
1788 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 );
1789 PRE_REG_READ3(int, "removexattr",
1790 const char*, "path", char*, "attrname", int, "options");
1791 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
1792 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
1798 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
1799 ARG1, ARG2, (HChar*)ARG2, ARG3 );
1800 PRE_REG_READ3(int, "fremovexattr",
1801 int, "fd", char*, "attrname", int, "options");
1802 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
1808 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
1809 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
1810 PRE_REG_READ4 (long, "listxattr",
1811 const char *,"path", char *,"namebuf",
1812 vki_size_t,"size", int,"options" );
1814 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
1815 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
1816 *flags |= SfMayBlock;
1821 vg_assert((vki_ssize_t)RES >= 0);
1822 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1828 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
1829 ARG1, ARG2, ARG3, ARG4 );
1830 PRE_REG_READ4 (long, "flistxattr",
1831 int, "fd", char *,"namebuf",
1832 vki_size_t,"size", int,"options" );
1833 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
1834 *flags |= SfMayBlock;
1839 vg_assert((vki_ssize_t)RES >= 0);
1840 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1847 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
1848 PRE_REG_READ3(long, "shmat",
1849 int, shmid, const void *, shmaddr, int, shmflg);
1850 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
1852 SET_STATUS_Failure( VKI_EINVAL );
1854 ARG2 = arg2tmp; // used in POST
1858 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
1863 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
1864 PRE_REG_READ3(long, "shmctl",
1865 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
1866 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
1870 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
1875 PRINT("shmdt ( %#lx )",ARG1);
1876 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
1877 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
1878 SET_STATUS_Failure( VKI_EINVAL );
1882 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
1887 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1888 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
1893 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
1894 PRE_REG_READ3(long, "shm_open",
1895 const char *,"name", int,"flags", vki_mode_t,"mode");
1897 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
1899 *flags |= SfMayBlock;
1904 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
1906 SET_STATUS_Failure( VKI_EMFILE );
1908 if (VG_(clo_track_fds))
1909 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
1916 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1917 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1918 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
1919 void *, fsacl, vki_size_t *, fsacl_size);
1920 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
1921 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1922 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1923 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1924 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1928 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1929 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1930 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1931 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1937 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1938 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1939 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
1940 void *, fsacl, vki_size_t *, fsacl_size);
1941 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
1942 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1943 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1944 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1945 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1947 POST(lstat_extended)
1949 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1950 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1951 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1952 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1958 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
1959 ARG1, ARG2, ARG3, ARG4);
1960 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
1961 void *, fsacl, vki_size_t *, fsacl_size);
1962 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1963 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1964 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1965 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1967 POST(fstat_extended)
1969 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1970 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1971 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1972 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1976 PRE(stat64_extended)
1978 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1979 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1980 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
1981 void *, fsacl, vki_size_t *, fsacl_size);
1982 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
1983 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1984 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1985 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1986 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1988 POST(stat64_extended)
1990 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1991 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1992 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1993 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1997 PRE(lstat64_extended)
1999 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2000 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2001 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2002 void *, fsacl, vki_size_t *, fsacl_size);
2003 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2004 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2005 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2006 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2007 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2009 POST(lstat64_extended)
2011 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2012 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2013 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2014 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2018 PRE(fstat64_extended)
2020 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2021 ARG1, ARG2, ARG3, ARG4);
2022 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2023 void *, fsacl, vki_size_t *, fsacl_size);
2024 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2025 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2026 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2027 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2029 POST(fstat64_extended)
2031 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2032 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2033 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2034 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2038 PRE(fchmod_extended)
2040 /* DDD: Note: this is not really correct. Handling of
2041 chmod_extended is broken in the same way. */
2042 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2043 ARG1, ARG2, ARG3, ARG4, ARG5);
2044 PRE_REG_READ5(long, "fchmod_extended",
2045 unsigned int, fildes,
2049 void* /*really,user_addr_t*/, xsecurity);
2050 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2051 is just way wrong. [The trouble is with the size, which depends on a
2052 non-trival kernel computation] */
2054 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2055 sizeof(struct vki_kauth_filesec) );
2061 /* DDD: Note: this is not really correct. Handling of
2062 fchmod_extended is broken in the same way. */
2063 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2064 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2065 PRE_REG_READ5(long, "chmod_extended",
2066 unsigned int, fildes,
2070 void* /*really,user_addr_t*/, xsecurity);
2071 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2072 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2073 is just way wrong. [The trouble is with the size, which depends on a
2074 non-trival kernel computation] */
2076 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2077 sizeof(struct vki_kauth_filesec) );
2083 /* DDD: Note: this is not really correct. Handling of
2084 {,f}chmod_extended is broken in the same way. */
2085 PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )",
2086 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2087 ARG2, ARG3, ARG4, ARG5, ARG6);
2088 PRE_REG_READ6(long, "open_extended",
2094 void* /*really,user_addr_t*/, xsecurity);
2095 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2096 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2097 is just way wrong. [The trouble is with the size, which depends on a
2098 non-trival kernel computation] */
2100 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2101 sizeof(struct vki_kauth_filesec) );
2104 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2105 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2106 // by one or more strings. Each accessx_descriptor contains a field,
2107 // 'ad_name_offset', which points to one of the strings (or it can contain
2108 // zero which means "reuse the string from the previous accessx_descriptor").
2110 // What's really ridiculous is that we are only given the size of the overall
2111 // buffer, not the number of accessx_descriptors, nor the number of strings.
2112 // The kernel determines the number of accessx_descriptors by walking through
2113 // them one by one, checking that the ad_name_offset points within the buffer,
2114 // past the current point (or that it's a zero, unless its the first
2115 // descriptor); if so, we assume that this really is an accessx_descriptor,
2116 // if not, we assume we've hit the strings section. Gah.
2118 // This affects us here because number of entries in the 'results' buffer is
2119 // determined by the number of accessx_descriptors. So we have to know that
2120 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2121 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2122 // computation after the syscall has succeeded, because the kernel will have
2123 // checked for all the zillion different ways this syscall can fail, and we'll
2124 // know we have a well-formed 'entries' buffer. This means we might miss some
2125 // uses of unaddressable memory but oh well.
2127 PRE(access_extended)
2129 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2130 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2131 // XXX: the accessx_descriptor struct contains padding, so this can cause
2132 // unnecessary undefined value errors. But you arguably shouldn't be
2133 // passing undefined values to the kernel anyway...
2134 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2135 vki_errno_t *, results, vki_uid_t *, uid);
2136 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2138 // XXX: as mentioned above, this check is too hard to do before the
2140 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2142 POST(access_extended)
2144 // 'n_descs' is the number of descriptors we think are in the buffer. We
2145 // start with the maximum possible value, which occurs if we have the
2146 // shortest possible string section. The shortest string section allowed
2147 // consists of a single one-char string (plus the NUL char). Hence the
2149 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2151 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2152 Int i; // Current position in the descriptors section array.
2153 Int u; // Upper bound on the length of the descriptors array
2154 // (recomputed each time around the loop)
2155 vg_assert(n_descs > 0);
2157 // Step through the descriptors, lowering 'n_descs' until we know we've
2158 // reached the string section.
2159 for (i = 0; True; i++) {
2160 // If we're past our estimate, we must be one past the end of the
2161 // descriptors section (ie. at the start of the string section). Stop.
2165 // Get the array index for the string, but pretend momentarily that it
2166 // is actually another accessx_descriptor. That gives us an upper bound
2167 // on the length of the descriptors section. (Unless the index is zero,
2168 // in which case we have no new info.)
2169 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2175 // If the upper bound is below our current estimate, revise that
2176 // estimate downwards.
2182 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2184 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2190 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2191 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2192 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2194 // GrP fixme sanity-check flags value?
2199 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2200 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2202 // GrP fixme sanity-check flags value?
2207 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2208 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2209 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2210 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2214 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2219 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2220 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2221 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2222 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2226 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2231 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2232 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2233 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2237 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2242 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2243 PRE_REG_READ3(int, "getfsstat",
2244 struct vki_statfs *, buf, int, bufsize, int, flags);
2246 // ARG2 is a BYTE SIZE
2247 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2253 // RES is a STRUCT COUNT
2254 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2260 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2261 PRE_REG_READ3(int, "getfsstat64",
2262 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2264 // ARG2 is a BYTE SIZE
2265 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2271 // RES is a STRUCT COUNT
2272 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2278 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2279 // We are conservative and check everything, except the memory pointed to
2281 *flags |= SfMayBlock;
2282 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2283 ARG1,(Char*)ARG1, ARG2,(Char*)ARG2, ARG3, ARG4);
2284 PRE_REG_READ4(long, "mount",
2285 const char *, type, const char *, dir,
2286 int, flags, void *, data);
2287 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2288 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2292 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2293 void *attrBuf, SizeT attrBufSize,
2294 void (*fn)(ThreadId, void *attrData, SizeT size)
2301 static const attrspec commonattr[] = {
2302 // This order is important.
2303 #if DARWIN_VERS >= DARWIN_10_6
2304 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
2306 { ATTR_CMN_NAME, -1 },
2307 { ATTR_CMN_DEVID, sizeof(dev_t) },
2308 { ATTR_CMN_FSID, sizeof(fsid_t) },
2309 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
2310 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
2311 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
2312 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
2313 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
2314 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
2315 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
2316 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
2317 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
2318 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
2319 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
2320 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2321 { ATTR_CMN_OWNERID, sizeof(uid_t) },
2322 { ATTR_CMN_GRPID, sizeof(gid_t) },
2323 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
2324 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
2325 { ATTR_CMN_NAMEDATTRLIST, -1 },
2326 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
2327 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
2328 { ATTR_CMN_EXTENDED_SECURITY, -1 },
2329 { ATTR_CMN_UUID, sizeof(guid_t) },
2330 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
2331 { ATTR_CMN_FILEID, sizeof(uint64_t) },
2332 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
2333 #if DARWIN_VERS >= DARWIN_10_6
2334 { ATTR_CMN_FULLPATH, -1 },
2338 static const attrspec volattr[] = {
2339 // This order is important.
2340 { ATTR_VOL_INFO, 0 },
2341 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
2342 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
2343 { ATTR_VOL_SIZE, sizeof(off_t) },
2344 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
2345 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
2346 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
2347 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2348 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
2349 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
2350 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
2351 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
2352 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
2353 { ATTR_VOL_MOUNTPOINT, -1 },
2354 { ATTR_VOL_NAME, -1 },
2355 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
2356 { ATTR_VOL_MOUNTEDDEVICE, -1 },
2357 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
2358 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
2359 #if DARWIN_VERS >= DARWIN_10_6
2360 { ATTR_VOL_UUID, sizeof(uuid_t) },
2362 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
2365 static const attrspec dirattr[] = {
2366 // This order is important.
2367 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
2368 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
2369 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
2372 static const attrspec fileattr[] = {
2373 // This order is important.
2374 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
2375 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
2376 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
2377 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
2378 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
2379 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
2380 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
2381 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
2382 { ATTR_FILE_FORKLIST, -1 },
2383 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
2384 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
2385 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
2386 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
2387 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
2388 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
2391 static const attrspec forkattr[] = {
2392 // This order is important.
2393 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
2394 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
2398 static const attrspec *attrdefs[5] = {
2399 commonattr, volattr, dirattr, fileattr, forkattr
2405 vg_assert(attrList->bitmapcount == 5);
2406 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
2408 dend = d + attrBufSize;
2410 #if DARWIN_VERS >= DARWIN_10_6
2411 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
2412 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
2413 // fixme range check this?
2414 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
2415 fn(tid, d, sizeof(attribute_set_t));
2416 VG_(memcpy)(a, d, sizeof(a));
2420 for (g = 0; g < 5; g++) {
2421 for (i = 0; attrdefs[g][i].attrBit; i++) {
2422 uint32_t bit = attrdefs[g][i].attrBit;
2423 int32_t size = attrdefs[g][i].attrSize;
2426 a[g] &= ~bit; // clear bit for error check later
2428 attrreference_t *ref = (attrreference_t *)d;
2429 size = MIN(sizeof(attrreference_t), dend - d);
2431 if (size >= sizeof(attrreference_t) &&
2432 d + ref->attr_dataoffset < dend)
2434 fn(tid, d + ref->attr_dataoffset,
2435 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
2440 size = MIN(size, dend - d);
2445 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
2446 if (d > dend) d = dend;
2450 // Known bits are cleared. Die if any bits are left.
2452 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
2457 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2459 POST_MEM_WRITE((Addr)attrData, attrDataSize);
2462 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2464 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
2469 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2470 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2471 PRE_REG_READ5(int, "getattrlist",
2472 const char *,path, struct vki_attrlist *,attrList,
2473 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2474 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
2475 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2476 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
2481 if (ARG4 > sizeof(vki_uint32_t)) {
2482 // attrBuf is uint32_t size followed by attr data
2483 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
2484 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
2485 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
2486 // *sizep is bytes required for return value, including *sizep
2488 // *sizep is actual bytes returned, including *sizep
2490 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
2497 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2498 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2499 PRE_REG_READ5(int, "setattrlist",
2500 const char *,path, struct vki_attrlist *,attrList,
2501 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2502 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
2503 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2504 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
2508 PRE(getdirentriesattr)
2510 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
2511 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2512 PRE_REG_READ8(int, "getdirentriesattr",
2513 int,fd, struct vki_attrlist *,attrList,
2514 void *,attrBuf, size_t,attrBufSize,
2515 unsigned int *,count, unsigned int *,basep,
2516 unsigned int *,newState, unsigned int,options);
2517 PRE_MEM_READ("getdirentriesattr(attrList)",
2518 ARG2, sizeof(struct vki_attrlist));
2519 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
2520 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2521 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2522 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
2523 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
2525 POST(getdirentriesattr)
2531 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
2532 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
2533 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
2535 // return buffer is concatenation of variable-size structs
2536 count = *(unsigned int *)ARG5;
2538 end = (char *)ARG3 + ARG4;
2539 for (i = 0; i < count; i++) {
2540 vg_assert(p < end); // failure is kernel bug or Valgrind bug
2541 p += *(unsigned int *)p;
2544 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
2546 PRINT("got %d records, %ld/%lu bytes\n",
2547 count, (Addr)p-(Addr)ARG3, ARG4);
2553 #if VG_WORDSIZE == 4
2554 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
2556 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
2557 LOHI64(ARG4, ARG5));
2558 PRE_REG_READ5(ssize_t, "fsgetpath",
2559 void*,"buf", size_t,"bufsize",
2561 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
2563 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
2565 ((unsigned int *)ARG3)[0],
2566 ((unsigned int *)ARG3)[1], ARG4);
2567 PRE_REG_READ4(ssize_t, "fsgetpath",
2568 void*,"buf", size_t,"bufsize",
2569 fsid_t *,"fsid", uint64_t,"objid");
2571 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
2572 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
2577 POST_MEM_WRITE(ARG1, RES);
2580 PRE(audit_session_self)
2582 PRINT("audit_session_self()");
2585 POST(audit_session_self)
2587 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
2588 PRINT("audit-session %#lx", RES);
2593 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
2594 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
2595 PRE_REG_READ3(int, "exchangedata",
2596 char *, path1, char *, path2, unsigned long, options);
2597 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
2598 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
2603 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
2604 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2605 PRE_REG_READ4( long, "fsctl",
2606 char *,"path", unsigned int,"request",
2607 void *,"data", unsigned int,"options");
2609 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
2612 case VKI_afpfsByteRangeLock2FSCTL: {
2613 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2614 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
2616 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
2618 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
2620 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
2622 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
2625 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
2628 // GrP fixme check fd
2631 case VKI_FSIOC_SYNC_VOLUME:
2632 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
2636 // fsctl requests use ioctl encoding
2637 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
2645 case VKI_afpfsByteRangeLock2FSCTL: {
2646 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2647 POST_FIELD_WRITE(pb->retRangeStart);
2650 case VKI_FSIOC_SYNC_VOLUME:
2654 // fsctl requests use ioctl encoding
2655 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
2662 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
2663 PRE_REG_READ3(long, "initgroups",
2664 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
2665 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
2669 //--------- posix_spawn ---------//
2670 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
2671 the simpler AIX equivalent (syswrap-aix5.c). */
2672 // Pre_read a char** argument.
2673 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
2677 Addr* a_p = (Addr*)a;
2678 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2682 PRE_MEM_RASCIIZ( s2, a_deref );
2686 static SysRes simple_pre_exec_check ( const HChar* exe_name,
2687 Bool trace_this_child )
2691 Bool setuid_allowed;
2693 // Check it's readable
2694 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
2695 if (sr_isError(res)) {
2701 // Check we have execute permissions. We allow setuid executables
2702 // to be run only in the case when we are not simulating them, that
2703 // is, they to be run natively.
2704 setuid_allowed = trace_this_child ? False : True;
2705 ret = VG_(check_executable)(NULL/*&is_setuid*/,
2706 (HChar*)exe_name, setuid_allowed);
2708 return VG_(mk_SysRes_Error)(ret);
2710 return VG_(mk_SysRes_Success)(0);
2714 Char* path = NULL; /* path to executable */
2718 Char* launcher_basename = NULL;
2721 Bool trace_this_child;
2725 posix_spawn_file_actions_t* file_actions
2729 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
2730 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2732 /* Standard pre-syscall checks */
2734 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
2735 void*, file_actions, char**, argv, char**, envp );
2736 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
2737 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
2738 // DDD: check file_actions
2740 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
2741 "posix_spawn(argv[i])" );
2743 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
2744 "posix_spawn(envp[i])" );
2747 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
2748 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2750 /* Now follows a bunch of logic copied from PRE(sys_execve) in
2751 syswrap-generic.c. */
2753 /* Check that the name at least begins in client-accessible storage. */
2754 if (ARG2 == 0 /* obviously bogus */
2755 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
2756 SET_STATUS_Failure( VKI_EFAULT );
2760 // Decide whether or not we want to follow along
2761 { // Make 'child_argv' be a pointer to the child's arg vector
2762 // (skipping the exe name)
2763 HChar** child_argv = (HChar**)ARG4;
2764 if (child_argv && child_argv[0] == NULL)
2766 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
2769 // Do the important checks: it is a file, is executable, permissions are
2770 // ok, etc. We allow setuid executables to run only in the case when
2771 // we are not simulating them, that is, they to be run natively.
2772 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
2773 if (sr_isError(res)) {
2774 SET_STATUS_Failure( sr_Err(res) );
2778 /* If we're tracing the child, and the launcher name looks bogus
2779 (possibly because launcher.c couldn't figure it out, see
2780 comments therein) then we have no option but to fail. */
2781 if (trace_this_child
2782 && (VG_(name_of_launcher) == NULL
2783 || VG_(name_of_launcher)[0] != '/')) {
2784 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2788 /* Ok. So let's give it a try. */
2789 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2);
2791 // Terminate gdbserver if it is active.
2792 if (VG_(clo_vgdb) != Vg_VgdbNo) {
2793 // If the child will not be traced, we need to terminate gdbserver
2794 // to cleanup the gdbserver resources (e.g. the FIFO files).
2795 // If child will be traced, we also terminate gdbserver: the new
2796 // Valgrind will start a fresh gdbserver after exec.
2797 VG_(gdbserver) (tid);
2800 // Set up the child's exe path.
2802 if (trace_this_child) {
2804 // We want to exec the launcher. Get its pre-remembered path.
2805 path = VG_(name_of_launcher);
2806 // VG_(name_of_launcher) should have been acquired by m_main at
2807 // startup. The following two assertions should be assured by
2808 // the "If we're tracking the child .." test just above here.
2810 vg_assert(path[0] == '/');
2811 launcher_basename = path;
2817 // Set up the child's environment.
2819 // Remove the valgrind-specific stuff from the environment so the
2820 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
2821 // This is done unconditionally, since if we are tracing the child,
2822 // the child valgrind will set up the appropriate client environment.
2823 // Nb: we make a copy of the environment before trying to mangle it
2824 // as it might be in read-only memory (this was bug #101881).
2826 // Then, if tracing the child, set VALGRIND_LIB for it.
2831 envp = VG_(env_clone)( (Char**)ARG5 );
2833 VG_(env_remove_valgrind_env_stuff)( envp );
2836 if (trace_this_child) {
2837 // Set VALGRIND_LIB in ARG5 (the environment)
2838 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
2841 // Set up the child's args. If not tracing it, they are
2842 // simply ARG4. Otherwise, they are
2844 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
2846 // except that the first VG_(args_for_valgrind_noexecpass) args
2849 if (!trace_this_child) {
2850 argv = (Char**)ARG4;
2852 vg_assert( VG_(args_for_valgrind) );
2853 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2854 vg_assert( VG_(args_for_valgrind_noexecpass)
2855 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
2856 /* how many args in total will there be? */
2857 // launcher basename
2860 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
2861 tot_args -= VG_(args_for_valgrind_noexecpass);
2862 // name of client exe
2864 // args for client exe, skipping [0]
2865 arg2copy = (Char**)ARG4;
2866 if (arg2copy && arg2copy[0]) {
2867 for (i = 1; arg2copy[i]; i++)
2871 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
2872 (tot_args+1) * sizeof(HChar*) );
2876 argv[j++] = launcher_basename;
2877 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
2878 if (i < VG_(args_for_valgrind_noexecpass))
2880 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
2882 argv[j++] = (Char*)ARG2;
2883 if (arg2copy && arg2copy[0])
2884 for (i = 1; arg2copy[i]; i++)
2885 argv[j++] = arg2copy[i];
2888 vg_assert(j == tot_args+1);
2891 /* DDD: sort out the signal state. What signal
2892 state does the child inherit from the parent? */
2896 VG_(printf)("posix_spawn: %s\n", path);
2897 for (cpp = argv; cpp && *cpp; cpp++)
2898 VG_(printf)("argv: %s\n", *cpp);
2900 for (cpp = envp; cpp && *cpp; cpp++)
2901 VG_(printf)("env: %s\n", *cpp);
2904 /* Let the call go through as usual. However, we have to poke
2905 the altered arguments back into the argument slots. */
2910 /* not to mention .. */
2911 *flags |= SfMayBlock;
2916 //POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
2922 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2923 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
2930 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
2931 SET_STATUS_from_SysRes(r);
2937 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
2938 ARG1,ARG2,ARG3,ARG4,ARG5);
2939 PRE_REG_READ5(long, "setsockopt",
2940 int, s, int, level, int, optname,
2941 const void *, optval, vki_socklen_t, optlen);
2942 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
2948 Addr optval_p = ARG4;
2949 Addr optlen_p = ARG5;
2950 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
2951 ARG1,ARG2,ARG3,ARG4,ARG5);
2952 PRE_REG_READ5(long, "getsockopt",
2953 int, s, int, level, int, optname,
2954 void *, optval, vki_socklen_t *, optlen);
2955 /* int getsockopt(int socket, int level, int option_name,
2956 void *restrict option_value,
2957 socklen_t *restrict option_len); */
2958 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
2959 if (optval_p != (Addr)NULL) {
2960 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
2961 "socketcall.getsockopt(optval)",
2962 "socketcall.getsockopt(optlen)" );
2964 // DDD: #warning GrP fixme darwin-specific sockopts
2969 Addr optval_p = ARG4;
2970 Addr optlen_p = ARG5;
2972 if (optval_p != (Addr)NULL) {
2973 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
2975 "socketcall.getsockopt(optlen_out)" );
2976 // DDD: #warning GrP fixme darwin-specific sockopts
2983 *flags |= SfMayBlock;
2984 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2985 PRE_REG_READ3(long, "connect",
2986 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
2987 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
2993 *flags |= SfMayBlock;
2994 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2995 PRE_REG_READ3(long, "accept",
2996 int, s, struct sockaddr *, addr, int, *addrlen);
2997 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3004 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3006 SET_STATUS_from_SysRes(r);
3012 *flags |= SfMayBlock;
3013 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3014 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
3015 PRE_REG_READ6(long, "sendto",
3016 int, s, const void *, msg, int, len,
3017 unsigned int, flags,
3018 const struct sockaddr *, to, int, tolen);
3019 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3024 #if VG_WORDSIZE == 4
3025 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3026 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
3028 PRE_REG_READ7(long, "sendfile",
3029 int, fromfd, int, tofd,
3030 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3031 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3032 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3033 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3035 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
3036 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
3038 PRE_REG_READ6(long, "sendfile",
3039 int, fromfd, int, tofd,
3040 vki_uint64_t, offset,
3041 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3042 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3043 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3046 *flags |= SfMayBlock;
3050 #if VG_WORDSIZE == 4
3051 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3052 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3054 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3055 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3061 *flags |= SfMayBlock;
3062 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3063 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3064 PRE_REG_READ6(long, "recvfrom",
3065 int, s, void *, buf, int, len, unsigned int, flags,
3066 struct sockaddr *, from, int *, fromlen);
3067 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3073 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3074 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3080 *flags |= SfMayBlock;
3081 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3082 PRE_REG_READ3(long, "sendmsg",
3083 int, s, const struct msghdr *, msg, int, flags);
3084 ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
3090 *flags |= SfMayBlock;
3091 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3092 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3093 ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
3098 ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
3104 *flags |= SfMayBlock;
3105 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
3106 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3112 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3113 PRE_REG_READ3(long, "bind",
3114 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3115 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3121 PRINT("listen ( %ld, %ld )",ARG1,ARG2);
3122 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3128 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3129 PRE_REG_READ3(long, "getsockname",
3130 int, s, struct sockaddr *, name, int *, namelen);
3131 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3137 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3144 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3145 PRE_REG_READ3(long, "getpeername",
3146 int, s, struct sockaddr *, name, int *, namelen);
3147 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3153 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3160 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3161 PRE_REG_READ4(long, "socketpair",
3162 int, d, int, type, int, protocol, int *, sv);
3163 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3169 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3170 ARG1,ARG2,ARG3,ARG4);
3176 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3177 PRE_REG_READ2(int,"gethostuuid",
3179 const struct vki_timespec *,"timeout");
3181 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3182 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3184 *flags |= SfMayBlock;
3190 POST_MEM_WRITE(ARG1, 16);
3193 /* Darwin pipe() returns the two descriptors in two registers. */
3197 PRE_REG_READ0(int, "pipe");
3207 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3208 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3211 SET_STATUS_Failure( VKI_EMFILE );
3213 if (VG_(clo_track_fds)) {
3214 ML_(record_fd_open_nameless)(tid, p0);
3215 ML_(record_fd_open_nameless)(tid, p1);
3223 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3224 PRE_REG_READ2(long, "getlogin",
3225 char *,"namebuf", unsigned int,"namelen");
3227 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3232 POST_MEM_WRITE(ARG1, ARG2);
3238 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3239 PRE_REG_READ4(long, "ptrace",
3240 int,"request", vki_pid_t,"pid",
3241 vki_caddr_t,"addr", int,"data");
3243 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3245 // GrP fixme anything needed?
3251 PRINT("issetugid ( )");
3252 PRE_REG_READ0(long, "issetugid");
3258 PRINT("getdtablesize ( )");
3259 PRE_REG_READ0(long, "getdtablesize");
3264 // Subtract Valgrind's fd range from client's dtable
3265 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3270 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3271 PRE_REG_READ4(vki_off_t, "lseek",
3272 unsigned int,fd, int,offset_hi, int,offset_lo,
3273 unsigned int,whence);
3279 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3280 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3281 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3287 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3288 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3290 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3291 SET_STATUS_Failure( VKI_EBADF );
3297 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3298 PRE_REG_READ4(int, "getdirentries",
3299 int, fd, char *, buf, int, nbytes, long *, basep);
3300 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3301 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3306 POST_MEM_WRITE(ARG4, sizeof(long));
3307 // GrP fixme be specific about d_name?
3308 POST_MEM_WRITE(ARG2, RES);
3312 PRE(getdirentries64)
3314 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3315 PRE_REG_READ4(vki_ssize_t, "getdirentries",
3316 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3317 PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t));
3318 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3320 POST(getdirentries64)
3322 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3323 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3324 POST_MEM_WRITE(ARG2, RES);
3330 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3331 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3332 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3333 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3337 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3343 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3344 PRE_REG_READ2(long, "fstatfs64",
3345 unsigned int, fd, struct statfs *, buf);
3346 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3350 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3355 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
3356 PRE_REG_READ4(int, "csops",
3357 vki_pid_t, pid, uint32_t, ops,
3358 void *, useraddr, vki_size_t, usersize);
3360 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
3362 // If the pid is ours, don't mark the program as KILL or HARD
3363 // Maybe we should keep track of this for later calls to STATUS
3364 if (!ARG1 || VG_(getpid)() == ARG1) {
3366 case VKI_CS_OPS_MARKINVALID:
3367 case VKI_CS_OPS_MARKHARD:
3368 case VKI_CS_OPS_MARKKILL:
3369 SET_STATUS_Success(0);
3375 POST_MEM_WRITE( ARG3, ARG4 );
3380 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
3381 PRE_REG_READ3(int,"auditon",
3382 int,"cmd", void*,"data", unsigned int,"length");
3386 case VKI_A_SETPOLICY:
3387 case VKI_A_SETKMASK:
3388 case VKI_A_SETQCTRL:
3390 case VKI_A_SETCLASS:
3391 case VKI_A_SETPMASK:
3392 case VKI_A_SETFSIZE:
3393 #if DARWIN_VERS >= DARWIN_10_6
3394 case VKI_A_SENDTRIGGER:
3396 // kernel reads data..data+length
3397 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3400 case VKI_A_GETKMASK:
3401 case VKI_A_GETPOLICY:
3402 case VKI_A_GETQCTRL:
3403 case VKI_A_GETFSIZE:
3405 // kernel writes data..data+length
3406 // GrP fixme be precise about what gets written
3407 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3411 case VKI_A_GETCLASS:
3412 case VKI_A_GETPINFO:
3413 case VKI_A_GETPINFO_ADDR:
3414 #if DARWIN_VERS >= DARWIN_10_6
3415 case VKI_A_GETSINFO_ADDR:
3417 // kernel reads and writes data..data+length
3418 // GrP fixme be precise about what gets read and written
3419 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3420 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3423 case VKI_A_SETKAUDIT:
3425 case VKI_A_SETUMASK:
3426 case VKI_A_SETSMASK:
3427 case VKI_A_GETKAUDIT:
3431 // unimplemented on darwin
3435 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1);
3443 case VKI_A_SETPOLICY:
3444 case VKI_A_SETKMASK:
3445 case VKI_A_SETQCTRL:
3447 case VKI_A_SETCLASS:
3448 case VKI_A_SETPMASK:
3449 case VKI_A_SETFSIZE:
3450 #if DARWIN_VERS >= DARWIN_10_6
3451 case VKI_A_SENDTRIGGER:
3453 // kernel reads data..data+length
3456 case VKI_A_GETKMASK:
3457 case VKI_A_GETPOLICY:
3458 case VKI_A_GETQCTRL:
3459 case VKI_A_GETFSIZE:
3461 // kernel writes data..data+length
3462 // GrP fixme be precise about what gets written
3463 POST_MEM_WRITE(ARG2, ARG3);
3467 case VKI_A_GETCLASS:
3468 case VKI_A_GETPINFO:
3469 case VKI_A_GETPINFO_ADDR:
3470 #if DARWIN_VERS >= DARWIN_10_6
3471 case VKI_A_GETSINFO_ADDR:
3473 // kernel reads and writes data..data+length
3474 // GrP fixme be precise about what gets read and written
3475 POST_MEM_WRITE(ARG2, ARG3);
3478 case VKI_A_SETKAUDIT:
3480 case VKI_A_SETUMASK:
3481 case VKI_A_SETSMASK:
3482 case VKI_A_GETKAUDIT:
3486 // unimplemented on darwin
3499 #if VG_WORDSIZE == 4
3500 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
3501 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
3502 PRE_REG_READ7(Addr, "mmap",
3503 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3504 unsigned long,offset_hi, unsigned long,offset_lo);
3505 // GrP fixme V mmap and kernel mach_msg collided once - don't use
3506 // V's mechanism for now
3507 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
3508 // (Off64T)LOHI64(ARG6, ARG7) );
3510 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
3511 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3512 PRE_REG_READ6(long, "mmap",
3513 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3515 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3519 // SET_STATUS_from_SysRes(r);
3525 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
3526 // Try to load symbols from the region
3527 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/ );
3534 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
3535 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3537 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
3538 void*, oldp, vki_size_t *, oldlenp,
3539 void*, newp, vki_size_t *, newlenp);
3541 PRE_MEM_READ("sysctl(name)", ARG1, ARG2); // reads name[0..namelen-1]
3544 PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
3546 // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
3547 PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
3548 PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
3552 PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
3555 if (VG_(clo_trace_syscalls)) {
3557 int *name = (int *)ARG1;
3558 VG_(printf)(" mib: [ ");
3559 for (i = 0; i < ARG2; i++) {
3560 VG_(printf)("%d ", name[i]);
3565 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
3566 // (executable path and arguments and environment
3569 // Intercept sysctl(kern.usrstack). The kernel's reply would be
3570 // Valgrind's stack, not the client's stack.
3571 // GrP fixme kern_usrstack64
3572 if (ARG1 && ARG2 == 2 &&
3573 ((int *)ARG1)[0] == VKI_CTL_KERN &&
3574 #if VG_WORDSIZE == 4
3575 ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
3577 ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
3581 if (ARG5/*newp*/ || ARG6/*newlen*/) {
3582 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
3584 Addr *oldp = (Addr *)ARG3;
3585 size_t *oldlenp = (size_t *)ARG4;
3587 Addr stack_end = VG_(clstk_end)+1;
3588 size_t oldlen = *oldlenp;
3589 // always return actual size
3590 *oldlenp = sizeof(Addr);
3591 if (oldp && oldlen >= sizeof(Addr)) {
3592 // oldp is big enough
3593 // copy value and return 0
3595 SET_STATUS_Success(0);
3597 // oldp isn't big enough
3598 // copy as much as possible and return ENOMEM
3599 if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
3600 SET_STATUS_Failure(VKI_ENOMEM);
3607 if (!SUCCESS && !FAILURE) {
3608 // Don't set SfPostOnFail if we've already handled it locally.
3609 *flags |= SfPostOnFail;
3615 if (SUCCESS || ERR == VKI_ENOMEM) {
3616 // sysctl can write truncated data and return VKI_ENOMEM
3618 POST_MEM_WRITE(ARG4, sizeof(size_t));
3621 POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
3629 PRINT( "sigpending ( %#lx )", ARG1 );
3630 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
3631 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
3635 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
3642 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
3643 PRE_REG_READ3(long, "sigprocmask",
3644 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
3646 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
3648 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
3650 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
3651 value of 'how' is irrelevant, and it appears that Darwin's libc
3652 passes zero, which is not equal to any of
3653 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
3654 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
3655 value independently of the other args. Solution: in this case,
3656 simply pass a valid (but irrelevant) value for 'how'. */
3657 /* Also, in this case the new set is passed to the kernel by
3658 reference, not value, as in some other sigmask related Darwin
3661 if (ARG2 == 0 /* the new-set is NULL */
3662 && ARG1 != VKI_SIG_BLOCK
3663 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
3664 arg1 = VKI_SIG_SETMASK;
3666 SET_STATUS_from_SysRes(
3667 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
3668 (vki_sigset_t*)ARG3 )
3672 *flags |= SfPollAfter;
3678 if (RES == 0 && ARG3 != 0)
3679 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
3685 /* Just hand this off to the kernel. Is that really correct? And
3686 shouldn't we at least set SfPollAfter? These questions apply to
3687 all the Linux versions too. */
3688 /* I think the first arg is the 32-bit signal mask (by value), and
3689 the other two args are ignored. */
3690 *flags |= SfMayBlock;
3691 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
3692 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
3696 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
3697 and 32-bit wrappers are different.
3699 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
3700 length in the usual way. I have seen values NULL, 0 passed in some
3701 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
3702 basis that they don't do anything if the length is zero, so it's OK
3703 for the buffer pointer to be NULL in that case (meaning they don't
3706 int proc_info(int32_t callnum, int32_t pid,
3707 uint32_t flavor, uint64_t arg,
3708 user_addr_t buffer, int32_t buffersize)
3710 #if DARWIN_VERS >= DARWIN_10_6
3713 #if VG_WORDSIZE == 4
3714 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3715 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
3716 PRE_REG_READ7(int, "proc_info",
3717 int, callnum, int, pid, unsigned int, flavor,
3718 vki_uint32_t, arg_low32,
3719 vki_uint32_t, arg_high32,
3720 void*, buffer, int, buffersize);
3721 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
3723 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3724 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
3725 PRE_REG_READ6(int, "proc_info",
3726 int, callnum, int, pid, unsigned int, flavor,
3727 unsigned long long int, arg,
3728 void*, buffer, int, buffersize);
3729 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
3735 #if VG_WORDSIZE == 4
3737 POST_MEM_WRITE(ARG6, ARG7);
3740 POST_MEM_WRITE(ARG5, ARG6);
3744 #endif /* DARWIN_VERS >= DARWIN_10_6 */
3746 /* ---------------------------------------------------------------------
3748 ------------------------------------------------------------------ */
3750 // We must record the aiocbp for each aio_read() in a table so that when
3751 // aio_return() is called we can mark the memory written asynchronously by
3752 // aio_read() as having been written. We don't have to do this for
3753 // aio_write(). See bug 197227 for more details.
3754 static OSet* aiocbp_table = NULL;
3755 static Bool aio_init_done = False;
3757 static void aio_init(void)
3759 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
3760 aio_init_done = True;
3763 static Bool was_a_successful_aio_read = False;
3767 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3768 // This assumes that the kernel looks at the struct pointer, but not the
3769 // contents of the struct.
3770 PRINT( "aio_return ( %#lx )", ARG1 );
3771 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
3773 if (!aio_init_done) aio_init();
3774 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
3778 // If we found the aiocbp in our own table it must have been an aio_read(),
3779 // so mark the buffer as written. If we didn't find it, it must have been
3780 // an aio_write() or a bogus aio_return() (eg. a second one on the same
3781 // aiocbp). Either way, the buffer won't have been written so we don't
3782 // have to mark the buffer as written.
3783 if (was_a_successful_aio_read) {
3784 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3785 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3786 was_a_successful_aio_read = False;
3792 // This assumes that the kernel looks at the struct pointers in the list,
3793 // but not the contents of the structs.
3794 PRINT( "aio_suspend ( %#lx )", ARG1 );
3795 PRE_REG_READ3(long, "aio_suspend",
3796 const struct vki_aiocb *, aiocbp, int, nent,
3797 const struct vki_timespec *, timeout);
3799 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
3801 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
3806 // This assumes that the kernel looks at the struct pointer, but not the
3807 // contents of the struct.
3808 PRINT( "aio_error ( %#lx )", ARG1 );
3809 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
3814 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3816 PRINT( "aio_read ( %#lx )", ARG1 );
3817 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
3818 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3820 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3821 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
3822 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
3823 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3825 SET_STATUS_Failure( VKI_EBADF );
3828 SET_STATUS_Failure( VKI_EINVAL );
3833 // We have to record the fact that there is an asynchronous read request
3834 // pending. When a successful aio_return() occurs for this aiocb, then we
3835 // will mark the memory as having been defined.
3836 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3837 if (!aio_init_done) aio_init();
3838 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
3839 // should have caused the aio_read() to fail and we shouldn't have reached
3841 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
3846 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3848 PRINT( "aio_write ( %#lx )", ARG1 );
3849 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
3850 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3852 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3853 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
3854 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
3855 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3857 SET_STATUS_Failure( VKI_EBADF );
3860 SET_STATUS_Failure( VKI_EINVAL );
3864 /* ---------------------------------------------------------------------
3865 mach_msg: formatted messages
3866 ------------------------------------------------------------------ */
3868 static size_t desc_size(mach_msg_descriptor_t *desc)
3870 switch (desc->type.type) {
3871 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
3872 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
3873 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
3874 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
3876 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
3877 return sizeof(desc->type); // guess
3882 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
3886 mach_port_t *ports = (mach_port_t *)desc->address;
3887 for (i = 0; i < desc->count; i++) {
3888 assign_port_name(ports[i], name);
3893 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
3895 mach_msg_body_t *body;
3896 mach_msg_size_t count, i;
3898 mach_msg_descriptor_t *desc;
3900 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
3902 body = (mach_msg_body_t *)(mh+1);
3903 count = body->msgh_descriptor_count;
3904 p = (uint8_t *)(body+1);
3906 for (i = 0; i < count; i++) {
3907 desc = (mach_msg_descriptor_t *)p;
3908 p += desc_size(desc);
3910 switch (desc->type.type) {
3911 case MACH_MSG_PORT_DESCRIPTOR:
3913 record_unnamed_port(tid, desc->port.name, -1);
3914 record_port_insert_rights(desc->port.name, desc->port.disposition);
3915 PRINT("got port %s;\n", name_for_port(desc->port.name));
3918 case MACH_MSG_OOL_DESCRIPTOR:
3919 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3920 // out-of-line memory - map it
3921 // GrP fixme how is VOLATILE different? do we care?
3922 // GrP fixme do other flags tell us anything? assume shared for now
3923 // GrP fixme more SF_ flags marking mach_msg memory might be nice
3924 // GrP fixme protection
3925 if (desc->out_of_line.size > 0) {
3926 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
3927 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
3928 (Addr)desc->out_of_line.size);
3929 PRINT("got ool mem %p..%#lx;\n", desc->out_of_line.address,
3930 (Addr)desc->out_of_line.address+desc->out_of_line.size);
3932 ML_(notify_core_and_tool_of_mmap)(
3933 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3934 VKI_MAP_PRIVATE, -1, 0);
3936 // GrP fixme mark only un-rounded part as initialized
3939 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3940 // out-of-line array of ports - map it
3941 // GrP fixme see fixmes above
3942 PRINT("got %d ool ports %p..%#lx", desc->ool_ports.count, desc->ool_ports.address, (Addr)desc->ool_ports.address+desc->ool_ports.count*sizeof(mach_port_t));
3944 if (desc->ool_ports.count > 0) {
3945 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
3946 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
3947 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
3949 ML_(notify_core_and_tool_of_mmap)(
3950 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3951 VKI_MAP_PRIVATE, -1, 0);
3954 for (i = 0; i < desc->ool_ports.count; i++) {
3955 record_unnamed_port(tid, ports[i], -1);
3956 record_port_insert_rights(ports[i], desc->port.disposition);
3957 PRINT(" %s", name_for_port(ports[i]));
3964 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
3971 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
3976 mach_msg_size_t pad1;
3978 uint8_t disposition;
3980 } *desc = (void*)desc2;
3983 PRE_FIELD_READ("msg->desc.port.name", desc->name);
3984 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
3985 PRE_FIELD_READ("msg->desc.port.type", desc->type);
3989 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
3994 #if VG_WORDSIZE != 8
3995 mach_msg_size_t size;
4001 #if VG_WORDSIZE == 8
4002 mach_msg_size_t size;
4004 } *desc = (void*)desc2;
4007 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4008 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4009 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4010 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4011 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4014 static void pre_oolports_desc_read(ThreadId tid,
4015 mach_msg_ool_ports_descriptor_t *desc2)
4020 #if VG_WORDSIZE != 8
4021 mach_msg_size_t size;
4025 uint8_t disposition;
4027 #if VG_WORDSIZE == 8
4028 mach_msg_size_t size;
4030 } *desc = (void*)desc2;
4033 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4034 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4035 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4036 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4037 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4038 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4042 // Returns the size of the descriptor area
4043 // (mach_msg_body_t + any mach_msg_descriptor_t)
4044 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4046 mach_msg_body_t *body;
4047 mach_msg_size_t count, i;
4049 mach_msg_descriptor_t *desc;
4051 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4053 body = (mach_msg_body_t *)(mh+1);
4054 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4056 count = body->msgh_descriptor_count;
4057 p = (uint8_t *)(body+1);
4059 for (i = 0; i < count; i++) {
4060 desc = (mach_msg_descriptor_t *)p;
4061 p += desc_size(desc);
4063 switch (desc->type.type) {
4064 case MACH_MSG_PORT_DESCRIPTOR:
4065 // single port; no memory map effects
4066 pre_port_desc_read(tid, &desc->port);
4069 case MACH_MSG_OOL_DESCRIPTOR:
4070 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4071 // out-of-line memory - unmap it if it's marked dealloc
4072 // GrP fixme need to remap if message fails?
4073 // GrP fixme how is VOLATILE different? do we care?
4074 // GrP fixme struct is different for lp64
4075 pre_ool_desc_read(tid, &desc->out_of_line);
4077 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4078 vm_size_t size = desc->out_of_line.size;
4079 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4080 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4081 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4082 (Addr)desc->out_of_line.address + size);
4083 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4087 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4088 // out-of-line array of ports - unmap it if it's marked dealloc
4089 // GrP fixme need to remap if message fails?
4090 // GrP fixme struct different for lp64
4091 pre_oolports_desc_read(tid, &desc->ool_ports);
4093 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4094 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4095 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4096 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4097 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4098 (Addr)desc->ool_ports.address + size);
4099 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4103 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4108 return (size_t)((Addr)p - (Addr)body);
4112 /* ---------------------------------------------------------------------
4113 mach_msg: host-related messages
4114 ------------------------------------------------------------------ */
4121 mach_msg_header_t Head;
4123 kern_return_t RetCode;
4124 mach_msg_type_number_t host_info_outCnt;
4125 integer_t host_info_out[14];
4129 Reply *reply = (Reply *)ARG1;
4131 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4138 mach_msg_header_t Head;
4140 host_flavor_t flavor;
4141 mach_msg_type_number_t host_info_outCnt;
4145 Request *req = (Request *)ARG1;
4147 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4149 AFTER = POST_FN(host_info);
4153 POST(host_page_size)
4157 mach_msg_header_t Head;
4159 kern_return_t RetCode;
4160 vm_size_t out_page_size;
4164 Reply *reply = (Reply *)ARG1;
4166 if (!reply->RetCode) {
4167 PRINT("page size %llu", (ULong)reply->out_page_size);
4169 PRINT("mig return %d", reply->RetCode);
4175 PRINT("host_page_size(mach_host_self(), ...)");
4177 AFTER = POST_FN(host_page_size);
4181 POST(host_get_io_master)
4185 mach_msg_header_t Head;
4186 /* start of the kernel processed data */
4187 mach_msg_body_t msgh_body;
4188 mach_msg_port_descriptor_t io_master;
4189 /* end of the kernel processed data */
4193 Reply *reply = (Reply *)ARG1;
4195 assign_port_name(reply->io_master.name, "io_master-%p");
4196 PRINT("%s", name_for_port(reply->io_master.name));
4199 PRE(host_get_io_master)
4203 mach_msg_header_t Head;
4207 // Request *req = (Request *)ARG1;
4209 PRINT("host_get_io_master(mach_host_self())");
4211 AFTER = POST_FN(host_get_io_master);
4215 POST(host_get_clock_service)
4219 mach_msg_header_t Head;
4220 /* start of the kernel processed data */
4221 mach_msg_body_t msgh_body;
4222 mach_msg_port_descriptor_t clock_serv;
4223 /* end of the kernel processed data */
4227 Reply *reply = (Reply *)ARG1;
4229 assign_port_name(reply->clock_serv.name, "clock-%p");
4230 PRINT("%s", name_for_port(reply->clock_serv.name));
4233 PRE(host_get_clock_service)
4237 mach_msg_header_t Head;
4239 clock_id_t clock_id;
4243 Request *req = (Request *)ARG1;
4245 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4247 AFTER = POST_FN(host_get_clock_service);
4251 PRE(host_request_notification)
4255 mach_msg_header_t Head;
4256 /* start of the kernel processed data */
4257 mach_msg_body_t msgh_body;
4258 mach_msg_port_descriptor_t notify_port;
4259 /* end of the kernel processed data */
4261 host_flavor_t notify_type;
4265 Request *req = (Request *)ARG1;
4267 if (MACH_REMOTE == mach_task_self()) {
4268 if (req->notify_type == 0) {
4269 PRINT("host_request_notification(mach_host_self(), %s, %s)",
4270 "HOST_NOTIFY_CALENDAR_CHANGE",
4271 name_for_port(req->notify_port.name));
4273 PRINT("host_request_notification(mach_host_self(), %d, %s)",
4275 name_for_port(req->notify_port.name));
4278 PRINT("host_request_notification(%s, %d, %s)",
4279 name_for_port(MACH_REMOTE),
4281 name_for_port(req->notify_port.name));
4284 // GrP fixme only do this on success
4285 assign_port_name(req->notify_port.name, "host_notify-%p");
4289 /* ---------------------------------------------------------------------
4290 mach_msg: messages to a task
4291 ------------------------------------------------------------------ */
4298 mach_msg_header_t Head;
4300 mach_port_name_t name;
4304 Request *req = (Request *)ARG1;
4306 PRINT("mach_port_type(%s, %s, ...)",
4307 name_for_port(MACH_REMOTE), name_for_port(req->name));
4309 AFTER = POST_FN(mach_port_type);
4312 POST(mach_port_type)
4317 PRE(mach_port_extract_member)
4321 mach_msg_header_t Head;
4323 mach_port_name_t name;
4324 mach_port_name_t pset;
4328 Request *req = (Request *)ARG1;
4330 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
4331 name_for_port(MACH_REMOTE),
4332 req->name, req->pset);
4334 AFTER = POST_FN(mach_port_extract_member);
4336 // GrP fixme port tracker?
4339 POST(mach_port_extract_member)
4343 mach_msg_header_t Head;
4345 kern_return_t RetCode;
4349 Reply *reply = (Reply *)ARG1;
4351 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4355 PRE(mach_port_allocate)
4359 mach_msg_header_t Head;
4361 mach_port_right_t right;
4365 Request *req = (Request *)ARG1;
4367 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
4369 MACH_ARG(mach_port_allocate.right) = req->right;
4371 AFTER = POST_FN(mach_port_allocate);
4374 POST(mach_port_allocate)
4378 mach_msg_header_t Head;
4380 kern_return_t RetCode;
4381 mach_port_name_t name;
4385 Reply *reply = (Reply *)ARG1;
4387 if (!reply->RetCode) {
4388 if (MACH_REMOTE == vg_task_port) {
4389 // GrP fixme port tracking is too imprecise
4390 // vg_assert(!port_exists(reply->name));
4391 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
4392 PRINT("got port 0x%x", reply->name);
4394 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
4397 PRINT("mig return %d", reply->RetCode);
4402 PRE(mach_port_deallocate)
4406 mach_msg_header_t Head;
4408 mach_port_name_t name;
4412 Request *req = (Request *)ARG1;
4414 PRINT("mach_port_deallocate(%s, %s)",
4415 name_for_port(MACH_REMOTE),
4416 name_for_port(req->name));
4418 MACH_ARG(mach_port.port) = req->name;
4420 AFTER = POST_FN(mach_port_deallocate);
4422 // Must block to prevent race (other thread allocates and
4423 // notifies after we deallocate but before we notify)
4424 *flags &= ~SfMayBlock;
4427 POST(mach_port_deallocate)
4431 mach_msg_header_t Head;
4433 kern_return_t RetCode;
4437 Reply *reply = (Reply *)ARG1;
4439 if (!reply->RetCode) {
4440 if (MACH_REMOTE == vg_task_port) {
4441 // Must have cleared SfMayBlock in PRE to prevent race
4442 record_port_dealloc(MACH_ARG(mach_port.port));
4444 VG_(printf)("UNKNOWN remote port dealloc\n");
4447 PRINT("mig return %d", reply->RetCode);
4452 PRE(mach_port_get_refs)
4456 mach_msg_header_t Head;
4458 mach_port_name_t name;
4459 mach_port_right_t right;
4463 Request *req = (Request *)ARG1;
4465 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
4466 name_for_port(MACH_REMOTE),
4467 name_for_port(req->name), req->right);
4469 MACH_ARG(mach_port_mod_refs.port) = req->name;
4470 MACH_ARG(mach_port_mod_refs.right) = req->right;
4472 AFTER = POST_FN(mach_port_get_refs);
4475 POST(mach_port_get_refs)
4479 mach_msg_header_t Head;
4481 kern_return_t RetCode;
4482 mach_port_urefs_t refs;
4486 Reply *reply = (Reply *)ARG1;
4488 if (!reply->RetCode) {
4489 PRINT("got refs=%d", reply->refs);
4491 PRINT("mig return %d", reply->RetCode);
4496 PRE(mach_port_mod_refs)
4500 mach_msg_header_t Head;
4502 mach_port_name_t name;
4503 mach_port_right_t right;
4504 mach_port_delta_t delta;
4508 Request *req = (Request *)ARG1;
4510 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
4511 name_for_port(MACH_REMOTE),
4512 name_for_port(req->name), req->right, req->delta);
4514 MACH_ARG(mach_port_mod_refs.port) = req->name;
4515 MACH_ARG(mach_port_mod_refs.right) = req->right;
4516 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
4518 AFTER = POST_FN(mach_port_mod_refs);
4520 // Must block to prevent race (other thread allocates and
4521 // notifies after we deallocate but before we notify)
4522 *flags &= ~SfMayBlock;
4525 POST(mach_port_mod_refs)
4529 mach_msg_header_t Head;
4531 kern_return_t RetCode;
4535 Reply *reply = (Reply *)ARG1;
4537 if (!reply->RetCode) {
4538 if (MACH_REMOTE == vg_task_port) {
4539 // Must have cleared SfMayBlock in PRE to prevent race
4540 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
4541 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
4542 MACH_ARG(mach_port_mod_refs.delta));
4544 VG_(printf)("UNKNOWN remote port mod refs\n");
4547 PRINT("mig return %d", reply->RetCode);
4552 PRE(mach_port_get_set_status)
4556 mach_msg_header_t Head;
4558 mach_port_name_t name;
4562 Request *req = (Request *)ARG1;
4564 PRINT("mach_port_get_set_status(%s, %s)",
4565 name_for_port(MACH_REMOTE),
4566 name_for_port(req->name));
4568 AFTER = POST_FN(mach_port_get_set_status);
4571 POST(mach_port_get_set_status)
4575 mach_msg_header_t Head;
4576 /* start of the kernel processed data */
4577 mach_msg_body_t msgh_body;
4578 mach_msg_ool_descriptor_t members;
4579 /* end of the kernel processed data */
4581 mach_msg_type_number_t membersCnt;
4582 mach_msg_trailer_t trailer;
4586 // Reply *reply = (Reply *)ARG1;
4588 // GrP fixme nothing to do?
4592 PRE(mach_port_move_member)
4596 mach_msg_header_t Head;
4598 mach_port_name_t member;
4599 mach_port_name_t after;
4603 Request *req = (Request *)ARG1;
4605 PRINT("mach_port_move_member(%s, %s, %s)",
4606 name_for_port(MACH_REMOTE),
4607 name_for_port(req->member),
4608 name_for_port(req->after));
4610 MACH_ARG(mach_port_move_member.member) = req->member;
4611 MACH_ARG(mach_port_move_member.after) = req->after;
4613 AFTER = POST_FN(mach_port_move_member);
4616 POST(mach_port_move_member)
4620 mach_msg_header_t Head;
4622 kern_return_t RetCode;
4623 mach_msg_trailer_t trailer;
4627 Reply *reply = (Reply *)ARG1;
4629 if (!reply->RetCode) {
4630 // fixme port set tracker?
4632 PRINT("mig return %d", reply->RetCode);
4637 PRE(mach_port_destroy)
4641 mach_msg_header_t Head;
4643 mach_port_name_t name;
4647 Request *req = (Request *)ARG1;
4649 PRINT("mach_port_destroy(%s, %s)",
4650 name_for_port(MACH_REMOTE),
4651 name_for_port(req->name));
4653 MACH_ARG(mach_port.port) = req->name;
4655 AFTER = POST_FN(mach_port_destroy);
4657 // Must block to prevent race (other thread allocates and
4658 // notifies after we deallocate but before we notify)
4659 *flags &= ~SfMayBlock;
4662 POST(mach_port_destroy)
4666 mach_msg_header_t Head;
4668 kern_return_t RetCode;
4672 Reply *reply = (Reply *)ARG1;
4674 if (!reply->RetCode) {
4675 if (MACH_REMOTE == vg_task_port) {
4676 // Must have cleared SfMayBlock in PRE to prevent race
4677 record_port_destroy(MACH_ARG(mach_port.port));
4679 VG_(printf)("UNKNOWN remote port destroy\n");
4682 PRINT("mig return %d", reply->RetCode);
4687 PRE(mach_port_request_notification)
4691 mach_msg_header_t Head;
4692 /* start of the kernel processed data */
4693 mach_msg_body_t msgh_body;
4694 mach_msg_port_descriptor_t notify;
4695 /* end of the kernel processed data */
4697 mach_port_name_t name;
4698 mach_msg_id_t msgid;
4699 mach_port_mscount_t sync;
4703 Request *req = (Request *)ARG1;
4705 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
4706 name_for_port(MACH_REMOTE),
4707 name_for_port(req->name), req->msgid, req->sync,
4708 req->notify.name, req->notify.disposition);
4710 AFTER = POST_FN(mach_port_request_notification);
4713 POST(mach_port_request_notification)
4715 // GrP fixme port tracker? not sure
4719 PRE(mach_port_insert_right)
4723 mach_msg_header_t Head;
4724 /* start of the kernel processed data */
4725 mach_msg_body_t msgh_body;
4726 mach_msg_port_descriptor_t poly;
4727 /* end of the kernel processed data */
4729 mach_port_name_t name;
4733 Request *req = (Request *)ARG1;
4735 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
4736 name_for_port(MACH_REMOTE),
4737 name_for_port(req->name), req->poly.name, req->poly.disposition);
4739 AFTER = POST_FN(mach_port_insert_right);
4741 if (MACH_REMOTE == mach_task_self()) {
4742 // GrP fixme import_complex_message handles everything?
4743 // what about export_complex_message for MOVE variants?
4745 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
4746 // GrP fixme also may remove rights from this task?
4749 // GrP fixme port tracker?
4752 POST(mach_port_insert_right)
4757 PRE(mach_port_extract_right)
4761 mach_msg_header_t Head;
4763 mach_port_name_t name;
4764 mach_msg_type_name_t msgt_name;
4768 Request *req = (Request *)ARG1;
4770 PRINT("mach_port_extract_right(%s, %s, %d)",
4771 name_for_port(MACH_REMOTE),
4772 name_for_port(req->name), req->msgt_name);
4774 AFTER = POST_FN(mach_port_extract_right);
4776 // fixme port tracker?
4779 POST(mach_port_extract_right)
4781 // fixme import_complex_message handles the returned result, right?
4785 PRE(mach_port_get_attributes)
4789 mach_msg_header_t Head;
4791 mach_port_name_t name;
4792 mach_port_flavor_t flavor;
4793 mach_msg_type_number_t port_info_outCnt;
4797 Request *req = (Request *)ARG1;
4799 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
4800 name_for_port(MACH_REMOTE),
4801 name_for_port(req->name), req->flavor, req->port_info_outCnt);
4803 AFTER = POST_FN(mach_port_get_attributes);
4806 POST(mach_port_get_attributes)
4811 PRE(mach_port_set_attributes)
4815 mach_msg_header_t Head;
4817 mach_port_name_t name;
4818 mach_port_flavor_t flavor;
4819 mach_msg_type_number_t port_infoCnt;
4820 integer_t port_info[10];
4824 Request *req = (Request *)ARG1;
4826 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
4827 name_for_port(MACH_REMOTE),
4828 name_for_port(req->name), req->flavor, req->port_infoCnt);
4830 AFTER = POST_FN(mach_port_set_attributes);
4833 POST(mach_port_set_attributes)
4838 PRE(mach_port_insert_member)
4842 mach_msg_header_t Head;
4844 mach_port_name_t name;
4845 mach_port_name_t pset;
4849 Request *req = (Request *)ARG1;
4851 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
4852 name_for_port(MACH_REMOTE), req->name, req->pset);
4854 AFTER = POST_FN(mach_port_insert_member);
4856 // GrP fixme port tracker?
4859 POST(mach_port_insert_member)
4864 PRE(task_get_special_port)
4868 mach_msg_header_t Head;
4874 Request *req = (Request *)ARG1;
4876 switch (req->which_port) {
4877 case TASK_KERNEL_PORT:
4878 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
4879 name_for_port(MACH_REMOTE));
4881 case TASK_HOST_PORT:
4882 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
4883 name_for_port(MACH_REMOTE));
4885 case TASK_BOOTSTRAP_PORT:
4886 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
4887 name_for_port(MACH_REMOTE));
4889 case TASK_WIRED_LEDGER_PORT:
4890 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
4891 name_for_port(MACH_REMOTE));
4893 case TASK_PAGED_LEDGER_PORT:
4894 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
4895 name_for_port(MACH_REMOTE));
4898 PRINT("task_get_special_port(%s, %d)",
4899 name_for_port(MACH_REMOTE), req->which_port);
4903 MACH_ARG(task_get_special_port.which_port) = req->which_port;
4905 AFTER = POST_FN(task_get_special_port);
4908 POST(task_get_special_port)
4912 mach_msg_header_t Head;
4913 /* start of the kernel processed data */
4914 mach_msg_body_t msgh_body;
4915 mach_msg_port_descriptor_t special_port;
4916 /* end of the kernel processed data */
4920 Reply *reply = (Reply *)ARG1;
4922 PRINT("got port %#x ", reply->special_port.name);
4924 switch (MACH_ARG(task_get_special_port.which_port)) {
4925 case TASK_BOOTSTRAP_PORT:
4926 vg_bootstrap_port = reply->special_port.name;
4927 assign_port_name(reply->special_port.name, "bootstrap");
4929 case TASK_KERNEL_PORT:
4930 assign_port_name(reply->special_port.name, "kernel");
4932 case TASK_HOST_PORT:
4933 assign_port_name(reply->special_port.name, "host");
4935 case TASK_WIRED_LEDGER_PORT:
4936 assign_port_name(reply->special_port.name, "wired-ledger");
4938 case TASK_PAGED_LEDGER_PORT:
4939 assign_port_name(reply->special_port.name, "paged-ledger");
4942 assign_port_name(reply->special_port.name, "special-%p");
4946 PRINT("%s", name_for_port(reply->special_port.name));
4950 PRE(semaphore_create)
4954 mach_msg_header_t Head;
4961 Request *req = (Request *)ARG1;
4963 PRINT("semaphore_create(%s, ..., %d, %d)",
4964 name_for_port(MACH_REMOTE), req->policy, req->value);
4966 AFTER = POST_FN(semaphore_create);
4969 POST(semaphore_create)
4973 mach_msg_header_t Head;
4974 /* start of the kernel processed data */
4975 mach_msg_body_t msgh_body;
4976 mach_msg_port_descriptor_t semaphore;
4977 /* end of the kernel processed data */
4978 mach_msg_trailer_t trailer;
4982 Reply *reply = (Reply *)ARG1;
4984 assign_port_name(reply->semaphore.name, "semaphore-%p");
4985 PRINT("%s", name_for_port(reply->semaphore.name));
4989 PRE(semaphore_destroy)
4993 mach_msg_header_t Head;
4994 /* start of the kernel processed data */
4995 mach_msg_body_t msgh_body;
4996 mach_msg_port_descriptor_t semaphore;
4997 /* end of the kernel processed data */
4998 mach_msg_trailer_t trailer;
5002 Request *req = (Request *)ARG1;
5004 PRINT("semaphore_destroy(%s, %s)",
5005 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
5007 record_port_destroy(req->semaphore.name);
5009 AFTER = POST_FN(semaphore_destroy);
5012 POST(semaphore_destroy)
5016 mach_msg_header_t Head;
5018 kern_return_t RetCode;
5019 mach_msg_trailer_t trailer;
5023 Reply *reply = (Reply *)ARG1;
5024 if (!reply->RetCode) {
5026 PRINT("mig return %d", reply->RetCode);
5031 PRE(mach_ports_lookup)
5035 mach_msg_header_t Head;
5039 // Request *req = (Request *)ARG1;
5041 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
5043 AFTER = POST_FN(mach_ports_lookup);
5046 POST(mach_ports_lookup)
5050 mach_msg_header_t Head;
5051 /* start of the kernel processed data */
5052 mach_msg_body_t msgh_body;
5053 mach_msg_ool_ports_descriptor_t init_port_set;
5054 /* end of the kernel processed data */
5056 mach_msg_type_number_t init_port_setCnt;
5060 // Reply *reply = (Reply *)ARG1;
5068 mach_msg_header_t Head;
5072 // Request *req = (Request *)ARG1;
5074 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
5076 AFTER = POST_FN(task_threads);
5083 mach_msg_header_t Head;
5084 /* start of the kernel processed data */
5085 mach_msg_body_t msgh_body;
5086 mach_msg_ool_ports_descriptor_t act_list;
5087 /* end of the kernel processed data */
5089 mach_msg_type_number_t act_listCnt;
5090 mach_msg_trailer_t trailer;
5094 Reply *reply = (Reply *)ARG1;
5096 if (MACH_REMOTE == vg_task_port) {
5097 assign_port_names(&reply->act_list, "thread-%p");
5099 assign_port_names(&reply->act_list, "remote-thread-%p");
5106 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
5108 if (MACH_REMOTE == vg_task_port) {
5109 // GrP fixme self-suspend
5112 // suspend other - no problem
5115 AFTER = POST_FN(task_suspend);
5125 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
5127 if (MACH_REMOTE == vg_task_port) {
5128 // GrP fixme self-resume
5131 // resume other - no problem
5134 AFTER = POST_FN(task_resume);
5146 mach_msg_header_t Head;
5148 vm_address_t address;
5154 Request *req = (Request *)ARG1;
5156 PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
5157 name_for_port(MACH_REMOTE),
5158 (ULong)req->address, (ULong)req->size, req->flags);
5160 MACH_ARG(vm_allocate.size) = req->size;
5161 MACH_ARG(vm_allocate.flags) = req->flags;
5163 AFTER = POST_FN(vm_allocate);
5170 mach_msg_header_t Head;
5172 kern_return_t RetCode;
5173 vm_address_t address;
5174 mach_msg_trailer_t trailer;
5178 Reply *reply = (Reply *)ARG1;
5180 if (!reply->RetCode) {
5181 if (MACH_REMOTE == vg_task_port) {
5182 PRINT("allocated at %#llx", (ULong)reply->address);
5183 // requesting 0 bytes returns address 0 with no error
5184 if (MACH_ARG(vm_allocate.size)) {
5185 ML_(notify_core_and_tool_of_mmap)(
5186 reply->address, MACH_ARG(vm_allocate.size),
5187 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5190 PRINT("allocated at %#llx in remote task %s",
5191 (ULong)reply->address,
5192 name_for_port(MACH_REMOTE));
5195 PRINT("mig return %d", reply->RetCode);
5204 mach_msg_header_t Head;
5206 vm_address_t address;
5211 Request *req = (Request *)ARG1;
5213 PRINT("vm_deallocate(%s, at %#llx, size %lld)",
5214 name_for_port(MACH_REMOTE),
5215 (ULong)req->address, (ULong)req->size);
5217 MACH_ARG(vm_deallocate.address) = req->address;
5218 MACH_ARG(vm_deallocate.size) = req->size;
5220 AFTER = POST_FN(vm_deallocate);
5222 // Must block to prevent race (other thread allocates and
5223 // notifies after we deallocate but before we notify)
5224 *flags &= ~SfMayBlock;
5231 mach_msg_header_t Head;
5233 kern_return_t RetCode;
5234 mach_msg_trailer_t trailer;
5238 Reply *reply = (Reply *)ARG1;
5240 if (!reply->RetCode) {
5241 if (MACH_REMOTE == vg_task_port) {
5242 if (MACH_ARG(vm_deallocate.size)) {
5243 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
5244 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
5245 MACH_ARG(vm_deallocate.size));
5246 // Must have cleared SfMayBlock in PRE to prevent race
5247 ML_(notify_core_and_tool_of_munmap)(start, end - start);
5251 PRINT("mig return %d", reply->RetCode);
5260 mach_msg_header_t Head;
5262 vm_address_t address;
5264 boolean_t set_maximum;
5265 vm_prot_t new_protection;
5269 Request *req = (Request *)ARG1;
5271 PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
5272 name_for_port(MACH_REMOTE),
5273 (ULong)req->address, (ULong)req->size,
5274 req->set_maximum, req->new_protection);
5276 MACH_ARG(vm_protect.address) = req->address;
5277 MACH_ARG(vm_protect.size) = req->size;
5278 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
5279 MACH_ARG(vm_protect.new_protection) = req->new_protection;
5281 AFTER = POST_FN(vm_protect);
5288 mach_msg_header_t Head;
5290 kern_return_t RetCode;
5291 mach_msg_trailer_t trailer;
5295 Reply *reply = (Reply *)ARG1;
5297 if (!reply->RetCode) {
5298 if (MACH_REMOTE == vg_task_port) {
5299 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
5300 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
5301 MACH_ARG(vm_protect.size));
5302 UInt prot = MACH_ARG(vm_protect.new_protection);
5303 if (MACH_ARG(vm_protect.set_maximum)) {
5304 // GrP fixme mprotect max
5305 VG_(printf)("UNKNOWN vm_protect set maximum");
5306 //VG_(mprotect_max_range)(start, end-start, prot);
5308 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5312 PRINT("mig return %d", reply->RetCode);
5321 mach_msg_header_t Head;
5323 vm_address_t address;
5325 vm_inherit_t new_inheritance;
5329 Request *req = (Request *)ARG1;
5331 PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
5332 name_for_port(MACH_REMOTE),
5333 (ULong)req->address, (ULong)req->size,
5334 req->new_inheritance);
5336 AFTER = POST_FN(vm_inherit);
5343 mach_msg_header_t Head;
5345 kern_return_t RetCode;
5346 mach_msg_trailer_t trailer;
5350 Reply *reply = (Reply *)ARG1;
5352 if (!reply->RetCode) {
5353 if (MACH_REMOTE == vg_task_port) {
5354 // GrP fixme do something?
5357 PRINT("mig return %d", reply->RetCode);
5366 mach_msg_header_t Head;
5368 vm_address_t address;
5373 Request *req = (Request *)ARG1;
5375 PRINT("vm_read(from %s at %#llx size %llu)",
5376 name_for_port(MACH_REMOTE),
5377 (ULong)req->address, (ULong)req->size);
5379 MACH_ARG(vm_read.addr) = req->address;
5380 MACH_ARG(vm_read.size) = req->size;
5382 AFTER = POST_FN(vm_read);
5389 mach_msg_header_t Head;
5390 /* start of the kernel processed data */
5391 mach_msg_body_t msgh_body;
5392 mach_msg_ool_descriptor_t data;
5393 /* end of the kernel processed data */
5395 mach_msg_type_number_t dataCnt;
5399 // Reply *reply = (Reply *)ARG1;
5401 if (MACH_REMOTE == vg_task_port) {
5402 // vm_read from self
5403 // GrP fixme copy initialized state
5413 mach_msg_header_t Head;
5415 mach_vm_address_t address;
5416 mach_vm_size_t size;
5420 Request *req = (Request *)ARG1;
5422 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
5423 name_for_port(MACH_REMOTE), req->address, req->size);
5425 MACH_ARG(mach_vm_read.addr) = req->address;
5426 MACH_ARG(mach_vm_read.size) = req->size;
5428 AFTER = POST_FN(mach_vm_read);
5435 mach_msg_header_t Head;
5436 /* start of the kernel processed data */
5437 mach_msg_body_t msgh_body;
5438 mach_msg_ool_descriptor_t data;
5439 /* end of the kernel processed data */
5441 mach_msg_type_number_t dataCnt;
5445 // Reply *reply = (Reply *)ARG1;
5447 if (MACH_REMOTE == vg_task_port) {
5448 // vm_read from self
5449 // GrP fixme copy initialized state
5454 PRE(vm_read_overwrite)
5458 mach_msg_header_t Head;
5460 vm_address_t address;
5466 Request *req = (Request *)ARG1;
5468 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
5469 name_for_port(MACH_REMOTE),
5470 (ULong)req->address, (ULong)req->size, (ULong)req->data);
5472 MACH_ARG(vm_read_overwrite.addr) = req->address;
5473 MACH_ARG(vm_read_overwrite.size) = req->size;
5474 MACH_ARG(vm_read_overwrite.data) = req->data;
5476 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
5478 AFTER = POST_FN(vm_read_overwrite);
5481 POST(vm_read_overwrite)
5485 mach_msg_header_t Head;
5487 kern_return_t RetCode;
5492 Reply *reply = (Reply *)ARG1;
5494 if (reply->RetCode) {
5495 PRINT("mig return %d", reply->RetCode);
5497 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
5498 if (MACH_REMOTE == vg_task_port) {
5499 // vm_read_overwrite from self
5500 // GrP fixme copy initialized state
5501 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5503 // vm_read_overwrite from remote
5504 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5514 mach_msg_header_t Head;
5516 vm_address_t source_address;
5518 vm_address_t dest_address;
5522 Request *req = (Request *)ARG1;
5524 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
5525 name_for_port(MACH_REMOTE),
5526 (ULong)req->source_address,
5527 (ULong)req->size, (ULong)req->dest_address);
5529 MACH_ARG(vm_copy.src) = req->source_address;
5530 MACH_ARG(vm_copy.dst) = req->dest_address;
5531 MACH_ARG(vm_copy.size) = req->size;
5533 AFTER = POST_FN(vm_copy);
5540 mach_msg_header_t Head;
5542 kern_return_t RetCode;
5543 mach_msg_trailer_t trailer;
5547 Reply *reply = (Reply *)ARG1;
5549 if (!reply->RetCode) {
5550 if (MACH_REMOTE == vg_task_port) {
5551 // GrP fixme set dst's initialization equal to src's
5552 // and wipe any symbols or translations in dst
5555 PRINT("mig return %d", reply->RetCode);
5564 mach_msg_header_t Head;
5565 /* start of the kernel processed data */
5566 mach_msg_body_t msgh_body;
5567 mach_msg_port_descriptor_t object;
5568 /* end of the kernel processed data */
5570 vm_address_t address;
5576 vm_prot_t cur_protection;
5577 vm_prot_t max_protection;
5578 vm_inherit_t inheritance;
5582 Request *req = (Request *)ARG1;
5584 // GrP fixme check these
5585 PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)",
5586 name_for_port(MACH_REMOTE),
5587 (ULong)req->address, (ULong)req->size,
5588 name_for_port(req->object.name));
5590 MACH_ARG(vm_map.size) = req->size;
5591 MACH_ARG(vm_map.copy) = req->copy;
5592 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
5594 AFTER = POST_FN(vm_map);
5601 mach_msg_header_t Head;
5603 kern_return_t RetCode;
5604 vm_address_t address;
5605 mach_msg_trailer_t trailer;
5609 Reply *reply = (Reply *)ARG1;
5611 if (!reply->RetCode) {
5612 // GrP fixme check src and dest tasks
5613 PRINT("mapped at %#llx", (ULong)reply->address);
5614 // GrP fixme max prot
5615 ML_(notify_core_and_tool_of_mmap)(
5616 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
5617 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
5618 // GrP fixme VKI_MAP_PRIVATE if !copy?
5620 PRINT("mig return %d", reply->RetCode);
5629 mach_msg_header_t Head;
5630 /* start of the kernel processed data */
5631 mach_msg_body_t msgh_body;
5632 mach_msg_port_descriptor_t src_task;
5633 /* end of the kernel processed data */
5635 vm_address_t target_address;
5639 vm_address_t src_address;
5641 vm_inherit_t inheritance;
5645 Request *req = (Request *)ARG1;
5647 // GrP fixme check src and dest tasks
5649 if (VG_(clo_trace_syscalls)) {
5650 mach_port_name_t source_task = req->src_task.name;
5651 if (source_task == mach_task_self()) {
5652 PRINT("vm_remap(mach_task_self(), "
5653 "to %#llx size %lld, from mach_task_self() at %#llx, ...)",
5654 (ULong)req->target_address,
5655 (ULong)req->size, (ULong)req->src_address);
5657 PRINT("vm_remap(mach_task_self(), "
5658 "to %#llx size %lld, from task %u at %#llx, ...)",
5659 (ULong)req->target_address, (ULong)req->size,
5660 source_task, (ULong)req->src_address);
5665 // vt->syscall_arg2 = req->target_address;
5666 MACH_ARG(vm_remap.size) = req->size;
5667 // vt->syscall_arg4 = req->copy;
5669 AFTER = POST_FN(vm_remap);
5676 mach_msg_header_t Head;
5678 kern_return_t RetCode;
5679 vm_address_t target_address;
5680 vm_prot_t cur_protection;
5681 vm_prot_t max_protection;
5682 mach_msg_trailer_t trailer;
5686 Reply *reply = (Reply *)ARG1;
5688 if (!reply->RetCode) {
5689 // GrP fixme check src and dest tasks
5690 UInt prot = reply->cur_protection & reply->max_protection;
5691 // GrP fixme max prot
5692 PRINT("mapped at %#llx", (ULong)reply->target_address);
5693 ML_(notify_core_and_tool_of_mmap)(
5694 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
5695 prot, VKI_MAP_SHARED, -1, 0);
5696 // GrP fixme VKI_MAP_FIXED if !copy?
5697 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
5699 PRINT("mig return %d", reply->RetCode);
5704 PRE(mach_make_memory_entry_64)
5708 mach_msg_header_t Head;
5709 /* start of the kernel processed data */
5710 mach_msg_body_t msgh_body;
5711 mach_msg_port_descriptor_t parent_entry;
5712 /* end of the kernel processed data */
5714 memory_object_size_t size;
5715 memory_object_offset_t offset;
5716 vm_prot_t permission;
5720 Request *req = (Request *)ARG1;
5722 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
5723 name_for_port(MACH_REMOTE),
5724 req->size, req->offset, req->permission, req->parent_entry.type);
5726 AFTER = POST_FN(mach_make_memory_entry_64);
5729 POST(mach_make_memory_entry_64)
5733 mach_msg_header_t Head;
5734 mach_msg_body_t msgh_body;
5735 mach_msg_port_descriptor_t object;
5737 memory_object_size_t size;
5741 Reply *reply = (Reply *)ARG1;
5743 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
5744 assign_port_name(reply->object.name, "memory-%p");
5745 PRINT("%s", name_for_port(reply->object.name));
5750 PRE(vm_purgable_control)
5754 mach_msg_header_t Head;
5756 vm_address_t address;
5757 vm_purgable_t control;
5762 Request *req = (Request *)ARG1;
5764 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
5765 name_for_port(MACH_REMOTE),
5766 (ULong)req->address, req->control, req->state);
5768 // GrP fixme verify address?
5770 AFTER = POST_FN(vm_purgable_control);
5773 POST(vm_purgable_control)
5777 mach_msg_header_t Head;
5779 kern_return_t RetCode;
5784 Reply *reply = (Reply *)ARG1;
5786 if (!reply->RetCode) {
5788 PRINT("mig return %d", reply->RetCode);
5793 PRE(mach_vm_purgable_control)
5797 mach_msg_header_t Head;
5799 mach_vm_address_t address;
5800 vm_purgable_t control;
5805 Request *req = (Request *)ARG1;
5807 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
5808 name_for_port(MACH_REMOTE),
5809 (unsigned long long)req->address, req->control, req->state);
5811 // GrP fixme verify address?
5813 AFTER = POST_FN(mach_vm_purgable_control);
5816 POST(mach_vm_purgable_control)
5820 mach_msg_header_t Head;
5822 kern_return_t RetCode;
5827 Reply *reply = (Reply *)ARG1;
5829 if (!reply->RetCode) {
5831 PRINT("mig return %d", reply->RetCode);
5836 PRE(mach_vm_allocate)
5840 mach_msg_header_t Head;
5842 mach_vm_address_t address;
5843 mach_vm_size_t size;
5848 Request *req = (Request *)ARG1;
5850 PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
5851 name_for_port(MACH_REMOTE),
5852 req->address, req->size, req->flags);
5854 MACH_ARG(mach_vm_allocate.size) = req->size;
5855 MACH_ARG(mach_vm_allocate.flags) = req->flags;
5857 AFTER = POST_FN(mach_vm_allocate);
5860 POST(mach_vm_allocate)
5864 mach_msg_header_t Head;
5866 kern_return_t RetCode;
5867 mach_vm_address_t address;
5868 mach_msg_trailer_t trailer;
5872 Reply *reply = (Reply *)ARG1;
5874 if (!reply->RetCode) {
5875 if (MACH_REMOTE == vg_task_port) {
5876 PRINT("allocated at 0x%llx", reply->address);
5877 // requesting 0 bytes returns address 0 with no error
5878 if (MACH_ARG(mach_vm_allocate.size)) {
5879 ML_(notify_core_and_tool_of_mmap)(
5880 reply->address, MACH_ARG(mach_vm_allocate.size),
5881 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5884 PRINT("allocated at 0x%llx in remote task %s", reply->address,
5885 name_for_port(MACH_REMOTE));
5888 PRINT("mig return %d", reply->RetCode);
5893 PRE(mach_vm_deallocate)
5897 mach_msg_header_t Head;
5899 mach_vm_address_t address;
5900 mach_vm_size_t size;
5904 Request *req = (Request *)ARG1;
5906 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
5907 name_for_port(MACH_REMOTE),
5908 req->address, req->size);
5910 MACH_ARG(mach_vm_deallocate.address) = req->address;
5911 MACH_ARG(mach_vm_deallocate.size) = req->size;
5913 AFTER = POST_FN(mach_vm_deallocate);
5915 // Must block to prevent race (other thread allocates and
5916 // notifies after we deallocate but before we notify)
5917 *flags &= ~SfMayBlock;
5920 POST(mach_vm_deallocate)
5924 mach_msg_header_t Head;
5926 kern_return_t RetCode;
5927 mach_msg_trailer_t trailer;
5931 Reply *reply = (Reply *)ARG1;
5933 if (!reply->RetCode) {
5934 if (MACH_REMOTE == vg_task_port) {
5935 if (MACH_ARG(mach_vm_deallocate.size)) {
5936 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
5937 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
5938 MACH_ARG(mach_vm_deallocate.size));
5939 // Must have cleared SfMayBlock in PRE to prevent race
5940 ML_(notify_core_and_tool_of_munmap)(start, end - start);
5944 PRINT("mig return %d", reply->RetCode);
5949 PRE(mach_vm_protect)
5953 mach_msg_header_t Head;
5955 mach_vm_address_t address;
5956 mach_vm_size_t size;
5957 boolean_t set_maximum;
5958 vm_prot_t new_protection;
5962 Request *req = (Request *)ARG1;
5964 PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
5965 name_for_port(MACH_REMOTE), req->address, req->size,
5966 req->set_maximum, req->new_protection);
5968 MACH_ARG(mach_vm_protect.address) = req->address;
5969 MACH_ARG(mach_vm_protect.size) = req->size;
5970 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
5971 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
5973 AFTER = POST_FN(mach_vm_protect);
5976 POST(mach_vm_protect)
5980 mach_msg_header_t Head;
5982 kern_return_t RetCode;
5983 mach_msg_trailer_t trailer;
5987 Reply *reply = (Reply *)ARG1;
5989 if (!reply->RetCode) {
5990 if (MACH_REMOTE == vg_task_port) {
5991 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
5992 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
5993 MACH_ARG(mach_vm_protect.size));
5994 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
5995 if (MACH_ARG(mach_vm_protect.set_maximum)) {
5996 // DDD: #warning GrP fixme mprotect max
5997 //VG_(mprotect_max_range)(start, end-start, prot);
5999 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6003 PRINT("mig return %d", reply->RetCode);
6008 PRE(mach_vm_inherit)
6012 mach_msg_header_t Head;
6014 mach_vm_address_t address;
6015 mach_vm_size_t size;
6016 vm_inherit_t new_inheritance;
6020 Request *req = (Request *)ARG1;
6022 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
6023 name_for_port(MACH_REMOTE),
6024 req->address, req->size, req->new_inheritance);
6026 AFTER = POST_FN(mach_vm_inherit);
6029 POST(mach_vm_inherit)
6033 mach_msg_header_t Head;
6035 kern_return_t RetCode;
6036 mach_msg_trailer_t trailer;
6040 Reply *reply = (Reply *)ARG1;
6042 if (!reply->RetCode) {
6043 // no V-visible side effects
6044 // GrP fixme except maybe fork/exec
6046 PRINT("mig return %d", reply->RetCode);
6055 mach_msg_header_t Head;
6057 mach_vm_address_t source_address;
6058 mach_vm_size_t size;
6059 mach_vm_address_t dest_address;
6063 Request *req = (Request *)ARG1;
6065 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
6066 name_for_port(MACH_REMOTE),
6067 req->source_address, req->size, req->dest_address);
6070 // vt->syscall_arg2 = req->source_address;
6071 // vt->syscall_arg3 = req->size;
6072 // vt->syscall_arg4 = req->dest_address;
6074 AFTER = POST_FN(mach_vm_copy);
6081 mach_msg_header_t Head;
6083 kern_return_t RetCode;
6084 mach_msg_trailer_t trailer;
6088 Reply *reply = (Reply *)ARG1;
6090 if (!reply->RetCode) {
6091 if (MACH_REMOTE == vg_task_port) {
6092 // GrP fixme set dest's initialization equal to src's
6093 // BUT vm_copy allocates no memory
6096 PRINT("mig return %d", reply->RetCode);
6105 mach_msg_header_t Head;
6106 /* start of the kernel processed data */
6107 mach_msg_body_t msgh_body;
6108 mach_msg_port_descriptor_t object;
6109 /* end of the kernel processed data */
6111 mach_vm_address_t address;
6112 mach_vm_size_t size;
6113 mach_vm_address_t mask;
6115 memory_object_offset_t offset;
6117 vm_prot_t cur_protection;
6118 vm_prot_t max_protection;
6119 vm_inherit_t inheritance;
6123 Request *req = (Request *)ARG1;
6125 // GrP fixme check these
6126 PRINT("mach_vm_map(in %s, at 0x%llx, size %llu, from %s ...)",
6127 name_for_port(MACH_REMOTE),
6128 req->address, req->size,
6129 name_for_port(req->object.name));
6131 MACH_ARG(mach_vm_map.size) = req->size;
6132 MACH_ARG(mach_vm_map.copy) = req->copy;
6133 MACH_ARG(mach_vm_map.protection) =
6134 (req->cur_protection & req->max_protection);
6136 AFTER = POST_FN(mach_vm_map);
6143 mach_msg_header_t Head;
6145 kern_return_t RetCode;
6146 mach_vm_address_t address;
6147 mach_msg_trailer_t trailer;
6151 Reply *reply = (Reply *)ARG1;
6153 if (!reply->RetCode) {
6154 // GrP fixme check src and dest tasks
6155 PRINT("mapped at 0x%llx", reply->address);
6156 // GrP fixme max prot
6157 ML_(notify_core_and_tool_of_mmap)(
6158 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
6159 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
6160 // GrP fixme VKI_MAP_PRIVATE if !copy?
6162 PRINT("mig return %d", reply->RetCode);
6167 PRE(mach_vm_region_recurse)
6171 mach_msg_header_t Head;
6173 mach_vm_address_t address;
6174 natural_t nesting_depth;
6175 mach_msg_type_number_t infoCnt;
6179 Request *req = (Request *)ARG1;
6181 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
6182 name_for_port(MACH_REMOTE),
6183 req->address, req->nesting_depth, req->infoCnt);
6185 AFTER = POST_FN(mach_vm_region_recurse);
6188 POST(mach_vm_region_recurse)
6192 mach_msg_header_t Head;
6194 kern_return_t RetCode;
6195 mach_vm_address_t address;
6196 mach_vm_size_t size;
6197 natural_t nesting_depth;
6198 mach_msg_type_number_t infoCnt;
6203 Reply *reply = (Reply *)ARG1;
6205 if (!reply->RetCode) {
6206 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
6207 reply->address, reply->size,
6208 reply->nesting_depth, reply->infoCnt);
6209 // GrP fixme mark info contents beyond infoCnt as bogus
6211 PRINT("mig return %d", reply->RetCode);
6216 /* ---------------------------------------------------------------------
6217 mach_msg: messages to thread
6218 ------------------------------------------------------------------ */
6222 POST(thread_terminate)
6227 PRE(thread_terminate)
6229 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6230 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
6232 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
6234 AFTER = POST_FN(thread_terminate);
6236 if (self_terminate) {
6237 // Terminating this thread.
6238 // Copied from sys_exit.
6239 ThreadState *tst = VG_(get_ThreadState)(tid);
6240 tst->exitreason = VgSrc_ExitThread;
6241 tst->os_state.exitcode = 0; // GrP fixme anything better?
6242 // What we would like to do is:
6243 // SET_STATUS_Success(0);
6244 // but that doesn't work, because this is a MACH-class syscall,
6245 // and SET_STATUS_Success creates a UNIX-class syscall result.
6246 // Hence we have to laboriously construct the full SysRes "by hand"
6247 // and use that to set the syscall return status.
6248 SET_STATUS_from_SysRes(
6249 VG_(mk_SysRes_x86_darwin)(
6250 VG_DARWIN_SYSCALL_CLASS_MACH,
6251 False/*success*/, 0, 0
6254 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
6256 // Terminating some other thread.
6257 // Do keep the scheduler lock while terminating any other thread.
6258 // Otherwise we might halt the other thread while it holds the lock,
6259 // which would deadlock the process.
6260 // GrP fixme good enough?
6261 // GrP fixme need to clean up other thread's valgrind data?
6273 PRINT("thread_create(mach_task_self(), ...)");
6275 AFTER = POST_FN(thread_create);
6278 VG_(core_panic)("thread_create() unimplemented");
6282 PRE(thread_create_running)
6286 mach_msg_header_t Head;
6288 thread_state_flavor_t flavor;
6289 mach_msg_type_number_t new_stateCnt;
6290 natural_t new_state[144];
6295 thread_state_t regs;
6296 ThreadState *new_thread;
6298 PRINT("thread_create_running(mach_task_self(), ...)");
6300 // The new thread will immediately begin execution,
6301 // so we need to hijack the register state here.
6303 req = (Request *)ARG1;
6304 regs = (thread_state_t)req->new_state;
6306 // Build virtual thread.
6307 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
6309 // Edit the thread state to send to the real kernel.
6310 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
6312 AFTER = POST_FN(thread_create_running);
6316 POST(thread_create_running)
6320 mach_msg_header_t Head;
6321 /* start of the kernel processed data */
6322 mach_msg_body_t msgh_body;
6323 mach_msg_port_descriptor_t child_act;
6324 /* end of the kernel processed data */
6328 Reply *reply = (Reply *)ARG1;
6330 assign_port_name(reply->child_act.name, "thread-%p");
6331 PRINT("%s", name_for_port(reply->child_act.name));
6335 PRE(bsdthread_create)
6339 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
6340 ARG1, ARG2, ARG3, ARG4, ARG5);
6341 PRE_REG_READ5(pthread_t,"bsdthread_create",
6342 void *,"func", void *,"func_arg", void *,"stack",
6343 pthread_t,"thread", unsigned int,"flags");
6345 // The kernel will call V's pthread_hijack() to launch the thread.
6346 // Here we allocate the thread state and pass it to pthread_hijack()
6347 // via the func_arg parameter.
6349 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
6350 allocstack(tst->tid);
6352 tst->os_state.func_arg = (Addr)ARG2;
6355 // Create a semaphore that pthread_hijack will signal once it starts
6356 // POST(bsdthread_create) needs to wait for the new memory map to appear
6357 semaphore_create(mach_task_self(), &tst->os_state.child_go,
6358 SYNC_POLICY_FIFO, 0);
6359 semaphore_create(mach_task_self(), &tst->os_state.child_done,
6360 SYNC_POLICY_FIFO, 0);
6363 POST(bsdthread_create)
6365 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
6366 // We hold V's lock on the child's behalf.
6367 // If we return before letting pthread_hijack do its thing, V thinks
6368 // the new pthread struct is still unmapped when we return to libc,
6369 // causing false errors.
6371 ThreadState *tst = (ThreadState *)ARG2;
6372 semaphore_signal(tst->os_state.child_go);
6373 semaphore_wait(tst->os_state.child_done);
6374 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
6375 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
6377 // GrP fixme semaphore destroy needed when thread creation fails
6378 // GrP fixme probably other cleanup too
6379 // GrP fixme spinlocks might be good enough?
6381 // DDD: I'm not at all sure this is the right spot for this. It probably
6382 // should be in pthread_hijack instead, just before the call to
6383 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
6384 // parent tid value there...
6385 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
6389 PRE(bsdthread_terminate)
6393 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
6394 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
6395 PRE_REG_READ4(int,"bsdthread_terminate",
6396 void *,"freeaddr", size_t,"freesize",
6397 mach_port_t,"kport", mach_port_t,"joinsem");
6399 // Free memory and signal semaphore.
6400 // GrP fixme errors?
6401 if (ARG4) semaphore_signal((semaphore_t)ARG4);
6403 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
6404 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
6407 // Tell V to terminate the thread.
6408 // Copied from sys_exit.
6409 tst = VG_(get_ThreadState)(tid);
6410 tst->exitreason = VgSrc_ExitThread;
6411 tst->os_state.exitcode = 0; // GrP fixme anything better?
6412 SET_STATUS_Success(0);
6416 POST(thread_suspend)
6422 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6423 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
6425 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
6427 AFTER = POST_FN(thread_suspend);
6430 // Don't keep the scheduler lock while self-suspending.
6431 // Otherwise we might halt while still holding the lock,
6432 // which would deadlock the process.
6433 *flags |= SfMayBlock;
6435 // Do keep the scheduler lock while suspending any other thread.
6436 // Otherwise we might halt the other thread while it holds the lock,
6437 // which would deadlock the process.
6442 POST(thread_get_state)
6446 mach_msg_header_t Head;
6448 kern_return_t RetCode;
6449 mach_msg_type_number_t old_stateCnt;
6450 natural_t old_state[144];
6451 mach_msg_trailer_t trailer;
6455 Reply *reply = (Reply *)ARG1;
6456 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
6457 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
6459 if (!reply->RetCode) {
6460 thread_state_from_vex((thread_state_t)reply->old_state,
6461 flavor, reply->old_stateCnt,
6462 &VG_(get_ThreadState)(tid)->arch.vex);
6464 PRINT("mig return %d", reply->RetCode);
6468 PRE(thread_get_state)
6472 mach_msg_header_t Head;
6474 thread_state_flavor_t flavor;
6475 mach_msg_type_number_t old_stateCnt;
6479 Request *req = (Request *)ARG1;
6480 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
6482 // GrP fixme if (self) {
6483 PRINT("thread_get_state(%s, %d)",
6484 name_for_port(req->Head.msgh_request_port), req->flavor);
6486 PRINT("thread_get_state(0x%x, %d)",
6487 req->Head.msgh_request_port, req->flavor);
6490 // Hack the thread state after making the real call.
6491 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
6492 MACH_ARG(thread_get_state.flavor) = req->flavor;
6494 AFTER = POST_FN(thread_get_state);
6500 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6501 // Bool self = (mh->msgh_request_port == MACH_THREAD);
6503 // GrP fixme if (self) {
6504 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
6506 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
6509 AFTER = POST_FN(thread_policy);
6517 PRE(thread_policy_set)
6519 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6521 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
6523 AFTER = POST_FN(thread_policy_set);
6526 POST(thread_policy_set)
6533 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6535 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
6536 // GrP fixme does any thread info need to be hijacked?
6538 AFTER = POST_FN(thread_info);
6543 // GrP fixme mark unused parts of thread_info_out as uninitialized?
6548 /* ---------------------------------------------------------------------
6549 mach_msg: messages to bootstrap port
6550 ------------------------------------------------------------------ */
6553 POST(bootstrap_register)
6557 mach_msg_header_t Head;
6559 kern_return_t RetCode;
6560 mach_msg_trailer_t trailer;
6564 Reply *reply = (Reply *)ARG1;
6566 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
6569 PRE(bootstrap_register)
6573 mach_msg_header_t Head;
6574 /* start of the kernel processed data */
6575 mach_msg_body_t msgh_body;
6576 mach_msg_port_descriptor_t service_port;
6577 /* end of the kernel processed data */
6579 name_t service_name;
6583 Request *req = (Request *)ARG1;
6585 PRINT("bootstrap_register(port 0x%x, \"%s\")",
6586 req->service_port.name, req->service_name);
6588 assign_port_name(req->service_port.name, req->service_name);
6590 AFTER = POST_FN(bootstrap_register);
6594 POST(bootstrap_look_up)
6598 mach_msg_header_t Head;
6599 /* start of the kernel processed data */
6600 mach_msg_body_t msgh_body;
6601 mach_msg_port_descriptor_t service_port;
6602 /* end of the kernel processed data */
6603 mach_msg_trailer_t trailer;
6607 Reply *reply = (Reply *)ARG1;
6609 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
6610 reply->service_port.name)
6612 assign_port_name(reply->service_port.name,
6613 MACH_ARG(bootstrap_look_up.service_name));
6614 PRINT("%s", name_for_port(reply->service_port.name));
6618 VG_(arena_free)(VG_AR_CORE, MACH_ARG(bootstrap_look_up.service_name));
6621 PRE(bootstrap_look_up)
6625 mach_msg_header_t Head;
6627 name_t service_name;
6631 Request *req = (Request *)ARG1;
6633 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
6635 MACH_ARG(bootstrap_look_up.service_name) =
6636 VG_(arena_strdup)(VG_AR_CORE, "syswrap-darwin.bootstrap-name",
6639 AFTER = POST_FN(bootstrap_look_up);
6643 /* ---------------------------------------------------------------------
6644 mach_msg: receiver-specific handlers
6645 ------------------------------------------------------------------ */
6648 POST(mach_msg_receive)
6650 // mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6652 // GrP fixme don't know of anything interesting here currently
6653 // import_complex_message handles everything
6654 // PRINT("UNHANDLED reply %d", mh->msgh_id);
6656 // Assume the call may have mapped or unmapped memory
6657 ML_(sync_mappings)("after", "mach_msg_receive", 0);
6660 PRE(mach_msg_receive)
6662 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6664 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
6666 AFTER = POST_FN(mach_msg_receive);
6668 // no message sent, only listening for a reply
6669 // assume message may block
6670 *flags |= SfMayBlock;
6674 PRE(mach_msg_bootstrap)
6676 // message to bootstrap port
6678 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6680 switch (mh->msgh_id) {
6682 CALL_PRE(bootstrap_register);
6685 CALL_PRE(bootstrap_look_up);
6689 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
6690 mh->msgh_id, name_for_port(mh->msgh_request_port),
6691 mh->msgh_reply_port);
6699 // message to host self - check for host-level kernel calls
6701 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6703 switch (mh->msgh_id) {
6705 CALL_PRE(host_info);
6708 CALL_PRE(host_page_size);
6711 CALL_PRE(host_get_io_master);
6714 CALL_PRE(host_get_clock_service);
6717 CALL_PRE(host_request_notification);
6721 // unknown message to host self
6722 VG_(printf)("UNKNOWN host message [id %d, to %s, reply 0x%x]\n",
6723 mh->msgh_id, name_for_port(mh->msgh_request_port),
6724 mh->msgh_reply_port);
6731 // message to a task port
6733 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6735 switch (mh->msgh_id) {
6737 CALL_PRE(mach_port_type);
6740 CALL_PRE(mach_port_allocate);
6743 CALL_PRE(mach_port_destroy);
6746 CALL_PRE(mach_port_deallocate);
6749 CALL_PRE(mach_port_get_refs);
6752 CALL_PRE(mach_port_mod_refs);
6755 CALL_PRE(mach_port_get_set_status);
6758 CALL_PRE(mach_port_move_member);
6761 CALL_PRE(mach_port_request_notification);
6764 CALL_PRE(mach_port_insert_right);
6767 CALL_PRE(mach_port_extract_right);
6770 CALL_PRE(mach_port_get_attributes);
6773 CALL_PRE(mach_port_set_attributes);
6776 CALL_PRE(mach_port_insert_member);
6779 CALL_PRE(mach_port_extract_member);
6783 CALL_PRE(task_threads);
6786 CALL_PRE(mach_ports_lookup);
6790 CALL_PRE(task_suspend);
6793 CALL_PRE(task_resume);
6797 CALL_PRE(task_get_special_port);
6800 CALL_PRE(thread_create);
6803 CALL_PRE(thread_create_running);
6807 CALL_PRE(semaphore_create);
6810 CALL_PRE(semaphore_destroy);
6814 CALL_PRE(vm_allocate);
6817 CALL_PRE(vm_deallocate);
6820 CALL_PRE(vm_protect);
6823 CALL_PRE(vm_inherit);
6832 CALL_PRE(vm_read_overwrite);
6841 CALL_PRE(mach_make_memory_entry_64);
6844 CALL_PRE(vm_purgable_control);
6848 CALL_PRE(mach_vm_allocate);
6851 CALL_PRE(mach_vm_deallocate);
6854 CALL_PRE(mach_vm_protect);
6857 CALL_PRE(mach_vm_inherit);
6860 CALL_PRE(mach_vm_read);
6863 CALL_PRE(mach_vm_copy);
6866 CALL_PRE(mach_vm_map);
6869 CALL_PRE(mach_vm_region_recurse);
6872 CALL_PRE(mach_make_memory_entry_64);
6875 CALL_PRE(mach_vm_purgable_control);
6879 // unknown message to task self
6880 VG_(printf)("UNKNOWN task message [id %d, to %s, reply 0x%x]\n",
6881 mh->msgh_id, name_for_port(mh->msgh_remote_port),
6882 mh->msgh_reply_port);
6888 PRE(mach_msg_thread)
6890 // message to local thread - check for thread-level kernel calls
6892 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6894 switch (mh->msgh_id) {
6896 CALL_PRE(thread_terminate);
6899 CALL_PRE(thread_get_state);
6902 CALL_PRE(thread_suspend);
6905 CALL_PRE(thread_info);
6908 CALL_PRE(thread_policy);
6911 CALL_PRE(thread_policy_set);
6914 // unknown message to a thread
6915 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
6916 mh->msgh_id, name_for_port(mh->msgh_request_port),
6917 mh->msgh_reply_port);
6923 static int is_thread_port(mach_port_t port)
6925 if (port == 0) return False;
6927 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
6931 static int is_task_port(mach_port_t port)
6933 if (port == 0) return False;
6935 if (port == vg_task_port) return True;
6937 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
6941 /* ---------------------------------------------------------------------
6942 mach_msg: base handlers
6943 ------------------------------------------------------------------ */
6947 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6948 mach_msg_option_t option = (mach_msg_option_t)ARG2;
6949 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
6950 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
6951 // mach_port_t rcv_name = (mach_port_t)ARG5;
6952 size_t complex_header_size = 0;
6954 PRE_REG_READ7(long, "mach_msg",
6955 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
6956 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
6957 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
6958 mach_port_t,"notify");
6960 // Assume default POST handler until specified otherwise
6963 // Assume call may block unless specified otherwise
6964 *flags |= SfMayBlock;
6966 if (option & MACH_SEND_MSG) {
6967 // Validate outgoing message header
6968 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
6969 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
6970 // msgh_size not required, use parameter instead
6971 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
6972 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
6973 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
6974 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
6975 // msgh_reserved not required
6976 PRE_MEM_READ("mach_msg(msg.msgh_id)",
6977 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
6979 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6980 // Validate typed message data and handle memory map changes.
6981 complex_header_size = export_complex_message(tid, mh);
6984 // GrP fixme handle sender-specified message trailer
6985 // (but is this only for too-secure processes?)
6986 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
6988 MACH_REMOTE = mh->msgh_remote_port;
6989 MACH_MSGH_ID = mh->msgh_id;
6992 if (option & MACH_RCV_MSG) {
6993 // Pre-validate receive buffer
6994 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
6997 // Call a PRE handler. The PRE handler may set an AFTER handler.
6999 if (!(option & MACH_SEND_MSG)) {
7000 // no message sent, receive only
7001 CALL_PRE(mach_msg_receive);
7004 else if (mh->msgh_request_port == vg_host_port) {
7005 // message sent to mach_host_self()
7006 CALL_PRE(mach_msg_host);
7009 else if (is_task_port(mh->msgh_request_port)) {
7010 // message sent to a task
7011 CALL_PRE(mach_msg_task);
7014 else if (mh->msgh_request_port == vg_bootstrap_port) {
7015 // message sent to bootstrap port
7016 CALL_PRE(mach_msg_bootstrap);
7019 else if (is_thread_port(mh->msgh_request_port)) {
7020 // message sent to one of this process's threads
7021 CALL_PRE(mach_msg_thread);
7025 // arbitrary message to arbitrary port
7026 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
7027 mh->msgh_id, name_for_port(mh->msgh_request_port),
7028 mh->msgh_reply_port);
7030 AFTER = POST_FN(mach_msg_unhandled);
7032 // Assume the entire message body may be read.
7033 // GrP fixme generates false positives for unknown protocols
7035 PRE_MEM_READ("mach_msg(payload)",
7036 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
7037 send_size - sizeof(mach_msg_header_t) - complex_header_size);
7045 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7046 mach_msg_option_t option = (mach_msg_option_t)ARG2;
7048 if (option & MACH_RCV_MSG) {
7050 // error during send or receive
7051 // GrP fixme need to clean up port rights?
7053 mach_msg_trailer_t *mt =
7054 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
7056 // Assume the entire received message and trailer is initialized
7057 // GrP fixme would being more specific catch any bugs?
7058 POST_MEM_WRITE((Addr)mh,
7059 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
7061 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
7062 // Update memory map for out-of-line message data
7063 import_complex_message(tid, mh);
7068 // Call handler chosen by PRE(mach_msg)
7070 (*AFTER)(tid, arrghs, status);
7075 POST(mach_msg_unhandled)
7077 ML_(sync_mappings)("after", "mach_msg_receive (unhandled)", 0);
7081 /* ---------------------------------------------------------------------
7083 ------------------------------------------------------------------ */
7085 PRE(mach_reply_port)
7087 PRINT("mach_reply_port()");
7090 POST(mach_reply_port)
7092 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
7093 PRINT("reply port %s", name_for_port(RES));
7097 PRE(mach_thread_self)
7099 PRINT("mach_thread_self()");
7102 POST(mach_thread_self)
7104 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
7105 PRINT("thread %#lx", RES);
7111 PRINT("mach_host_self()");
7114 POST(mach_host_self)
7117 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
7118 PRINT("host %#lx", RES);
7124 PRINT("mach_task_self()");
7127 POST(mach_task_self)
7130 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
7131 PRINT("task %#lx", RES);
7135 PRE(syscall_thread_switch)
7137 PRINT("syscall_thread_switch(%s, %ld, %ld)",
7138 name_for_port(ARG1), ARG2, ARG3);
7139 PRE_REG_READ3(long, "syscall_thread_switch",
7140 mach_port_t,"thread", int,"option", natural_t,"timeout");
7142 *flags |= SfMayBlock;
7146 PRE(semaphore_signal)
7148 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
7149 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7153 PRE(semaphore_signal_all)
7155 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
7156 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
7160 PRE(semaphore_signal_thread)
7162 PRINT("semaphore_signal_thread(%s, %s)",
7163 name_for_port(ARG1), name_for_port(ARG2));
7164 PRE_REG_READ2(long, "semaphore_signal_thread",
7165 semaphore_t,"semaphore", mach_port_t,"thread");
7171 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
7172 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7174 *flags |= SfMayBlock;
7178 PRE(semaphore_wait_signal)
7180 PRINT("semaphore_wait_signal(%s, %s)",
7181 name_for_port(ARG1), name_for_port(ARG2));
7182 PRE_REG_READ2(long, "semaphore_wait_signal",
7183 semaphore_t,"wait_semaphore",
7184 semaphore_t,"signal_semaphore");
7186 *flags |= SfMayBlock;
7190 PRE(semaphore_timedwait)
7192 PRINT("semaphore_timedwait(%s, %g seconds)",
7193 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
7194 PRE_REG_READ3(long, "semaphore_wait_signal",
7195 semaphore_t,"semaphore",
7197 int,"wait_time_lo");
7199 *flags |= SfMayBlock;
7203 PRE(semaphore_timedwait_signal)
7205 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
7206 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
7207 PRE_REG_READ4(long, "semaphore_wait_signal",
7208 semaphore_t,"wait_semaphore",
7209 semaphore_t,"signal_semaphore",
7211 int,"wait_time_lo");
7213 *flags |= SfMayBlock;
7217 PRE(__semwait_signal)
7219 /* 10.5 args: int cond_sem, int mutex_sem,
7220 int timeout, int relative,
7221 time_t tv_sec, time_t tv_nsec */
7222 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
7223 name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
7224 PRE_REG_READ6(long, "__semwait_signal",
7225 int,"cond_sem", int,"mutex_sem",
7226 int,"timeout", int,"relative",
7227 vki_time_t,"tv_sec", int,"tv_nsec");
7229 *flags |= SfMayBlock;
7231 // GrP provided this alternative version for 10.6, but NjN
7232 // reckons the 10.5 is is still correct for 10.6. So, retaining
7233 // Greg's version as a comment just in case we need it later.
7234 //PRE(__semwait_signal)
7236 // /* 10.5 args: int cond_sem, int mutex_sem,
7237 // int timeout, int relative,
7238 // const timespec *ts */
7239 // PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
7240 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
7241 // PRE_REG_READ5(int, "__semwait_signal",
7242 // int,cond_sem, int,mutex_sem,
7243 // int,timeout, int,relative,
7244 // const struct vki_timespec *,ts);
7246 // if (ARG5) PRE_MEM_READ ("__semwait_signal(ts)",
7247 // ARG5, sizeof(struct vki_timespec));
7249 // *flags |= SfMayBlock;
7253 PRE(__thread_selfid)
7255 PRINT("__thread_selfid ()");
7256 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
7261 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
7262 PRE_REG_READ3(long, "task_for_pid",
7263 mach_port_t,"target",
7264 vki_pid_t, "pid", mach_port_t *,"task");
7265 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
7272 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
7274 task = *(mach_port_t *)ARG3;
7275 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
7276 PRINT("task 0x%x", task);
7282 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
7283 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
7284 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
7291 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
7293 pid = *(vki_pid_t *)ARG2;
7294 PRINT("pid %u", pid);
7298 PRE(mach_timebase_info)
7300 PRINT("mach_timebase_info(%#lx)", ARG1);
7301 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
7302 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
7305 POST(mach_timebase_info)
7307 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
7311 PRE(mach_wait_until)
7313 #if VG_WORDSIZE == 8
7314 PRINT("mach_wait_until(%lu)", ARG1);
7315 PRE_REG_READ1(long, "mach_wait_until",
7316 unsigned long long,"deadline");
7318 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
7319 PRE_REG_READ2(long, "mach_wait_until",
7320 int,"deadline_hi", int,"deadline_lo");
7322 *flags |= SfMayBlock;
7326 PRE(mk_timer_create)
7328 PRINT("mk_timer_create()");
7329 PRE_REG_READ0(long, "mk_timer_create");
7332 POST(mk_timer_create)
7334 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
7338 PRE(mk_timer_destroy)
7340 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
7341 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
7343 // Must block to prevent race (other thread allocates and
7344 // notifies after we deallocate but before we notify)
7345 *flags &= ~SfMayBlock;
7348 POST(mk_timer_destroy)
7350 // Must have cleared SfMayBlock in PRE to prevent race
7351 record_port_destroy(ARG1);
7357 #if VG_WORDSIZE == 8
7358 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
7359 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
7360 unsigned long,"expire_time");
7362 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
7363 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
7364 int,"expire_time_hi", int,"expire_time_lo");
7369 PRE(mk_timer_cancel)
7371 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
7372 PRE_REG_READ2(long, "mk_timer_cancel",
7373 mach_port_t,"name", Addr,"result_time");
7375 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
7379 POST(mk_timer_cancel)
7382 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
7387 PRE(iokit_user_client_trap)
7389 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
7390 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
7391 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
7392 mach_port_t,connect, unsigned int,index,
7393 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
7394 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
7396 // can't do anything else with this in general
7397 // might be able to use connect+index to choose something sometimes
7400 POST(iokit_user_client_trap)
7402 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
7409 PRE_REG_READ0(long, "swtch");
7411 *flags |= SfMayBlock;
7417 PRINT("swtch_pri ( %ld )", ARG1);
7418 PRE_REG_READ1(long, "swtch_pri", int,"pri");
7420 *flags |= SfMayBlock;
7426 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
7427 an explanation of what follows. */
7428 /* This handles the fake signal-return system call created by
7429 sigframe-x86-darwin.c. */
7430 /* See also comments just below on PRE(sigreturn). */
7432 PRINT("FAKE_SIGRETURN ( )");
7434 vg_assert(VG_(is_valid_tid)(tid));
7435 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7436 vg_assert(VG_(is_running_thread)(tid));
7438 /* Remove the signal frame from this thread's (guest) stack,
7439 in the process restoring the pre-signal guest state. */
7440 VG_(sigframe_destroy)(tid, True);
7442 /* Tell the driver not to update the guest state with the "result",
7443 and set a bogus result to keep it happy. */
7444 *flags |= SfNoWriteResult;
7445 SET_STATUS_Success(0);
7447 /* Check to see if any signals arose as a result of this. */
7448 *flags |= SfPollAfter;
7454 /* This is the "real" sigreturn. But because we construct all the
7455 signal frames ourselves (of course, in m_sigframe), this cannot
7456 happen as a result of normal signal delivery. I think it
7457 happens only when doing siglongjmp, in which case Darwin's Libc
7458 appears to use it for two different purposes: to mess with the
7459 per-thread sigaltstack flags (as per arg 2), or to restore the
7460 thread's state from a ucontext* (as per arg 1). */
7462 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
7464 vg_assert(VG_(is_valid_tid)(tid));
7465 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7466 vg_assert(VG_(is_running_thread)(tid));
7468 if (ARG2 == VKI_UC_SET_ALT_STACK) {
7469 /* This is confusing .. the darwin kernel sources imply there is
7470 a per-thread on-altstack/not-on-altstack flag, which is set
7471 by this flag. Just ignore it and claim success for the time
7473 VG_(debugLog)(0, "syswrap-darwin",
7474 "WARNING: Ignoring sigreturn( ..., "
7475 "UC_SET_ALT_STACK );\n");
7476 SET_STATUS_Success(0);
7479 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
7481 VG_(debugLog)(0, "syswrap-darwin",
7482 "WARNING: Ignoring sigreturn( ..., "
7483 "UC_RESET_ALT_STACK );\n");
7484 SET_STATUS_Success(0);
7488 /* Otherwise claim this isn't supported. (Could be
7491 What do we have to do if we do need to support it?
7493 1. Change the second argument of VG_(sigframe_destroy) from
7494 "Bool isRT" to "UInt sysno", so we can pass the syscall
7495 number, so it can distinguish this case from the
7496 __NR_DARWIN_FAKE_SIGRETURN case.
7498 2. In VG_(sigframe_destroy), look at sysno to distinguish the
7499 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
7500 For this case, restore the thread's CPU state (or at least
7501 the integer regs) from the ucontext in ARG1 (and do all the
7502 other "signal-returns" stuff too).
7504 3. For (2), how do we know where the ucontext is? One way is to
7505 temporarily copy ARG1 into this thread's guest_EBX (or any
7506 other int reg), and have VG_(sigframe_destroy) read
7507 guest_EBX. Why is it ok to trash guest_EBX (or any other int
7508 reg)? Because VG_(sigframe_destroy) is just about to
7509 overwrite all the regs anyway -- since the primary purpose of
7510 calling it is to restore the register state from the ucontext
7513 Hey, it's uggerly. But at least it's documented.
7515 /* But in the meantime ... */
7516 VG_(debugLog)(0, "syswrap-darwin",
7517 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
7518 VG_(debugLog)(0, "syswrap-darwin",
7519 "WARNING: Thread/program/Valgrind "
7520 "will likely segfault now.\n");
7521 VG_(debugLog)(0, "syswrap-darwin",
7522 "WARNING: Please file a bug report at "
7523 "http://www.valgrind.org.\n");
7524 SET_STATUS_Failure( VKI_ENOSYS );
7528 /* ---------------------------------------------------------------------
7529 machine-dependent traps
7530 ------------------------------------------------------------------ */
7532 #if defined(VGA_x86)
7533 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
7535 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
7536 return VG_(arena_calloc)(VG_AR_CORE, "syswrap-darwin.ldt", nbytes, 1);
7540 PRE(thread_fast_set_cthread_self)
7542 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
7543 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
7545 #if defined(VGA_x86)
7546 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
7548 VexGuestX86SegDescr *ldt;
7549 ThreadState *tst = VG_(get_ThreadState)(tid);
7550 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
7552 ldt = alloc_zeroed_x86_LDT();
7553 tst->arch.vex.guest_LDT = (HWord)ldt;
7555 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
7556 ldt[6].LdtEnt.Bits.LimitLow = 1;
7557 ldt[6].LdtEnt.Bits.LimitHi = 0;
7558 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
7559 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
7560 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
7561 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
7562 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
7563 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
7564 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
7565 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
7567 tst->os_state.pthread = ARG1;
7568 tst->arch.vex.guest_GS = 0x37;
7570 // What we would like to do is:
7571 // SET_STATUS_Success(0x37);
7572 // but that doesn't work, because this is a MDEP-class syscall,
7573 // and SET_STATUS_Success creates a UNIX-class syscall result.
7574 // Hence we have to laboriously construct the full SysRes "by hand"
7575 // and use that to set the syscall return status.
7576 SET_STATUS_from_SysRes(
7577 VG_(mk_SysRes_x86_darwin)(
7578 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7584 #elif defined(VGA_amd64)
7585 // GrP fixme bigger hack than x86
7587 ThreadState *tst = VG_(get_ThreadState)(tid);
7588 tst->os_state.pthread = ARG1;
7589 tst->arch.vex.guest_GS_0x60 = ARG1;
7590 // SET_STATUS_Success(0x60);
7591 // see comments on x86 case just above
7592 SET_STATUS_from_SysRes(
7593 VG_(mk_SysRes_amd64_darwin)(
7594 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7601 #error unknown architecture
7606 /* ---------------------------------------------------------------------
7608 ------------------------------------------------------------------ */
7610 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
7611 #define MACX_(sysno, name) WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7612 #define MACXY(sysno, name) WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7613 #define _____(sysno) GENX_(sysno, sys_ni_syscall)
7616 _____ : unsupported by the kernel (sys_ni_syscall)
7617 // _____ : unimplemented in valgrind
7618 GEN : handlers are in syswrap-generic.c
7619 MAC : handlers are in this file
7620 X_ : PRE handler only
7621 XY : PRE and POST handlers
7623 const SyscallTableEntry ML_(syscall_table)[] = {
7624 // _____(__NR_syscall), // 0
7625 MACX_(__NR_exit, exit),
7626 GENX_(__NR_fork, sys_fork),
7627 GENXY(__NR_read, sys_read),
7628 GENX_(__NR_write, sys_write),
7629 GENXY(__NR_open, sys_open),
7630 GENXY(__NR_close, sys_close),
7631 GENXY(__NR_wait4, sys_wait4),
7632 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
7633 GENX_(__NR_link, sys_link),
7634 GENX_(__NR_unlink, sys_unlink),
7635 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
7636 GENX_(__NR_chdir, sys_chdir),
7637 GENX_(__NR_fchdir, sys_fchdir),
7638 GENX_(__NR_mknod, sys_mknod),
7639 GENX_(__NR_chmod, sys_chmod),
7640 GENX_(__NR_chown, sys_chown),
7641 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
7642 MACXY(__NR_getfsstat, getfsstat),
7643 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
7644 GENX_(__NR_getpid, sys_getpid), // 20
7645 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
7646 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
7647 GENX_(__NR_setuid, sys_setuid),
7648 GENX_(__NR_getuid, sys_getuid),
7649 GENX_(__NR_geteuid, sys_geteuid),
7650 MACX_(__NR_ptrace, ptrace),
7651 MACXY(__NR_recvmsg, recvmsg),
7652 MACX_(__NR_sendmsg, sendmsg),
7653 MACXY(__NR_recvfrom, recvfrom),
7654 MACXY(__NR_accept, accept),
7655 MACXY(__NR_getpeername, getpeername),
7656 MACXY(__NR_getsockname, getsockname),
7657 GENX_(__NR_access, sys_access),
7658 MACX_(__NR_chflags, chflags),
7659 MACX_(__NR_fchflags, fchflags),
7660 GENX_(__NR_sync, sys_sync),
7661 GENX_(__NR_kill, sys_kill),
7662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
7663 GENX_(__NR_getppid, sys_getppid),
7664 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
7665 GENXY(__NR_dup, sys_dup),
7666 MACXY(__NR_pipe, pipe),
7667 GENX_(__NR_getegid, sys_getegid),
7668 // _____(__NR_profil),
7669 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
7670 MACXY(__NR_sigaction, sigaction),
7671 GENX_(__NR_getgid, sys_getgid),
7672 MACXY(__NR_sigprocmask, sigprocmask),
7673 MACXY(__NR_getlogin, getlogin),
7674 // _____(__NR_setlogin),
7675 // _____(__NR_acct),
7676 MACXY(__NR_sigpending, sigpending),
7677 GENXY(__NR_sigaltstack, sys_sigaltstack),
7678 MACXY(__NR_ioctl, ioctl),
7679 // _____(__NR_reboot),
7680 // _____(__NR_revoke),
7681 GENX_(__NR_symlink, sys_symlink), // 57
7682 GENX_(__NR_readlink, sys_readlink),
7683 GENX_(__NR_execve, sys_execve),
7684 GENX_(__NR_umask, sys_umask), // 60
7685 GENX_(__NR_chroot, sys_chroot),
7686 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
7687 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
7688 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
7689 GENX_(__NR_msync, sys_msync),
7690 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
7691 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
7692 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
7693 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
7694 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
7695 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
7696 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
7697 GENXY(__NR_munmap, sys_munmap),
7698 GENXY(__NR_mprotect, sys_mprotect),
7699 GENX_(__NR_madvise, sys_madvise),
7700 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
7701 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
7702 GENXY(__NR_mincore, sys_mincore),
7703 GENXY(__NR_getgroups, sys_getgroups),
7704 // _____(__NR_setgroups), // 80
7705 GENX_(__NR_getpgrp, sys_getpgrp),
7706 GENX_(__NR_setpgid, sys_setpgid),
7707 GENXY(__NR_setitimer, sys_setitimer),
7708 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
7709 // _____(__NR_swapon),
7710 GENXY(__NR_getitimer, sys_getitimer),
7711 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
7712 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
7713 MACXY(__NR_getdtablesize, getdtablesize),
7714 GENXY(__NR_dup2, sys_dup2),
7715 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
7716 MACXY(__NR_fcntl, fcntl),
7717 GENX_(__NR_select, sys_select),
7718 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
7719 GENX_(__NR_fsync, sys_fsync),
7720 GENX_(__NR_setpriority, sys_setpriority),
7721 MACXY(__NR_socket, socket),
7722 MACX_(__NR_connect, connect),
7723 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
7724 GENX_(__NR_getpriority, sys_getpriority), // 100
7725 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
7726 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
7727 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
7728 MACX_(__NR_bind, bind),
7729 MACX_(__NR_setsockopt, setsockopt),
7730 MACX_(__NR_listen, listen),
7731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
7732 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
7733 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
7734 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
7735 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
7736 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
7737 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
7738 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
7739 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
7740 GENXY(__NR_gettimeofday, sys_gettimeofday),
7741 GENXY(__NR_getrusage, sys_getrusage),
7742 MACXY(__NR_getsockopt, getsockopt),
7743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
7744 GENXY(__NR_readv, sys_readv), // 120
7745 GENX_(__NR_writev, sys_writev),
7746 // _____(__NR_settimeofday),
7747 GENX_(__NR_fchown, sys_fchown),
7748 GENX_(__NR_fchmod, sys_fchmod),
7749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
7750 // _____(__NR_setreuid),
7751 // _____(__NR_setregid),
7752 GENX_(__NR_rename, sys_rename),
7753 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
7754 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
7755 GENX_(__NR_flock, sys_flock),
7756 // _____(__NR_mkfifo),
7757 MACX_(__NR_sendto, sendto),
7758 MACX_(__NR_shutdown, shutdown),
7759 MACXY(__NR_socketpair, socketpair),
7760 GENX_(__NR_mkdir, sys_mkdir),
7761 GENX_(__NR_rmdir, sys_rmdir),
7762 GENX_(__NR_utimes, sys_utimes),
7763 MACX_(__NR_futimes, futimes),
7764 // _____(__NR_adjtime), // 140
7765 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
7766 MACXY(__NR_gethostuuid, gethostuuid),
7767 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
7768 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
7769 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
7770 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
7771 GENX_(__NR_setsid, sys_setsid),
7772 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
7773 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
7774 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
7775 // _____(__NR_getpgid),
7776 // _____(__NR_setprivexec),
7777 GENXY(__NR_pread, sys_pread64),
7778 GENX_(__NR_pwrite, sys_pwrite64),
7779 // _____(__NR_nfssvc),
7780 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
7781 GENXY(__NR_statfs, sys_statfs),
7782 GENXY(__NR_fstatfs, sys_fstatfs),
7783 // _____(__NR_unmount),
7784 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
7785 // _____(__NR_getfh),
7786 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
7787 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
7788 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
7789 // _____(__NR_quotactl),
7790 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
7791 MACX_(__NR_mount, mount),
7792 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
7793 MACXY(__NR_csops, csops), // code-signing ops
7794 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
7795 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
7796 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
7797 // _____(__NR_waitid),
7798 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
7799 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
7800 // _____(__NR_add_profil),
7801 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
7802 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
7803 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
7804 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
7805 GENX_(__NR_setgid, sys_setgid),
7806 MACX_(__NR_setegid, setegid),
7807 MACX_(__NR_seteuid, seteuid),
7808 MACX_(__NR_sigreturn, sigreturn),
7809 // _____(__NR_chud),
7810 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
7811 #if DARWIN_VERS >= DARWIN_10_6
7812 // _____(__NR_fdatasync),
7814 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
7816 GENXY(__NR_stat, sys_newstat),
7817 GENXY(__NR_fstat, sys_newfstat),
7818 GENXY(__NR_lstat, sys_newlstat),
7819 MACX_(__NR_pathconf, pathconf),
7820 MACX_(__NR_fpathconf, fpathconf),
7821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
7822 GENXY(__NR_getrlimit, sys_getrlimit),
7823 GENX_(__NR_setrlimit, sys_setrlimit),
7824 MACXY(__NR_getdirentries, getdirentries),
7825 MACXY(__NR_mmap, mmap),
7826 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
7827 MACX_(__NR_lseek, lseek),
7828 GENX_(__NR_truncate, sys_truncate64), // 200
7829 GENX_(__NR_ftruncate, sys_ftruncate64),
7830 MACXY(__NR___sysctl, __sysctl),
7831 GENX_(__NR_mlock, sys_mlock),
7832 GENX_(__NR_munlock, sys_munlock),
7833 // _____(__NR_undelete),
7834 // _____(__NR_ATsocket),
7835 // _____(__NR_ATgetmsg),
7836 // _____(__NR_ATputmsg),
7837 // _____(__NR_ATPsndreq),
7838 // _____(__NR_ATPsndrsp),
7839 // _____(__NR_ATPgetreq),
7840 // _____(__NR_ATPgetrsp),
7841 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
7842 #if DARWIN_VERS >= DARWIN_10_6
7843 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
7844 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
7846 // _____(__NR_kqueue_from_portset_np),
7847 // _____(__NR_kqueue_portset_np),
7849 // _____(__NR_mkcomplex),
7850 // _____(__NR_statv),
7851 // _____(__NR_lstatv),
7852 // _____(__NR_fstatv),
7853 MACXY(__NR_getattrlist, getattrlist), // 220
7854 MACX_(__NR_setattrlist, setattrlist),
7855 MACXY(__NR_getdirentriesattr, getdirentriesattr),
7856 MACX_(__NR_exchangedata, exchangedata),
7857 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
7858 // _____(__NR_searchfs),
7859 GENX_(__NR_delete, sys_unlink),
7860 // _____(__NR_copyfile),
7861 #if DARWIN_VERS >= DARWIN_10_6
7862 // _____(__NR_fgetattrlist),
7863 // _____(__NR_fsetattrlist),
7865 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
7866 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
7868 GENXY(__NR_poll, sys_poll),
7869 MACX_(__NR_watchevent, watchevent),
7870 MACXY(__NR_waitevent, waitevent),
7871 MACX_(__NR_modwatch, modwatch),
7872 MACXY(__NR_getxattr, getxattr),
7873 MACXY(__NR_fgetxattr, fgetxattr),
7874 MACX_(__NR_setxattr, setxattr),
7875 MACX_(__NR_fsetxattr, fsetxattr),
7876 MACX_(__NR_removexattr, removexattr),
7877 MACX_(__NR_fremovexattr, fremovexattr),
7878 MACXY(__NR_listxattr, listxattr), // 240
7879 MACXY(__NR_flistxattr, flistxattr),
7880 MACXY(__NR_fsctl, fsctl),
7881 MACX_(__NR_initgroups, initgroups),
7882 MACXY(__NR_posix_spawn, posix_spawn),
7883 #if DARWIN_VERS >= DARWIN_10_6
7884 // _____(__NR_ffsctl),
7886 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
7888 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
7889 // _____(__NR_nfsclnt),
7890 // _____(__NR_fhopen),
7891 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
7892 // _____(__NR_minherit),
7893 // _____(__NR_semsys),
7894 // _____(__NR_msgsys),
7895 // _____(__NR_shmsys),
7896 MACXY(__NR_semctl, semctl),
7897 MACX_(__NR_semget, semget),
7898 MACX_(__NR_semop, semop),
7899 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
7900 // _____(__NR_msgctl),
7901 // _____(__NR_msgget),
7902 // _____(__NR_msgsnd), // 260
7903 // _____(__NR_msgrcv),
7904 MACXY(__NR_shmat, shmat),
7905 MACXY(__NR_shmctl, shmctl),
7906 MACXY(__NR_shmdt, shmdt),
7907 MACX_(__NR_shmget, shmget),
7908 MACXY(__NR_shm_open, shm_open),
7909 // _____(__NR_shm_unlink),
7910 MACX_(__NR_sem_open, sem_open),
7911 MACX_(__NR_sem_close, sem_close),
7912 MACX_(__NR_sem_unlink, sem_unlink),
7913 MACX_(__NR_sem_wait, sem_wait),
7914 MACX_(__NR_sem_trywait, sem_trywait),
7915 MACX_(__NR_sem_post, sem_post),
7916 // _____(__NR_sem_getvalue),
7917 MACXY(__NR_sem_init, sem_init),
7918 MACX_(__NR_sem_destroy, sem_destroy),
7919 MACX_(__NR_open_extended, open_extended), // 277
7920 // _____(__NR_umask_extended),
7921 MACXY(__NR_stat_extended, stat_extended),
7922 MACXY(__NR_lstat_extended, lstat_extended), // 280
7923 MACXY(__NR_fstat_extended, fstat_extended),
7924 MACX_(__NR_chmod_extended, chmod_extended),
7925 MACX_(__NR_fchmod_extended,fchmod_extended),
7926 MACXY(__NR_access_extended,access_extended),
7927 MACX_(__NR_settid, settid),
7928 // _____(__NR_gettid),
7929 // _____(__NR_setsgroups),
7930 // _____(__NR_getsgroups),
7931 // _____(__NR_setwgroups),
7932 // _____(__NR_getwgroups),
7933 // _____(__NR_mkfifo_extended),
7934 // _____(__NR_mkdir_extended),
7935 // _____(__NR_identitysvc),
7936 // _____(__NR_shared_region_check_np),
7937 // _____(__NR_shared_region_map_np),
7938 #if DARWIN_VERS >= DARWIN_10_6
7939 // _____(__NR_vm_pressure_monitor),
7941 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
7943 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
7944 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
7945 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
7946 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
7947 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(301)), // ???
7948 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(302)), // ???
7949 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(303)), // ???
7950 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(304)), // ???
7951 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(305)), // ???
7952 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(306)), // ???
7953 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(307)), // ???
7954 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // ???
7955 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(309)), // ???
7956 // _____(__NR_getsid),
7957 // _____(__NR_settid_with_pid),
7958 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(312)), // ???
7959 // _____(__NR_aio_fsync),
7960 MACXY(__NR_aio_return, aio_return),
7961 MACX_(__NR_aio_suspend, aio_suspend),
7962 // _____(__NR_aio_cancel),
7963 MACX_(__NR_aio_error, aio_error),
7964 MACXY(__NR_aio_read, aio_read),
7965 MACX_(__NR_aio_write, aio_write),
7966 // _____(__NR_lio_listio), // 320
7967 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
7968 // _____(__NR_iopolicysys),
7969 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
7970 // _____(__NR_mlockall),
7971 // _____(__NR_munlockall),
7972 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
7973 MACX_(__NR_issetugid, issetugid),
7974 MACX_(__NR___pthread_kill, __pthread_kill),
7975 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
7976 // _____(__NR___sigwait),
7977 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
7978 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
7979 MACX_(__NR___pthread_canceled, __pthread_canceled),
7980 MACX_(__NR___semwait_signal, __semwait_signal),
7981 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
7982 #if DARWIN_VERS >= DARWIN_10_6
7983 MACXY(__NR_proc_info, proc_info), // 336
7985 MACXY(__NR_sendfile, sendfile),
7986 MACXY(__NR_stat64, stat64),
7987 MACXY(__NR_fstat64, fstat64),
7988 MACXY(__NR_lstat64, lstat64), // 340
7989 MACXY(__NR_stat64_extended, stat64_extended),
7990 MACXY(__NR_lstat64_extended, lstat64_extended),
7991 MACXY(__NR_fstat64_extended, fstat64_extended),
7992 MACXY(__NR_getdirentries64, getdirentries64),
7993 MACXY(__NR_statfs64, statfs64),
7994 MACXY(__NR_fstatfs64, fstatfs64),
7995 MACXY(__NR_getfsstat64, getfsstat64),
7996 // _____(__NR___pthread_chdir),
7997 // _____(__NR___pthread_fchdir),
7998 // _____(__NR_audit),
7999 MACXY(__NR_auditon, auditon),
8000 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
8001 // _____(__NR_getauid),
8002 // _____(__NR_setauid),
8003 // _____(__NR_getaudit),
8004 // _____(__NR_setaudit),
8005 // _____(__NR_getaudit_addr),
8006 // _____(__NR_setaudit_addr),
8007 // _____(__NR_auditctl),
8008 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
8009 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
8010 MACXY(__NR_kqueue, kqueue),
8011 MACXY(__NR_kevent, kevent),
8012 GENX_(__NR_lchown, sys_lchown),
8013 // _____(__NR_stack_snapshot),
8014 MACX_(__NR_bsdthread_register, bsdthread_register),
8015 MACX_(__NR_workq_open, workq_open),
8016 MACXY(__NR_workq_ops, workq_ops),
8017 #if DARWIN_VERS >= DARWIN_10_6
8018 // _____(__NR_kevent64),
8020 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
8022 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // ???
8023 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // ???
8024 #if DARWIN_VERS >= DARWIN_10_6
8025 MACX_(__NR___thread_selfid, __thread_selfid),
8027 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
8029 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
8030 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
8031 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
8032 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
8033 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
8034 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
8035 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
8036 // _____(__NR___mac_execve), // 380
8037 MACX_(__NR___mac_syscall, __mac_syscall),
8038 // _____(__NR___mac_get_file),
8039 // _____(__NR___mac_set_file),
8040 // _____(__NR___mac_get_link),
8041 // _____(__NR___mac_set_link),
8042 // _____(__NR___mac_get_proc),
8043 // _____(__NR___mac_set_proc),
8044 // _____(__NR___mac_get_fd),
8045 // _____(__NR___mac_set_fd),
8046 // _____(__NR___mac_get_pid),
8047 // _____(__NR___mac_get_lcid),
8048 // _____(__NR___mac_get_lctx),
8049 // _____(__NR___mac_set_lctx),
8050 // _____(__NR_setlcid),
8051 // _____(__NR_getlcid),
8052 // GrP fixme need any special nocancel handling?
8053 GENXY(__NR_read_nocancel, sys_read),
8054 GENX_(__NR_write_nocancel, sys_write),
8055 GENXY(__NR_open_nocancel, sys_open),
8056 GENXY(__NR_close_nocancel, sys_close),
8057 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
8058 MACXY(__NR_recvmsg_nocancel, recvmsg),
8059 MACX_(__NR_sendmsg_nocancel, sendmsg),
8060 MACXY(__NR_recvfrom_nocancel, recvfrom),
8061 MACXY(__NR_accept_nocancel, accept),
8062 GENX_(__NR_msync_nocancel, sys_msync),
8063 MACXY(__NR_fcntl_nocancel, fcntl),
8064 GENX_(__NR_select_nocancel, sys_select),
8065 GENX_(__NR_fsync_nocancel, sys_fsync),
8066 MACX_(__NR_connect_nocancel, connect),
8067 // _____(__NR_sigsuspend_nocancel),
8068 GENXY(__NR_readv_nocancel, sys_readv),
8069 GENX_(__NR_writev_nocancel, sys_writev),
8070 MACX_(__NR_sendto_nocancel, sendto),
8071 GENXY(__NR_pread_nocancel, sys_pread64),
8072 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
8073 // _____(__NR_waitid_nocancel),
8074 GENXY(__NR_poll_nocancel, sys_poll),
8075 // _____(__NR_msgsnd_nocancel),
8076 // _____(__NR_msgrcv_nocancel),
8077 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
8078 // _____(__NR_aio_suspend_nocancel),
8079 // _____(__NR___sigwait_nocancel),
8080 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
8081 // _____(__NR___mac_mount),
8082 // _____(__NR___mac_get_mount),
8083 // _____(__NR___mac_getfsstat),
8084 #if DARWIN_VERS >= DARWIN_10_6
8085 MACXY(__NR_fsgetpath, fsgetpath),
8086 MACXY(__NR_audit_session_self, audit_session_self),
8087 // _____(__NR_audit_session_join),
8090 // _____(__NR_MAXSYSCALL)
8091 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
8095 // Mach traps use negative syscall numbers.
8096 // Use ML_(mach_trap_table)[-mach_trap_number] .
8098 const SyscallTableEntry ML_(mach_trap_table)[] = {
8099 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
8100 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
8101 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
8102 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
8103 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
8104 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
8105 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
8106 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
8107 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
8108 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
8109 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
8110 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
8111 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
8112 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
8113 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
8114 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
8115 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
8116 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
8117 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
8118 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
8119 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)), // -20
8120 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
8121 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
8122 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
8123 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
8124 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
8125 MACXY(__NR_mach_reply_port, mach_reply_port),
8126 MACXY(__NR_thread_self_trap, mach_thread_self),
8127 MACXY(__NR_task_self_trap, mach_task_self),
8128 MACXY(__NR_host_self_trap, mach_host_self),
8129 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
8130 MACXY(__NR_mach_msg_trap, mach_msg),
8131 // _____(__NR_mach_msg_overwrite_trap),
8132 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
8133 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
8134 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
8135 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
8136 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
8137 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
8138 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
8139 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
8140 #if defined(VGA_x86)
8141 // _____(__NR_init_process),
8142 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
8143 // _____(__NR_map_fd),
8145 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
8146 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
8147 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
8149 // _____(__NR_task_name_for_pid),
8150 MACXY(__NR_task_for_pid, task_for_pid),
8151 MACXY(__NR_pid_for_task, pid_for_task),
8152 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
8153 #if defined(VGA_x86)
8154 // _____(__NR_macx_swapon),
8155 // _____(__NR_macx_swapoff),
8156 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
8157 // _____(__NR_macx_triggers),
8158 // _____(__NR_macx_backing_store_suspend),
8159 // _____(__NR_macx_backing_store_recovery),
8161 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
8162 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
8163 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
8164 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
8165 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
8166 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
8168 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
8169 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
8170 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
8171 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
8172 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
8173 MACX_(__NR_swtch_pri, swtch_pri),
8174 MACX_(__NR_swtch, swtch), // -60
8175 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
8176 // _____(__NR_clock_sleep_trap),
8177 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
8178 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
8179 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
8180 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
8181 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
8182 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
8183 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
8184 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
8185 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
8186 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
8187 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
8188 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
8189 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
8190 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
8191 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
8192 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
8193 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
8194 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
8195 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
8196 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
8197 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
8198 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
8199 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
8200 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
8201 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
8202 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
8203 MACXY(__NR_mach_timebase_info, mach_timebase_info),
8204 MACX_(__NR_mach_wait_until, mach_wait_until),
8205 MACXY(__NR_mk_timer_create, mk_timer_create),
8206 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
8207 MACX_(__NR_mk_timer_arm, mk_timer_arm),
8208 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
8209 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
8210 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
8211 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
8212 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
8213 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
8214 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
8218 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
8219 // calling convention instead of the syscall convention.
8220 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
8222 #if defined(VGA_x86)
8223 const SyscallTableEntry ML_(mdep_trap_table)[] = {
8224 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
8226 #elif defined(VGA_amd64)
8227 const SyscallTableEntry ML_(mdep_trap_table)[] = {
8228 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
8231 #error unknown architecture
8234 const UInt ML_(syscall_table_size) =
8235 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
8237 const UInt ML_(mach_trap_table_size) =
8238 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
8240 const UInt ML_(mdep_trap_table_size) =
8241 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
8243 #endif // defined(VGO_darwin)
8245 /*--------------------------------------------------------------------*/
8247 /*--------------------------------------------------------------------*/