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_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_xarray.h"
39 #include "pub_core_clientstate.h"
40 #include "pub_core_debuglog.h"
41 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
42 #include "pub_core_transtab.h" // VG_(discard_translations)
43 #include "pub_core_libcbase.h"
44 #include "pub_core_libcassert.h"
45 #include "pub_core_libcfile.h"
46 #include "pub_core_libcprint.h"
47 #include "pub_core_libcproc.h"
48 #include "pub_core_libcsignal.h"
49 #include "pub_core_machine.h" // VG_(get_SP)
50 #include "pub_core_mallocfree.h"
51 #include "pub_core_options.h"
52 #include "pub_core_oset.h"
53 #include "pub_core_scheduler.h"
54 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
55 #include "pub_core_signals.h"
56 #include "pub_core_syscall.h"
57 #include "pub_core_syswrap.h"
58 #include "pub_core_tooliface.h"
60 #include "priv_types_n_macros.h"
61 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
62 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
63 #include "priv_syswrap-main.h"
65 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
66 #include <mach/mach.h>
67 #include <mach/mach_vm.h>
68 #include <semaphore.h>
69 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
71 #define msgh_request_port msgh_remote_port
72 #define msgh_reply_port msgh_local_port
73 #define BOOTSTRAP_MAX_NAME_LEN 128
74 typedef char name_t[BOOTSTRAP_MAX_NAME_LEN];
76 typedef uint64_t mig_addr_t;
80 static mach_port_t vg_host_port = 0;
81 static mach_port_t vg_task_port = 0;
82 static mach_port_t vg_bootstrap_port = 0;
84 // Run a thread from beginning to end and return the thread's
85 // scheduler-return-code.
86 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
88 VgSchedReturnCode ret;
89 ThreadId tid = (ThreadId)tidW;
90 ThreadState* tst = VG_(get_ThreadState)(tid);
92 VG_(debugLog)(1, "syswrap-darwin",
93 "thread_wrapper(tid=%lld): entry\n",
96 vg_assert(tst->status == VgTs_Init);
98 /* make sure we get the CPU lock before doing anything significant */
99 VG_(acquire_BigLock)(tid, "thread_wrapper");
102 VG_(printf)("thread tid %d started: stack = %p\n",
105 VG_TRACK(pre_thread_first_insn, tid);
107 tst->os_state.lwpid = VG_(gettid)();
108 tst->os_state.threadgroup = VG_(getpid)();
110 /* Thread created with all signals blocked; scheduler will set the
113 ret = VG_(scheduler)(tid);
115 vg_assert(VG_(is_exiting)(tid));
117 vg_assert(tst->status == VgTs_Runnable);
118 vg_assert(VG_(is_running_thread)(tid));
120 VG_(debugLog)(1, "syswrap-darwin",
121 "thread_wrapper(tid=%lld): done\n",
124 /* Return to caller, still holding the lock. */
130 /* Allocate a stack for this thread, if it doesn't already have one.
131 Returns the initial stack pointer value to use, or 0 if allocation
134 Addr allocstack ( ThreadId tid )
136 ThreadState* tst = VG_(get_ThreadState)(tid);
140 /* Either the stack_base and stack_init_SP are both zero (in which
141 case a stack hasn't been allocated) or they are both non-zero,
142 in which case it has. */
144 if (tst->os_state.valgrind_stack_base == 0)
145 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
147 if (tst->os_state.valgrind_stack_base != 0)
148 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
150 /* If no stack is present, allocate one. */
152 if (tst->os_state.valgrind_stack_base == 0) {
153 stack = VG_(am_alloc_VgStack)( &initial_SP );
155 tst->os_state.valgrind_stack_base = (Addr)stack;
156 tst->os_state.valgrind_stack_init_SP = initial_SP;
160 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
162 (void*)tst->os_state.valgrind_stack_base,
163 (void*)tst->os_state.valgrind_stack_init_SP );
165 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
167 return tst->os_state.valgrind_stack_init_SP;
171 void find_stack_segment(ThreadId tid, Addr sp)
173 /* We don't really know where the client stack is, because it's
174 allocated by the client. The best we can do is look at the
175 memory mappings and try to derive some useful information. We
176 assume that esp starts near its highest possible value, and can
177 only go down to the start of the mmaped segment. */
178 ThreadState *tst = VG_(get_ThreadState)(tid);
179 const NSegment *seg = VG_(am_find_nsegment)(sp);
180 if (seg && seg->kind != SkResvn) {
181 tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
182 tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
185 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
186 tid, seg->start, VG_PGROUNDUP(sp));
188 VG_(printf)("couldn't find user stack\n");
189 VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
191 tst->client_stack_szB = 0;
196 /* Run a thread all the way to the end, then do appropriate exit actions
197 (this is the last-one-out-turn-off-the-lights bit).
199 static void run_a_thread_NORETURN ( Word tidW )
202 VgSchedReturnCode src;
203 ThreadId tid = (ThreadId)tidW;
205 VG_(debugLog)(1, "syswrap-darwin",
206 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
209 /* Run the thread all the way through. */
210 src = thread_wrapper(tid);
212 VG_(debugLog)(1, "syswrap-darwin",
213 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
216 c = VG_(count_living_threads)();
217 vg_assert(c >= 1); /* stay sane */
219 // Tell the tool this thread is exiting
220 VG_TRACK( pre_thread_ll_exit, tid );
224 VG_(debugLog)(1, "syswrap-darwin",
225 "run_a_thread_NORETURN(tid=%lld): "
226 "last one standing\n",
229 /* We are the last one standing. Keep hold of the lock and
230 carry on to show final tool results, then exit the entire system.
231 Use the continuation pointer set at startup in m_main. */
232 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
237 mach_msg_header_t msg;
239 VG_(debugLog)(1, "syswrap-darwin",
240 "run_a_thread_NORETURN(tid=%lld): "
241 "not last one standing\n",
244 /* OK, thread is dead, but others still exist. Just exit. */
245 tst = VG_(get_ThreadState)(tid);
247 /* This releases the run lock */
248 VG_(exit_thread)(tid);
249 vg_assert(tst->status == VgTs_Zombie);
251 /* tid is now invalid. */
253 // GrP fixme exit race
254 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
255 msg.msgh_request_port = VG_(gettid)();
256 msg.msgh_reply_port = 0;
257 msg.msgh_id = 3600; // thread_terminate
259 tst->status = VgTs_Empty;
260 // GrP fixme race here! new thread may claim this V thread stack
261 // before we get out here!
262 // GrP fixme use bsdthread_terminate for safe cleanup?
263 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
264 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
266 // DDD: This is reached sometimes on none/tests/manythreads, maybe
267 // because of the race above.
268 VG_(core_panic)("Thread exit failed?\n");
276 /* Allocate a stack for the main thread, and run it all the way to the
277 end. Although we already have a working VgStack
278 (VG_(interim_stack)) it's better to allocate a new one, so that
279 overflow detection works uniformly for all threads.
281 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
284 VG_(debugLog)(1, "syswrap-darwin",
285 "entering VG_(main_thread_wrapper_NORETURN)\n");
287 sp = allocstack(tid);
289 /* If we can't even allocate the first thread's stack, we're hosed.
291 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
293 /* shouldn't be any other threads around yet */
294 vg_assert( VG_(count_living_threads)() == 1 );
296 call_on_new_stack_0_1(
297 (Addr)sp, /* stack */
298 0, /*bogus return address*/
299 run_a_thread_NORETURN, /* fn to call */
300 (Word)tid /* arg to give it */
308 void start_thread_NORETURN ( Word arg )
310 ThreadState* tst = (ThreadState*)arg;
311 ThreadId tid = tst->tid;
313 run_a_thread_NORETURN ( (Word)tid );
319 void VG_(cleanup_thread) ( ThreadArchState* arch )
324 /* ---------------------------------------------------------------------
325 Mach port tracking (based on syswrap-generic's fd tracker)
326 ------------------------------------------------------------------ */
328 /* One of these is allocated for each open port. */
329 typedef struct OpenPort
332 mach_port_type_t type; /* right type(s) */
333 Int send_count; /* number of send rights */
334 Char *name; /* bootstrap name or NULL */
335 ExeContext *where; /* first allocation only */
336 struct OpenPort *next, *prev;
339 // strlen("0x12345678")
340 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
342 /* List of allocated ports. */
343 static OpenPort *allocated_ports;
345 /* Count of open ports. */
346 static Int allocated_port_count = 0;
349 __attribute__((unused))
350 static Bool port_exists(mach_port_t port)
354 /* Check to see if this port is already open. */
357 if (i->port == port) {
366 static OpenPort *info_for_port(mach_port_t port)
369 if (!port) return NULL;
373 if (i->port == port) {
383 // Give a port a name, without changing its refcount
384 // GrP fixme don't override name if it already has a specific one
385 __private_extern__ void assign_port_name(mach_port_t port, const char *name)
391 i = info_for_port(port);
394 if (i->name) VG_(arena_free)(VG_AR_CORE, i->name);
396 VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name",
397 VG_(strlen)(name) + PORT_STRLEN + 1);
398 VG_(sprintf)(i->name, name, port);
402 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
403 static const char *name_for_port(mach_port_t port)
405 static char buf[8 + PORT_STRLEN + 1];
409 if (port == VG_(gettid)()) return "mach_thread_self()";
410 if (port == 0) return "NULL";
414 if (i->port == port) {
420 VG_(sprintf)(buf, "NONPORT-%#x", port);
424 /* Note the fact that a port was just deallocated. */
427 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
429 OpenPort *i = allocated_ports;
433 if(i->port == port) {
434 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
435 if (right & MACH_PORT_TYPE_SEND) {
436 // send rights are refcounted
437 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
438 i->send_count += delta;
439 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
440 else i->type &= ~MACH_PORT_TYPE_SEND;
442 right = right & ~MACH_PORT_TYPE_SEND;
444 // other rights are not refcounted
447 } else if (delta < 0) {
452 if (i->type != 0) return;
454 // Port has no rights left. Kill it.
455 // VG_(printf)("deleting port %p %s", i->port, i->name);
457 i->prev->next = i->next;
459 allocated_ports = i->next;
461 i->next->prev = i->prev;
463 VG_(arena_free) (VG_AR_CORE, i->name);
464 VG_(arena_free) (VG_AR_CORE, i);
465 allocated_port_count--;
471 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
475 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
478 case MACH_MSG_TYPE_PORT_NAME:
479 // this task has no rights for the name
481 case MACH_MSG_TYPE_PORT_RECEIVE:
482 // this task gets receive rights
483 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
485 case MACH_MSG_TYPE_PORT_SEND:
486 // this task gets a send right
487 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
489 case MACH_MSG_TYPE_PORT_SEND_ONCE:
490 // this task gets send-once rights
491 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
500 void record_port_dealloc(mach_port_t port)
502 // deletes 1 send or send-once right (port can't have both)
503 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
507 void record_port_destroy(mach_port_t port)
509 // deletes all rights to port
510 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
514 /* Note the fact that a Mach port was just allocated or transferred.
515 If the port is already known, increment its reference count. */
516 void record_named_port(ThreadId tid, mach_port_t port,
517 mach_port_right_t right, const char *name)
522 /* Check to see if this port is already open. */
525 if (i->port == port) {
526 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
532 /* Not already one: allocate an OpenPort */
534 i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port",
538 i->next = allocated_ports;
539 if(allocated_ports) allocated_ports->prev = i;
541 allocated_port_count++;
544 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
547 i->type = MACH_PORT_TYPE(right);
548 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
554 assign_port_name(port, name);
559 // Record opening of a nameless port.
560 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
562 record_named_port(tid, port, right, "unnamed-%p");
566 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
567 void VG_(show_open_ports)(void)
571 VG_(message)(Vg_UserMsg,
572 "MACH PORTS: %d open at exit.", allocated_port_count);
574 for (i = allocated_ports; i; i = i->next) {
576 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name);
578 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port);
582 VG_(pp_ExeContext)(i->where);
583 VG_(message)(Vg_UserMsg, "");
587 VG_(message)(Vg_UserMsg, "");
591 /* ---------------------------------------------------------------------
593 ------------------------------------------------------------------ */
595 void ML_(sync_mappings)(const HChar *when, const HChar *where, Int num)
597 // Usually the number of segments added/removed in a single calls is very
598 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
599 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
600 // because we can't do dynamic allocation within VG_(get_changed_segments),
601 // because it's in m_aspacemgr.
602 ChangedSeg* css = NULL;
608 if (VG_(clo_trace_syscalls)) {
609 VG_(debugLog)(0, "syswrap-darwin",
610 "sync_mappings(\"%s\", \"%s\", %d)\n",
614 // 16 is enough for most cases, but small enough that overflow happens
615 // occasionally and thus the overflow path gets some test coverage.
619 VG_(free)(css); // css is NULL on first iteration; that's ok.
620 css = VG_(malloc)("sys_wrap.sync_mappings", css_size*sizeof(ChangedSeg));
621 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
625 // Now add/remove them.
626 for (i = 0; i < css_used; i++) {
627 ChangedSeg* cs = &css[i];
630 ML_(notify_core_and_tool_of_mmap)(
631 cs->start, cs->end - cs->start + 1,
632 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
633 // should this call VG_(di_notify_mmap) also?
637 ML_(notify_core_and_tool_of_munmap)(
638 cs->start, cs->end - cs->start + 1);
641 if (VG_(clo_trace_syscalls)) {
642 VG_(debugLog)(0, "syswrap-darwin",
643 " %s region 0x%010lx..0x%010lx at %s (%s)\n",
644 action, cs->start, cs->end + 1, where, when);
651 /* ---------------------------------------------------------------------
653 ------------------------------------------------------------------ */
655 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
656 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
658 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
659 #define POST_FN(name) vgSysWrap_darwin_##name##_after
661 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
662 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
665 // Combine two 32-bit values into a 64-bit value
666 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
667 # if defined(VGA_x86)
668 # define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
670 # error unknown architecture
674 // Retrieve the current Mach thread
675 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
677 // Set the POST handler for a mach_msg derivative
678 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
680 // Set or get values saved from Mach messages
681 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
682 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
683 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
685 /* ---------------------------------------------------------------------
687 ------------------------------------------------------------------ */
691 *flags |= SfMayBlock;
692 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
693 PRE_REG_READ3(long, "ioctl",
694 unsigned int, fd, unsigned int, request, unsigned long, arg);
696 switch (ARG2 /* request */) {
698 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
701 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
704 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
707 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
710 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
713 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
716 /* Get process group ID for foreground processing group. */
717 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
720 /* Set a process group ID? */
721 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
724 /* Just takes an int value. */
727 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
730 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
732 case VKI_FIONREAD: /* identical to SIOCINQ */
733 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
737 /* These all use struct ifreq AFAIK */
738 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
739 case VKI_SIOCGIFFLAGS: /* get flags */
740 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
741 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
742 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
744 case VKI_SIOCGIFMTU: /* get MTU size */
745 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
746 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
747 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
749 case VKI_SIOCGIFADDR: /* get PA address */
750 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
751 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
752 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
754 case VKI_SIOCGIFNETMASK: /* get network PA mask */
755 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
756 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
757 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
759 case VKI_SIOCGIFMETRIC: /* get metric */
760 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
761 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
762 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
764 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
765 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
766 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
767 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
769 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
770 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
771 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
772 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
774 case VKI_SIOCGIFCONF: /* get iface list */
776 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
777 KERNEL_DO_SYSCALL(tid,RES);
778 if (!VG_(is_kerror)(RES) && RES == 0)
779 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
781 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
782 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
783 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
784 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
785 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
786 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
788 // TODO len must be readable and writable
789 // buf pointer only needs to be readable
790 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
791 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
792 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
796 case VKI_SIOCSIFFLAGS: /* set flags */
797 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
798 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
799 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
800 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
801 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
803 case VKI_SIOCSIFADDR: /* set PA address */
804 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
805 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
806 case VKI_SIOCSIFNETMASK: /* set network PA mask */
807 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
808 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
809 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
810 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
811 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
813 case VKI_SIOCSIFMETRIC: /* set metric */
814 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
815 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
816 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
817 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
818 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
820 case VKI_SIOCSIFMTU: /* set MTU size */
821 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
822 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
823 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
824 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
825 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
827 /* Routing table calls. */
829 case VKI_SIOCADDRT: /* add routing table entry */
830 case VKI_SIOCDELRT: /* delete routing table entry */
831 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
832 sizeof(struct vki_rtentry));
837 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
840 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
841 //tst->sys_flags &= ~SfMayBlock;
845 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
848 case VKI_DTRACEHIOC_REMOVE:
849 case VKI_DTRACEHIOC_ADDDOF:
854 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
857 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
860 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
863 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
865 case VKI_TIOCPTYGNAME:
866 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
868 case VKI_TIOCPTYGRANT:
869 case VKI_TIOCPTYUNLK:
873 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
882 switch (ARG2 /* request */) {
884 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
892 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
895 /* Get process group ID for foreground processing group. */
896 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
899 /* Set a process group ID? */
900 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
908 case VKI_FIONREAD: /* identical to SIOCINQ */
909 POST_MEM_WRITE( ARG3, sizeof(int) );
912 /* These all use struct ifreq AFAIK */
913 case VKI_SIOCGIFFLAGS: /* get flags */
914 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
915 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
917 case VKI_SIOCGIFMTU: /* get MTU size */
918 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
919 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
921 case VKI_SIOCGIFADDR: /* get PA address */
922 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
923 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
924 case VKI_SIOCGIFNETMASK: /* get network PA mask */
926 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
927 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
929 case VKI_SIOCGIFMETRIC: /* get metric */
931 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
932 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
934 case VKI_SIOCGIFCONF: /* get iface list */
936 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
937 KERNEL_DO_SYSCALL(tid,RES);
938 if (!VG_(is_kerror)(RES) && RES == 0)
939 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
941 if (RES == 0 && ARG3 ) {
942 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
943 if (ifc->vki_ifc_buf != NULL)
944 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
948 case VKI_SIOCSIFFLAGS: /* set flags */
949 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
950 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
951 case VKI_SIOCSIFNETMASK: /* set network PA mask */
952 case VKI_SIOCSIFMETRIC: /* set metric */
953 case VKI_SIOCSIFADDR: /* set PA address */
954 case VKI_SIOCSIFMTU: /* set MTU size */
958 /* Routing table calls. */
959 case VKI_SIOCADDRT: /* add routing table entry */
960 case VKI_SIOCDELRT: /* delete routing table entry */
965 POST_MEM_WRITE(ARG3, sizeof(int));
971 POST_MEM_WRITE( ARG3, sizeof(int) );
974 case VKI_DTRACEHIOC_REMOVE:
975 case VKI_DTRACEHIOC_ADDDOF:
980 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
985 POST_MEM_WRITE( ARG3, sizeof(int) );
989 case VKI_TIOCPTYGNAME:
990 POST_MEM_WRITE( ARG3, 128);
992 case VKI_TIOCPTYGRANT:
993 case VKI_TIOCPTYUNLK:
1002 /* ---------------------------------------------------------------------
1003 darwin fcntl wrapper
1004 ------------------------------------------------------------------ */
1005 static const char *name_for_fcntl(UWord cmd) {
1006 #define F(n) case VKI_##n: return #n
1014 F(F_GLOBAL_NOCACHE);
1019 F(F_WRITEBOOTSTRAP);
1033 // These ones ignore ARG3.
1037 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1038 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1041 // These ones use ARG3 as "arg".
1046 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1047 PRE_REG_READ3(long, "fcntl",
1048 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1051 // These ones use ARG3 as "lock".
1055 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1056 PRE_REG_READ3(long, "fcntl",
1057 unsigned int, fd, unsigned int, cmd,
1058 struct flock64 *, lock);
1059 // GrP fixme mem read sizeof(flock64)
1060 if (ARG2 == VKI_F_SETLKW)
1061 *flags |= SfMayBlock;
1065 case VKI_F_CHKCLEAN:
1068 case VKI_F_FULLFSYNC:
1069 case VKI_F_FREEZE_FS:
1071 case VKI_F_GLOBAL_NOCACHE:
1072 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1073 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1077 case VKI_F_PREALLOCATE:
1078 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1079 PRE_REG_READ3(long, "fcntl",
1080 unsigned int, fd, unsigned int, cmd,
1081 struct fstore *, fstore);
1083 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1084 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1085 fstore->fst_flags );
1086 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1087 fstore->fst_posmode );
1088 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1089 fstore->fst_offset );
1090 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1091 fstore->fst_length );
1092 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1093 fstore->fst_bytesalloc);
1099 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1100 PRE_REG_READ3(long, "fcntl",
1101 unsigned int, fd, unsigned int, cmd,
1102 vki_off_t *, offset);
1106 case VKI_F_RDADVISE:
1107 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1108 PRE_REG_READ3(long, "fcntl",
1109 unsigned int, fd, unsigned int, cmd,
1110 struct vki_radvisory *, radvisory);
1112 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1113 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1114 radvisory->ra_offset );
1115 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1116 radvisory->ra_count );
1120 // struct fbootstraptransfer
1121 case VKI_F_READBOOTSTRAP:
1122 case VKI_F_WRITEBOOTSTRAP:
1123 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1124 PRE_REG_READ3(long, "fcntl",
1125 unsigned int, fd, unsigned int, cmd,
1126 struct fbootstraptransfer *, bootstrap);
1127 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1128 ARG3, sizeof(struct vki_fbootstraptransfer) );
1131 // struct log2phys (out)
1132 case VKI_F_LOG2PHYS:
1133 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1134 PRE_REG_READ3(long, "fcntl",
1135 unsigned int, fd, unsigned int, cmd,
1136 struct log2phys *, l2p);
1137 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1138 ARG3, sizeof(struct vki_log2phys) );
1141 // char[maxpathlen] (out)
1143 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1144 PRE_REG_READ3(long, "fcntl",
1145 unsigned int, fd, unsigned int, cmd,
1147 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1148 ARG3, VKI_MAXPATHLEN );
1151 // char[maxpathlen] (in)
1152 case VKI_F_PATHPKG_CHECK:
1153 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1155 PRE_REG_READ3(long, "fcntl",
1156 unsigned int, fd, unsigned int, cmd,
1158 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1161 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1162 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1163 PRE_REG_READ3(long, "fcntl",
1164 unsigned int, fd, unsigned int, cmd,
1165 vki_fsignatures_t *, sigs);
1168 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1169 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1170 fsigs->fs_blob_start);
1171 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1172 fsigs->fs_blob_size);
1174 if (fsigs->fs_blob_start)
1175 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1176 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1181 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1182 VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
1192 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1194 SET_STATUS_Failure( VKI_EMFILE );
1196 if (VG_(clo_track_fds))
1197 ML_(record_fd_open_named)(tid, RES);
1212 case VKI_F_PREALLOCATE:
1214 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1215 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1219 case VKI_F_LOG2PHYS:
1220 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1224 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1225 PRINT("\"%s\"", (char*)ARG3);
1229 // DDD: ugh, missing lots of cases here, not nice
1234 /* ---------------------------------------------------------------------
1236 ------------------------------------------------------------------ */
1240 PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
1241 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1242 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1243 SET_STATUS_Failure( VKI_EBADF );
1244 } else if (ARG2 != 0) {
1245 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1246 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1252 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1253 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1258 *flags |= SfMayBlock;
1259 PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
1260 PRE_REG_READ3(long, "semop",
1261 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1262 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1270 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1271 PRE_REG_READ4(long, "semctl",
1272 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1276 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1277 PRE_REG_READ4(long, "semctl",
1278 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1281 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1282 PRE_REG_READ4(long, "semctl",
1283 int, semid, int, semnum, int, cmd, int, arg);
1286 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1287 PRE_REG_READ3(long, "semctl",
1288 int, semid, int, semnum, int, cmd);
1291 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1295 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1300 if (ARG2 & VKI_O_CREAT) {
1302 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1303 ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1304 PRE_REG_READ4(vki_sem_t *, "sem_open",
1305 const char *, name, int, oflag, vki_mode_t, mode,
1306 unsigned int, value);
1309 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1310 PRE_REG_READ2(vki_sem_t *, "sem_open",
1311 const char *, name, int, oflag);
1313 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1315 /* Otherwise handle normally */
1316 *flags |= SfMayBlock;
1321 PRINT("sem_close( %#lx )", ARG1);
1322 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1327 PRINT("sem_unlink( %#lx(%s) )", ARG1,(char*)ARG1);
1328 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1329 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1334 PRINT("sem_post( %#lx )", ARG1);
1335 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1336 *flags |= SfMayBlock;
1341 PRINT("sem_destroy( %#lx )", ARG1);
1342 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1343 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1348 PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
1349 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1350 int, pshared, unsigned int, value);
1351 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1356 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1361 PRINT("sem_wait( %#lx )", ARG1);
1362 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1363 *flags |= SfMayBlock;
1368 PRINT("sem_trywait( %#lx )", ARG1);
1369 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1370 *flags |= SfMayBlock;
1380 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1382 SET_STATUS_Failure( VKI_EMFILE );
1384 if (VG_(clo_track_fds)) {
1385 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1392 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1393 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1394 PRE_REG_READ6(int,"kevent", int,kq,
1395 const struct vki_kevent *,changelist, int,nchanges,
1396 struct vki_kevent *,eventlist, int,nevents,
1397 const struct vki_timespec *,timeout);
1399 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
1400 ARG2, ARG3 * sizeof(struct vki_kevent));
1401 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
1402 ARG4, ARG5 * sizeof(struct vki_kevent));
1403 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
1404 ARG6, sizeof(struct vki_timespec));
1406 *flags |= SfMayBlock;
1411 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
1412 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
1416 Addr pthread_starter = 0;
1417 Addr wqthread_starter = 0;
1418 SizeT pthread_structsize = 0;
1420 PRE(bsdthread_register)
1422 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
1423 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
1424 void *,"wqthread", size_t,"pthsize");
1426 pthread_starter = ARG1;
1427 wqthread_starter = ARG2;
1428 pthread_structsize = ARG3;
1429 ARG1 = (Word)&pthread_hijack_asm;
1430 ARG2 = (Word)&wqthread_hijack_asm;
1435 PRINT("workq_open()");
1436 PRE_REG_READ0(int, "workq_open");
1438 // This creates lots of threads and thread stacks under the covers,
1439 // but we ignore them all until some work item starts running on it.
1442 static const char *workqop_name(int op)
1445 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
1446 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
1447 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
1448 default: return "?";
1455 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
1457 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
1461 case VKI_WQOPS_QUEUE_ADD:
1462 case VKI_WQOPS_QUEUE_REMOVE:
1463 // GrP fixme need anything here?
1464 // GrP fixme may block?
1467 case VKI_WQOPS_THREAD_RETURN: {
1468 // The interesting case. The kernel will do one of two things:
1469 // 1. Return normally. We continue; libc proceeds to stop the thread.
1470 // V does nothing special here.
1471 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
1472 // new work item, and never returns from workq_ops.
1473 // V handles this by longjmp() from wqthread_hijack back to the
1474 // scheduler, which continues at the new client SP/IP/state.
1475 // This works something like V's signal handling.
1476 // To the tool, this looks like workq_ops() sometimes returns
1477 // to a strange address.
1478 ThreadState *tst = VG_(get_ThreadState)(tid);
1479 tst->os_state.wq_jmpbuf_valid = True;
1480 *flags |= SfMayBlock; // GrP fixme true?
1485 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
1491 ThreadState *tst = VG_(get_ThreadState)(tid);
1492 tst->os_state.wq_jmpbuf_valid = False;
1499 PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
1500 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
1501 int,"call", void *,"arg");
1503 // GrP fixme check call's arg?
1504 // GrP fixme check policy?
1508 /* Not like syswrap-generic's sys_exit, which exits only one thread.
1509 More like syswrap-generic's sys_exit_group. */
1515 PRINT("darwin exit( %ld )", ARG1);
1516 PRE_REG_READ1(void, "exit", int, status);
1518 tst = VG_(get_ThreadState)(tid);
1520 /* A little complex; find all the threads with the same threadgroup
1521 as this one (including this one), and mark them to exit */
1522 for (t = 1; t < VG_N_THREADS; t++) {
1523 if ( /* not alive */
1524 VG_(threads)[t].status == VgTs_Empty
1525 /* GrP fixme zombie? */
1529 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
1530 VG_(threads)[t].os_state.exitcode = ARG1;
1533 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
1536 /* We have to claim the syscall already succeeded. */
1537 SET_STATUS_Success(0);
1543 PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
1544 PRE_REG_READ3(long, "sigaction",
1545 int, signum, vki_sigaction_toK_t *, act,
1546 vki_sigaction_fromK_t *, oldact);
1549 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
1550 PRE_MEM_READ( "sigaction(act->sa_handler)",
1551 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1552 PRE_MEM_READ( "sigaction(act->sa_mask)",
1553 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1554 PRE_MEM_READ( "sigaction(act->sa_flags)",
1555 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
1558 PRE_MEM_WRITE( "sigaction(oldact)",
1559 ARG3, sizeof(vki_sigaction_fromK_t));
1561 SET_STATUS_from_SysRes(
1562 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
1563 (vki_sigaction_fromK_t *)ARG3)
1569 if (RES == 0 && ARG3 != 0)
1570 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
1576 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
1577 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
1581 PRE(__pthread_sigmask)
1584 // JRS: arguments are identical to sigprocmask
1585 // (how, sigset_t*, sigset_t*). Perhaps behave identically?
1588 VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. "
1589 "This warning will not be repeated.\n");
1592 SET_STATUS_Success( 0 );
1596 PRE(__pthread_canceled)
1598 *flags |= SfMayBlock; /* might kill this thread??? */
1599 /* I don't think so -- I think it just changes the cancellation
1600 state. But taking no chances. */
1601 PRINT("__pthread_canceled ( %ld )", ARG1);
1602 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
1606 PRE(__pthread_markcancel)
1608 *flags |= SfMayBlock; /* might kill this thread??? */
1609 PRINT("__pthread_markcancel ( %#lx )", ARG1);
1610 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
1611 /* Just let it go through. No idea if this is correct. */
1615 PRE(__disable_threadsignal)
1618 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
1619 /* I don't think this really looks at its arguments. So don't
1620 bother to check them. */
1622 VG_(sigfillset)( &set );
1623 SET_STATUS_from_SysRes(
1624 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
1627 /* We don't expect that blocking all signals for this thread could
1628 cause any more to be delivered (how could it?), but just in case
1631 *flags |= SfPollAfter;
1637 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
1638 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1640 Don't check anything - some clients pass fewer arguments.
1641 PRE_REG_READ6(long, "kdebug_trace",
1642 int,"code", int,"arg1", int,"arg2",
1643 int,"arg3", int,"arg4", int,"arg5");
1650 PRINT("seteuid(%ld)", ARG1);
1651 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
1657 PRINT("setegid(%ld)", ARG1);
1658 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
1663 PRINT("settid(%ld, %ld)", ARG1, ARG2);
1664 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
1667 /* XXX need to check whether we need POST operations for
1668 * waitevent, watchevent, modwatch -- jpeach
1672 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
1673 PRE_REG_READ2(long, "watchevent",
1674 vki_eventreq *, "event", unsigned int, "eventmask");
1676 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
1677 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
1678 *flags |= SfMayBlock;
1681 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
1684 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
1685 PRE_REG_READ2(long, "waitevent",
1686 vki_eventreq *, "event", struct timeval *, "timeout");
1687 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
1689 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
1690 PRE_timeval_READ("waitevent(timeout)", ARG2);
1693 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
1694 *flags |= SfMayBlock;
1699 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
1704 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
1705 PRE_REG_READ2(long, "modwatch",
1706 vki_eventreq *, "event", unsigned int, "eventmask");
1708 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
1709 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
1714 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
1715 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1717 PRE_REG_READ6(vki_ssize_t, "getxattr",
1718 const char *, path, char *, name, void *, value,
1719 vki_size_t, size, uint32_t, position, int, options);
1720 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
1721 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1722 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1727 vg_assert((vki_ssize_t)RES >= 0);
1728 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1733 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
1734 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1736 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
1737 int, fd, char *, name, void *, value,
1738 vki_size_t, size, uint32_t, position, int, options);
1739 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1740 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1745 vg_assert((vki_ssize_t)RES >= 0);
1746 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1751 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
1752 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1753 PRE_REG_READ6(int, "setxattr",
1754 const char *,"path", char *,"name", void *,"value",
1755 vki_size_t,"size", uint32_t,"position", int,"options" );
1757 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
1758 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
1759 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
1765 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
1766 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1767 PRE_REG_READ6(int, "fsetxattr",
1768 int,"fd", char *,"name", void *,"value",
1769 vki_size_t,"size", uint32_t,"position", int,"options" );
1771 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
1772 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
1778 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
1779 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
1780 PRE_REG_READ4 (long, "listxattr",
1781 const char *,"path", char *,"namebuf",
1782 vki_size_t,"size", int,"options" );
1784 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
1785 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
1786 *flags |= SfMayBlock;
1791 vg_assert((vki_ssize_t)RES >= 0);
1792 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1798 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
1799 ARG1, ARG2, ARG3, ARG4 );
1800 PRE_REG_READ4 (long, "flistxattr",
1801 int, "fd", char *,"namebuf",
1802 vki_size_t,"size", int,"options" );
1803 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
1804 *flags |= SfMayBlock;
1809 vg_assert((vki_ssize_t)RES >= 0);
1810 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1817 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
1818 PRE_REG_READ3(long, "shmat",
1819 int, shmid, const void *, shmaddr, int, shmflg);
1820 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
1822 SET_STATUS_Failure( VKI_EINVAL );
1824 ARG2 = arg2tmp; // used in POST
1828 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
1833 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
1834 PRE_REG_READ3(long, "shmctl",
1835 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
1836 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
1840 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
1845 PRINT("shmdt ( %#lx )",ARG1);
1846 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
1847 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
1848 SET_STATUS_Failure( VKI_EINVAL );
1852 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
1857 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1858 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
1863 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
1864 PRE_REG_READ3(long, "shm_open",
1865 const char *,"name", int,"flags", vki_mode_t,"mode");
1867 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
1869 *flags |= SfMayBlock;
1874 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
1876 SET_STATUS_Failure( VKI_EMFILE );
1878 if (VG_(clo_track_fds))
1879 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
1886 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1887 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1888 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
1889 void *, fsacl, vki_size_t *, fsacl_size);
1890 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
1891 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1892 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1893 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1894 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1898 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1899 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1900 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1901 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1907 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1908 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1909 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
1910 void *, fsacl, vki_size_t *, fsacl_size);
1911 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
1912 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1913 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1914 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1915 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1917 POST(lstat_extended)
1919 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1920 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1921 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1922 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1928 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
1929 ARG1, ARG2, ARG3, ARG4);
1930 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
1931 void *, fsacl, vki_size_t *, fsacl_size);
1932 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1933 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1934 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1935 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1937 POST(fstat_extended)
1939 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1940 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1941 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1942 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1946 PRE(stat64_extended)
1948 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1949 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1950 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
1951 void *, fsacl, vki_size_t *, fsacl_size);
1952 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
1953 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1954 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1955 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1956 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1958 POST(stat64_extended)
1960 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1961 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1962 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1963 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1967 PRE(lstat64_extended)
1969 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1970 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1971 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
1972 void *, fsacl, vki_size_t *, fsacl_size);
1973 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
1974 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1975 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1976 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1977 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1979 POST(lstat64_extended)
1981 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1982 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1983 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1984 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1988 PRE(fstat64_extended)
1990 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
1991 ARG1, ARG2, ARG3, ARG4);
1992 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
1993 void *, fsacl, vki_size_t *, fsacl_size);
1994 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1995 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1996 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1997 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1999 POST(fstat64_extended)
2001 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2002 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2003 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2004 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2008 PRE(fchmod_extended)
2010 /* DDD: Note: this is not really correct. Handling of
2011 chmod_extended is broken in the same way. */
2012 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2013 ARG1, ARG2, ARG3, ARG4, ARG5);
2014 PRE_REG_READ5(long, "fchmod",
2015 unsigned int, fildes,
2019 void* /*really,user_addr_t*/, xsecurity);
2020 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2021 is just way wrong. [The trouble is with the size, which depends on a
2022 non-trival kernel computation] */
2023 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2024 sizeof(struct vki_kauth_filesec) );
2029 /* DDD: Note: this is not really correct. Handling of
2030 fchmod_extended is broken in the same way. */
2031 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2032 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2033 PRE_REG_READ5(long, "chmod",
2034 unsigned int, fildes,
2038 void* /*really,user_addr_t*/, xsecurity);
2039 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2040 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2041 is just way wrong. [The trouble is with the size, which depends on a
2042 non-trival kernel computation] */
2043 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2044 sizeof(struct vki_kauth_filesec) );
2048 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2049 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2050 // by one or more strings. Each accessx_descriptor contains a field,
2051 // 'ad_name_offset', which points to one of the strings (or it can contain
2052 // zero which means "reuse the string from the previous accessx_descriptor").
2054 // What's really ridiculous is that we are only given the size of the overall
2055 // buffer, not the number of accessx_descriptors, nor the number of strings.
2056 // The kernel determines the number of accessx_descriptors by walking through
2057 // them one by one, checking that the ad_name_offset points within the buffer,
2058 // past the current point (or that it's a zero, unless its the first
2059 // descriptor); if so, we assume that this really is an accessx_descriptor,
2060 // if not, we assume we've hit the strings section. Gah.
2062 // This affects us here because number of entries in the 'results' buffer is
2063 // determined by the number of accessx_descriptors. So we have to know that
2064 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2065 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2066 // computation after the syscall has succeeded, because the kernel will have
2067 // checked for all the zillion different ways this syscall can fail, and we'll
2068 // know we have a well-formed 'entries' buffer. This means we might miss some
2069 // uses of unaddressable memory but oh well.
2071 PRE(access_extended)
2073 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2074 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2075 // XXX: the accessx_descriptor struct contains padding, so this can cause
2076 // unnecessary undefined value errors. But you arguably shouldn't be
2077 // passing undefined values to the kernel anyway...
2078 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2079 vki_errno_t *, results, vki_uid_t *, uid);
2080 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2082 // XXX: as mentioned above, this check is too hard to do before the
2084 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2086 POST(access_extended)
2088 // 'n_descs' is the number of descriptors we think are in the buffer. We
2089 // start with the maximum possible value, which occurs if we have the
2090 // shortest possible string section. The shortest string section allowed
2091 // consists of a single one-char string (plus the NUL char). Hence the
2093 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2095 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2096 Int i; // Current position in the descriptors section array.
2097 Int u; // Upper bound on the length of the descriptors array
2098 // (recomputed each time around the loop)
2099 vg_assert(n_descs > 0);
2101 // Step through the descriptors, lowering 'n_descs' until we know we've
2102 // reached the string section.
2103 for (i = 0; True; i++) {
2104 // If we're past our estimate, we must be one past the end of the
2105 // descriptors section (ie. at the start of the string section). Stop.
2109 // Get the array index for the string, but pretend momentarily that it
2110 // is actually another accessx_descriptor. That gives us an upper bound
2111 // on the length of the descriptors section. (Unless the index is zero,
2112 // in which case we have no new info.)
2113 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2119 // If the upper bound is below our current estimate, revise that
2120 // estimate downwards.
2126 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2128 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2134 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2135 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2136 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2138 // GrP fixme sanity-check flags value?
2143 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2144 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2146 // GrP fixme sanity-check flags value?
2151 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2152 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2153 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2154 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2158 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2163 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2164 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2165 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2166 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2170 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2175 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2176 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2177 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2181 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2186 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2187 PRE_REG_READ3(int, "getfsstat",
2188 struct vki_statfs *, buf, int, bufsize, int, flags);
2190 // ARG2 is a BYTE SIZE
2191 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2197 // RES is a STRUCT COUNT
2198 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2204 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2205 PRE_REG_READ3(int, "getfsstat64",
2206 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2208 // ARG2 is a BYTE SIZE
2209 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2215 // RES is a STRUCT COUNT
2216 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2222 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2223 // We are conservative and check everything, except the memory pointed to
2225 *flags |= SfMayBlock;
2226 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2227 ARG1,(Char*)ARG1, ARG2,(Char*)ARG2, ARG3, ARG4);
2228 PRE_REG_READ4(long, "mount",
2229 const char *, type, const char *, dir,
2230 int, flags, void *, data);
2231 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2232 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2236 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2237 void *attrBuf, SizeT attrBufSize,
2238 void (*fn)(ThreadId, void *attrData, SizeT size)
2245 static const attrspec commonattr[] = {
2246 // This order is important.
2247 #if DARWIN_VERS >= DARWIN_10_6
2248 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
2250 { ATTR_CMN_NAME, -1 },
2251 { ATTR_CMN_DEVID, sizeof(dev_t) },
2252 { ATTR_CMN_FSID, sizeof(fsid_t) },
2253 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
2254 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
2255 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
2256 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
2257 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
2258 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
2259 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
2260 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
2261 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
2262 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
2263 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
2264 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2265 { ATTR_CMN_OWNERID, sizeof(uid_t) },
2266 { ATTR_CMN_GRPID, sizeof(gid_t) },
2267 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
2268 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
2269 { ATTR_CMN_NAMEDATTRLIST, -1 },
2270 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
2271 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
2272 { ATTR_CMN_EXTENDED_SECURITY, -1 },
2273 { ATTR_CMN_UUID, sizeof(guid_t) },
2274 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
2275 { ATTR_CMN_FILEID, sizeof(uint64_t) },
2276 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
2277 #if DARWIN_VERS >= DARWIN_10_6
2278 { ATTR_CMN_FULLPATH, -1 },
2282 static const attrspec volattr[] = {
2283 // This order is important.
2284 { ATTR_VOL_INFO, 0 },
2285 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
2286 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
2287 { ATTR_VOL_SIZE, sizeof(off_t) },
2288 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
2289 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
2290 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
2291 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2292 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
2293 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
2294 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
2295 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
2296 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
2297 { ATTR_VOL_MOUNTPOINT, -1 },
2298 { ATTR_VOL_NAME, -1 },
2299 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
2300 { ATTR_VOL_MOUNTEDDEVICE, -1 },
2301 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
2302 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
2303 #if DARWIN_VERS >= DARWIN_10_6
2304 { ATTR_VOL_UUID, sizeof(uuid_t) },
2306 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
2309 static const attrspec dirattr[] = {
2310 // This order is important.
2311 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
2312 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
2313 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
2316 static const attrspec fileattr[] = {
2317 // This order is important.
2318 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
2319 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
2320 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
2321 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
2322 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
2323 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
2324 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
2325 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
2326 { ATTR_FILE_FORKLIST, -1 },
2327 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
2328 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
2329 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
2330 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
2331 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
2332 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
2335 static const attrspec forkattr[] = {
2336 // This order is important.
2337 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
2338 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
2342 static const attrspec *attrdefs[5] = {
2343 commonattr, volattr, dirattr, fileattr, forkattr
2349 vg_assert(attrList->bitmapcount == 5);
2350 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
2352 dend = d + attrBufSize;
2354 #if DARWIN_VERS >= DARWIN_10_6
2355 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
2356 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
2357 // fixme range check this?
2358 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
2359 fn(tid, d, sizeof(attribute_set_t));
2360 VG_(memcpy)(a, d, sizeof(a));
2364 for (g = 0; g < 5; g++) {
2365 for (i = 0; attrdefs[g][i].attrBit; i++) {
2366 uint32_t bit = attrdefs[g][i].attrBit;
2367 int32_t size = attrdefs[g][i].attrSize;
2370 a[g] &= ~bit; // clear bit for error check later
2372 attrreference_t *ref = (attrreference_t *)d;
2373 size = MIN(sizeof(attrreference_t), dend - d);
2375 if (size >= sizeof(attrreference_t) &&
2376 d + ref->attr_dataoffset < dend)
2378 fn(tid, d + ref->attr_dataoffset,
2379 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
2384 size = MIN(size, dend - d);
2389 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
2390 if (d > dend) d = dend;
2394 // Known bits are cleared. Die if any bits are left.
2396 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
2401 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2403 POST_MEM_WRITE((Addr)attrData, attrDataSize);
2406 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2408 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
2413 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2414 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2415 PRE_REG_READ5(int, "getattrlist",
2416 const char *,path, struct vki_attrlist *,attrList,
2417 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2418 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
2419 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2420 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
2425 if (ARG4 > sizeof(vki_uint32_t)) {
2426 // attrBuf is uint32_t size followed by attr data
2427 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
2428 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
2429 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
2430 // *sizep is bytes required for return value, including *sizep
2432 // *sizep is actual bytes returned, including *sizep
2434 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
2441 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2442 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2443 PRE_REG_READ5(int, "setattrlist",
2444 const char *,path, struct vki_attrlist *,attrList,
2445 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2446 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
2447 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2448 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
2452 PRE(getdirentriesattr)
2454 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
2455 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2456 PRE_REG_READ8(int, "getdirentriesattr",
2457 int,fd, struct vki_attrlist *,attrList,
2458 void *,attrBuf, size_t,attrBufSize,
2459 unsigned int *,count, unsigned int *,basep,
2460 unsigned int *,newState, unsigned int,options);
2461 PRE_MEM_READ("getdirentriesattr(attrList)",
2462 ARG2, sizeof(struct vki_attrlist));
2463 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
2464 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2465 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2466 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
2467 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
2469 POST(getdirentriesattr)
2475 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
2476 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
2477 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
2479 // return buffer is concatenation of variable-size structs
2480 count = *(unsigned int *)ARG5;
2482 end = (char *)ARG3 + ARG4;
2483 for (i = 0; i < count; i++) {
2484 vg_assert(p < end); // failure is kernel bug or Valgrind bug
2485 p += *(unsigned int *)p;
2488 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
2490 PRINT("got %d records, %ld/%lu bytes\n",
2491 count, (Addr)p-(Addr)ARG3, ARG4);
2497 #if VG_WORDSIZE == 4
2498 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
2500 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
2501 LOHI64(ARG4, ARG5));
2502 PRE_REG_READ5(ssize_t, "fsgetpath",
2503 void*,"buf", size_t,"bufsize",
2505 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
2507 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
2509 ((unsigned int *)ARG3)[0],
2510 ((unsigned int *)ARG3)[1], ARG4);
2511 PRE_REG_READ4(ssize_t, "fsgetpath",
2512 void*,"buf", size_t,"bufsize",
2513 fsid_t *,"fsid", uint64_t,"objid");
2515 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
2516 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
2521 POST_MEM_WRITE(ARG1, RES);
2524 PRE(audit_session_self)
2526 PRINT("audit_session_self()");
2529 POST(audit_session_self)
2531 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
2532 PRINT("audit-session %#lx", RES);
2537 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
2538 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
2539 PRE_REG_READ3(int, "exchangedata",
2540 char *, path1, char *, path2, unsigned long, options);
2541 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
2542 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
2547 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
2548 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2549 PRE_REG_READ4( long, "fsctl",
2550 char *,"path", unsigned int,"request",
2551 void *,"data", unsigned int,"options");
2553 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
2556 case VKI_afpfsByteRangeLock2FSCTL: {
2557 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2558 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
2560 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
2562 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
2564 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
2566 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
2569 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
2572 // GrP fixme check fd
2575 case VKI_FSIOC_SYNC_VOLUME:
2576 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
2580 // fsctl requests use ioctl encoding
2581 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
2589 case VKI_afpfsByteRangeLock2FSCTL: {
2590 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2591 POST_FIELD_WRITE(pb->retRangeStart);
2594 case VKI_FSIOC_SYNC_VOLUME:
2598 // fsctl requests use ioctl encoding
2599 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
2606 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
2607 PRE_REG_READ3(long, "initgroups",
2608 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
2609 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
2613 //--------- posix_spawn ---------//
2614 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
2615 the simpler AIX equivalent (syswrap-aix5.c). */
2616 // Pre_read a char** argument.
2617 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
2621 Addr* a_p = (Addr*)a;
2622 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2626 PRE_MEM_RASCIIZ( s2, a_deref );
2630 static SysRes simple_pre_exec_check ( const HChar* exe_name,
2631 Bool trace_this_child )
2635 Bool setuid_allowed;
2637 // Check it's readable
2638 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
2639 if (sr_isError(res)) {
2645 // Check we have execute permissions. We allow setuid executables
2646 // to be run only in the case when we are not simulating them, that
2647 // is, they to be run natively.
2648 setuid_allowed = trace_this_child ? False : True;
2649 ret = VG_(check_executable)(NULL/*&is_setuid*/,
2650 (HChar*)exe_name, setuid_allowed);
2652 return VG_(mk_SysRes_Error)(ret);
2654 return VG_(mk_SysRes_Success)(0);
2658 Char* path = NULL; /* path to executable */
2662 Char* launcher_basename = NULL;
2665 Bool trace_this_child;
2669 posix_spawn_file_actions_t* file_actions
2673 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
2674 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2676 /* Standard pre-syscall checks */
2678 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
2679 void*, file_actions, char**, argv, char**, envp );
2680 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
2681 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
2682 // DDD: check file_actions
2684 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
2685 "posix_spawn(argv[i])" );
2687 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
2688 "posix_spawn(envp[i])" );
2691 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
2692 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2694 /* Now follows a bunch of logic copied from PRE(sys_execve) in
2695 syswrap-generic.c. */
2697 /* Check that the name at least begins in client-accessible storage. */
2698 if (ARG2 == 0 /* obviously bogus */
2699 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
2700 SET_STATUS_Failure( VKI_EFAULT );
2704 // Decide whether or not we want to follow along
2705 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2 );
2707 // Do the important checks: it is a file, is executable, permissions are
2708 // ok, etc. We allow setuid executables to run only in the case when
2709 // we are not simulating them, that is, they to be run natively.
2710 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
2711 if (sr_isError(res)) {
2712 SET_STATUS_Failure( sr_Err(res) );
2716 /* If we're tracing the child, and the launcher name looks bogus
2717 (possibly because launcher.c couldn't figure it out, see
2718 comments therein) then we have no option but to fail. */
2719 if (trace_this_child
2720 && (VG_(name_of_launcher) == NULL
2721 || VG_(name_of_launcher)[0] != '/')) {
2722 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2726 /* Ok. So let's give it a try. */
2727 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2);
2729 // Set up the child's exe path.
2731 if (trace_this_child) {
2733 // We want to exec the launcher. Get its pre-remembered path.
2734 path = VG_(name_of_launcher);
2735 // VG_(name_of_launcher) should have been acquired by m_main at
2736 // startup. The following two assertions should be assured by
2737 // the "If we're tracking the child .." test just above here.
2739 vg_assert(path[0] == '/');
2740 launcher_basename = path;
2746 // Set up the child's environment.
2748 // Remove the valgrind-specific stuff from the environment so the
2749 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
2750 // This is done unconditionally, since if we are tracing the child,
2751 // the child valgrind will set up the appropriate client environment.
2752 // Nb: we make a copy of the environment before trying to mangle it
2753 // as it might be in read-only memory (this was bug #101881).
2755 // Then, if tracing the child, set VALGRIND_LIB for it.
2760 envp = VG_(env_clone)( (Char**)ARG5 );
2762 VG_(env_remove_valgrind_env_stuff)( envp );
2765 if (trace_this_child) {
2766 // Set VALGRIND_LIB in ARG5 (the environment)
2767 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
2770 // Set up the child's args. If not tracing it, they are
2771 // simply ARG4. Otherwise, they are
2773 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
2775 // except that the first VG_(args_for_valgrind_noexecpass) args
2778 if (!trace_this_child) {
2779 argv = (Char**)ARG4;
2781 vg_assert( VG_(args_for_valgrind) );
2782 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2783 vg_assert( VG_(args_for_valgrind_noexecpass)
2784 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
2785 /* how many args in total will there be? */
2786 // launcher basename
2789 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
2790 tot_args -= VG_(args_for_valgrind_noexecpass);
2791 // name of client exe
2793 // args for client exe, skipping [0]
2794 arg2copy = (Char**)ARG4;
2795 if (arg2copy && arg2copy[0]) {
2796 for (i = 1; arg2copy[i]; i++)
2800 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
2801 (tot_args+1) * sizeof(HChar*) );
2805 argv[j++] = launcher_basename;
2806 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
2807 if (i < VG_(args_for_valgrind_noexecpass))
2809 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
2811 argv[j++] = (Char*)ARG2;
2812 if (arg2copy && arg2copy[0])
2813 for (i = 1; arg2copy[i]; i++)
2814 argv[j++] = arg2copy[i];
2817 vg_assert(j == tot_args+1);
2820 /* DDD: sort out the signal state. What signal
2821 state does the child inherit from the parent? */
2825 VG_(printf)("posix_spawn: %s\n", path);
2826 for (cpp = argv; cpp && *cpp; cpp++)
2827 VG_(printf)("argv: %s\n", *cpp);
2829 for (cpp = envp; cpp && *cpp; cpp++)
2830 VG_(printf)("env: %s\n", *cpp);
2833 /* Let the call go through as usual. However, we have to poke
2834 the altered arguments back into the argument slots. */
2839 /* not to mention .. */
2840 *flags |= SfMayBlock;
2845 //POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
2851 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2852 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
2859 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
2860 SET_STATUS_from_SysRes(r);
2866 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
2867 ARG1,ARG2,ARG3,ARG4,ARG5);
2868 PRE_REG_READ5(long, "setsockopt",
2869 int, s, int, level, int, optname,
2870 const void *, optval, vki_socklen_t, optlen);
2871 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
2877 Addr optval_p = ARG4;
2878 Addr optlen_p = ARG5;
2879 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
2880 ARG1,ARG2,ARG3,ARG4,ARG5);
2881 PRE_REG_READ5(long, "getsockopt",
2882 int, s, int, level, int, optname,
2883 void *, optval, vki_socklen_t *, optlen);
2884 /* int getsockopt(int socket, int level, int option_name,
2885 void *restrict option_value,
2886 socklen_t *restrict option_len); */
2887 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
2888 if (optval_p != (Addr)NULL) {
2889 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
2890 "socketcall.getsockopt(optval)",
2891 "socketcall.getsockopt(optlen)" );
2893 // DDD: #warning GrP fixme darwin-specific sockopts
2898 Addr optval_p = ARG4;
2899 Addr optlen_p = ARG5;
2901 if (optval_p != (Addr)NULL) {
2902 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
2904 "socketcall.getsockopt(optlen_out)" );
2905 // DDD: #warning GrP fixme darwin-specific sockopts
2912 *flags |= SfMayBlock;
2913 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2914 PRE_REG_READ3(long, "connect",
2915 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
2916 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
2922 *flags |= SfMayBlock;
2923 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2924 PRE_REG_READ3(long, "accept",
2925 int, s, struct sockaddr *, addr, int, *addrlen);
2926 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
2933 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
2935 SET_STATUS_from_SysRes(r);
2941 *flags |= SfMayBlock;
2942 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
2943 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
2944 PRE_REG_READ6(long, "sendto",
2945 int, s, const void *, msg, int, len,
2946 unsigned int, flags,
2947 const struct sockaddr *, to, int, tolen);
2948 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2953 #if VG_WORDSIZE == 4
2954 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
2955 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
2957 PRE_REG_READ7(long, "sendfile",
2958 int, fromfd, int, tofd,
2959 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
2960 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
2961 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
2962 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
2964 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
2965 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2967 PRE_REG_READ6(long, "sendfile",
2968 int, fromfd, int, tofd,
2969 vki_uint64_t, offset,
2970 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
2971 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
2972 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
2975 *flags |= SfMayBlock;
2979 #if VG_WORDSIZE == 4
2980 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
2981 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
2983 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
2984 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
2990 *flags |= SfMayBlock;
2991 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
2992 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2993 PRE_REG_READ6(long, "recvfrom",
2994 int, s, void *, buf, int, len, unsigned int, flags,
2995 struct sockaddr *, from, int *, fromlen);
2996 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3002 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3003 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3009 *flags |= SfMayBlock;
3010 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3011 PRE_REG_READ3(long, "sendmsg",
3012 int, s, const struct msghdr *, msg, int, flags);
3013 ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
3019 *flags |= SfMayBlock;
3020 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3021 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3022 ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
3027 ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
3033 *flags |= SfMayBlock;
3034 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
3035 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3041 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3042 PRE_REG_READ3(long, "bind",
3043 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3044 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3050 PRINT("listen ( %ld, %ld )",ARG1,ARG2);
3051 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3057 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3058 PRE_REG_READ3(long, "getsockname",
3059 int, s, struct sockaddr *, name, int *, namelen);
3060 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3066 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3073 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3074 PRE_REG_READ3(long, "getpeername",
3075 int, s, struct sockaddr *, name, int *, namelen);
3076 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3082 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3089 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3090 PRE_REG_READ4(long, "socketpair",
3091 int, d, int, type, int, protocol, int *, sv);
3092 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3098 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3099 ARG1,ARG2,ARG3,ARG4);
3105 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3106 PRE_REG_READ2(int,"gethostuuid",
3108 const struct vki_timespec *,"timeout");
3110 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3111 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3113 *flags |= SfMayBlock;
3119 POST_MEM_WRITE(ARG1, 16);
3122 /* Darwin pipe() returns the two descriptors in two registers. */
3126 PRE_REG_READ0(int, "pipe");
3136 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3137 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3140 SET_STATUS_Failure( VKI_EMFILE );
3142 if (VG_(clo_track_fds)) {
3143 ML_(record_fd_open_nameless)(tid, p0);
3144 ML_(record_fd_open_nameless)(tid, p1);
3152 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3153 PRE_REG_READ2(long, "getlogin",
3154 char *,"namebuf", unsigned int,"namelen");
3156 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3161 POST_MEM_WRITE(ARG1, ARG2);
3167 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3168 PRE_REG_READ4(long, "ptrace",
3169 int,"request", vki_pid_t,"pid",
3170 vki_caddr_t,"addr", int,"data");
3172 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3174 // GrP fixme anything needed?
3180 PRINT("issetugid ( )");
3181 PRE_REG_READ0(long, "issetugid");
3187 PRINT("getdtablesize ( )");
3188 PRE_REG_READ0(long, "getdtablesize");
3193 // Subtract Valgrind's fd range from client's dtable
3194 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3199 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3200 PRE_REG_READ4(vki_off_t, "lseek",
3201 unsigned int,fd, int,offset_hi, int,offset_lo,
3202 unsigned int,whence);
3208 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3209 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3210 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3216 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3217 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3219 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3220 SET_STATUS_Failure( VKI_EBADF );
3226 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3227 PRE_REG_READ4(int, "getdirentries",
3228 int, fd, char *, buf, int, nbytes, long *, basep);
3229 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3230 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3235 POST_MEM_WRITE(ARG4, sizeof(long));
3236 // GrP fixme be specific about d_name?
3237 POST_MEM_WRITE(ARG2, RES);
3241 PRE(getdirentries64)
3243 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3244 PRE_REG_READ4(vki_ssize_t, "getdirentries",
3245 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3246 PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t));
3247 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3249 POST(getdirentries64)
3251 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3252 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3253 POST_MEM_WRITE(ARG2, RES);
3259 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3260 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3261 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3262 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3266 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3272 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3273 PRE_REG_READ2(long, "fstatfs64",
3274 unsigned int, fd, struct statfs *, buf);
3275 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3279 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3284 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
3285 PRE_REG_READ4(int, "csops",
3286 vki_pid_t, pid, uint32_t, ops,
3287 void *, useraddr, vki_size_t, usersize);
3289 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
3291 // If the pid is ours, don't mark the program as KILL or HARD
3292 // Maybe we should keep track of this for later calls to STATUS
3293 if (!ARG1 || VG_(getpid)() == ARG1) {
3295 case VKI_CS_OPS_MARKINVALID:
3296 case VKI_CS_OPS_MARKHARD:
3297 case VKI_CS_OPS_MARKKILL:
3298 SET_STATUS_Success(0);
3304 POST_MEM_WRITE( ARG3, ARG4 );
3309 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
3310 PRE_REG_READ3(int,"auditon",
3311 int,"cmd", void*,"data", unsigned int,"length");
3315 case VKI_A_SETPOLICY:
3316 case VKI_A_SETKMASK:
3317 case VKI_A_SETQCTRL:
3319 case VKI_A_SETCLASS:
3320 case VKI_A_SETPMASK:
3321 case VKI_A_SETFSIZE:
3322 #if DARWIN_VERS >= DARWIN_10_6
3323 case VKI_A_SENDTRIGGER:
3325 // kernel reads data..data+length
3326 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3329 case VKI_A_GETKMASK:
3330 case VKI_A_GETPOLICY:
3331 case VKI_A_GETQCTRL:
3332 case VKI_A_GETFSIZE:
3334 // kernel writes data..data+length
3335 // GrP fixme be precise about what gets written
3336 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3340 case VKI_A_GETCLASS:
3341 case VKI_A_GETPINFO:
3342 case VKI_A_GETPINFO_ADDR:
3343 #if DARWIN_VERS >= DARWIN_10_6
3344 case VKI_A_GETSINFO_ADDR:
3346 // kernel reads and writes data..data+length
3347 // GrP fixme be precise about what gets read and written
3348 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3349 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3352 case VKI_A_SETKAUDIT:
3354 case VKI_A_SETUMASK:
3355 case VKI_A_SETSMASK:
3356 case VKI_A_GETKAUDIT:
3360 // unimplemented on darwin
3364 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1);
3372 case VKI_A_SETPOLICY:
3373 case VKI_A_SETKMASK:
3374 case VKI_A_SETQCTRL:
3376 case VKI_A_SETCLASS:
3377 case VKI_A_SETPMASK:
3378 case VKI_A_SETFSIZE:
3379 #if DARWIN_VERS >= DARWIN_10_6
3380 case VKI_A_SENDTRIGGER:
3382 // kernel reads data..data+length
3385 case VKI_A_GETKMASK:
3386 case VKI_A_GETPOLICY:
3387 case VKI_A_GETQCTRL:
3388 case VKI_A_GETFSIZE:
3390 // kernel writes data..data+length
3391 // GrP fixme be precise about what gets written
3392 POST_MEM_WRITE(ARG2, ARG3);
3396 case VKI_A_GETCLASS:
3397 case VKI_A_GETPINFO:
3398 case VKI_A_GETPINFO_ADDR:
3399 #if DARWIN_VERS >= DARWIN_10_6
3400 case VKI_A_GETSINFO_ADDR:
3402 // kernel reads and writes data..data+length
3403 // GrP fixme be precise about what gets read and written
3404 POST_MEM_WRITE(ARG2, ARG3);
3407 case VKI_A_SETKAUDIT:
3409 case VKI_A_SETUMASK:
3410 case VKI_A_SETSMASK:
3411 case VKI_A_GETKAUDIT:
3415 // unimplemented on darwin
3428 #if VG_WORDSIZE == 4
3429 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
3430 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
3431 PRE_REG_READ7(Addr, "mmap",
3432 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3433 unsigned long,offset_hi, unsigned long,offset_lo);
3434 // GrP fixme V mmap and kernel mach_msg collided once - don't use
3435 // V's mechanism for now
3436 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
3437 // (Off64T)LOHI64(ARG6, ARG7) );
3439 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
3440 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3441 PRE_REG_READ6(long, "mmap",
3442 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3444 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3448 // SET_STATUS_from_SysRes(r);
3454 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
3455 // Try to load symbols from the region
3456 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/ );
3463 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
3464 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3466 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
3467 void*, oldp, vki_size_t *, oldlenp,
3468 void*, newp, vki_size_t *, newlenp);
3470 PRE_MEM_READ("sysctl(name)", ARG1, ARG2); // reads name[0..namelen-1]
3473 PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
3475 // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
3476 PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
3477 PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
3481 PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
3484 if (VG_(clo_trace_syscalls)) {
3486 int *name = (int *)ARG1;
3487 VG_(printf)(" mib: [ ");
3488 for (i = 0; i < ARG2; i++) {
3489 VG_(printf)("%d ", name[i]);
3494 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
3495 // (executable path and arguments and environment
3498 // Intercept sysctl(kern.usrstack). The kernel's reply would be
3499 // Valgrind's stack, not the client's stack.
3500 // GrP fixme kern_usrstack64
3501 if (ARG1 && ARG2 == 2 &&
3502 ((int *)ARG1)[0] == VKI_CTL_KERN &&
3503 #if VG_WORDSIZE == 4
3504 ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
3506 ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
3510 if (ARG5/*newp*/ || ARG6/*newlen*/) {
3511 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
3513 Addr *oldp = (Addr *)ARG3;
3514 size_t *oldlenp = (size_t *)ARG4;
3516 Addr stack_end = VG_(clstk_end)+1;
3517 size_t oldlen = *oldlenp;
3518 // always return actual size
3519 *oldlenp = sizeof(Addr);
3520 if (oldp && oldlen >= sizeof(Addr)) {
3521 // oldp is big enough
3522 // copy value and return 0
3524 SET_STATUS_Success(0);
3526 // oldp isn't big enough
3527 // copy as much as possible and return ENOMEM
3528 if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
3529 SET_STATUS_Failure(VKI_ENOMEM);
3536 if (!SUCCESS && !FAILURE) {
3537 // Don't set SfPostOnFail if we've already handled it locally.
3538 *flags |= SfPostOnFail;
3544 if (SUCCESS || ERR == VKI_ENOMEM) {
3545 // sysctl can write truncated data and return VKI_ENOMEM
3547 POST_MEM_WRITE(ARG4, sizeof(size_t));
3550 POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
3558 PRINT( "sigpending ( %#lx )", ARG1 );
3559 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
3560 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
3564 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
3571 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
3572 PRE_REG_READ3(long, "sigprocmask",
3573 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
3575 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
3577 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
3579 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
3580 value of 'how' is irrelevant, and it appears that Darwin's libc
3581 passes zero, which is not equal to any of
3582 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
3583 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
3584 value independently of the other args. Solution: in this case,
3585 simply pass a valid (but irrelevant) value for 'how'. */
3586 /* Also, in this case the new set is passed to the kernel by
3587 reference, not value, as in some other sigmask related Darwin
3590 if (ARG2 == 0 /* the new-set is NULL */
3591 && ARG1 != VKI_SIG_BLOCK
3592 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
3593 arg1 = VKI_SIG_SETMASK;
3595 SET_STATUS_from_SysRes(
3596 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
3597 (vki_sigset_t*)ARG3 )
3601 *flags |= SfPollAfter;
3607 if (RES == 0 && ARG3 != 0)
3608 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
3614 /* Just hand this off to the kernel. Is that really correct? And
3615 shouldn't we at least set SfPollAfter? These questions apply to
3616 all the Linux versions too. */
3617 /* I think the first arg is the 32-bit signal mask (by value), and
3618 the other two args are ignored. */
3619 *flags |= SfMayBlock;
3620 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
3621 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
3625 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
3626 and 32-bit wrappers are different.
3628 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
3629 length in the usual way. I have seen values NULL, 0 passed in some
3630 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
3631 basis that they don't do anything if the length is zero, so it's OK
3632 for the buffer pointer to be NULL in that case (meaning they don't
3635 int proc_info(int32_t callnum, int32_t pid,
3636 uint32_t flavor, uint64_t arg,
3637 user_addr_t buffer, int32_t buffersize)
3639 #if DARWIN_VERS >= DARWIN_10_6
3642 #if VG_WORDSIZE == 4
3643 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3644 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
3645 PRE_REG_READ7(int, "proc_info",
3646 int, callnum, int, pid, unsigned int, flavor,
3647 vki_uint32_t, arg_low32,
3648 vki_uint32_t, arg_high32,
3649 void*, buffer, int, buffersize);
3650 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
3652 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3653 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
3654 PRE_REG_READ6(int, "proc_info",
3655 int, callnum, int, pid, unsigned int, flavor,
3656 unsigned long long int, arg,
3657 void*, buffer, int, buffersize);
3658 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
3664 #if VG_WORDSIZE == 4
3666 POST_MEM_WRITE(ARG6, ARG7);
3669 POST_MEM_WRITE(ARG5, ARG6);
3673 #endif /* DARWIN_VERS >= DARWIN_10_6 */
3675 /* ---------------------------------------------------------------------
3677 ------------------------------------------------------------------ */
3679 // We must record the aiocbp for each aio_read() in a table so that when
3680 // aio_return() is called we can mark the memory written asynchronously by
3681 // aio_read() as having been written. We don't have to do this for
3682 // aio_write(). See bug 197227 for more details.
3683 static OSet* aiocbp_table = NULL;
3684 static Bool aio_init_done = False;
3686 static void aio_init(void)
3688 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
3689 aio_init_done = True;
3692 static Bool was_a_successful_aio_read = False;
3696 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3697 // This assumes that the kernel looks at the struct pointer, but not the
3698 // contents of the struct.
3699 PRINT( "aio_return ( %#lx )", ARG1 );
3700 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
3702 if (!aio_init_done) aio_init();
3703 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
3707 // If we found the aiocbp in our own table it must have been an aio_read(),
3708 // so mark the buffer as written. If we didn't find it, it must have been
3709 // an aio_write() or a bogus aio_return() (eg. a second one on the same
3710 // aiocbp). Either way, the buffer won't have been written so we don't
3711 // have to mark the buffer as written.
3712 if (was_a_successful_aio_read) {
3713 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3714 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3715 was_a_successful_aio_read = False;
3721 // This assumes that the kernel looks at the struct pointers in the list,
3722 // but not the contents of the structs.
3723 PRINT( "aio_suspend ( %#lx )", ARG1 );
3724 PRE_REG_READ3(long, "aio_suspend",
3725 const struct vki_aiocb *, aiocbp, int, nent,
3726 const struct vki_timespec *, timeout);
3728 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
3730 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
3735 // This assumes that the kernel looks at the struct pointer, but not the
3736 // contents of the struct.
3737 PRINT( "aio_error ( %#lx )", ARG1 );
3738 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
3743 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3745 PRINT( "aio_read ( %#lx )", ARG1 );
3746 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
3747 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3749 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3750 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
3751 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
3752 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3754 SET_STATUS_Failure( VKI_EBADF );
3757 SET_STATUS_Failure( VKI_EINVAL );
3762 // We have to record the fact that there is an asynchronous read request
3763 // pending. When a successful aio_return() occurs for this aiocb, then we
3764 // will mark the memory as having been defined.
3765 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3766 if (!aio_init_done) aio_init();
3767 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
3768 // should have caused the aio_read() to fail and we shouldn't have reached
3770 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
3775 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3777 PRINT( "aio_write ( %#lx )", ARG1 );
3778 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
3779 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3781 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3782 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
3783 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
3784 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3786 SET_STATUS_Failure( VKI_EBADF );
3789 SET_STATUS_Failure( VKI_EINVAL );
3793 /* ---------------------------------------------------------------------
3794 mach_msg: formatted messages
3795 ------------------------------------------------------------------ */
3797 static size_t desc_size(mach_msg_descriptor_t *desc)
3799 switch (desc->type.type) {
3800 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
3801 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
3802 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
3803 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
3805 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
3806 return sizeof(desc->type); // guess
3811 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
3815 mach_port_t *ports = (mach_port_t *)desc->address;
3816 for (i = 0; i < desc->count; i++) {
3817 assign_port_name(ports[i], name);
3822 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
3824 mach_msg_body_t *body;
3825 mach_msg_size_t count, i;
3827 mach_msg_descriptor_t *desc;
3829 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
3831 body = (mach_msg_body_t *)(mh+1);
3832 count = body->msgh_descriptor_count;
3833 p = (uint8_t *)(body+1);
3835 for (i = 0; i < count; i++) {
3836 desc = (mach_msg_descriptor_t *)p;
3837 p += desc_size(desc);
3839 switch (desc->type.type) {
3840 case MACH_MSG_PORT_DESCRIPTOR:
3842 record_unnamed_port(tid, desc->port.name, -1);
3843 record_port_insert_rights(desc->port.name, desc->port.disposition);
3844 PRINT("got port %s;\n", name_for_port(desc->port.name));
3847 case MACH_MSG_OOL_DESCRIPTOR:
3848 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3849 // out-of-line memory - map it
3850 // GrP fixme how is VOLATILE different? do we care?
3851 // GrP fixme do other flags tell us anything? assume shared for now
3852 // GrP fixme more SF_ flags marking mach_msg memory might be nice
3853 // GrP fixme protection
3854 if (desc->out_of_line.size > 0) {
3855 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
3856 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
3857 (Addr)desc->out_of_line.size);
3858 PRINT("got ool mem %p..%#lx;\n", desc->out_of_line.address,
3859 (Addr)desc->out_of_line.address+desc->out_of_line.size);
3861 ML_(notify_core_and_tool_of_mmap)(
3862 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3863 VKI_MAP_PRIVATE, -1, 0);
3865 // GrP fixme mark only un-rounded part as initialized
3868 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3869 // out-of-line array of ports - map it
3870 // GrP fixme see fixmes above
3871 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));
3873 if (desc->ool_ports.count > 0) {
3874 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
3875 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
3876 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
3878 ML_(notify_core_and_tool_of_mmap)(
3879 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3880 VKI_MAP_PRIVATE, -1, 0);
3883 for (i = 0; i < desc->ool_ports.count; i++) {
3884 record_unnamed_port(tid, ports[i], -1);
3885 record_port_insert_rights(ports[i], desc->port.disposition);
3886 PRINT(" %s", name_for_port(ports[i]));
3893 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
3900 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
3905 mach_msg_size_t pad1;
3907 uint8_t disposition;
3909 } *desc = (void*)desc2;
3912 PRE_FIELD_READ("msg->desc.port.name", desc->name);
3913 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
3914 PRE_FIELD_READ("msg->desc.port.type", desc->type);
3918 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
3923 #if VG_WORDSIZE != 8
3924 mach_msg_size_t size;
3930 #if VG_WORDSIZE == 8
3931 mach_msg_size_t size;
3933 } *desc = (void*)desc2;
3936 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
3937 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
3938 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
3939 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
3940 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
3943 static void pre_oolports_desc_read(ThreadId tid,
3944 mach_msg_ool_ports_descriptor_t *desc2)
3949 #if VG_WORDSIZE != 8
3950 mach_msg_size_t size;
3954 uint8_t disposition;
3956 #if VG_WORDSIZE == 8
3957 mach_msg_size_t size;
3959 } *desc = (void*)desc2;
3962 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
3963 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
3964 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
3965 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
3966 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
3967 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
3971 // Returns the size of the descriptor area
3972 // (mach_msg_body_t + any mach_msg_descriptor_t)
3973 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
3975 mach_msg_body_t *body;
3976 mach_msg_size_t count, i;
3978 mach_msg_descriptor_t *desc;
3980 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
3982 body = (mach_msg_body_t *)(mh+1);
3983 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
3985 count = body->msgh_descriptor_count;
3986 p = (uint8_t *)(body+1);
3988 for (i = 0; i < count; i++) {
3989 desc = (mach_msg_descriptor_t *)p;
3990 p += desc_size(desc);
3992 switch (desc->type.type) {
3993 case MACH_MSG_PORT_DESCRIPTOR:
3994 // single port; no memory map effects
3995 pre_port_desc_read(tid, &desc->port);
3998 case MACH_MSG_OOL_DESCRIPTOR:
3999 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4000 // out-of-line memory - unmap it if it's marked dealloc
4001 // GrP fixme need to remap if message fails?
4002 // GrP fixme how is VOLATILE different? do we care?
4003 // GrP fixme struct is different for lp64
4004 pre_ool_desc_read(tid, &desc->out_of_line);
4006 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4007 vm_size_t size = desc->out_of_line.size;
4008 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4009 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4010 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4011 (Addr)desc->out_of_line.address + size);
4012 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4016 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4017 // out-of-line array of ports - unmap it if it's marked dealloc
4018 // GrP fixme need to remap if message fails?
4019 // GrP fixme struct different for lp64
4020 pre_oolports_desc_read(tid, &desc->ool_ports);
4022 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4023 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4024 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4025 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4026 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4027 (Addr)desc->ool_ports.address + size);
4028 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4032 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4037 return (size_t)((Addr)p - (Addr)body);
4041 /* ---------------------------------------------------------------------
4042 mach_msg: host-related messages
4043 ------------------------------------------------------------------ */
4050 mach_msg_header_t Head;
4052 kern_return_t RetCode;
4053 mach_msg_type_number_t host_info_outCnt;
4054 integer_t host_info_out[14];
4058 Reply *reply = (Reply *)ARG1;
4060 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4067 mach_msg_header_t Head;
4069 host_flavor_t flavor;
4070 mach_msg_type_number_t host_info_outCnt;
4074 Request *req = (Request *)ARG1;
4076 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4078 AFTER = POST_FN(host_info);
4082 POST(host_page_size)
4086 mach_msg_header_t Head;
4088 kern_return_t RetCode;
4089 vm_size_t out_page_size;
4093 Reply *reply = (Reply *)ARG1;
4095 if (!reply->RetCode) {
4096 PRINT("page size %llu", (ULong)reply->out_page_size);
4098 PRINT("mig return %d", reply->RetCode);
4104 PRINT("host_page_size(mach_host_self(), ...)");
4106 AFTER = POST_FN(host_page_size);
4110 POST(host_get_io_master)
4114 mach_msg_header_t Head;
4115 /* start of the kernel processed data */
4116 mach_msg_body_t msgh_body;
4117 mach_msg_port_descriptor_t io_master;
4118 /* end of the kernel processed data */
4122 Reply *reply = (Reply *)ARG1;
4124 assign_port_name(reply->io_master.name, "io_master-%p");
4125 PRINT("%s", name_for_port(reply->io_master.name));
4128 PRE(host_get_io_master)
4132 mach_msg_header_t Head;
4136 // Request *req = (Request *)ARG1;
4138 PRINT("host_get_io_master(mach_host_self())");
4140 AFTER = POST_FN(host_get_io_master);
4144 POST(host_get_clock_service)
4148 mach_msg_header_t Head;
4149 /* start of the kernel processed data */
4150 mach_msg_body_t msgh_body;
4151 mach_msg_port_descriptor_t clock_serv;
4152 /* end of the kernel processed data */
4156 Reply *reply = (Reply *)ARG1;
4158 assign_port_name(reply->clock_serv.name, "clock-%p");
4159 PRINT("%s", name_for_port(reply->clock_serv.name));
4162 PRE(host_get_clock_service)
4166 mach_msg_header_t Head;
4168 clock_id_t clock_id;
4172 Request *req = (Request *)ARG1;
4174 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4176 AFTER = POST_FN(host_get_clock_service);
4180 PRE(host_request_notification)
4184 mach_msg_header_t Head;
4185 /* start of the kernel processed data */
4186 mach_msg_body_t msgh_body;
4187 mach_msg_port_descriptor_t notify_port;
4188 /* end of the kernel processed data */
4190 host_flavor_t notify_type;
4194 Request *req = (Request *)ARG1;
4196 if (MACH_REMOTE == mach_task_self()) {
4197 if (req->notify_type == 0) {
4198 PRINT("host_request_notification(mach_host_self(), %s, %s)",
4199 "HOST_NOTIFY_CALENDAR_CHANGE",
4200 name_for_port(req->notify_port.name));
4202 PRINT("host_request_notification(mach_host_self(), %d, %s)",
4204 name_for_port(req->notify_port.name));
4207 PRINT("host_request_notification(%s, %d, %s)",
4208 name_for_port(MACH_REMOTE),
4210 name_for_port(req->notify_port.name));
4213 // GrP fixme only do this on success
4214 assign_port_name(req->notify_port.name, "host_notify-%p");
4218 /* ---------------------------------------------------------------------
4219 mach_msg: messages to a task
4220 ------------------------------------------------------------------ */
4227 mach_msg_header_t Head;
4229 mach_port_name_t name;
4233 Request *req = (Request *)ARG1;
4235 PRINT("mach_port_type(%s, %s, ...)",
4236 name_for_port(MACH_REMOTE), name_for_port(req->name));
4238 AFTER = POST_FN(mach_port_type);
4241 POST(mach_port_type)
4246 PRE(mach_port_extract_member)
4250 mach_msg_header_t Head;
4252 mach_port_name_t name;
4253 mach_port_name_t pset;
4257 Request *req = (Request *)ARG1;
4259 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
4260 name_for_port(MACH_REMOTE),
4261 req->name, req->pset);
4263 AFTER = POST_FN(mach_port_extract_member);
4265 // GrP fixme port tracker?
4268 POST(mach_port_extract_member)
4272 mach_msg_header_t Head;
4274 kern_return_t RetCode;
4278 Reply *reply = (Reply *)ARG1;
4280 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4284 PRE(mach_port_allocate)
4288 mach_msg_header_t Head;
4290 mach_port_right_t right;
4294 Request *req = (Request *)ARG1;
4296 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
4298 MACH_ARG(mach_port_allocate.right) = req->right;
4300 AFTER = POST_FN(mach_port_allocate);
4303 POST(mach_port_allocate)
4307 mach_msg_header_t Head;
4309 kern_return_t RetCode;
4310 mach_port_name_t name;
4314 Reply *reply = (Reply *)ARG1;
4316 if (!reply->RetCode) {
4317 if (MACH_REMOTE == vg_task_port) {
4318 // GrP fixme port tracking is too imprecise
4319 // vg_assert(!port_exists(reply->name));
4320 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
4321 PRINT("got port 0x%x", reply->name);
4323 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
4326 PRINT("mig return %d", reply->RetCode);
4331 PRE(mach_port_deallocate)
4335 mach_msg_header_t Head;
4337 mach_port_name_t name;
4341 Request *req = (Request *)ARG1;
4343 PRINT("mach_port_deallocate(%s, %s)",
4344 name_for_port(MACH_REMOTE),
4345 name_for_port(req->name));
4347 MACH_ARG(mach_port.port) = req->name;
4349 AFTER = POST_FN(mach_port_deallocate);
4351 // Must block to prevent race (other thread allocates and
4352 // notifies after we deallocate but before we notify)
4353 *flags &= ~SfMayBlock;
4356 POST(mach_port_deallocate)
4360 mach_msg_header_t Head;
4362 kern_return_t RetCode;
4366 Reply *reply = (Reply *)ARG1;
4368 if (!reply->RetCode) {
4369 if (MACH_REMOTE == vg_task_port) {
4370 // Must have cleared SfMayBlock in PRE to prevent race
4371 record_port_dealloc(MACH_ARG(mach_port.port));
4373 VG_(printf)("UNKNOWN remote port dealloc\n");
4376 PRINT("mig return %d", reply->RetCode);
4381 PRE(mach_port_get_refs)
4385 mach_msg_header_t Head;
4387 mach_port_name_t name;
4388 mach_port_right_t right;
4392 Request *req = (Request *)ARG1;
4394 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
4395 name_for_port(MACH_REMOTE),
4396 name_for_port(req->name), req->right);
4398 MACH_ARG(mach_port_mod_refs.port) = req->name;
4399 MACH_ARG(mach_port_mod_refs.right) = req->right;
4401 AFTER = POST_FN(mach_port_get_refs);
4404 POST(mach_port_get_refs)
4408 mach_msg_header_t Head;
4410 kern_return_t RetCode;
4411 mach_port_urefs_t refs;
4415 Reply *reply = (Reply *)ARG1;
4417 if (!reply->RetCode) {
4418 PRINT("got refs=%d", reply->refs);
4420 PRINT("mig return %d", reply->RetCode);
4425 PRE(mach_port_mod_refs)
4429 mach_msg_header_t Head;
4431 mach_port_name_t name;
4432 mach_port_right_t right;
4433 mach_port_delta_t delta;
4437 Request *req = (Request *)ARG1;
4439 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
4440 name_for_port(MACH_REMOTE),
4441 name_for_port(req->name), req->right, req->delta);
4443 MACH_ARG(mach_port_mod_refs.port) = req->name;
4444 MACH_ARG(mach_port_mod_refs.right) = req->right;
4445 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
4447 AFTER = POST_FN(mach_port_mod_refs);
4449 // Must block to prevent race (other thread allocates and
4450 // notifies after we deallocate but before we notify)
4451 *flags &= ~SfMayBlock;
4454 POST(mach_port_mod_refs)
4458 mach_msg_header_t Head;
4460 kern_return_t RetCode;
4464 Reply *reply = (Reply *)ARG1;
4466 if (!reply->RetCode) {
4467 if (MACH_REMOTE == vg_task_port) {
4468 // Must have cleared SfMayBlock in PRE to prevent race
4469 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
4470 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
4471 MACH_ARG(mach_port_mod_refs.delta));
4473 VG_(printf)("UNKNOWN remote port mod refs\n");
4476 PRINT("mig return %d", reply->RetCode);
4481 PRE(mach_port_get_set_status)
4485 mach_msg_header_t Head;
4487 mach_port_name_t name;
4491 Request *req = (Request *)ARG1;
4493 PRINT("mach_port_get_set_status(%s, %s)",
4494 name_for_port(MACH_REMOTE),
4495 name_for_port(req->name));
4497 AFTER = POST_FN(mach_port_get_set_status);
4500 POST(mach_port_get_set_status)
4504 mach_msg_header_t Head;
4505 /* start of the kernel processed data */
4506 mach_msg_body_t msgh_body;
4507 mach_msg_ool_descriptor_t members;
4508 /* end of the kernel processed data */
4510 mach_msg_type_number_t membersCnt;
4511 mach_msg_trailer_t trailer;
4515 // Reply *reply = (Reply *)ARG1;
4517 // GrP fixme nothing to do?
4521 PRE(mach_port_move_member)
4525 mach_msg_header_t Head;
4527 mach_port_name_t member;
4528 mach_port_name_t after;
4532 Request *req = (Request *)ARG1;
4534 PRINT("mach_port_move_member(%s, %s, %s)",
4535 name_for_port(MACH_REMOTE),
4536 name_for_port(req->member),
4537 name_for_port(req->after));
4539 MACH_ARG(mach_port_move_member.member) = req->member;
4540 MACH_ARG(mach_port_move_member.after) = req->after;
4542 AFTER = POST_FN(mach_port_move_member);
4545 POST(mach_port_move_member)
4549 mach_msg_header_t Head;
4551 kern_return_t RetCode;
4552 mach_msg_trailer_t trailer;
4556 Reply *reply = (Reply *)ARG1;
4558 if (!reply->RetCode) {
4559 // fixme port set tracker?
4561 PRINT("mig return %d", reply->RetCode);
4566 PRE(mach_port_destroy)
4570 mach_msg_header_t Head;
4572 mach_port_name_t name;
4576 Request *req = (Request *)ARG1;
4578 PRINT("mach_port_destroy(%s, %s)",
4579 name_for_port(MACH_REMOTE),
4580 name_for_port(req->name));
4582 MACH_ARG(mach_port.port) = req->name;
4584 AFTER = POST_FN(mach_port_destroy);
4586 // Must block to prevent race (other thread allocates and
4587 // notifies after we deallocate but before we notify)
4588 *flags &= ~SfMayBlock;
4591 POST(mach_port_destroy)
4595 mach_msg_header_t Head;
4597 kern_return_t RetCode;
4601 Reply *reply = (Reply *)ARG1;
4603 if (!reply->RetCode) {
4604 if (MACH_REMOTE == vg_task_port) {
4605 // Must have cleared SfMayBlock in PRE to prevent race
4606 record_port_destroy(MACH_ARG(mach_port.port));
4608 VG_(printf)("UNKNOWN remote port destroy\n");
4611 PRINT("mig return %d", reply->RetCode);
4616 PRE(mach_port_request_notification)
4620 mach_msg_header_t Head;
4621 /* start of the kernel processed data */
4622 mach_msg_body_t msgh_body;
4623 mach_msg_port_descriptor_t notify;
4624 /* end of the kernel processed data */
4626 mach_port_name_t name;
4627 mach_msg_id_t msgid;
4628 mach_port_mscount_t sync;
4632 Request *req = (Request *)ARG1;
4634 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
4635 name_for_port(MACH_REMOTE),
4636 name_for_port(req->name), req->msgid, req->sync,
4637 req->notify.name, req->notify.disposition);
4639 AFTER = POST_FN(mach_port_request_notification);
4642 POST(mach_port_request_notification)
4644 // GrP fixme port tracker? not sure
4648 PRE(mach_port_insert_right)
4652 mach_msg_header_t Head;
4653 /* start of the kernel processed data */
4654 mach_msg_body_t msgh_body;
4655 mach_msg_port_descriptor_t poly;
4656 /* end of the kernel processed data */
4658 mach_port_name_t name;
4662 Request *req = (Request *)ARG1;
4664 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
4665 name_for_port(MACH_REMOTE),
4666 name_for_port(req->name), req->poly.name, req->poly.disposition);
4668 AFTER = POST_FN(mach_port_insert_right);
4670 if (MACH_REMOTE == mach_task_self()) {
4671 // GrP fixme import_complex_message handles everything?
4672 // what about export_complex_message for MOVE variants?
4674 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
4675 // GrP fixme also may remove rights from this task?
4678 // GrP fixme port tracker?
4681 POST(mach_port_insert_right)
4686 PRE(mach_port_extract_right)
4690 mach_msg_header_t Head;
4692 mach_port_name_t name;
4693 mach_msg_type_name_t msgt_name;
4697 Request *req = (Request *)ARG1;
4699 PRINT("mach_port_extract_right(%s, %s, %d)",
4700 name_for_port(MACH_REMOTE),
4701 name_for_port(req->name), req->msgt_name);
4703 AFTER = POST_FN(mach_port_extract_right);
4705 // fixme port tracker?
4708 POST(mach_port_extract_right)
4710 // fixme import_complex_message handles the returned result, right?
4714 PRE(mach_port_get_attributes)
4718 mach_msg_header_t Head;
4720 mach_port_name_t name;
4721 mach_port_flavor_t flavor;
4722 mach_msg_type_number_t port_info_outCnt;
4726 Request *req = (Request *)ARG1;
4728 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
4729 name_for_port(MACH_REMOTE),
4730 name_for_port(req->name), req->flavor, req->port_info_outCnt);
4732 AFTER = POST_FN(mach_port_get_attributes);
4735 POST(mach_port_get_attributes)
4740 PRE(mach_port_set_attributes)
4744 mach_msg_header_t Head;
4746 mach_port_name_t name;
4747 mach_port_flavor_t flavor;
4748 mach_msg_type_number_t port_infoCnt;
4749 integer_t port_info[10];
4753 Request *req = (Request *)ARG1;
4755 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
4756 name_for_port(MACH_REMOTE),
4757 name_for_port(req->name), req->flavor, req->port_infoCnt);
4759 AFTER = POST_FN(mach_port_set_attributes);
4762 POST(mach_port_set_attributes)
4767 PRE(mach_port_insert_member)
4771 mach_msg_header_t Head;
4773 mach_port_name_t name;
4774 mach_port_name_t pset;
4778 Request *req = (Request *)ARG1;
4780 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
4781 name_for_port(MACH_REMOTE), req->name, req->pset);
4783 AFTER = POST_FN(mach_port_insert_member);
4785 // GrP fixme port tracker?
4788 POST(mach_port_insert_member)
4793 PRE(task_get_special_port)
4797 mach_msg_header_t Head;
4803 Request *req = (Request *)ARG1;
4805 switch (req->which_port) {
4806 case TASK_KERNEL_PORT:
4807 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
4808 name_for_port(MACH_REMOTE));
4810 case TASK_HOST_PORT:
4811 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
4812 name_for_port(MACH_REMOTE));
4814 case TASK_BOOTSTRAP_PORT:
4815 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
4816 name_for_port(MACH_REMOTE));
4818 case TASK_WIRED_LEDGER_PORT:
4819 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
4820 name_for_port(MACH_REMOTE));
4822 case TASK_PAGED_LEDGER_PORT:
4823 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
4824 name_for_port(MACH_REMOTE));
4827 PRINT("task_get_special_port(%s, %d)",
4828 name_for_port(MACH_REMOTE), req->which_port);
4832 MACH_ARG(task_get_special_port.which_port) = req->which_port;
4834 AFTER = POST_FN(task_get_special_port);
4837 POST(task_get_special_port)
4841 mach_msg_header_t Head;
4842 /* start of the kernel processed data */
4843 mach_msg_body_t msgh_body;
4844 mach_msg_port_descriptor_t special_port;
4845 /* end of the kernel processed data */
4849 Reply *reply = (Reply *)ARG1;
4851 PRINT("got port %#x ", reply->special_port.name);
4853 switch (MACH_ARG(task_get_special_port.which_port)) {
4854 case TASK_BOOTSTRAP_PORT:
4855 vg_bootstrap_port = reply->special_port.name;
4856 assign_port_name(reply->special_port.name, "bootstrap");
4858 case TASK_KERNEL_PORT:
4859 assign_port_name(reply->special_port.name, "kernel");
4861 case TASK_HOST_PORT:
4862 assign_port_name(reply->special_port.name, "host");
4864 case TASK_WIRED_LEDGER_PORT:
4865 assign_port_name(reply->special_port.name, "wired-ledger");
4867 case TASK_PAGED_LEDGER_PORT:
4868 assign_port_name(reply->special_port.name, "paged-ledger");
4871 assign_port_name(reply->special_port.name, "special-%p");
4875 PRINT("%s", name_for_port(reply->special_port.name));
4879 PRE(semaphore_create)
4883 mach_msg_header_t Head;
4890 Request *req = (Request *)ARG1;
4892 PRINT("semaphore_create(%s, ..., %d, %d)",
4893 name_for_port(MACH_REMOTE), req->policy, req->value);
4895 AFTER = POST_FN(semaphore_create);
4898 POST(semaphore_create)
4902 mach_msg_header_t Head;
4903 /* start of the kernel processed data */
4904 mach_msg_body_t msgh_body;
4905 mach_msg_port_descriptor_t semaphore;
4906 /* end of the kernel processed data */
4907 mach_msg_trailer_t trailer;
4911 Reply *reply = (Reply *)ARG1;
4913 assign_port_name(reply->semaphore.name, "semaphore-%p");
4914 PRINT("%s", name_for_port(reply->semaphore.name));
4918 PRE(semaphore_destroy)
4922 mach_msg_header_t Head;
4923 /* start of the kernel processed data */
4924 mach_msg_body_t msgh_body;
4925 mach_msg_port_descriptor_t semaphore;
4926 /* end of the kernel processed data */
4927 mach_msg_trailer_t trailer;
4931 Request *req = (Request *)ARG1;
4933 PRINT("semaphore_destroy(%s, %s)",
4934 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
4936 record_port_destroy(req->semaphore.name);
4938 AFTER = POST_FN(semaphore_destroy);
4941 POST(semaphore_destroy)
4945 mach_msg_header_t Head;
4947 kern_return_t RetCode;
4948 mach_msg_trailer_t trailer;
4952 Reply *reply = (Reply *)ARG1;
4953 if (!reply->RetCode) {
4955 PRINT("mig return %d", reply->RetCode);
4960 PRE(mach_ports_lookup)
4964 mach_msg_header_t Head;
4968 // Request *req = (Request *)ARG1;
4970 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
4972 AFTER = POST_FN(mach_ports_lookup);
4975 POST(mach_ports_lookup)
4979 mach_msg_header_t Head;
4980 /* start of the kernel processed data */
4981 mach_msg_body_t msgh_body;
4982 mach_msg_ool_ports_descriptor_t init_port_set;
4983 /* end of the kernel processed data */
4985 mach_msg_type_number_t init_port_setCnt;
4989 // Reply *reply = (Reply *)ARG1;
4997 mach_msg_header_t Head;
5001 // Request *req = (Request *)ARG1;
5003 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
5005 AFTER = POST_FN(task_threads);
5012 mach_msg_header_t Head;
5013 /* start of the kernel processed data */
5014 mach_msg_body_t msgh_body;
5015 mach_msg_ool_ports_descriptor_t act_list;
5016 /* end of the kernel processed data */
5018 mach_msg_type_number_t act_listCnt;
5019 mach_msg_trailer_t trailer;
5023 Reply *reply = (Reply *)ARG1;
5025 if (MACH_REMOTE == vg_task_port) {
5026 assign_port_names(&reply->act_list, "thread-%p");
5028 assign_port_names(&reply->act_list, "remote-thread-%p");
5035 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
5037 if (MACH_REMOTE == vg_task_port) {
5038 // GrP fixme self-suspend
5041 // suspend other - no problem
5044 AFTER = POST_FN(task_suspend);
5054 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
5056 if (MACH_REMOTE == vg_task_port) {
5057 // GrP fixme self-resume
5060 // resume other - no problem
5063 AFTER = POST_FN(task_resume);
5075 mach_msg_header_t Head;
5077 vm_address_t address;
5083 Request *req = (Request *)ARG1;
5085 PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
5086 name_for_port(MACH_REMOTE),
5087 (ULong)req->address, (ULong)req->size, req->flags);
5089 MACH_ARG(vm_allocate.size) = req->size;
5090 MACH_ARG(vm_allocate.flags) = req->flags;
5092 AFTER = POST_FN(vm_allocate);
5099 mach_msg_header_t Head;
5101 kern_return_t RetCode;
5102 vm_address_t address;
5103 mach_msg_trailer_t trailer;
5107 Reply *reply = (Reply *)ARG1;
5109 if (!reply->RetCode) {
5110 if (MACH_REMOTE == vg_task_port) {
5111 PRINT("allocated at %#llx", (ULong)reply->address);
5112 // requesting 0 bytes returns address 0 with no error
5113 if (MACH_ARG(vm_allocate.size)) {
5114 ML_(notify_core_and_tool_of_mmap)(
5115 reply->address, MACH_ARG(vm_allocate.size),
5116 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5119 PRINT("allocated at %#llx in remote task %s",
5120 (ULong)reply->address,
5121 name_for_port(MACH_REMOTE));
5124 PRINT("mig return %d", reply->RetCode);
5133 mach_msg_header_t Head;
5135 vm_address_t address;
5140 Request *req = (Request *)ARG1;
5142 PRINT("vm_deallocate(%s, at %#llx, size %lld)",
5143 name_for_port(MACH_REMOTE),
5144 (ULong)req->address, (ULong)req->size);
5146 MACH_ARG(vm_deallocate.address) = req->address;
5147 MACH_ARG(vm_deallocate.size) = req->size;
5149 AFTER = POST_FN(vm_deallocate);
5151 // Must block to prevent race (other thread allocates and
5152 // notifies after we deallocate but before we notify)
5153 *flags &= ~SfMayBlock;
5160 mach_msg_header_t Head;
5162 kern_return_t RetCode;
5163 mach_msg_trailer_t trailer;
5167 Reply *reply = (Reply *)ARG1;
5169 if (!reply->RetCode) {
5170 if (MACH_REMOTE == vg_task_port) {
5171 if (MACH_ARG(vm_deallocate.size)) {
5172 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
5173 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
5174 MACH_ARG(vm_deallocate.size));
5175 // Must have cleared SfMayBlock in PRE to prevent race
5176 ML_(notify_core_and_tool_of_munmap)(start, end - start);
5180 PRINT("mig return %d", reply->RetCode);
5189 mach_msg_header_t Head;
5191 vm_address_t address;
5193 boolean_t set_maximum;
5194 vm_prot_t new_protection;
5198 Request *req = (Request *)ARG1;
5200 PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
5201 name_for_port(MACH_REMOTE),
5202 (ULong)req->address, (ULong)req->size,
5203 req->set_maximum, req->new_protection);
5205 MACH_ARG(vm_protect.address) = req->address;
5206 MACH_ARG(vm_protect.size) = req->size;
5207 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
5208 MACH_ARG(vm_protect.new_protection) = req->new_protection;
5210 AFTER = POST_FN(vm_protect);
5217 mach_msg_header_t Head;
5219 kern_return_t RetCode;
5220 mach_msg_trailer_t trailer;
5224 Reply *reply = (Reply *)ARG1;
5226 if (!reply->RetCode) {
5227 if (MACH_REMOTE == vg_task_port) {
5228 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
5229 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
5230 MACH_ARG(vm_protect.size));
5231 UInt prot = MACH_ARG(vm_protect.new_protection);
5232 if (MACH_ARG(vm_protect.set_maximum)) {
5233 // GrP fixme mprotect max
5234 VG_(printf)("UNKNOWN vm_protect set maximum");
5235 //VG_(mprotect_max_range)(start, end-start, prot);
5237 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5241 PRINT("mig return %d", reply->RetCode);
5250 mach_msg_header_t Head;
5252 vm_address_t address;
5254 vm_inherit_t new_inheritance;
5258 Request *req = (Request *)ARG1;
5260 PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
5261 name_for_port(MACH_REMOTE),
5262 (ULong)req->address, (ULong)req->size,
5263 req->new_inheritance);
5265 AFTER = POST_FN(vm_inherit);
5272 mach_msg_header_t Head;
5274 kern_return_t RetCode;
5275 mach_msg_trailer_t trailer;
5279 Reply *reply = (Reply *)ARG1;
5281 if (!reply->RetCode) {
5282 if (MACH_REMOTE == vg_task_port) {
5283 // GrP fixme do something?
5286 PRINT("mig return %d", reply->RetCode);
5295 mach_msg_header_t Head;
5297 vm_address_t address;
5302 Request *req = (Request *)ARG1;
5304 PRINT("vm_read(from %s at %#llx size %llu)",
5305 name_for_port(MACH_REMOTE),
5306 (ULong)req->address, (ULong)req->size);
5308 MACH_ARG(vm_read.addr) = req->address;
5309 MACH_ARG(vm_read.size) = req->size;
5311 AFTER = POST_FN(vm_read);
5318 mach_msg_header_t Head;
5319 /* start of the kernel processed data */
5320 mach_msg_body_t msgh_body;
5321 mach_msg_ool_descriptor_t data;
5322 /* end of the kernel processed data */
5324 mach_msg_type_number_t dataCnt;
5328 // Reply *reply = (Reply *)ARG1;
5330 if (MACH_REMOTE == vg_task_port) {
5331 // vm_read from self
5332 // GrP fixme copy initialized state
5342 mach_msg_header_t Head;
5344 mach_vm_address_t address;
5345 mach_vm_size_t size;
5349 Request *req = (Request *)ARG1;
5351 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
5352 name_for_port(MACH_REMOTE), req->address, req->size);
5354 MACH_ARG(mach_vm_read.addr) = req->address;
5355 MACH_ARG(mach_vm_read.size) = req->size;
5357 AFTER = POST_FN(mach_vm_read);
5364 mach_msg_header_t Head;
5365 /* start of the kernel processed data */
5366 mach_msg_body_t msgh_body;
5367 mach_msg_ool_descriptor_t data;
5368 /* end of the kernel processed data */
5370 mach_msg_type_number_t dataCnt;
5374 // Reply *reply = (Reply *)ARG1;
5376 if (MACH_REMOTE == vg_task_port) {
5377 // vm_read from self
5378 // GrP fixme copy initialized state
5383 PRE(vm_read_overwrite)
5387 mach_msg_header_t Head;
5389 vm_address_t address;
5395 Request *req = (Request *)ARG1;
5397 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
5398 name_for_port(MACH_REMOTE),
5399 (ULong)req->address, (ULong)req->size, (ULong)req->data);
5401 MACH_ARG(vm_read_overwrite.addr) = req->address;
5402 MACH_ARG(vm_read_overwrite.size) = req->size;
5403 MACH_ARG(vm_read_overwrite.data) = req->data;
5405 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
5407 AFTER = POST_FN(vm_read_overwrite);
5410 POST(vm_read_overwrite)
5414 mach_msg_header_t Head;
5416 kern_return_t RetCode;
5421 Reply *reply = (Reply *)ARG1;
5423 if (reply->RetCode) {
5424 PRINT("mig return %d", reply->RetCode);
5426 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
5427 if (MACH_REMOTE == vg_task_port) {
5428 // vm_read_overwrite from self
5429 // GrP fixme copy initialized state
5430 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5432 // vm_read_overwrite from remote
5433 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5443 mach_msg_header_t Head;
5445 vm_address_t source_address;
5447 vm_address_t dest_address;
5451 Request *req = (Request *)ARG1;
5453 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
5454 name_for_port(MACH_REMOTE),
5455 (ULong)req->source_address,
5456 (ULong)req->size, (ULong)req->dest_address);
5458 MACH_ARG(vm_copy.src) = req->source_address;
5459 MACH_ARG(vm_copy.dst) = req->dest_address;
5460 MACH_ARG(vm_copy.size) = req->size;
5462 AFTER = POST_FN(vm_copy);
5469 mach_msg_header_t Head;
5471 kern_return_t RetCode;
5472 mach_msg_trailer_t trailer;
5476 Reply *reply = (Reply *)ARG1;
5478 if (!reply->RetCode) {
5479 if (MACH_REMOTE == vg_task_port) {
5480 // GrP fixme set dst's initialization equal to src's
5481 // and wipe any symbols or translations in dst
5484 PRINT("mig return %d", reply->RetCode);
5493 mach_msg_header_t Head;
5494 /* start of the kernel processed data */
5495 mach_msg_body_t msgh_body;
5496 mach_msg_port_descriptor_t object;
5497 /* end of the kernel processed data */
5499 vm_address_t address;
5505 vm_prot_t cur_protection;
5506 vm_prot_t max_protection;
5507 vm_inherit_t inheritance;
5511 Request *req = (Request *)ARG1;
5513 // GrP fixme check these
5514 PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)",
5515 name_for_port(MACH_REMOTE),
5516 (ULong)req->address, (ULong)req->size,
5517 name_for_port(req->object.name));
5519 MACH_ARG(vm_map.size) = req->size;
5520 MACH_ARG(vm_map.copy) = req->copy;
5521 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
5523 AFTER = POST_FN(vm_map);
5530 mach_msg_header_t Head;
5532 kern_return_t RetCode;
5533 vm_address_t address;
5534 mach_msg_trailer_t trailer;
5538 Reply *reply = (Reply *)ARG1;
5540 if (!reply->RetCode) {
5541 // GrP fixme check src and dest tasks
5542 PRINT("mapped at %#llx", (ULong)reply->address);
5543 // GrP fixme max prot
5544 ML_(notify_core_and_tool_of_mmap)(
5545 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
5546 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
5547 // GrP fixme VKI_MAP_PRIVATE if !copy?
5549 PRINT("mig return %d", reply->RetCode);
5558 mach_msg_header_t Head;
5559 /* start of the kernel processed data */
5560 mach_msg_body_t msgh_body;
5561 mach_msg_port_descriptor_t src_task;
5562 /* end of the kernel processed data */
5564 vm_address_t target_address;
5568 vm_address_t src_address;
5570 vm_inherit_t inheritance;
5574 Request *req = (Request *)ARG1;
5576 // GrP fixme check src and dest tasks
5578 if (VG_(clo_trace_syscalls)) {
5579 mach_port_name_t source_task = req->src_task.name;
5580 if (source_task == mach_task_self()) {
5581 PRINT("vm_remap(mach_task_self(), "
5582 "to %#llx size %lld, from mach_task_self() at %#llx, ...)",
5583 (ULong)req->target_address,
5584 (ULong)req->size, (ULong)req->src_address);
5586 PRINT("vm_remap(mach_task_self(), "
5587 "to %#llx size %lld, from task %u at %#llx, ...)",
5588 (ULong)req->target_address, (ULong)req->size,
5589 source_task, (ULong)req->src_address);
5594 // vt->syscall_arg2 = req->target_address;
5595 MACH_ARG(vm_remap.size) = req->size;
5596 // vt->syscall_arg4 = req->copy;
5598 AFTER = POST_FN(vm_remap);
5605 mach_msg_header_t Head;
5607 kern_return_t RetCode;
5608 vm_address_t target_address;
5609 vm_prot_t cur_protection;
5610 vm_prot_t max_protection;
5611 mach_msg_trailer_t trailer;
5615 Reply *reply = (Reply *)ARG1;
5617 if (!reply->RetCode) {
5618 // GrP fixme check src and dest tasks
5619 UInt prot = reply->cur_protection & reply->max_protection;
5620 // GrP fixme max prot
5621 PRINT("mapped at %#llx", (ULong)reply->target_address);
5622 ML_(notify_core_and_tool_of_mmap)(
5623 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
5624 prot, VKI_MAP_SHARED, -1, 0);
5625 // GrP fixme VKI_MAP_FIXED if !copy?
5626 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
5628 PRINT("mig return %d", reply->RetCode);
5633 PRE(mach_make_memory_entry_64)
5637 mach_msg_header_t Head;
5638 /* start of the kernel processed data */
5639 mach_msg_body_t msgh_body;
5640 mach_msg_port_descriptor_t parent_entry;
5641 /* end of the kernel processed data */
5643 memory_object_size_t size;
5644 memory_object_offset_t offset;
5645 vm_prot_t permission;
5649 Request *req = (Request *)ARG1;
5651 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
5652 name_for_port(MACH_REMOTE),
5653 req->size, req->offset, req->permission, req->parent_entry.type);
5655 AFTER = POST_FN(mach_make_memory_entry_64);
5658 POST(mach_make_memory_entry_64)
5662 mach_msg_header_t Head;
5663 mach_msg_body_t msgh_body;
5664 mach_msg_port_descriptor_t object;
5666 memory_object_size_t size;
5670 Reply *reply = (Reply *)ARG1;
5672 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
5673 assign_port_name(reply->object.name, "memory-%p");
5674 PRINT("%s", name_for_port(reply->object.name));
5679 PRE(vm_purgable_control)
5683 mach_msg_header_t Head;
5685 vm_address_t address;
5686 vm_purgable_t control;
5691 Request *req = (Request *)ARG1;
5693 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
5694 name_for_port(MACH_REMOTE),
5695 (ULong)req->address, req->control, req->state);
5697 // GrP fixme verify address?
5699 AFTER = POST_FN(vm_purgable_control);
5702 POST(vm_purgable_control)
5706 mach_msg_header_t Head;
5708 kern_return_t RetCode;
5713 Reply *reply = (Reply *)ARG1;
5715 if (!reply->RetCode) {
5717 PRINT("mig return %d", reply->RetCode);
5722 PRE(mach_vm_purgable_control)
5726 mach_msg_header_t Head;
5728 mach_vm_address_t address;
5729 vm_purgable_t control;
5734 Request *req = (Request *)ARG1;
5736 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
5737 name_for_port(MACH_REMOTE),
5738 (unsigned long long)req->address, req->control, req->state);
5740 // GrP fixme verify address?
5742 AFTER = POST_FN(mach_vm_purgable_control);
5745 POST(mach_vm_purgable_control)
5749 mach_msg_header_t Head;
5751 kern_return_t RetCode;
5756 Reply *reply = (Reply *)ARG1;
5758 if (!reply->RetCode) {
5760 PRINT("mig return %d", reply->RetCode);
5765 PRE(mach_vm_allocate)
5769 mach_msg_header_t Head;
5771 mach_vm_address_t address;
5772 mach_vm_size_t size;
5777 Request *req = (Request *)ARG1;
5779 PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
5780 name_for_port(MACH_REMOTE),
5781 req->address, req->size, req->flags);
5783 MACH_ARG(mach_vm_allocate.size) = req->size;
5784 MACH_ARG(mach_vm_allocate.flags) = req->flags;
5786 AFTER = POST_FN(mach_vm_allocate);
5789 POST(mach_vm_allocate)
5793 mach_msg_header_t Head;
5795 kern_return_t RetCode;
5796 mach_vm_address_t address;
5797 mach_msg_trailer_t trailer;
5801 Reply *reply = (Reply *)ARG1;
5803 if (!reply->RetCode) {
5804 if (MACH_REMOTE == vg_task_port) {
5805 PRINT("allocated at 0x%llx", reply->address);
5806 // requesting 0 bytes returns address 0 with no error
5807 if (MACH_ARG(mach_vm_allocate.size)) {
5808 ML_(notify_core_and_tool_of_mmap)(
5809 reply->address, MACH_ARG(mach_vm_allocate.size),
5810 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5813 PRINT("allocated at 0x%llx in remote task %s", reply->address,
5814 name_for_port(MACH_REMOTE));
5817 PRINT("mig return %d", reply->RetCode);
5822 PRE(mach_vm_deallocate)
5826 mach_msg_header_t Head;
5828 mach_vm_address_t address;
5829 mach_vm_size_t size;
5833 Request *req = (Request *)ARG1;
5835 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
5836 name_for_port(MACH_REMOTE),
5837 req->address, req->size);
5839 MACH_ARG(mach_vm_deallocate.address) = req->address;
5840 MACH_ARG(mach_vm_deallocate.size) = req->size;
5842 AFTER = POST_FN(mach_vm_deallocate);
5844 // Must block to prevent race (other thread allocates and
5845 // notifies after we deallocate but before we notify)
5846 *flags &= ~SfMayBlock;
5849 POST(mach_vm_deallocate)
5853 mach_msg_header_t Head;
5855 kern_return_t RetCode;
5856 mach_msg_trailer_t trailer;
5860 Reply *reply = (Reply *)ARG1;
5862 if (!reply->RetCode) {
5863 if (MACH_REMOTE == vg_task_port) {
5864 if (MACH_ARG(mach_vm_deallocate.size)) {
5865 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
5866 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
5867 MACH_ARG(mach_vm_deallocate.size));
5868 // Must have cleared SfMayBlock in PRE to prevent race
5869 ML_(notify_core_and_tool_of_munmap)(start, end - start);
5873 PRINT("mig return %d", reply->RetCode);
5878 PRE(mach_vm_protect)
5882 mach_msg_header_t Head;
5884 mach_vm_address_t address;
5885 mach_vm_size_t size;
5886 boolean_t set_maximum;
5887 vm_prot_t new_protection;
5891 Request *req = (Request *)ARG1;
5893 PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
5894 name_for_port(MACH_REMOTE), req->address, req->size,
5895 req->set_maximum, req->new_protection);
5897 MACH_ARG(mach_vm_protect.address) = req->address;
5898 MACH_ARG(mach_vm_protect.size) = req->size;
5899 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
5900 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
5902 AFTER = POST_FN(mach_vm_protect);
5905 POST(mach_vm_protect)
5909 mach_msg_header_t Head;
5911 kern_return_t RetCode;
5912 mach_msg_trailer_t trailer;
5916 Reply *reply = (Reply *)ARG1;
5918 if (!reply->RetCode) {
5919 if (MACH_REMOTE == vg_task_port) {
5920 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
5921 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
5922 MACH_ARG(mach_vm_protect.size));
5923 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
5924 if (MACH_ARG(mach_vm_protect.set_maximum)) {
5925 // DDD: #warning GrP fixme mprotect max
5926 //VG_(mprotect_max_range)(start, end-start, prot);
5928 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5932 PRINT("mig return %d", reply->RetCode);
5937 PRE(mach_vm_inherit)
5941 mach_msg_header_t Head;
5943 mach_vm_address_t address;
5944 mach_vm_size_t size;
5945 vm_inherit_t new_inheritance;
5949 Request *req = (Request *)ARG1;
5951 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
5952 name_for_port(MACH_REMOTE),
5953 req->address, req->size, req->new_inheritance);
5955 AFTER = POST_FN(mach_vm_inherit);
5958 POST(mach_vm_inherit)
5962 mach_msg_header_t Head;
5964 kern_return_t RetCode;
5965 mach_msg_trailer_t trailer;
5969 Reply *reply = (Reply *)ARG1;
5971 if (!reply->RetCode) {
5972 // no V-visible side effects
5973 // GrP fixme except maybe fork/exec
5975 PRINT("mig return %d", reply->RetCode);
5984 mach_msg_header_t Head;
5986 mach_vm_address_t source_address;
5987 mach_vm_size_t size;
5988 mach_vm_address_t dest_address;
5992 Request *req = (Request *)ARG1;
5994 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
5995 name_for_port(MACH_REMOTE),
5996 req->source_address, req->size, req->dest_address);
5999 // vt->syscall_arg2 = req->source_address;
6000 // vt->syscall_arg3 = req->size;
6001 // vt->syscall_arg4 = req->dest_address;
6003 AFTER = POST_FN(mach_vm_copy);
6010 mach_msg_header_t Head;
6012 kern_return_t RetCode;
6013 mach_msg_trailer_t trailer;
6017 Reply *reply = (Reply *)ARG1;
6019 if (!reply->RetCode) {
6020 if (MACH_REMOTE == vg_task_port) {
6021 // GrP fixme set dest's initialization equal to src's
6022 // BUT vm_copy allocates no memory
6025 PRINT("mig return %d", reply->RetCode);
6034 mach_msg_header_t Head;
6035 /* start of the kernel processed data */
6036 mach_msg_body_t msgh_body;
6037 mach_msg_port_descriptor_t object;
6038 /* end of the kernel processed data */
6040 mach_vm_address_t address;
6041 mach_vm_size_t size;
6042 mach_vm_address_t mask;
6044 memory_object_offset_t offset;
6046 vm_prot_t cur_protection;
6047 vm_prot_t max_protection;
6048 vm_inherit_t inheritance;
6052 Request *req = (Request *)ARG1;
6054 // GrP fixme check these
6055 PRINT("mach_vm_map(in %s, at 0x%llx, size %llu, from %s ...)",
6056 name_for_port(MACH_REMOTE),
6057 req->address, req->size,
6058 name_for_port(req->object.name));
6060 MACH_ARG(mach_vm_map.size) = req->size;
6061 MACH_ARG(mach_vm_map.copy) = req->copy;
6062 MACH_ARG(mach_vm_map.protection) =
6063 (req->cur_protection & req->max_protection);
6065 AFTER = POST_FN(mach_vm_map);
6072 mach_msg_header_t Head;
6074 kern_return_t RetCode;
6075 mach_vm_address_t address;
6076 mach_msg_trailer_t trailer;
6080 Reply *reply = (Reply *)ARG1;
6082 if (!reply->RetCode) {
6083 // GrP fixme check src and dest tasks
6084 PRINT("mapped at 0x%llx", reply->address);
6085 // GrP fixme max prot
6086 ML_(notify_core_and_tool_of_mmap)(
6087 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
6088 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
6089 // GrP fixme VKI_MAP_PRIVATE if !copy?
6091 PRINT("mig return %d", reply->RetCode);
6096 PRE(mach_vm_region_recurse)
6100 mach_msg_header_t Head;
6102 mach_vm_address_t address;
6103 natural_t nesting_depth;
6104 mach_msg_type_number_t infoCnt;
6108 Request *req = (Request *)ARG1;
6110 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
6111 name_for_port(MACH_REMOTE),
6112 req->address, req->nesting_depth, req->infoCnt);
6114 AFTER = POST_FN(mach_vm_region_recurse);
6117 POST(mach_vm_region_recurse)
6121 mach_msg_header_t Head;
6123 kern_return_t RetCode;
6124 mach_vm_address_t address;
6125 mach_vm_size_t size;
6126 natural_t nesting_depth;
6127 mach_msg_type_number_t infoCnt;
6132 Reply *reply = (Reply *)ARG1;
6134 if (!reply->RetCode) {
6135 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
6136 reply->address, reply->size,
6137 reply->nesting_depth, reply->infoCnt);
6138 // GrP fixme mark info contents beyond infoCnt as bogus
6140 PRINT("mig return %d", reply->RetCode);
6145 /* ---------------------------------------------------------------------
6146 mach_msg: messages to thread
6147 ------------------------------------------------------------------ */
6151 POST(thread_terminate)
6156 PRE(thread_terminate)
6158 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6159 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
6161 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
6163 AFTER = POST_FN(thread_terminate);
6165 if (self_terminate) {
6166 // Terminating this thread.
6167 // Copied from sys_exit.
6168 ThreadState *tst = VG_(get_ThreadState)(tid);
6169 tst->exitreason = VgSrc_ExitThread;
6170 tst->os_state.exitcode = 0; // GrP fixme anything better?
6171 // What we would like to do is:
6172 // SET_STATUS_Success(0);
6173 // but that doesn't work, because this is a MACH-class syscall,
6174 // and SET_STATUS_Success creates a UNIX-class syscall result.
6175 // Hence we have to laboriously construct the full SysRes "by hand"
6176 // and use that to set the syscall return status.
6177 SET_STATUS_from_SysRes(
6178 VG_(mk_SysRes_x86_darwin)(
6179 VG_DARWIN_SYSCALL_CLASS_MACH,
6180 False/*success*/, 0, 0
6183 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
6185 // Terminating some other thread.
6186 // Do keep the scheduler lock while terminating any other thread.
6187 // Otherwise we might halt the other thread while it holds the lock,
6188 // which would deadlock the process.
6189 // GrP fixme good enough?
6190 // GrP fixme need to clean up other thread's valgrind data?
6202 PRINT("thread_create(mach_task_self(), ...)");
6204 AFTER = POST_FN(thread_create);
6207 VG_(core_panic)("thread_create() unimplemented");
6211 PRE(thread_create_running)
6215 mach_msg_header_t Head;
6217 thread_state_flavor_t flavor;
6218 mach_msg_type_number_t new_stateCnt;
6219 natural_t new_state[144];
6224 thread_state_t regs;
6225 ThreadState *new_thread;
6227 PRINT("thread_create_running(mach_task_self(), ...)");
6229 // The new thread will immediately begin execution,
6230 // so we need to hijack the register state here.
6232 req = (Request *)ARG1;
6233 regs = (thread_state_t)req->new_state;
6235 // Build virtual thread.
6236 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
6238 // Edit the thread state to send to the real kernel.
6239 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
6241 AFTER = POST_FN(thread_create_running);
6245 POST(thread_create_running)
6249 mach_msg_header_t Head;
6250 /* start of the kernel processed data */
6251 mach_msg_body_t msgh_body;
6252 mach_msg_port_descriptor_t child_act;
6253 /* end of the kernel processed data */
6257 Reply *reply = (Reply *)ARG1;
6259 assign_port_name(reply->child_act.name, "thread-%p");
6260 PRINT("%s", name_for_port(reply->child_act.name));
6264 PRE(bsdthread_create)
6268 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
6269 ARG1, ARG2, ARG3, ARG4, ARG5);
6270 PRE_REG_READ5(pthread_t,"bsdthread_create",
6271 void *,"func", void *,"func_arg", void *,"stack",
6272 pthread_t,"thread", unsigned int,"flags");
6274 // The kernel will call V's pthread_hijack() to launch the thread.
6275 // Here we allocate the thread state and pass it to pthread_hijack()
6276 // via the func_arg parameter.
6278 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
6279 allocstack(tst->tid);
6281 tst->os_state.func_arg = (Addr)ARG2;
6284 // Create a semaphore that pthread_hijack will signal once it starts
6285 // POST(bsdthread_create) needs to wait for the new memory map to appear
6286 semaphore_create(mach_task_self(), &tst->os_state.child_go,
6287 SYNC_POLICY_FIFO, 0);
6288 semaphore_create(mach_task_self(), &tst->os_state.child_done,
6289 SYNC_POLICY_FIFO, 0);
6292 POST(bsdthread_create)
6294 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
6295 // We hold V's lock on the child's behalf.
6296 // If we return before letting pthread_hijack do its thing, V thinks
6297 // the new pthread struct is still unmapped when we return to libc,
6298 // causing false errors.
6300 ThreadState *tst = (ThreadState *)ARG2;
6301 semaphore_signal(tst->os_state.child_go);
6302 semaphore_wait(tst->os_state.child_done);
6303 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
6304 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
6306 // GrP fixme semaphore destroy needed when thread creation fails
6307 // GrP fixme probably other cleanup too
6308 // GrP fixme spinlocks might be good enough?
6310 // DDD: I'm not at all sure this is the right spot for this. It probably
6311 // should be in pthread_hijack instead, just before the call to
6312 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
6313 // parent tid value there...
6314 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
6318 PRE(bsdthread_terminate)
6322 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
6323 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
6324 PRE_REG_READ4(int,"bsdthread_terminate",
6325 void *,"freeaddr", size_t,"freesize",
6326 mach_port_t,"kport", mach_port_t,"joinsem");
6328 // Free memory and signal semaphore.
6329 // GrP fixme errors?
6330 if (ARG4) semaphore_signal((semaphore_t)ARG4);
6332 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
6333 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
6336 // Tell V to terminate the thread.
6337 // Copied from sys_exit.
6338 tst = VG_(get_ThreadState)(tid);
6339 tst->exitreason = VgSrc_ExitThread;
6340 tst->os_state.exitcode = 0; // GrP fixme anything better?
6341 SET_STATUS_Success(0);
6345 POST(thread_suspend)
6351 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6352 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
6354 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
6356 AFTER = POST_FN(thread_suspend);
6359 // Don't keep the scheduler lock while self-suspending.
6360 // Otherwise we might halt while still holding the lock,
6361 // which would deadlock the process.
6362 *flags |= SfMayBlock;
6364 // Do keep the scheduler lock while suspending any other thread.
6365 // Otherwise we might halt the other thread while it holds the lock,
6366 // which would deadlock the process.
6371 POST(thread_get_state)
6375 mach_msg_header_t Head;
6377 kern_return_t RetCode;
6378 mach_msg_type_number_t old_stateCnt;
6379 natural_t old_state[144];
6380 mach_msg_trailer_t trailer;
6384 Reply *reply = (Reply *)ARG1;
6385 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
6386 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
6388 if (!reply->RetCode) {
6389 thread_state_from_vex((thread_state_t)reply->old_state,
6390 flavor, reply->old_stateCnt,
6391 &VG_(get_ThreadState)(tid)->arch.vex);
6393 PRINT("mig return %d", reply->RetCode);
6397 PRE(thread_get_state)
6401 mach_msg_header_t Head;
6403 thread_state_flavor_t flavor;
6404 mach_msg_type_number_t old_stateCnt;
6408 Request *req = (Request *)ARG1;
6409 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
6411 // GrP fixme if (self) {
6412 PRINT("thread_get_state(%s, %d)",
6413 name_for_port(req->Head.msgh_request_port), req->flavor);
6415 PRINT("thread_get_state(0x%x, %d)",
6416 req->Head.msgh_request_port, req->flavor);
6419 // Hack the thread state after making the real call.
6420 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
6421 MACH_ARG(thread_get_state.flavor) = req->flavor;
6423 AFTER = POST_FN(thread_get_state);
6429 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6430 // Bool self = (mh->msgh_request_port == MACH_THREAD);
6432 // GrP fixme if (self) {
6433 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
6435 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
6438 AFTER = POST_FN(thread_policy);
6446 PRE(thread_policy_set)
6448 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6450 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
6452 AFTER = POST_FN(thread_policy_set);
6455 POST(thread_policy_set)
6462 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6464 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
6465 // GrP fixme does any thread info need to be hijacked?
6467 AFTER = POST_FN(thread_info);
6472 // GrP fixme mark unused parts of thread_info_out as uninitialized?
6477 /* ---------------------------------------------------------------------
6478 mach_msg: messages to bootstrap port
6479 ------------------------------------------------------------------ */
6482 POST(bootstrap_register)
6486 mach_msg_header_t Head;
6488 kern_return_t RetCode;
6489 mach_msg_trailer_t trailer;
6493 Reply *reply = (Reply *)ARG1;
6495 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
6498 PRE(bootstrap_register)
6502 mach_msg_header_t Head;
6503 /* start of the kernel processed data */
6504 mach_msg_body_t msgh_body;
6505 mach_msg_port_descriptor_t service_port;
6506 /* end of the kernel processed data */
6508 name_t service_name;
6512 Request *req = (Request *)ARG1;
6514 PRINT("bootstrap_register(port 0x%x, \"%s\")",
6515 req->service_port.name, req->service_name);
6517 assign_port_name(req->service_port.name, req->service_name);
6519 AFTER = POST_FN(bootstrap_register);
6523 POST(bootstrap_look_up)
6527 mach_msg_header_t Head;
6528 /* start of the kernel processed data */
6529 mach_msg_body_t msgh_body;
6530 mach_msg_port_descriptor_t service_port;
6531 /* end of the kernel processed data */
6532 mach_msg_trailer_t trailer;
6536 Reply *reply = (Reply *)ARG1;
6538 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
6539 reply->service_port.name)
6541 assign_port_name(reply->service_port.name,
6542 MACH_ARG(bootstrap_look_up.service_name));
6543 PRINT("%s", name_for_port(reply->service_port.name));
6547 VG_(arena_free)(VG_AR_CORE, MACH_ARG(bootstrap_look_up.service_name));
6550 PRE(bootstrap_look_up)
6554 mach_msg_header_t Head;
6556 name_t service_name;
6560 Request *req = (Request *)ARG1;
6562 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
6564 MACH_ARG(bootstrap_look_up.service_name) =
6565 VG_(arena_strdup)(VG_AR_CORE, "syswrap-darwin.bootstrap-name",
6568 AFTER = POST_FN(bootstrap_look_up);
6572 /* ---------------------------------------------------------------------
6573 mach_msg: receiver-specific handlers
6574 ------------------------------------------------------------------ */
6577 POST(mach_msg_receive)
6579 // mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6581 // GrP fixme don't know of anything interesting here currently
6582 // import_complex_message handles everything
6583 // PRINT("UNHANDLED reply %d", mh->msgh_id);
6585 // Assume the call may have mapped or unmapped memory
6586 ML_(sync_mappings)("after", "mach_msg_receive", 0);
6589 PRE(mach_msg_receive)
6591 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6593 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
6595 AFTER = POST_FN(mach_msg_receive);
6597 // no message sent, only listening for a reply
6598 // assume message may block
6599 *flags |= SfMayBlock;
6603 PRE(mach_msg_bootstrap)
6605 // message to bootstrap port
6607 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6609 switch (mh->msgh_id) {
6611 CALL_PRE(bootstrap_register);
6614 CALL_PRE(bootstrap_look_up);
6618 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
6619 mh->msgh_id, name_for_port(mh->msgh_request_port),
6620 mh->msgh_reply_port);
6628 // message to host self - check for host-level kernel calls
6630 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6632 switch (mh->msgh_id) {
6634 CALL_PRE(host_info);
6637 CALL_PRE(host_page_size);
6640 CALL_PRE(host_get_io_master);
6643 CALL_PRE(host_get_clock_service);
6646 CALL_PRE(host_request_notification);
6650 // unknown message to host self
6651 VG_(printf)("UNKNOWN host message [id %d, to %s, reply 0x%x]\n",
6652 mh->msgh_id, name_for_port(mh->msgh_request_port),
6653 mh->msgh_reply_port);
6660 // message to a task port
6662 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6664 switch (mh->msgh_id) {
6666 CALL_PRE(mach_port_type);
6669 CALL_PRE(mach_port_allocate);
6672 CALL_PRE(mach_port_destroy);
6675 CALL_PRE(mach_port_deallocate);
6678 CALL_PRE(mach_port_get_refs);
6681 CALL_PRE(mach_port_mod_refs);
6684 CALL_PRE(mach_port_get_set_status);
6687 CALL_PRE(mach_port_move_member);
6690 CALL_PRE(mach_port_request_notification);
6693 CALL_PRE(mach_port_insert_right);
6696 CALL_PRE(mach_port_extract_right);
6699 CALL_PRE(mach_port_get_attributes);
6702 CALL_PRE(mach_port_set_attributes);
6705 CALL_PRE(mach_port_insert_member);
6708 CALL_PRE(mach_port_extract_member);
6712 CALL_PRE(task_threads);
6715 CALL_PRE(mach_ports_lookup);
6719 CALL_PRE(task_suspend);
6722 CALL_PRE(task_resume);
6726 CALL_PRE(task_get_special_port);
6729 CALL_PRE(thread_create);
6732 CALL_PRE(thread_create_running);
6736 CALL_PRE(semaphore_create);
6739 CALL_PRE(semaphore_destroy);
6743 CALL_PRE(vm_allocate);
6746 CALL_PRE(vm_deallocate);
6749 CALL_PRE(vm_protect);
6752 CALL_PRE(vm_inherit);
6761 CALL_PRE(vm_read_overwrite);
6770 CALL_PRE(mach_make_memory_entry_64);
6773 CALL_PRE(vm_purgable_control);
6777 CALL_PRE(mach_vm_allocate);
6780 CALL_PRE(mach_vm_deallocate);
6783 CALL_PRE(mach_vm_protect);
6786 CALL_PRE(mach_vm_inherit);
6789 CALL_PRE(mach_vm_read);
6792 CALL_PRE(mach_vm_copy);
6795 CALL_PRE(mach_vm_map);
6798 CALL_PRE(mach_vm_region_recurse);
6801 CALL_PRE(mach_make_memory_entry_64);
6804 CALL_PRE(mach_vm_purgable_control);
6808 // unknown message to task self
6809 VG_(printf)("UNKNOWN task message [id %d, to %s, reply 0x%x]\n",
6810 mh->msgh_id, name_for_port(mh->msgh_remote_port),
6811 mh->msgh_reply_port);
6817 PRE(mach_msg_thread)
6819 // message to local thread - check for thread-level kernel calls
6821 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6823 switch (mh->msgh_id) {
6825 CALL_PRE(thread_terminate);
6828 CALL_PRE(thread_get_state);
6831 CALL_PRE(thread_suspend);
6834 CALL_PRE(thread_info);
6837 CALL_PRE(thread_policy);
6840 CALL_PRE(thread_policy_set);
6843 // unknown message to a thread
6844 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
6845 mh->msgh_id, name_for_port(mh->msgh_request_port),
6846 mh->msgh_reply_port);
6852 static int is_thread_port(mach_port_t port)
6854 if (port == 0) return False;
6856 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
6860 static int is_task_port(mach_port_t port)
6862 if (port == 0) return False;
6864 if (port == vg_task_port) return True;
6866 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
6870 /* ---------------------------------------------------------------------
6871 mach_msg: base handlers
6872 ------------------------------------------------------------------ */
6876 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6877 mach_msg_option_t option = (mach_msg_option_t)ARG2;
6878 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
6879 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
6880 // mach_port_t rcv_name = (mach_port_t)ARG5;
6881 size_t complex_header_size = 0;
6883 PRE_REG_READ7(long, "mach_msg",
6884 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
6885 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
6886 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
6887 mach_port_t,"notify");
6889 // Assume default POST handler until specified otherwise
6892 // Assume call may block unless specified otherwise
6893 *flags |= SfMayBlock;
6895 if (option & MACH_SEND_MSG) {
6896 // Validate outgoing message header
6897 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
6898 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
6899 // msgh_size not required, use parameter instead
6900 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
6901 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
6902 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
6903 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
6904 // msgh_reserved not required
6905 PRE_MEM_READ("mach_msg(msg.msgh_id)",
6906 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
6908 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6909 // Validate typed message data and handle memory map changes.
6910 complex_header_size = export_complex_message(tid, mh);
6913 // GrP fixme handle sender-specified message trailer
6914 // (but is this only for too-secure processes?)
6915 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
6917 MACH_REMOTE = mh->msgh_remote_port;
6918 MACH_MSGH_ID = mh->msgh_id;
6921 if (option & MACH_RCV_MSG) {
6922 // Pre-validate receive buffer
6923 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
6926 // Call a PRE handler. The PRE handler may set an AFTER handler.
6928 if (!(option & MACH_SEND_MSG)) {
6929 // no message sent, receive only
6930 CALL_PRE(mach_msg_receive);
6933 else if (mh->msgh_request_port == vg_host_port) {
6934 // message sent to mach_host_self()
6935 CALL_PRE(mach_msg_host);
6938 else if (is_task_port(mh->msgh_request_port)) {
6939 // message sent to a task
6940 CALL_PRE(mach_msg_task);
6943 else if (mh->msgh_request_port == vg_bootstrap_port) {
6944 // message sent to bootstrap port
6945 CALL_PRE(mach_msg_bootstrap);
6948 else if (is_thread_port(mh->msgh_request_port)) {
6949 // message sent to one of this process's threads
6950 CALL_PRE(mach_msg_thread);
6954 // arbitrary message to arbitrary port
6955 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
6956 mh->msgh_id, name_for_port(mh->msgh_request_port),
6957 mh->msgh_reply_port);
6959 AFTER = POST_FN(mach_msg_unhandled);
6961 // Assume the entire message body may be read.
6962 // GrP fixme generates false positives for unknown protocols
6964 PRE_MEM_READ("mach_msg(payload)",
6965 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
6966 send_size - sizeof(mach_msg_header_t) - complex_header_size);
6974 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6975 mach_msg_option_t option = (mach_msg_option_t)ARG2;
6977 if (option & MACH_RCV_MSG) {
6979 // error during send or receive
6980 // GrP fixme need to clean up port rights?
6982 mach_msg_trailer_t *mt =
6983 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
6985 // Assume the entire received message and trailer is initialized
6986 // GrP fixme would being more specific catch any bugs?
6987 POST_MEM_WRITE((Addr)mh,
6988 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
6990 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6991 // Update memory map for out-of-line message data
6992 import_complex_message(tid, mh);
6997 // Call handler chosen by PRE(mach_msg)
6999 (*AFTER)(tid, arrghs, status);
7004 POST(mach_msg_unhandled)
7006 ML_(sync_mappings)("after", "mach_msg_receive (unhandled)", 0);
7010 /* ---------------------------------------------------------------------
7012 ------------------------------------------------------------------ */
7014 PRE(mach_reply_port)
7016 PRINT("mach_reply_port()");
7019 POST(mach_reply_port)
7021 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
7022 PRINT("reply port %s", name_for_port(RES));
7026 PRE(mach_thread_self)
7028 PRINT("mach_thread_self()");
7031 POST(mach_thread_self)
7033 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
7034 PRINT("thread %#lx", RES);
7040 PRINT("mach_host_self()");
7043 POST(mach_host_self)
7046 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
7047 PRINT("host %#lx", RES);
7053 PRINT("mach_task_self()");
7056 POST(mach_task_self)
7059 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
7060 PRINT("task %#lx", RES);
7064 PRE(syscall_thread_switch)
7066 PRINT("syscall_thread_switch(%s, %ld, %ld)",
7067 name_for_port(ARG1), ARG2, ARG3);
7068 PRE_REG_READ3(long, "syscall_thread_switch",
7069 mach_port_t,"thread", int,"option", natural_t,"timeout");
7071 *flags |= SfMayBlock;
7075 PRE(semaphore_signal)
7077 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
7078 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7082 PRE(semaphore_signal_all)
7084 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
7085 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
7089 PRE(semaphore_signal_thread)
7091 PRINT("semaphore_signal_thread(%s, %s)",
7092 name_for_port(ARG1), name_for_port(ARG2));
7093 PRE_REG_READ2(long, "semaphore_signal_thread",
7094 semaphore_t,"semaphore", mach_port_t,"thread");
7100 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
7101 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7103 *flags |= SfMayBlock;
7107 PRE(semaphore_wait_signal)
7109 PRINT("semaphore_wait_signal(%s, %s)",
7110 name_for_port(ARG1), name_for_port(ARG2));
7111 PRE_REG_READ2(long, "semaphore_wait_signal",
7112 semaphore_t,"wait_semaphore",
7113 semaphore_t,"signal_semaphore");
7115 *flags |= SfMayBlock;
7119 PRE(semaphore_timedwait)
7121 PRINT("semaphore_timedwait(%s, %g seconds)",
7122 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
7123 PRE_REG_READ3(long, "semaphore_wait_signal",
7124 semaphore_t,"semaphore",
7126 int,"wait_time_lo");
7128 *flags |= SfMayBlock;
7132 PRE(semaphore_timedwait_signal)
7134 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
7135 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
7136 PRE_REG_READ4(long, "semaphore_wait_signal",
7137 semaphore_t,"wait_semaphore",
7138 semaphore_t,"signal_semaphore",
7140 int,"wait_time_lo");
7142 *flags |= SfMayBlock;
7146 PRE(__semwait_signal)
7148 /* 10.5 args: int cond_sem, int mutex_sem,
7149 int timeout, int relative,
7150 time_t tv_sec, time_t tv_nsec */
7151 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
7152 name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
7153 PRE_REG_READ6(long, "__semwait_signal",
7154 int,"cond_sem", int,"mutex_sem",
7155 int,"timeout", int,"relative",
7156 vki_time_t,"tv_sec", int,"tv_nsec");
7158 *flags |= SfMayBlock;
7160 // GrP provided this alternative version for 10.6, but NjN
7161 // reckons the 10.5 is is still correct for 10.6. So, retaining
7162 // Greg's version as a comment just in case we need it later.
7163 //PRE(__semwait_signal)
7165 // /* 10.5 args: int cond_sem, int mutex_sem,
7166 // int timeout, int relative,
7167 // const timespec *ts */
7168 // PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
7169 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
7170 // PRE_REG_READ5(int, "__semwait_signal",
7171 // int,cond_sem, int,mutex_sem,
7172 // int,timeout, int,relative,
7173 // const struct vki_timespec *,ts);
7175 // if (ARG5) PRE_MEM_READ ("__semwait_signal(ts)",
7176 // ARG5, sizeof(struct vki_timespec));
7178 // *flags |= SfMayBlock;
7182 PRE(__thread_selfid)
7184 PRINT("__thread_selfid ()");
7185 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
7190 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
7191 PRE_REG_READ3(long, "task_for_pid",
7192 mach_port_t,"target",
7193 vki_pid_t, "pid", mach_port_t *,"task");
7194 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
7201 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
7203 task = *(mach_port_t *)ARG3;
7204 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
7205 PRINT("task 0x%x", task);
7211 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
7212 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
7213 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
7220 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
7222 pid = *(vki_pid_t *)ARG2;
7223 PRINT("pid %u", pid);
7227 PRE(mach_timebase_info)
7229 PRINT("mach_timebase_info(%#lx)", ARG1);
7230 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
7231 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
7234 POST(mach_timebase_info)
7236 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
7240 PRE(mach_wait_until)
7242 #if VG_WORDSIZE == 8
7243 PRINT("mach_wait_until(%lu)", ARG1);
7244 PRE_REG_READ1(long, "mach_wait_until",
7245 unsigned long long,"deadline");
7247 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
7248 PRE_REG_READ2(long, "mach_wait_until",
7249 int,"deadline_hi", int,"deadline_lo");
7251 *flags |= SfMayBlock;
7255 PRE(mk_timer_create)
7257 PRINT("mk_timer_create()");
7258 PRE_REG_READ0(long, "mk_timer_create");
7261 POST(mk_timer_create)
7263 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
7267 PRE(mk_timer_destroy)
7269 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
7270 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
7272 // Must block to prevent race (other thread allocates and
7273 // notifies after we deallocate but before we notify)
7274 *flags &= ~SfMayBlock;
7277 POST(mk_timer_destroy)
7279 // Must have cleared SfMayBlock in PRE to prevent race
7280 record_port_destroy(ARG1);
7286 #if VG_WORDSIZE == 8
7287 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
7288 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
7289 unsigned long,"expire_time");
7291 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
7292 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
7293 int,"expire_time_hi", int,"expire_time_lo");
7298 PRE(mk_timer_cancel)
7300 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
7301 PRE_REG_READ2(long, "mk_timer_cancel",
7302 mach_port_t,"name", Addr,"result_time");
7304 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
7308 POST(mk_timer_cancel)
7311 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
7316 PRE(iokit_user_client_trap)
7318 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
7319 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
7320 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
7321 mach_port_t,connect, unsigned int,index,
7322 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
7323 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
7325 // can't do anything else with this in general
7326 // might be able to use connect+index to choose something sometimes
7329 POST(iokit_user_client_trap)
7331 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
7338 PRE_REG_READ0(long, "swtch");
7340 *flags |= SfMayBlock;
7346 PRINT("swtch_pri ( %ld )", ARG1);
7347 PRE_REG_READ1(long, "swtch_pri", int,"pri");
7349 *flags |= SfMayBlock;
7355 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
7356 an explanation of what follows. */
7357 /* This handles the fake signal-return system call created by
7358 sigframe-x86-darwin.c. */
7359 /* See also comments just below on PRE(sigreturn). */
7361 PRINT("FAKE_SIGRETURN ( )");
7363 vg_assert(VG_(is_valid_tid)(tid));
7364 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7365 vg_assert(VG_(is_running_thread)(tid));
7367 /* Remove the signal frame from this thread's (guest) stack,
7368 in the process restoring the pre-signal guest state. */
7369 VG_(sigframe_destroy)(tid, True);
7371 /* Tell the driver not to update the guest state with the "result",
7372 and set a bogus result to keep it happy. */
7373 *flags |= SfNoWriteResult;
7374 SET_STATUS_Success(0);
7376 /* Check to see if any signals arose as a result of this. */
7377 *flags |= SfPollAfter;
7383 /* This is the "real" sigreturn. But because we construct all the
7384 signal frames ourselves (of course, in m_sigframe), this cannot
7385 happen as a result of normal signal delivery. I think it
7386 happens only when doing siglongjmp, in which case Darwin's Libc
7387 appears to use it for two different purposes: to mess with the
7388 per-thread sigaltstack flags (as per arg 2), or to restore the
7389 thread's state from a ucontext* (as per arg 1). */
7391 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
7393 vg_assert(VG_(is_valid_tid)(tid));
7394 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7395 vg_assert(VG_(is_running_thread)(tid));
7397 if (ARG2 == VKI_UC_SET_ALT_STACK) {
7398 /* This is confusing .. the darwin kernel sources imply there is
7399 a per-thread on-altstack/not-on-altstack flag, which is set
7400 by this flag. Just ignore it and claim success for the time
7402 VG_(debugLog)(0, "syswrap-darwin",
7403 "WARNING: Ignoring sigreturn( ..., "
7404 "UC_SET_ALT_STACK );\n");
7405 SET_STATUS_Success(0);
7408 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
7410 VG_(debugLog)(0, "syswrap-darwin",
7411 "WARNING: Ignoring sigreturn( ..., "
7412 "UC_RESET_ALT_STACK );\n");
7413 SET_STATUS_Success(0);
7417 /* Otherwise claim this isn't supported. (Could be
7420 What do we have to do if we do need to support it?
7422 1. Change the second argument of VG_(sigframe_destroy) from
7423 "Bool isRT" to "UInt sysno", so we can pass the syscall
7424 number, so it can distinguish this case from the
7425 __NR_DARWIN_FAKE_SIGRETURN case.
7427 2. In VG_(sigframe_destroy), look at sysno to distinguish the
7428 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
7429 For this case, restore the thread's CPU state (or at least
7430 the integer regs) from the ucontext in ARG1 (and do all the
7431 other "signal-returns" stuff too).
7433 3. For (2), how do we know where the ucontext is? One way is to
7434 temporarily copy ARG1 into this thread's guest_EBX (or any
7435 other int reg), and have VG_(sigframe_destroy) read
7436 guest_EBX. Why is it ok to trash guest_EBX (or any other int
7437 reg)? Because VG_(sigframe_destroy) is just about to
7438 overwrite all the regs anyway -- since the primary purpose of
7439 calling it is to restore the register state from the ucontext
7442 Hey, it's uggerly. But at least it's documented.
7444 /* But in the meantime ... */
7445 VG_(debugLog)(0, "syswrap-darwin",
7446 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
7447 VG_(debugLog)(0, "syswrap-darwin",
7448 "WARNING: Thread/program/Valgrind "
7449 "will likely segfault now.\n");
7450 VG_(debugLog)(0, "syswrap-darwin",
7451 "WARNING: Please file a bug report at "
7452 "http://www.valgrind.org.\n");
7453 SET_STATUS_Failure( VKI_ENOSYS );
7457 /* ---------------------------------------------------------------------
7458 machine-dependent traps
7459 ------------------------------------------------------------------ */
7461 #if defined(VGA_x86)
7462 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
7464 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
7465 return VG_(arena_calloc)(VG_AR_CORE, "syswrap-darwin.ldt", nbytes, 1);
7469 PRE(thread_fast_set_cthread_self)
7471 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
7472 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
7474 #if defined(VGA_x86)
7475 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
7477 VexGuestX86SegDescr *ldt;
7478 ThreadState *tst = VG_(get_ThreadState)(tid);
7479 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
7481 ldt = alloc_zeroed_x86_LDT();
7482 tst->arch.vex.guest_LDT = (HWord)ldt;
7484 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
7485 ldt[6].LdtEnt.Bits.LimitLow = 1;
7486 ldt[6].LdtEnt.Bits.LimitHi = 0;
7487 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
7488 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
7489 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
7490 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
7491 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
7492 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
7493 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
7494 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
7496 tst->os_state.pthread = ARG1;
7497 tst->arch.vex.guest_GS = 0x37;
7499 // What we would like to do is:
7500 // SET_STATUS_Success(0x37);
7501 // but that doesn't work, because this is a MDEP-class syscall,
7502 // and SET_STATUS_Success creates a UNIX-class syscall result.
7503 // Hence we have to laboriously construct the full SysRes "by hand"
7504 // and use that to set the syscall return status.
7505 SET_STATUS_from_SysRes(
7506 VG_(mk_SysRes_x86_darwin)(
7507 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7513 #elif defined(VGA_amd64)
7514 // GrP fixme bigger hack than x86
7516 ThreadState *tst = VG_(get_ThreadState)(tid);
7517 tst->os_state.pthread = ARG1;
7518 tst->arch.vex.guest_GS_0x60 = ARG1;
7519 // SET_STATUS_Success(0x60);
7520 // see comments on x86 case just above
7521 SET_STATUS_from_SysRes(
7522 VG_(mk_SysRes_amd64_darwin)(
7523 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7530 #error unknown architecture
7535 /* ---------------------------------------------------------------------
7537 ------------------------------------------------------------------ */
7539 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
7540 #define MACX_(sysno, name) WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7541 #define MACXY(sysno, name) WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7542 #define _____(sysno) GENX_(sysno, sys_ni_syscall)
7545 _____ : unsupported by the kernel (sys_ni_syscall)
7546 // _____ : unimplemented in valgrind
7547 GEN : handlers are in syswrap-generic.c
7548 MAC : handlers are in this file
7549 X_ : PRE handler only
7550 XY : PRE and POST handlers
7552 const SyscallTableEntry ML_(syscall_table)[] = {
7553 // _____(__NR_syscall), // 0
7554 MACX_(__NR_exit, exit),
7555 GENX_(__NR_fork, sys_fork),
7556 GENXY(__NR_read, sys_read),
7557 GENX_(__NR_write, sys_write),
7558 GENXY(__NR_open, sys_open),
7559 GENXY(__NR_close, sys_close),
7560 GENXY(__NR_wait4, sys_wait4),
7561 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
7562 GENX_(__NR_link, sys_link),
7563 GENX_(__NR_unlink, sys_unlink),
7564 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
7565 GENX_(__NR_chdir, sys_chdir),
7566 GENX_(__NR_fchdir, sys_fchdir),
7567 GENX_(__NR_mknod, sys_mknod),
7568 GENX_(__NR_chmod, sys_chmod),
7569 GENX_(__NR_chown, sys_chown),
7570 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
7571 MACXY(__NR_getfsstat, getfsstat),
7572 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
7573 GENX_(__NR_getpid, sys_getpid), // 20
7574 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
7575 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
7576 GENX_(__NR_setuid, sys_setuid),
7577 GENX_(__NR_getuid, sys_getuid),
7578 GENX_(__NR_geteuid, sys_geteuid),
7579 MACX_(__NR_ptrace, ptrace),
7580 MACXY(__NR_recvmsg, recvmsg),
7581 MACX_(__NR_sendmsg, sendmsg),
7582 MACXY(__NR_recvfrom, recvfrom),
7583 MACXY(__NR_accept, accept),
7584 MACXY(__NR_getpeername, getpeername),
7585 MACXY(__NR_getsockname, getsockname),
7586 GENX_(__NR_access, sys_access),
7587 MACX_(__NR_chflags, chflags),
7588 MACX_(__NR_fchflags, fchflags),
7589 GENX_(__NR_sync, sys_sync),
7590 GENX_(__NR_kill, sys_kill),
7591 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
7592 GENX_(__NR_getppid, sys_getppid),
7593 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
7594 GENXY(__NR_dup, sys_dup),
7595 MACXY(__NR_pipe, pipe),
7596 GENX_(__NR_getegid, sys_getegid),
7597 // _____(__NR_profil),
7598 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
7599 MACXY(__NR_sigaction, sigaction),
7600 GENX_(__NR_getgid, sys_getgid),
7601 MACXY(__NR_sigprocmask, sigprocmask),
7602 MACXY(__NR_getlogin, getlogin),
7603 // _____(__NR_setlogin),
7604 // _____(__NR_acct),
7605 MACXY(__NR_sigpending, sigpending),
7606 GENXY(__NR_sigaltstack, sys_sigaltstack),
7607 MACXY(__NR_ioctl, ioctl),
7608 // _____(__NR_reboot),
7609 // _____(__NR_revoke),
7610 GENX_(__NR_symlink, sys_symlink), // 57
7611 GENX_(__NR_readlink, sys_readlink),
7612 GENX_(__NR_execve, sys_execve),
7613 GENX_(__NR_umask, sys_umask), // 60
7614 GENX_(__NR_chroot, sys_chroot),
7615 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
7616 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
7617 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
7618 GENX_(__NR_msync, sys_msync),
7619 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
7620 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
7621 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
7622 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
7623 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
7624 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
7625 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
7626 GENXY(__NR_munmap, sys_munmap),
7627 GENXY(__NR_mprotect, sys_mprotect),
7628 GENX_(__NR_madvise, sys_madvise),
7629 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
7630 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
7631 GENXY(__NR_mincore, sys_mincore),
7632 GENXY(__NR_getgroups, sys_getgroups),
7633 // _____(__NR_setgroups), // 80
7634 GENX_(__NR_getpgrp, sys_getpgrp),
7635 GENX_(__NR_setpgid, sys_setpgid),
7636 GENXY(__NR_setitimer, sys_setitimer),
7637 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
7638 // _____(__NR_swapon),
7639 GENXY(__NR_getitimer, sys_getitimer),
7640 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
7641 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
7642 MACXY(__NR_getdtablesize, getdtablesize),
7643 GENXY(__NR_dup2, sys_dup2),
7644 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
7645 MACXY(__NR_fcntl, fcntl),
7646 GENX_(__NR_select, sys_select),
7647 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
7648 GENX_(__NR_fsync, sys_fsync),
7649 GENX_(__NR_setpriority, sys_setpriority),
7650 MACXY(__NR_socket, socket),
7651 MACX_(__NR_connect, connect),
7652 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
7653 GENX_(__NR_getpriority, sys_getpriority), // 100
7654 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
7655 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
7656 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
7657 MACX_(__NR_bind, bind),
7658 MACX_(__NR_setsockopt, setsockopt),
7659 MACX_(__NR_listen, listen),
7660 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
7661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
7662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
7663 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
7664 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
7665 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
7666 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
7667 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
7668 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
7669 GENXY(__NR_gettimeofday, sys_gettimeofday),
7670 GENXY(__NR_getrusage, sys_getrusage),
7671 MACXY(__NR_getsockopt, getsockopt),
7672 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
7673 GENXY(__NR_readv, sys_readv), // 120
7674 GENX_(__NR_writev, sys_writev),
7675 // _____(__NR_settimeofday),
7676 GENX_(__NR_fchown, sys_fchown),
7677 GENX_(__NR_fchmod, sys_fchmod),
7678 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
7679 // _____(__NR_setreuid),
7680 // _____(__NR_setregid),
7681 GENX_(__NR_rename, sys_rename),
7682 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
7683 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
7684 GENX_(__NR_flock, sys_flock),
7685 // _____(__NR_mkfifo),
7686 MACX_(__NR_sendto, sendto),
7687 MACX_(__NR_shutdown, shutdown),
7688 MACXY(__NR_socketpair, socketpair),
7689 GENX_(__NR_mkdir, sys_mkdir),
7690 GENX_(__NR_rmdir, sys_rmdir),
7691 GENX_(__NR_utimes, sys_utimes),
7692 MACX_(__NR_futimes, futimes),
7693 // _____(__NR_adjtime), // 140
7694 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
7695 MACXY(__NR_gethostuuid, gethostuuid),
7696 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
7697 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
7698 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
7699 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
7700 GENX_(__NR_setsid, sys_setsid),
7701 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
7702 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
7703 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
7704 // _____(__NR_getpgid),
7705 // _____(__NR_setprivexec),
7706 GENXY(__NR_pread, sys_pread64),
7707 GENX_(__NR_pwrite, sys_pwrite64),
7708 // _____(__NR_nfssvc),
7709 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
7710 GENXY(__NR_statfs, sys_statfs),
7711 GENXY(__NR_fstatfs, sys_fstatfs),
7712 // _____(__NR_unmount),
7713 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
7714 // _____(__NR_getfh),
7715 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
7716 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
7717 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
7718 // _____(__NR_quotactl),
7719 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
7720 MACX_(__NR_mount, mount),
7721 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
7722 MACXY(__NR_csops, csops), // code-signing ops
7723 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
7724 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
7725 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
7726 // _____(__NR_waitid),
7727 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
7728 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
7729 // _____(__NR_add_profil),
7730 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
7731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
7732 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
7733 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
7734 GENX_(__NR_setgid, sys_setgid),
7735 MACX_(__NR_setegid, setegid),
7736 MACX_(__NR_seteuid, seteuid),
7737 MACX_(__NR_sigreturn, sigreturn),
7738 // _____(__NR_chud),
7739 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
7740 #if DARWIN_VERS >= DARWIN_10_6
7741 // _____(__NR_fdatasync),
7743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
7745 GENXY(__NR_stat, sys_newstat),
7746 GENXY(__NR_fstat, sys_newfstat),
7747 GENXY(__NR_lstat, sys_newlstat),
7748 MACX_(__NR_pathconf, pathconf),
7749 MACX_(__NR_fpathconf, fpathconf),
7750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
7751 GENXY(__NR_getrlimit, sys_getrlimit),
7752 GENX_(__NR_setrlimit, sys_setrlimit),
7753 MACXY(__NR_getdirentries, getdirentries),
7754 MACXY(__NR_mmap, mmap),
7755 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
7756 MACX_(__NR_lseek, lseek),
7757 GENX_(__NR_truncate, sys_truncate64), // 200
7758 GENX_(__NR_ftruncate, sys_ftruncate64),
7759 MACXY(__NR___sysctl, __sysctl),
7760 GENX_(__NR_mlock, sys_mlock),
7761 GENX_(__NR_munlock, sys_munlock),
7762 // _____(__NR_undelete),
7763 // _____(__NR_ATsocket),
7764 // _____(__NR_ATgetmsg),
7765 // _____(__NR_ATputmsg),
7766 // _____(__NR_ATPsndreq),
7767 // _____(__NR_ATPsndrsp),
7768 // _____(__NR_ATPgetreq),
7769 // _____(__NR_ATPgetrsp),
7770 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
7771 #if DARWIN_VERS >= DARWIN_10_6
7772 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
7773 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
7775 // _____(__NR_kqueue_from_portset_np),
7776 // _____(__NR_kqueue_portset_np),
7778 // _____(__NR_mkcomplex),
7779 // _____(__NR_statv),
7780 // _____(__NR_lstatv),
7781 // _____(__NR_fstatv),
7782 MACXY(__NR_getattrlist, getattrlist), // 220
7783 MACX_(__NR_setattrlist, setattrlist),
7784 MACXY(__NR_getdirentriesattr, getdirentriesattr),
7785 MACX_(__NR_exchangedata, exchangedata),
7786 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
7787 // _____(__NR_searchfs),
7788 GENX_(__NR_delete, sys_unlink),
7789 // _____(__NR_copyfile),
7790 #if DARWIN_VERS >= DARWIN_10_6
7791 // _____(__NR_fgetattrlist),
7792 // _____(__NR_fsetattrlist),
7794 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
7795 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
7797 GENXY(__NR_poll, sys_poll),
7798 MACX_(__NR_watchevent, watchevent),
7799 MACXY(__NR_waitevent, waitevent),
7800 MACX_(__NR_modwatch, modwatch),
7801 MACXY(__NR_getxattr, getxattr),
7802 MACXY(__NR_fgetxattr, fgetxattr),
7803 MACX_(__NR_setxattr, setxattr),
7804 MACX_(__NR_fsetxattr, fsetxattr),
7805 // _____(__NR_removexattr),
7806 // _____(__NR_fremovexattr),
7807 MACXY(__NR_listxattr, listxattr), // 240
7808 MACXY(__NR_flistxattr, flistxattr),
7809 MACXY(__NR_fsctl, fsctl),
7810 MACX_(__NR_initgroups, initgroups),
7811 MACXY(__NR_posix_spawn, posix_spawn),
7812 #if DARWIN_VERS >= DARWIN_10_6
7813 // _____(__NR_ffsctl),
7815 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
7817 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
7818 // _____(__NR_nfsclnt),
7819 // _____(__NR_fhopen),
7820 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
7821 // _____(__NR_minherit),
7822 // _____(__NR_semsys),
7823 // _____(__NR_msgsys),
7824 // _____(__NR_shmsys),
7825 MACXY(__NR_semctl, semctl),
7826 MACX_(__NR_semget, semget),
7827 MACX_(__NR_semop, semop),
7828 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
7829 // _____(__NR_msgctl),
7830 // _____(__NR_msgget),
7831 // _____(__NR_msgsnd), // 260
7832 // _____(__NR_msgrcv),
7833 MACXY(__NR_shmat, shmat),
7834 MACXY(__NR_shmctl, shmctl),
7835 MACXY(__NR_shmdt, shmdt),
7836 MACX_(__NR_shmget, shmget),
7837 MACXY(__NR_shm_open, shm_open),
7838 // _____(__NR_shm_unlink),
7839 MACX_(__NR_sem_open, sem_open),
7840 MACX_(__NR_sem_close, sem_close),
7841 MACX_(__NR_sem_unlink, sem_unlink),
7842 MACX_(__NR_sem_wait, sem_wait),
7843 MACX_(__NR_sem_trywait, sem_trywait),
7844 MACX_(__NR_sem_post, sem_post),
7845 // _____(__NR_sem_getvalue),
7846 MACXY(__NR_sem_init, sem_init),
7847 MACX_(__NR_sem_destroy, sem_destroy),
7848 // _____(__NR_open_extended),
7849 // _____(__NR_umask_extended),
7850 MACXY(__NR_stat_extended, stat_extended),
7851 MACXY(__NR_lstat_extended, lstat_extended), // 280
7852 MACXY(__NR_fstat_extended, fstat_extended),
7853 MACX_(__NR_chmod_extended, chmod_extended),
7854 MACX_(__NR_fchmod_extended,fchmod_extended),
7855 MACXY(__NR_access_extended,access_extended),
7856 MACX_(__NR_settid, settid),
7857 // _____(__NR_gettid),
7858 // _____(__NR_setsgroups),
7859 // _____(__NR_getsgroups),
7860 // _____(__NR_setwgroups),
7861 // _____(__NR_getwgroups),
7862 // _____(__NR_mkfifo_extended),
7863 // _____(__NR_mkdir_extended),
7864 // _____(__NR_identitysvc),
7865 // _____(__NR_shared_region_check_np),
7866 // _____(__NR_shared_region_map_np),
7867 #if DARWIN_VERS >= DARWIN_10_6
7868 // _____(__NR_vm_pressure_monitor),
7870 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
7872 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
7873 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
7874 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
7875 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
7876 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(301)), // ???
7877 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(302)), // ???
7878 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(303)), // ???
7879 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(304)), // ???
7880 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(305)), // ???
7881 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(306)), // ???
7882 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(307)), // ???
7883 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // ???
7884 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(309)), // ???
7885 // _____(__NR_getsid),
7886 // _____(__NR_settid_with_pid),
7887 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(312)), // ???
7888 // _____(__NR_aio_fsync),
7889 MACXY(__NR_aio_return, aio_return),
7890 MACX_(__NR_aio_suspend, aio_suspend),
7891 // _____(__NR_aio_cancel),
7892 MACX_(__NR_aio_error, aio_error),
7893 MACXY(__NR_aio_read, aio_read),
7894 MACX_(__NR_aio_write, aio_write),
7895 // _____(__NR_lio_listio), // 320
7896 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
7897 // _____(__NR_iopolicysys),
7898 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
7899 // _____(__NR_mlockall),
7900 // _____(__NR_munlockall),
7901 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
7902 MACX_(__NR_issetugid, issetugid),
7903 MACX_(__NR___pthread_kill, __pthread_kill),
7904 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
7905 // _____(__NR___sigwait),
7906 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
7907 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
7908 MACX_(__NR___pthread_canceled, __pthread_canceled),
7909 MACX_(__NR___semwait_signal, __semwait_signal),
7910 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
7911 #if DARWIN_VERS >= DARWIN_10_6
7912 MACXY(__NR_proc_info, proc_info), // 336
7914 MACXY(__NR_sendfile, sendfile),
7915 MACXY(__NR_stat64, stat64),
7916 MACXY(__NR_fstat64, fstat64),
7917 MACXY(__NR_lstat64, lstat64), // 340
7918 MACXY(__NR_stat64_extended, stat64_extended),
7919 MACXY(__NR_lstat64_extended, lstat64_extended),
7920 MACXY(__NR_fstat64_extended, fstat64_extended),
7921 MACXY(__NR_getdirentries64, getdirentries64),
7922 MACXY(__NR_statfs64, statfs64),
7923 MACXY(__NR_fstatfs64, fstatfs64),
7924 MACXY(__NR_getfsstat64, getfsstat64),
7925 // _____(__NR___pthread_chdir),
7926 // _____(__NR___pthread_fchdir),
7927 // _____(__NR_audit),
7928 MACXY(__NR_auditon, auditon),
7929 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
7930 // _____(__NR_getauid),
7931 // _____(__NR_setauid),
7932 // _____(__NR_getaudit),
7933 // _____(__NR_setaudit),
7934 // _____(__NR_getaudit_addr),
7935 // _____(__NR_setaudit_addr),
7936 // _____(__NR_auditctl),
7937 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
7938 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
7939 MACXY(__NR_kqueue, kqueue),
7940 MACXY(__NR_kevent, kevent),
7941 GENX_(__NR_lchown, sys_lchown),
7942 // _____(__NR_stack_snapshot),
7943 MACX_(__NR_bsdthread_register, bsdthread_register),
7944 MACX_(__NR_workq_open, workq_open),
7945 MACXY(__NR_workq_ops, workq_ops),
7946 #if DARWIN_VERS >= DARWIN_10_6
7947 // _____(__NR_kevent64),
7949 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
7951 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // ???
7952 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // ???
7953 #if DARWIN_VERS >= DARWIN_10_6
7954 MACX_(__NR___thread_selfid, __thread_selfid),
7956 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
7958 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
7959 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
7960 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
7961 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
7962 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
7963 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
7964 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
7965 // _____(__NR___mac_execve), // 380
7966 MACX_(__NR___mac_syscall, __mac_syscall),
7967 // _____(__NR___mac_get_file),
7968 // _____(__NR___mac_set_file),
7969 // _____(__NR___mac_get_link),
7970 // _____(__NR___mac_set_link),
7971 // _____(__NR___mac_get_proc),
7972 // _____(__NR___mac_set_proc),
7973 // _____(__NR___mac_get_fd),
7974 // _____(__NR___mac_set_fd),
7975 // _____(__NR___mac_get_pid),
7976 // _____(__NR___mac_get_lcid),
7977 // _____(__NR___mac_get_lctx),
7978 // _____(__NR___mac_set_lctx),
7979 // _____(__NR_setlcid),
7980 // _____(__NR_getlcid),
7981 // GrP fixme need any special nocancel handling?
7982 GENXY(__NR_read_nocancel, sys_read),
7983 GENX_(__NR_write_nocancel, sys_write),
7984 GENXY(__NR_open_nocancel, sys_open),
7985 GENXY(__NR_close_nocancel, sys_close),
7986 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
7987 MACXY(__NR_recvmsg_nocancel, recvmsg),
7988 MACX_(__NR_sendmsg_nocancel, sendmsg),
7989 MACXY(__NR_recvfrom_nocancel, recvfrom),
7990 MACXY(__NR_accept_nocancel, accept),
7991 GENX_(__NR_msync_nocancel, sys_msync),
7992 MACXY(__NR_fcntl_nocancel, fcntl),
7993 GENX_(__NR_select_nocancel, sys_select),
7994 GENX_(__NR_fsync_nocancel, sys_fsync),
7995 MACX_(__NR_connect_nocancel, connect),
7996 // _____(__NR_sigsuspend_nocancel),
7997 GENXY(__NR_readv_nocancel, sys_readv),
7998 GENX_(__NR_writev_nocancel, sys_writev),
7999 MACX_(__NR_sendto_nocancel, sendto),
8000 GENXY(__NR_pread_nocancel, sys_pread64),
8001 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
8002 // _____(__NR_waitid_nocancel),
8003 GENXY(__NR_poll_nocancel, sys_poll),
8004 // _____(__NR_msgsnd_nocancel),
8005 // _____(__NR_msgrcv_nocancel),
8006 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
8007 // _____(__NR_aio_suspend_nocancel),
8008 // _____(__NR___sigwait_nocancel),
8009 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
8010 // _____(__NR___mac_mount),
8011 // _____(__NR___mac_get_mount),
8012 // _____(__NR___mac_getfsstat),
8013 #if DARWIN_VERS >= DARWIN_10_6
8014 MACXY(__NR_fsgetpath, fsgetpath),
8015 MACXY(__NR_audit_session_self, audit_session_self),
8016 // _____(__NR_audit_session_join),
8019 // _____(__NR_MAXSYSCALL)
8020 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
8024 // Mach traps use negative syscall numbers.
8025 // Use ML_(mach_trap_table)[-mach_trap_number] .
8027 const SyscallTableEntry ML_(mach_trap_table)[] = {
8028 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
8029 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
8030 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
8031 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
8032 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
8033 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
8034 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
8035 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
8036 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
8037 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
8038 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
8039 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
8040 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
8041 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
8042 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
8043 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
8044 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
8045 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
8046 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
8047 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
8048 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)), // -20
8049 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
8050 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
8051 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
8052 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
8053 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
8054 MACXY(__NR_mach_reply_port, mach_reply_port),
8055 MACXY(__NR_thread_self_trap, mach_thread_self),
8056 MACXY(__NR_task_self_trap, mach_task_self),
8057 MACXY(__NR_host_self_trap, mach_host_self),
8058 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
8059 MACXY(__NR_mach_msg_trap, mach_msg),
8060 // _____(__NR_mach_msg_overwrite_trap),
8061 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
8062 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
8063 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
8064 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
8065 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
8066 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
8067 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
8068 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
8069 #if defined(VGA_x86)
8070 // _____(__NR_init_process),
8071 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
8072 // _____(__NR_map_fd),
8074 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
8075 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
8076 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
8078 // _____(__NR_task_name_for_pid),
8079 MACXY(__NR_task_for_pid, task_for_pid),
8080 MACXY(__NR_pid_for_task, pid_for_task),
8081 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
8082 #if defined(VGA_x86)
8083 // _____(__NR_macx_swapon),
8084 // _____(__NR_macx_swapoff),
8085 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
8086 // _____(__NR_macx_triggers),
8087 // _____(__NR_macx_backing_store_suspend),
8088 // _____(__NR_macx_backing_store_recovery),
8090 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
8091 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
8092 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
8093 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
8094 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
8095 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
8097 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
8098 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
8099 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
8100 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
8101 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
8102 MACX_(__NR_swtch_pri, swtch_pri),
8103 MACX_(__NR_swtch, swtch), // -60
8104 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
8105 // _____(__NR_clock_sleep_trap),
8106 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
8107 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
8108 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
8109 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
8110 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
8111 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
8112 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
8113 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
8114 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
8115 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
8116 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
8117 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
8118 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
8119 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
8120 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
8121 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
8122 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
8123 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
8124 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
8125 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
8126 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
8127 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
8128 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
8129 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
8130 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
8131 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
8132 MACXY(__NR_mach_timebase_info, mach_timebase_info),
8133 MACX_(__NR_mach_wait_until, mach_wait_until),
8134 MACXY(__NR_mk_timer_create, mk_timer_create),
8135 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
8136 MACX_(__NR_mk_timer_arm, mk_timer_arm),
8137 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
8138 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
8139 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
8140 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
8141 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
8142 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
8143 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
8147 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
8148 // calling convention instead of the syscall convention.
8149 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
8151 #if defined(VGA_x86)
8152 const SyscallTableEntry ML_(mdep_trap_table)[] = {
8153 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
8155 #elif defined(VGA_amd64)
8156 const SyscallTableEntry ML_(mdep_trap_table)[] = {
8157 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
8160 #error unknown architecture
8163 const UInt ML_(syscall_table_size) =
8164 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
8166 const UInt ML_(mach_trap_table_size) =
8167 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
8169 const UInt ML_(mdep_trap_table_size) =
8170 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
8172 #endif // defined(VGO_darwin)
8174 /*--------------------------------------------------------------------*/
8176 /*--------------------------------------------------------------------*/