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 #include <sys/acl.h> /* struct kauth_filesec */
70 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
72 #define msgh_request_port msgh_remote_port
73 #define msgh_reply_port msgh_local_port
74 #define BOOTSTRAP_MAX_NAME_LEN 128
75 typedef char name_t[BOOTSTRAP_MAX_NAME_LEN];
77 typedef uint64_t mig_addr_t;
81 static mach_port_t vg_host_port = 0;
82 static mach_port_t vg_task_port = 0;
83 static mach_port_t vg_bootstrap_port = 0;
85 // Run a thread from beginning to end and return the thread's
86 // scheduler-return-code.
87 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
89 VgSchedReturnCode ret;
90 ThreadId tid = (ThreadId)tidW;
91 ThreadState* tst = VG_(get_ThreadState)(tid);
93 VG_(debugLog)(1, "syswrap-darwin",
94 "thread_wrapper(tid=%lld): entry\n",
97 vg_assert(tst->status == VgTs_Init);
99 /* make sure we get the CPU lock before doing anything significant */
100 VG_(acquire_BigLock)(tid, "thread_wrapper");
103 VG_(printf)("thread tid %d started: stack = %p\n",
106 VG_TRACK(pre_thread_first_insn, tid);
108 tst->os_state.lwpid = VG_(gettid)();
109 tst->os_state.threadgroup = VG_(getpid)();
111 /* Thread created with all signals blocked; scheduler will set the
114 ret = VG_(scheduler)(tid);
116 vg_assert(VG_(is_exiting)(tid));
118 vg_assert(tst->status == VgTs_Runnable);
119 vg_assert(VG_(is_running_thread)(tid));
121 VG_(debugLog)(1, "syswrap-darwin",
122 "thread_wrapper(tid=%lld): done\n",
125 /* Return to caller, still holding the lock. */
131 /* Allocate a stack for this thread, if it doesn't already have one.
132 Returns the initial stack pointer value to use, or 0 if allocation
135 Addr allocstack ( ThreadId tid )
137 ThreadState* tst = VG_(get_ThreadState)(tid);
141 /* Either the stack_base and stack_init_SP are both zero (in which
142 case a stack hasn't been allocated) or they are both non-zero,
143 in which case it has. */
145 if (tst->os_state.valgrind_stack_base == 0)
146 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
148 if (tst->os_state.valgrind_stack_base != 0)
149 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
151 /* If no stack is present, allocate one. */
153 if (tst->os_state.valgrind_stack_base == 0) {
154 stack = VG_(am_alloc_VgStack)( &initial_SP );
156 tst->os_state.valgrind_stack_base = (Addr)stack;
157 tst->os_state.valgrind_stack_init_SP = initial_SP;
161 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
163 (void*)tst->os_state.valgrind_stack_base,
164 (void*)tst->os_state.valgrind_stack_init_SP );
166 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
168 return tst->os_state.valgrind_stack_init_SP;
172 void find_stack_segment(ThreadId tid, Addr sp)
174 /* We don't really know where the client stack is, because it's
175 allocated by the client. The best we can do is look at the
176 memory mappings and try to derive some useful information. We
177 assume that esp starts near its highest possible value, and can
178 only go down to the start of the mmaped segment. */
179 ThreadState *tst = VG_(get_ThreadState)(tid);
180 const NSegment *seg = VG_(am_find_nsegment)(sp);
181 if (seg && seg->kind != SkResvn) {
182 tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
183 tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
186 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
187 tid, seg->start, VG_PGROUNDUP(sp));
189 VG_(printf)("couldn't find user stack\n");
190 VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
192 tst->client_stack_szB = 0;
197 /* Run a thread all the way to the end, then do appropriate exit actions
198 (this is the last-one-out-turn-off-the-lights bit).
200 static void run_a_thread_NORETURN ( Word tidW )
203 VgSchedReturnCode src;
204 ThreadId tid = (ThreadId)tidW;
206 VG_(debugLog)(1, "syswrap-darwin",
207 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
210 /* Run the thread all the way through. */
211 src = thread_wrapper(tid);
213 VG_(debugLog)(1, "syswrap-darwin",
214 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
217 c = VG_(count_living_threads)();
218 vg_assert(c >= 1); /* stay sane */
220 // Tell the tool this thread is exiting
221 VG_TRACK( pre_thread_ll_exit, tid );
225 VG_(debugLog)(1, "syswrap-darwin",
226 "run_a_thread_NORETURN(tid=%lld): "
227 "last one standing\n",
230 /* We are the last one standing. Keep hold of the lock and
231 carry on to show final tool results, then exit the entire system.
232 Use the continuation pointer set at startup in m_main. */
233 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
238 mach_msg_header_t msg;
240 VG_(debugLog)(1, "syswrap-darwin",
241 "run_a_thread_NORETURN(tid=%lld): "
242 "not last one standing\n",
245 /* OK, thread is dead, but others still exist. Just exit. */
246 tst = VG_(get_ThreadState)(tid);
248 /* This releases the run lock */
249 VG_(exit_thread)(tid);
250 vg_assert(tst->status == VgTs_Zombie);
252 /* tid is now invalid. */
254 // GrP fixme exit race
255 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
256 msg.msgh_request_port = VG_(gettid)();
257 msg.msgh_reply_port = 0;
258 msg.msgh_id = 3600; // thread_terminate
260 tst->status = VgTs_Empty;
261 // GrP fixme race here! new thread may claim this V thread stack
262 // before we get out here!
263 // GrP fixme use bsdthread_terminate for safe cleanup?
264 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
265 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
267 // DDD: This is reached sometimes on none/tests/manythreads, maybe
268 // because of the race above.
269 VG_(core_panic)("Thread exit failed?\n");
277 /* Allocate a stack for the main thread, and run it all the way to the
278 end. Although we already have a working VgStack
279 (VG_(interim_stack)) it's better to allocate a new one, so that
280 overflow detection works uniformly for all threads.
282 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
285 VG_(debugLog)(1, "syswrap-darwin",
286 "entering VG_(main_thread_wrapper_NORETURN)\n");
288 sp = allocstack(tid);
290 /* If we can't even allocate the first thread's stack, we're hosed.
292 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
294 /* shouldn't be any other threads around yet */
295 vg_assert( VG_(count_living_threads)() == 1 );
297 call_on_new_stack_0_1(
298 (Addr)sp, /* stack */
299 0, /*bogus return address*/
300 run_a_thread_NORETURN, /* fn to call */
301 (Word)tid /* arg to give it */
309 void start_thread_NORETURN ( Word arg )
311 ThreadState* tst = (ThreadState*)arg;
312 ThreadId tid = tst->tid;
314 run_a_thread_NORETURN ( (Word)tid );
320 void VG_(cleanup_thread) ( ThreadArchState* arch )
325 /* ---------------------------------------------------------------------
326 Mach port tracking (based on syswrap-generic's fd tracker)
327 ------------------------------------------------------------------ */
329 /* One of these is allocated for each open port. */
330 typedef struct OpenPort
333 mach_port_type_t type; /* right type(s) */
334 Int send_count; /* number of send rights */
335 Char *name; /* bootstrap name or NULL */
336 ExeContext *where; /* first allocation only */
337 struct OpenPort *next, *prev;
340 // strlen("0x12345678")
341 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
343 /* List of allocated ports. */
344 static OpenPort *allocated_ports;
346 /* Count of open ports. */
347 static Int allocated_port_count = 0;
350 __attribute__((unused))
351 static Bool port_exists(mach_port_t port)
355 /* Check to see if this port is already open. */
358 if (i->port == port) {
367 static OpenPort *info_for_port(mach_port_t port)
370 if (!port) return NULL;
374 if (i->port == port) {
384 // Give a port a name, without changing its refcount
385 // GrP fixme don't override name if it already has a specific one
386 __private_extern__ void assign_port_name(mach_port_t port, const char *name)
392 i = info_for_port(port);
395 if (i->name) VG_(arena_free)(VG_AR_CORE, i->name);
397 VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name",
398 VG_(strlen)(name) + PORT_STRLEN + 1);
399 VG_(sprintf)(i->name, name, port);
403 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
404 static const char *name_for_port(mach_port_t port)
406 static char buf[8 + PORT_STRLEN + 1];
410 if (port == VG_(gettid)()) return "mach_thread_self()";
411 if (port == 0) return "NULL";
415 if (i->port == port) {
421 VG_(sprintf)(buf, "NONPORT-%#x", port);
425 /* Note the fact that a port was just deallocated. */
428 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
430 OpenPort *i = allocated_ports;
434 if(i->port == port) {
435 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
436 if (right & MACH_PORT_TYPE_SEND) {
437 // send rights are refcounted
438 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
439 i->send_count += delta;
440 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
441 else i->type &= ~MACH_PORT_TYPE_SEND;
443 right = right & ~MACH_PORT_TYPE_SEND;
445 // other rights are not refcounted
448 } else if (delta < 0) {
453 if (i->type != 0) return;
455 // Port has no rights left. Kill it.
456 // VG_(printf)("deleting port %p %s", i->port, i->name);
458 i->prev->next = i->next;
460 allocated_ports = i->next;
462 i->next->prev = i->prev;
464 VG_(arena_free) (VG_AR_CORE, i->name);
465 VG_(arena_free) (VG_AR_CORE, i);
466 allocated_port_count--;
472 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
476 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
479 case MACH_MSG_TYPE_PORT_NAME:
480 // this task has no rights for the name
482 case MACH_MSG_TYPE_PORT_RECEIVE:
483 // this task gets receive rights
484 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
486 case MACH_MSG_TYPE_PORT_SEND:
487 // this task gets a send right
488 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
490 case MACH_MSG_TYPE_PORT_SEND_ONCE:
491 // this task gets send-once rights
492 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
501 void record_port_dealloc(mach_port_t port)
503 // deletes 1 send or send-once right (port can't have both)
504 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
508 void record_port_destroy(mach_port_t port)
510 // deletes all rights to port
511 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
515 /* Note the fact that a Mach port was just allocated or transferred.
516 If the port is already known, increment its reference count. */
517 void record_named_port(ThreadId tid, mach_port_t port,
518 mach_port_right_t right, const char *name)
523 /* Check to see if this port is already open. */
526 if (i->port == port) {
527 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
533 /* Not already one: allocate an OpenPort */
535 i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port",
539 i->next = allocated_ports;
540 if(allocated_ports) allocated_ports->prev = i;
542 allocated_port_count++;
545 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
548 i->type = MACH_PORT_TYPE(right);
549 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
555 assign_port_name(port, name);
560 // Record opening of a nameless port.
561 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
563 record_named_port(tid, port, right, "unnamed-%p");
567 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
568 void VG_(show_open_ports)(void)
572 VG_(message)(Vg_UserMsg,
573 "MACH PORTS: %d open at exit.", allocated_port_count);
575 for (i = allocated_ports; i; i = i->next) {
577 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name);
579 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port);
583 VG_(pp_ExeContext)(i->where);
584 VG_(message)(Vg_UserMsg, "");
588 VG_(message)(Vg_UserMsg, "");
592 /* ---------------------------------------------------------------------
594 ------------------------------------------------------------------ */
596 void ML_(sync_mappings)(const HChar *when, const HChar *where, Int num)
598 // Usually the number of segments added/removed in a single calls is very
599 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
600 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
601 // because we can't do dynamic allocation within VG_(get_changed_segments),
602 // because it's in m_aspacemgr.
603 ChangedSeg* css = NULL;
609 if (VG_(clo_trace_syscalls)) {
610 VG_(debugLog)(0, "syswrap-darwin",
611 "sync_mappings(\"%s\", \"%s\", %d)\n",
615 // 16 is enough for most cases, but small enough that overflow happens
616 // occasionally and thus the overflow path gets some test coverage.
620 VG_(free)(css); // css is NULL on first iteration; that's ok.
621 css = VG_(malloc)("sys_wrap.sync_mappings", css_size*sizeof(ChangedSeg));
622 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
626 // Now add/remove them.
627 for (i = 0; i < css_used; i++) {
628 ChangedSeg* cs = &css[i];
631 ML_(notify_core_and_tool_of_mmap)(
632 cs->start, cs->end - cs->start + 1,
633 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
634 // should this call VG_(di_notify_mmap) also?
638 ML_(notify_core_and_tool_of_munmap)(
639 cs->start, cs->end - cs->start + 1);
642 if (VG_(clo_trace_syscalls)) {
643 VG_(debugLog)(0, "syswrap-darwin",
644 " %s region 0x%010lx..0x%010lx at %s (%s)\n",
645 action, cs->start, cs->end + 1, where, when);
652 /* ---------------------------------------------------------------------
654 ------------------------------------------------------------------ */
656 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
657 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
659 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
660 #define POST_FN(name) vgSysWrap_darwin_##name##_after
662 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
663 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
666 // Combine two 32-bit values into a 64-bit value
667 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
668 # if defined(VGA_x86)
669 # define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
671 # error unknown architecture
675 // Retrieve the current Mach thread
676 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
678 // Set the POST handler for a mach_msg derivative
679 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
681 // Set or get values saved from Mach messages
682 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
683 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
684 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
686 /* ---------------------------------------------------------------------
688 ------------------------------------------------------------------ */
692 *flags |= SfMayBlock;
693 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
694 PRE_REG_READ3(long, "ioctl",
695 unsigned int, fd, unsigned int, request, unsigned long, arg);
697 switch (ARG2 /* request */) {
699 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
702 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
705 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
708 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
711 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
714 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
717 /* Get process group ID for foreground processing group. */
718 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
721 /* Set a process group ID? */
722 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
725 /* Just takes an int value. */
728 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
731 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
733 case VKI_FIONREAD: /* identical to SIOCINQ */
734 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
738 /* These all use struct ifreq AFAIK */
739 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
740 case VKI_SIOCGIFFLAGS: /* get flags */
741 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
742 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
743 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
745 case VKI_SIOCGIFMTU: /* get MTU size */
746 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
747 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
748 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
750 case VKI_SIOCGIFADDR: /* get PA address */
751 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
752 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
753 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
755 case VKI_SIOCGIFNETMASK: /* get network PA mask */
756 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
757 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
758 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
760 case VKI_SIOCGIFMETRIC: /* get metric */
761 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
762 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
763 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
765 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
766 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
767 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
768 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
770 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
771 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
772 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
773 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
775 case VKI_SIOCGIFCONF: /* get iface list */
777 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
778 KERNEL_DO_SYSCALL(tid,RES);
779 if (!VG_(is_kerror)(RES) && RES == 0)
780 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
782 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
783 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
784 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
785 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
786 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
787 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
789 // TODO len must be readable and writable
790 // buf pointer only needs to be readable
791 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
792 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
793 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
797 case VKI_SIOCSIFFLAGS: /* set flags */
798 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
799 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
800 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
801 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
802 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
804 case VKI_SIOCSIFADDR: /* set PA address */
805 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
806 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
807 case VKI_SIOCSIFNETMASK: /* set network PA mask */
808 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
809 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
810 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
811 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
812 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
814 case VKI_SIOCSIFMETRIC: /* set metric */
815 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
816 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
817 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
818 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
819 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
821 case VKI_SIOCSIFMTU: /* set MTU size */
822 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
823 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
824 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
825 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
826 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
828 /* Routing table calls. */
830 case VKI_SIOCADDRT: /* add routing table entry */
831 case VKI_SIOCDELRT: /* delete routing table entry */
832 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
833 sizeof(struct vki_rtentry));
838 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
841 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
842 //tst->sys_flags &= ~SfMayBlock;
846 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
849 case VKI_DTRACEHIOC_REMOVE:
850 case VKI_DTRACEHIOC_ADDDOF:
855 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
858 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
861 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
864 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
866 case VKI_TIOCPTYGNAME:
867 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
869 case VKI_TIOCPTYGRANT:
870 case VKI_TIOCPTYUNLK:
874 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
883 switch (ARG2 /* request */) {
885 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
893 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
896 /* Get process group ID for foreground processing group. */
897 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
900 /* Set a process group ID? */
901 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
909 case VKI_FIONREAD: /* identical to SIOCINQ */
910 POST_MEM_WRITE( ARG3, sizeof(int) );
913 /* These all use struct ifreq AFAIK */
914 case VKI_SIOCGIFFLAGS: /* get flags */
915 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
916 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
918 case VKI_SIOCGIFMTU: /* get MTU size */
919 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
920 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
922 case VKI_SIOCGIFADDR: /* get PA address */
923 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
924 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
925 case VKI_SIOCGIFNETMASK: /* get network PA mask */
927 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
928 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
930 case VKI_SIOCGIFMETRIC: /* get metric */
932 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
933 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
935 case VKI_SIOCGIFCONF: /* get iface list */
937 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
938 KERNEL_DO_SYSCALL(tid,RES);
939 if (!VG_(is_kerror)(RES) && RES == 0)
940 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
942 if (RES == 0 && ARG3 ) {
943 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
944 if (ifc->vki_ifc_buf != NULL)
945 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
949 case VKI_SIOCSIFFLAGS: /* set flags */
950 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
951 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
952 case VKI_SIOCSIFNETMASK: /* set network PA mask */
953 case VKI_SIOCSIFMETRIC: /* set metric */
954 case VKI_SIOCSIFADDR: /* set PA address */
955 case VKI_SIOCSIFMTU: /* set MTU size */
959 /* Routing table calls. */
960 case VKI_SIOCADDRT: /* add routing table entry */
961 case VKI_SIOCDELRT: /* delete routing table entry */
966 POST_MEM_WRITE(ARG3, sizeof(int));
972 POST_MEM_WRITE( ARG3, sizeof(int) );
975 case VKI_DTRACEHIOC_REMOVE:
976 case VKI_DTRACEHIOC_ADDDOF:
981 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
986 POST_MEM_WRITE( ARG3, sizeof(int) );
990 case VKI_TIOCPTYGNAME:
991 POST_MEM_WRITE( ARG3, 128);
993 case VKI_TIOCPTYGRANT:
994 case VKI_TIOCPTYUNLK:
1003 /* ---------------------------------------------------------------------
1004 darwin fcntl wrapper
1005 ------------------------------------------------------------------ */
1006 static const char *name_for_fcntl(UWord cmd) {
1007 #define F(n) case VKI_##n: return #n
1015 F(F_GLOBAL_NOCACHE);
1020 F(F_WRITEBOOTSTRAP);
1034 // These ones ignore ARG3.
1038 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1039 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1042 // These ones use ARG3 as "arg".
1047 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1048 PRE_REG_READ3(long, "fcntl",
1049 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1052 // These ones use ARG3 as "lock".
1056 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1057 PRE_REG_READ3(long, "fcntl",
1058 unsigned int, fd, unsigned int, cmd,
1059 struct flock64 *, lock);
1060 // GrP fixme mem read sizeof(flock64)
1061 if (ARG2 == VKI_F_SETLKW)
1062 *flags |= SfMayBlock;
1066 case VKI_F_CHKCLEAN:
1069 case VKI_F_FULLFSYNC:
1070 case VKI_F_FREEZE_FS:
1072 case VKI_F_GLOBAL_NOCACHE:
1073 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1074 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1078 case VKI_F_PREALLOCATE:
1079 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1080 PRE_REG_READ3(long, "fcntl",
1081 unsigned int, fd, unsigned int, cmd,
1082 struct fstore *, fstore);
1084 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1085 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1086 fstore->fst_flags );
1087 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1088 fstore->fst_posmode );
1089 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1090 fstore->fst_offset );
1091 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1092 fstore->fst_length );
1093 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1094 fstore->fst_bytesalloc);
1100 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1101 PRE_REG_READ3(long, "fcntl",
1102 unsigned int, fd, unsigned int, cmd,
1103 vki_off_t *, offset);
1107 case VKI_F_RDADVISE:
1108 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1109 PRE_REG_READ3(long, "fcntl",
1110 unsigned int, fd, unsigned int, cmd,
1111 struct vki_radvisory *, radvisory);
1113 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1114 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1115 radvisory->ra_offset );
1116 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1117 radvisory->ra_count );
1121 // struct fbootstraptransfer
1122 case VKI_F_READBOOTSTRAP:
1123 case VKI_F_WRITEBOOTSTRAP:
1124 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1125 PRE_REG_READ3(long, "fcntl",
1126 unsigned int, fd, unsigned int, cmd,
1127 struct fbootstraptransfer *, bootstrap);
1128 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1129 ARG3, sizeof(struct vki_fbootstraptransfer) );
1132 // struct log2phys (out)
1133 case VKI_F_LOG2PHYS:
1134 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1135 PRE_REG_READ3(long, "fcntl",
1136 unsigned int, fd, unsigned int, cmd,
1137 struct log2phys *, l2p);
1138 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1139 ARG3, sizeof(struct vki_log2phys) );
1142 // char[maxpathlen] (out)
1144 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1145 PRE_REG_READ3(long, "fcntl",
1146 unsigned int, fd, unsigned int, cmd,
1148 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1149 ARG3, VKI_MAXPATHLEN );
1152 // char[maxpathlen] (in)
1153 case VKI_F_PATHPKG_CHECK:
1154 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1156 PRE_REG_READ3(long, "fcntl",
1157 unsigned int, fd, unsigned int, cmd,
1159 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1162 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1163 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1164 PRE_REG_READ3(long, "fcntl",
1165 unsigned int, fd, unsigned int, cmd,
1166 vki_fsignatures_t *, sigs);
1169 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1170 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1171 fsigs->fs_blob_start);
1172 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1173 fsigs->fs_blob_size);
1175 if (fsigs->fs_blob_start)
1176 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1177 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1182 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1183 VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
1193 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1195 SET_STATUS_Failure( VKI_EMFILE );
1197 if (VG_(clo_track_fds))
1198 ML_(record_fd_open_named)(tid, RES);
1213 case VKI_F_PREALLOCATE:
1215 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1216 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1220 case VKI_F_LOG2PHYS:
1221 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1225 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1226 PRINT("\"%s\"", (char*)ARG3);
1230 // DDD: ugh, missing lots of cases here, not nice
1235 /* ---------------------------------------------------------------------
1237 ------------------------------------------------------------------ */
1241 PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
1242 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1244 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1245 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1251 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1252 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1257 *flags |= SfMayBlock;
1258 PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
1259 PRE_REG_READ3(long, "semop",
1260 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1261 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1269 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1270 PRE_REG_READ4(long, "semctl",
1271 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1275 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1276 PRE_REG_READ4(long, "semctl",
1277 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1280 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1281 PRE_REG_READ4(long, "semctl",
1282 int, semid, int, semnum, int, cmd, int, arg);
1285 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1286 PRE_REG_READ3(long, "semctl",
1287 int, semid, int, semnum, int, cmd);
1290 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1294 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1299 if (ARG2 & VKI_O_CREAT) {
1301 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1302 ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1303 PRE_REG_READ4(vki_sem_t *, "sem_open",
1304 const char *, name, int, oflag, vki_mode_t, mode,
1305 unsigned int, value);
1308 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1309 PRE_REG_READ2(vki_sem_t *, "sem_open",
1310 const char *, name, int, oflag);
1312 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1314 /* Otherwise handle normally */
1315 *flags |= SfMayBlock;
1320 PRINT("sem_close( %#lx )", ARG1);
1321 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1326 PRINT("sem_unlink( %#lx(%s) )", ARG1,(char*)ARG1);
1327 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1328 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1333 PRINT("sem_post( %#lx )", ARG1);
1334 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1335 *flags |= SfMayBlock;
1340 PRINT("sem_destroy( %#lx )", ARG1);
1341 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1342 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1347 PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
1348 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1349 int, pshared, unsigned int, value);
1350 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1355 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1360 PRINT("sem_wait( %#lx )", ARG1);
1361 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1362 *flags |= SfMayBlock;
1367 PRINT("sem_trywait( %#lx )", ARG1);
1368 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1369 *flags |= SfMayBlock;
1379 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1381 SET_STATUS_Failure( VKI_EMFILE );
1383 if (VG_(clo_track_fds)) {
1384 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1391 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1392 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1393 PRE_REG_READ6(int,"kevent", int,kq,
1394 const struct vki_kevent *,changelist, int,nchanges,
1395 struct vki_kevent *,eventlist, int,nevents,
1396 const struct vki_timespec *,timeout);
1398 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
1399 ARG2, ARG3 * sizeof(struct vki_kevent));
1400 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
1401 ARG4, ARG5 * sizeof(struct vki_kevent));
1402 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
1403 ARG6, sizeof(struct vki_timespec));
1405 *flags |= SfMayBlock;
1410 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
1411 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
1415 Addr pthread_starter = 0;
1416 Addr wqthread_starter = 0;
1417 SizeT pthread_structsize = 0;
1419 PRE(bsdthread_register)
1421 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
1422 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
1423 void *,"wqthread", size_t,"pthsize");
1425 pthread_starter = ARG1;
1426 wqthread_starter = ARG2;
1427 pthread_structsize = ARG3;
1428 ARG1 = (Word)&pthread_hijack_asm;
1429 ARG2 = (Word)&wqthread_hijack_asm;
1434 PRINT("workq_open()");
1435 PRE_REG_READ0(int, "workq_open");
1437 // This creates lots of threads and thread stacks under the covers,
1438 // but we ignore them all until some work item starts running on it.
1441 static const char *workqop_name(int op)
1444 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
1445 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
1446 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
1447 default: return "?";
1454 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
1456 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
1460 case VKI_WQOPS_QUEUE_ADD:
1461 case VKI_WQOPS_QUEUE_REMOVE:
1462 // GrP fixme need anything here?
1463 // GrP fixme may block?
1466 case VKI_WQOPS_THREAD_RETURN: {
1467 // The interesting case. The kernel will do one of two things:
1468 // 1. Return normally. We continue; libc proceeds to stop the thread.
1469 // V does nothing special here.
1470 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
1471 // new work item, and never returns from workq_ops.
1472 // V handles this by longjmp() from wqthread_hijack back to the
1473 // scheduler, which continues at the new client SP/IP/state.
1474 // This works something like V's signal handling.
1475 // To the tool, this looks like workq_ops() sometimes returns
1476 // to a strange address.
1477 ThreadState *tst = VG_(get_ThreadState)(tid);
1478 tst->os_state.wq_jmpbuf_valid = True;
1479 *flags |= SfMayBlock; // GrP fixme true?
1484 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
1490 ThreadState *tst = VG_(get_ThreadState)(tid);
1491 tst->os_state.wq_jmpbuf_valid = False;
1498 PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
1499 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
1500 int,"call", void *,"arg");
1502 // GrP fixme check call's arg?
1503 // GrP fixme check policy?
1507 /* Not like syswrap-generic's sys_exit, which exits only one thread.
1508 More like syswrap-generic's sys_exit_group. */
1514 PRINT("darwin exit( %ld )", ARG1);
1515 PRE_REG_READ1(void, "exit", int, status);
1517 tst = VG_(get_ThreadState)(tid);
1519 /* A little complex; find all the threads with the same threadgroup
1520 as this one (including this one), and mark them to exit */
1521 for (t = 1; t < VG_N_THREADS; t++) {
1522 if ( /* not alive */
1523 VG_(threads)[t].status == VgTs_Empty
1524 /* GrP fixme zombie? */
1528 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
1529 VG_(threads)[t].os_state.exitcode = ARG1;
1532 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
1535 /* We have to claim the syscall already succeeded. */
1536 SET_STATUS_Success(0);
1542 PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
1543 PRE_REG_READ3(long, "sigaction",
1544 int, signum, vki_sigaction_toK_t *, act,
1545 vki_sigaction_fromK_t *, oldact);
1548 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
1549 PRE_MEM_READ( "sigaction(act->sa_handler)",
1550 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1551 PRE_MEM_READ( "sigaction(act->sa_mask)",
1552 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1553 PRE_MEM_READ( "sigaction(act->sa_flags)",
1554 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
1557 PRE_MEM_WRITE( "sigaction(oldact)",
1558 ARG3, sizeof(vki_sigaction_fromK_t));
1560 SET_STATUS_from_SysRes(
1561 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
1562 (vki_sigaction_fromK_t *)ARG3)
1568 if (RES == 0 && ARG3 != 0)
1569 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
1575 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
1576 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
1580 PRE(__pthread_sigmask)
1583 // JRS: arguments are identical to sigprocmask
1584 // (how, sigset_t*, sigset_t*). Perhaps behave identically?
1587 VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. "
1588 "This warning will not be repeated.\n");
1591 SET_STATUS_Success( 0 );
1595 PRE(__pthread_canceled)
1597 *flags |= SfMayBlock; /* might kill this thread??? */
1598 /* I don't think so -- I think it just changes the cancellation
1599 state. But taking no chances. */
1600 PRINT("__pthread_canceled ( %ld )", ARG1);
1601 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
1605 PRE(__pthread_markcancel)
1607 *flags |= SfMayBlock; /* might kill this thread??? */
1608 PRINT("__pthread_markcancel ( %#lx )", ARG1);
1609 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
1610 /* Just let it go through. No idea if this is correct. */
1614 PRE(__disable_threadsignal)
1617 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
1618 /* I don't think this really looks at its arguments. So don't
1619 bother to check them. */
1621 VG_(sigfillset)( &set );
1622 SET_STATUS_from_SysRes(
1623 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
1626 /* We don't expect that blocking all signals for this thread could
1627 cause any more to be delivered (how could it?), but just in case
1630 *flags |= SfPollAfter;
1636 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
1637 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1638 PRE_REG_READ6(long, "kdebug_trace",
1639 int,"code", int,"arg1", int,"arg2",
1640 int,"arg3", int,"arg4", int,"arg5");
1641 // GrP fixme anything else?
1647 PRINT("seteuid(%ld)", ARG1);
1648 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
1654 PRINT("setegid(%ld)", ARG1);
1655 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
1660 PRINT("settid(%ld, %ld)", ARG1, ARG2);
1661 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
1664 /* XXX need to check whether we need POST operations for
1665 * waitevent, watchevent, modwatch -- jpeach
1669 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
1670 PRE_REG_READ2(long, "watchevent",
1671 vki_eventreq *, "event", unsigned int, "eventmask");
1673 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
1674 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
1675 *flags |= SfMayBlock;
1678 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
1681 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
1682 PRE_REG_READ2(long, "waitevent",
1683 vki_eventreq *, "event", struct timeval *, "timeout");
1684 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
1686 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
1687 PRE_timeval_READ("waitevent(timeout)", ARG2);
1690 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
1691 *flags |= SfMayBlock;
1696 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
1701 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
1702 PRE_REG_READ2(long, "modwatch",
1703 vki_eventreq *, "event", unsigned int, "eventmask");
1705 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
1706 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
1711 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
1712 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1714 PRE_REG_READ6(vki_ssize_t, "getxattr",
1715 const char *, path, char *, name, void *, value,
1716 vki_size_t, size, uint32_t, position, int, options);
1717 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
1718 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1719 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1724 vg_assert((vki_ssize_t)RES >= 0);
1725 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1730 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
1731 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1733 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
1734 int, fd, char *, name, void *, value,
1735 vki_size_t, size, uint32_t, position, int, options);
1736 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1737 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1742 vg_assert((vki_ssize_t)RES >= 0);
1743 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1748 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
1749 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1750 PRE_REG_READ6(int, "setxattr",
1751 const char *,"path", char *,"name", void *,"value",
1752 vki_size_t,"size", uint32_t,"position", int,"options" );
1754 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
1755 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
1756 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
1762 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
1763 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1764 PRE_REG_READ6(int, "fsetxattr",
1765 int,"fd", char *,"name", void *,"value",
1766 vki_size_t,"size", uint32_t,"position", int,"options" );
1768 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
1769 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
1775 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
1776 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
1777 PRE_REG_READ4 (long, "listxattr",
1778 const char *,"path", char *,"namebuf",
1779 vki_size_t,"size", int,"options" );
1781 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
1782 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
1783 *flags |= SfMayBlock;
1788 vg_assert((vki_ssize_t)RES >= 0);
1789 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1795 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
1796 ARG1, ARG2, ARG3, ARG4 );
1797 PRE_REG_READ4 (long, "flistxattr",
1798 int, "fd", char *,"namebuf",
1799 vki_size_t,"size", int,"options" );
1800 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
1801 *flags |= SfMayBlock;
1806 vg_assert((vki_ssize_t)RES >= 0);
1807 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1814 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
1815 PRE_REG_READ3(long, "shmat",
1816 int, shmid, const void *, shmaddr, int, shmflg);
1817 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
1819 SET_STATUS_Failure( VKI_EINVAL );
1821 ARG2 = arg2tmp; // used in POST
1825 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
1830 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
1831 PRE_REG_READ3(long, "shmctl",
1832 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
1833 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
1837 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
1842 PRINT("shmdt ( %#lx )",ARG1);
1843 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
1844 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
1845 SET_STATUS_Failure( VKI_EINVAL );
1849 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
1854 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1855 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
1860 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
1861 PRE_REG_READ3(long, "shm_open",
1862 const char *,"name", int,"flags", vki_mode_t,"mode");
1864 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
1866 *flags |= SfMayBlock;
1871 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
1873 SET_STATUS_Failure( VKI_EMFILE );
1875 if (VG_(clo_track_fds))
1876 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
1883 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1884 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1885 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
1886 void *, fsacl, vki_size_t *, fsacl_size);
1887 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
1888 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1889 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1890 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1891 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1895 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1896 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1897 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1898 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1904 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1905 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1906 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
1907 void *, fsacl, vki_size_t *, fsacl_size);
1908 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
1909 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1910 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1911 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1912 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1914 POST(lstat_extended)
1916 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1917 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1918 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1919 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1925 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
1926 ARG1, ARG2, ARG3, ARG4);
1927 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
1928 void *, fsacl, vki_size_t *, fsacl_size);
1929 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
1930 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1931 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1932 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1934 POST(fstat_extended)
1936 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
1937 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1938 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1939 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1943 PRE(stat64_extended)
1945 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1946 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1947 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
1948 void *, fsacl, vki_size_t *, fsacl_size);
1949 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
1950 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1951 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1952 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1953 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1955 POST(stat64_extended)
1957 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1958 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1959 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1960 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1964 PRE(lstat64_extended)
1966 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
1967 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
1968 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
1969 void *, fsacl, vki_size_t *, fsacl_size);
1970 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
1971 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1972 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1973 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1974 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1976 POST(lstat64_extended)
1978 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1979 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1980 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
1981 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
1985 PRE(fstat64_extended)
1987 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
1988 ARG1, ARG2, ARG3, ARG4);
1989 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
1990 void *, fsacl, vki_size_t *, fsacl_size);
1991 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
1992 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
1993 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
1994 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
1996 POST(fstat64_extended)
1998 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1999 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2000 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2001 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2005 PRE(fchmod_extended)
2007 /* DDD: Note: this is not really correct. Handling of
2008 chmod_extended is broken in the same way. */
2009 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2010 ARG1, ARG2, ARG3, ARG4, ARG5);
2011 PRE_REG_READ5(long, "fchmod",
2012 unsigned int, fildes,
2016 void* /*really,user_addr_t*/, xsecurity);
2017 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2018 is just way wrong. [The trouble is with the size, which depends on a
2019 non-trival kernel computation] */
2020 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2021 sizeof(struct kauth_filesec) );
2026 /* DDD: Note: this is not really correct. Handling of
2027 fchmod_extended is broken in the same way. */
2028 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2029 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2030 PRE_REG_READ5(long, "chmod",
2031 unsigned int, fildes,
2035 void* /*really,user_addr_t*/, xsecurity);
2036 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2037 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2038 is just way wrong. [The trouble is with the size, which depends on a
2039 non-trival kernel computation] */
2040 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2041 sizeof(struct kauth_filesec) );
2045 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2046 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2047 // by one or more strings. Each accessx_descriptor contains a field,
2048 // 'ad_name_offset', which points to one of the strings (or it can contain
2049 // zero which means "reuse the string from the previous accessx_descriptor").
2051 // What's really ridiculous is that we are only given the size of the overall
2052 // buffer, not the number of accessx_descriptors, nor the number of strings.
2053 // The kernel determines the number of accessx_descriptors by walking through
2054 // them one by one, checking that the ad_name_offset points within the buffer,
2055 // past the current point (or that it's a zero, unless its the first
2056 // descriptor); if so, we assume that this really is an accessx_descriptor,
2057 // if not, we assume we've hit the strings section. Gah.
2059 // This affects us here because number of entries in the 'results' buffer is
2060 // determined by the number of accessx_descriptors. So we have to know that
2061 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2062 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2063 // computation after the syscall has succeeded, because the kernel will have
2064 // checked for all the zillion different ways this syscall can fail, and we'll
2065 // know we have a well-formed 'entries' buffer. This means we might miss some
2066 // uses of unaddressable memory but oh well.
2068 PRE(access_extended)
2070 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2071 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2072 // XXX: the accessx_descriptor struct contains padding, so this can cause
2073 // unnecessary undefined value errors. But you arguably shouldn't be
2074 // passing undefined values to the kernel anyway...
2075 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2076 vki_errno_t *, results, vki_uid_t *, uid);
2077 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2079 // XXX: as mentioned above, this check is too hard to do before the
2081 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2083 POST(access_extended)
2085 // 'n_descs' is the number of descriptors we think are in the buffer. We
2086 // start with the maximum possible value, which occurs if we have the
2087 // shortest possible string section. The shortest string section allowed
2088 // consists of a single one-char string (plus the NUL char). Hence the
2090 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2092 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2093 Int i; // Current position in the descriptors section array.
2094 Int u; // Upper bound on the length of the descriptors array
2095 // (recomputed each time around the loop)
2096 vg_assert(n_descs > 0);
2098 // Step through the descriptors, lowering 'n_descs' until we know we've
2099 // reached the string section.
2100 for (i = 0; True; i++) {
2101 // If we're past our estimate, we must be one past the end of the
2102 // descriptors section (ie. at the start of the string section). Stop.
2106 // Get the array index for the string, but pretend momentarily that it
2107 // is actually another accessx_descriptor. That gives us an upper bound
2108 // on the length of the descriptors section. (Unless the index is zero,
2109 // in which case we have no new info.)
2110 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2116 // If the upper bound is below our current estimate, revise that
2117 // estimate downwards.
2123 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2125 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2131 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2132 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2133 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2135 // GrP fixme sanity-check flags value?
2140 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2141 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2143 // GrP fixme sanity-check flags value?
2148 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2149 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2150 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2151 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2155 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2160 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2161 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2162 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2163 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2167 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2172 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2173 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2174 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2178 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2183 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2184 PRE_REG_READ3(int, "getfsstat",
2185 struct vki_statfs *, buf, int, bufsize, int, flags);
2187 // ARG2 is a BYTE SIZE
2188 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2194 // RES is a STRUCT COUNT
2195 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2201 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2202 PRE_REG_READ3(int, "getfsstat64",
2203 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2205 // ARG2 is a BYTE SIZE
2206 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2212 // RES is a STRUCT COUNT
2213 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2219 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2220 // We are conservative and check everything, except the memory pointed to
2222 *flags |= SfMayBlock;
2223 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2224 ARG1,(Char*)ARG1, ARG2,(Char*)ARG2, ARG3, ARG4);
2225 PRE_REG_READ4(long, "mount",
2226 const char *, type, const char *, dir,
2227 int, flags, void *, data);
2228 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2229 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2233 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2234 void *attrBuf, SizeT attrBufSize,
2235 void (*fn)(ThreadId, void *attrData, SizeT size)
2242 static const attrspec commonattr[] = {
2243 // This order is important.
2244 { ATTR_CMN_NAME, -1 },
2245 { ATTR_CMN_DEVID, sizeof(dev_t) },
2246 { ATTR_CMN_FSID, sizeof(fsid_t) },
2247 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
2248 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
2249 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
2250 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
2251 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
2252 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
2253 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
2254 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
2255 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
2256 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
2257 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
2258 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2259 { ATTR_CMN_OWNERID, sizeof(uid_t) },
2260 { ATTR_CMN_GRPID, sizeof(gid_t) },
2261 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
2262 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
2263 { ATTR_CMN_NAMEDATTRLIST, -1 },
2264 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
2265 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
2266 { ATTR_CMN_FILEID, sizeof(uint64_t) },
2267 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
2270 static const attrspec volattr[] = {
2271 // This order is important.
2272 { ATTR_VOL_INFO, 0 },
2273 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
2274 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
2275 { ATTR_VOL_SIZE, sizeof(off_t) },
2276 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
2277 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
2278 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
2279 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2280 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
2281 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
2282 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
2283 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
2284 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
2285 { ATTR_VOL_MOUNTPOINT, -1 },
2286 { ATTR_VOL_NAME, -1 },
2287 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
2288 { ATTR_VOL_MOUNTEDDEVICE, -1 },
2289 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
2290 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
2291 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
2294 static const attrspec dirattr[] = {
2295 // This order is important.
2296 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
2297 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
2298 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
2301 static const attrspec fileattr[] = {
2302 // This order is important.
2303 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
2304 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
2305 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
2306 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
2307 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
2308 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
2309 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
2310 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
2311 { ATTR_FILE_FORKLIST, -1 },
2312 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
2313 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
2314 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
2315 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
2316 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
2317 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
2320 static const attrspec forkattr[] = {
2321 // This order is important.
2322 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
2323 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
2327 static const attrspec *attrdefs[5] = {
2328 commonattr, volattr, dirattr, fileattr, forkattr
2334 vg_assert(attrList->bitmapcount == 5);
2335 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
2337 dend = d + attrBufSize;
2339 for (g = 0; g < 5; g++) {
2340 for (i = 0; attrdefs[g][i].attrBit; i++) {
2341 uint32_t bit = attrdefs[g][i].attrBit;
2342 int32_t size = attrdefs[g][i].attrSize;
2345 a[g] &= ~bit; // clear bit for error check later
2347 attrreference_t *ref = (attrreference_t *)d;
2348 size = MIN(sizeof(attrreference_t), dend - d);
2350 if (size >= sizeof(attrreference_t) &&
2351 d + ref->attr_dataoffset < dend)
2353 fn(tid, d + ref->attr_dataoffset,
2354 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
2359 size = MIN(size, dend - d);
2364 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
2365 if (d > dend) d = dend;
2369 // Known bits are cleared. Die if any bits are left.
2371 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
2376 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2378 POST_MEM_WRITE((Addr)attrData, attrDataSize);
2381 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2383 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
2388 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2389 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2390 PRE_REG_READ5(int, "getattrlist",
2391 const char *,path, struct vki_attrlist *,attrList,
2392 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2393 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
2394 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2395 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
2400 if (ARG4 > sizeof(vki_uint32_t)) {
2401 // attrBuf is uint32_t bytes written followed by attr data
2402 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
2403 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
2404 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, *sizep, &get1attr);
2411 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2412 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2413 PRE_REG_READ5(int, "setattrlist",
2414 const char *,path, struct vki_attrlist *,attrList,
2415 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2416 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
2417 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2418 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
2422 PRE(getdirentriesattr)
2424 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
2425 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2426 PRE_REG_READ8(int, "getdirentriesattr",
2427 int,fd, struct vki_attrlist *,attrList,
2428 void *,attrBuf, size_t,attrBufSize,
2429 unsigned int *,count, unsigned int *,basep,
2430 unsigned int *,newState, unsigned int,options);
2431 PRE_MEM_READ("getdirentriesattr(attrList)",
2432 ARG2, sizeof(struct vki_attrlist));
2433 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
2434 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2435 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2436 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
2437 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
2439 POST(getdirentriesattr)
2445 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
2446 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
2447 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
2449 // return buffer is concatenation of variable-size structs
2450 count = *(unsigned int *)ARG5;
2452 end = (char *)ARG3 + ARG4;
2453 for (i = 0; i < count; i++) {
2454 vg_assert(p < end); // failure is kernel bug or Valgrind bug
2455 p += *(unsigned int *)p;
2458 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
2460 PRINT("got %d records, %d/%lu bytes\n", count, p-(char *)ARG3, ARG4);
2466 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
2467 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
2468 PRE_REG_READ3(int, "exchangedata",
2469 char *, path1, char *, path2, unsigned long, options);
2470 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
2471 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
2476 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
2477 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2478 PRE_REG_READ4( long, "fsctl",
2479 char *,"path", unsigned int,"request",
2480 void *,"data", unsigned int,"options");
2482 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
2485 case VKI_afpfsByteRangeLock2FSCTL: {
2486 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2487 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
2489 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
2491 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
2493 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
2495 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
2498 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
2501 // GrP fixme check fd
2504 case VKI_FSIOC_SYNC_VOLUME:
2505 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
2509 // fsctl requests use ioctl encoding
2510 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
2518 case VKI_afpfsByteRangeLock2FSCTL: {
2519 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2520 POST_FIELD_WRITE(pb->retRangeStart);
2523 case VKI_FSIOC_SYNC_VOLUME:
2527 // fsctl requests use ioctl encoding
2528 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
2535 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
2536 PRE_REG_READ3(long, "initgroups",
2537 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
2538 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
2542 //--------- posix_spawn ---------//
2543 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
2544 the simpler AIX equivalent (syswrap-aix5.c). */
2545 // Pre_read a char** argument.
2546 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
2550 Addr* a_p = (Addr*)a;
2551 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2555 PRE_MEM_RASCIIZ( s2, a_deref );
2559 static SysRes simple_pre_exec_check ( const HChar* exe_name,
2560 Bool trace_this_child )
2564 Bool setuid_allowed;
2566 // Check it's readable
2567 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
2568 if (sr_isError(res)) {
2574 // Check we have execute permissions. We allow setuid executables
2575 // to be run only in the case when we are not simulating them, that
2576 // is, they to be run natively.
2577 setuid_allowed = trace_this_child ? False : True;
2578 ret = VG_(check_executable)(NULL/*&is_setuid*/,
2579 (HChar*)exe_name, setuid_allowed);
2581 return VG_(mk_SysRes_Error)(ret);
2583 return VG_(mk_SysRes_Success)(0);
2587 Char* path = NULL; /* path to executable */
2591 Char* launcher_basename = NULL;
2594 Bool trace_this_child;
2598 posix_spawn_file_actions_t* file_actions
2602 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
2603 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2605 /* Standard pre-syscall checks */
2607 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
2608 void*, file_actions, char**, argv, char**, envp );
2609 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
2610 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
2611 // DDD: check file_actions
2613 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
2614 "posix_spawn(argv[i])" );
2616 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
2617 "posix_spawn(envp[i])" );
2620 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
2621 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2623 /* Now follows a bunch of logic copied from PRE(sys_execve) in
2624 syswrap-generic.c. */
2626 /* Check that the name at least begins in client-accessible storage. */
2627 if (ARG2 == 0 /* obviously bogus */
2628 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
2629 SET_STATUS_Failure( VKI_EFAULT );
2633 // Decide whether or not we want to follow along
2634 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2 );
2636 // Do the important checks: it is a file, is executable, permissions are
2637 // ok, etc. We allow setuid executables to run only in the case when
2638 // we are not simulating them, that is, they to be run natively.
2639 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
2640 if (sr_isError(res)) {
2641 SET_STATUS_Failure( sr_Err(res) );
2645 /* If we're tracing the child, and the launcher name looks bogus
2646 (possibly because launcher.c couldn't figure it out, see
2647 comments therein) then we have no option but to fail. */
2648 if (trace_this_child
2649 && (VG_(name_of_launcher) == NULL
2650 || VG_(name_of_launcher)[0] != '/')) {
2651 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2655 /* Ok. So let's give it a try. */
2656 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2);
2658 // Set up the child's exe path.
2660 if (trace_this_child) {
2662 // We want to exec the launcher. Get its pre-remembered path.
2663 path = VG_(name_of_launcher);
2664 // VG_(name_of_launcher) should have been acquired by m_main at
2665 // startup. The following two assertions should be assured by
2666 // the "If we're tracking the child .." test just above here.
2668 vg_assert(path[0] == '/');
2669 launcher_basename = path;
2675 // Set up the child's environment.
2677 // Remove the valgrind-specific stuff from the environment so the
2678 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
2679 // This is done unconditionally, since if we are tracing the child,
2680 // the child valgrind will set up the appropriate client environment.
2681 // Nb: we make a copy of the environment before trying to mangle it
2682 // as it might be in read-only memory (this was bug #101881).
2684 // Then, if tracing the child, set VALGRIND_LIB for it.
2689 envp = VG_(env_clone)( (Char**)ARG5 );
2691 VG_(env_remove_valgrind_env_stuff)( envp );
2694 if (trace_this_child) {
2695 // Set VALGRIND_LIB in ARG5 (the environment)
2696 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
2699 // Set up the child's args. If not tracing it, they are
2700 // simply ARG4. Otherwise, they are
2702 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
2704 // except that the first VG_(args_for_valgrind_noexecpass) args
2707 if (!trace_this_child) {
2708 argv = (Char**)ARG4;
2710 vg_assert( VG_(args_for_valgrind) );
2711 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2712 vg_assert( VG_(args_for_valgrind_noexecpass)
2713 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
2714 /* how many args in total will there be? */
2715 // launcher basename
2718 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
2719 tot_args -= VG_(args_for_valgrind_noexecpass);
2720 // name of client exe
2722 // args for client exe, skipping [0]
2723 arg2copy = (Char**)ARG4;
2724 if (arg2copy && arg2copy[0]) {
2725 for (i = 1; arg2copy[i]; i++)
2729 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
2730 (tot_args+1) * sizeof(HChar*) );
2734 argv[j++] = launcher_basename;
2735 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
2736 if (i < VG_(args_for_valgrind_noexecpass))
2738 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
2740 argv[j++] = (Char*)ARG2;
2741 if (arg2copy && arg2copy[0])
2742 for (i = 1; arg2copy[i]; i++)
2743 argv[j++] = arg2copy[i];
2746 vg_assert(j == tot_args+1);
2749 /* DDD: sort out the signal state. What signal
2750 state does the child inherit from the parent? */
2754 VG_(printf)("posix_spawn: %s\n", path);
2755 for (cpp = argv; cpp && *cpp; cpp++)
2756 VG_(printf)("argv: %s\n", *cpp);
2758 for (cpp = envp; cpp && *cpp; cpp++)
2759 VG_(printf)("env: %s\n", *cpp);
2762 /* Let the call go through as usual. However, we have to poke
2763 the altered arguments back into the argument slots. */
2768 /* not to mention .. */
2769 *flags |= SfMayBlock;
2774 //POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
2780 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2781 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
2788 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
2789 SET_STATUS_from_SysRes(r);
2795 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
2796 ARG1,ARG2,ARG3,ARG4,ARG5);
2797 PRE_REG_READ5(long, "setsockopt",
2798 int, s, int, level, int, optname,
2799 const void *, optval, vki_socklen_t, optlen);
2800 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
2806 Addr optval_p = ARG4;
2807 Addr optlen_p = ARG5;
2808 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
2809 ARG1,ARG2,ARG3,ARG4,ARG5);
2810 PRE_REG_READ5(long, "getsockopt",
2811 int, s, int, level, int, optname,
2812 void *, optval, vki_socklen_t *, optlen);
2813 /* int getsockopt(int socket, int level, int option_name,
2814 void *restrict option_value,
2815 socklen_t *restrict option_len); */
2816 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
2817 if (optval_p != (Addr)NULL) {
2818 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
2819 "socketcall.getsockopt(optval)",
2820 "socketcall.getsockopt(optlen)" );
2822 // DDD: #warning GrP fixme darwin-specific sockopts
2827 Addr optval_p = ARG4;
2828 Addr optlen_p = ARG5;
2830 if (optval_p != (Addr)NULL) {
2831 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
2833 "socketcall.getsockopt(optlen_out)" );
2834 // DDD: #warning GrP fixme darwin-specific sockopts
2841 *flags |= SfMayBlock;
2842 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2843 PRE_REG_READ3(long, "connect",
2844 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
2845 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
2851 *flags |= SfMayBlock;
2852 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2853 PRE_REG_READ3(long, "accept",
2854 int, s, struct sockaddr *, addr, int, *addrlen);
2855 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
2862 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
2864 SET_STATUS_from_SysRes(r);
2870 *flags |= SfMayBlock;
2871 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
2872 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
2873 PRE_REG_READ6(long, "sendto",
2874 int, s, const void *, msg, int, len,
2875 unsigned int, flags,
2876 const struct sockaddr *, to, int, tolen);
2877 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2882 #if VG_WORDSIZE == 4
2883 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
2884 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
2886 PRE_REG_READ7(long, "sendfile",
2887 int, fromfd, int, tofd,
2888 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
2889 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
2890 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
2891 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
2893 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
2894 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2896 PRE_REG_READ6(long, "sendfile",
2897 int, fromfd, int, tofd,
2898 vki_uint64_t, offset,
2899 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
2900 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
2901 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
2904 *flags |= SfMayBlock;
2908 #if VG_WORDSIZE == 4
2909 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
2910 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
2912 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
2913 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
2919 *flags |= SfMayBlock;
2920 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
2921 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2922 PRE_REG_READ6(long, "recvfrom",
2923 int, s, void *, buf, int, len, unsigned int, flags,
2924 struct sockaddr *, from, int *, fromlen);
2925 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2931 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
2932 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
2938 *flags |= SfMayBlock;
2939 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2940 PRE_REG_READ3(long, "sendmsg",
2941 int, s, const struct msghdr *, msg, int, flags);
2942 ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
2948 *flags |= SfMayBlock;
2949 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2950 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
2951 ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
2956 ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
2962 *flags |= SfMayBlock;
2963 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
2964 PRE_REG_READ2(int, "shutdown", int, s, int, how);
2970 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2971 PRE_REG_READ3(long, "bind",
2972 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
2973 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
2979 PRINT("listen ( %ld, %ld )",ARG1,ARG2);
2980 PRE_REG_READ2(long, "listen", int, s, int, backlog);
2986 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
2987 PRE_REG_READ3(long, "getsockname",
2988 int, s, struct sockaddr *, name, int *, namelen);
2989 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
2995 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3002 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3003 PRE_REG_READ3(long, "getpeername",
3004 int, s, struct sockaddr *, name, int *, namelen);
3005 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3011 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3018 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3019 PRE_REG_READ4(long, "socketpair",
3020 int, d, int, type, int, protocol, int *, sv);
3021 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3027 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3028 ARG1,ARG2,ARG3,ARG4);
3034 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3035 PRE_REG_READ2(int,"gethostuuid",
3037 const struct vki_timespec *,"timeout");
3039 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3040 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3042 *flags |= SfMayBlock;
3048 POST_MEM_WRITE(ARG1, 16);
3051 /* Darwin pipe() returns the two descriptors in two registers. */
3055 PRE_REG_READ0(int, "pipe");
3065 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3066 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3069 SET_STATUS_Failure( VKI_EMFILE );
3071 if (VG_(clo_track_fds)) {
3072 ML_(record_fd_open_nameless)(tid, p0);
3073 ML_(record_fd_open_nameless)(tid, p1);
3081 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3082 PRE_REG_READ2(long, "getlogin",
3083 char *,"namebuf", unsigned int,"namelen");
3085 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3090 POST_MEM_WRITE(ARG1, ARG2);
3096 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3097 PRE_REG_READ4(long, "ptrace",
3098 int,"request", vki_pid_t,"pid",
3099 vki_caddr_t,"addr", int,"data");
3101 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3103 // GrP fixme anything needed?
3109 PRINT("issetugid ( )");
3110 PRE_REG_READ0(long, "issetugid");
3116 PRINT("getdtablesize ( )");
3117 PRE_REG_READ0(long, "getdtablesize");
3122 // Subtract Valgrind's fd range from client's dtable
3123 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3128 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3129 PRE_REG_READ4(vki_off_t, "lseek",
3130 unsigned int,fd, int,offset_hi, int,offset_lo,
3131 unsigned int,whence);
3137 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3138 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3139 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3145 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3146 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3148 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3149 SET_STATUS_Failure( VKI_EBADF );
3155 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3156 PRE_REG_READ4(int, "getdirentries",
3157 int, fd, char *, buf, int, nbytes, long *, basep);
3158 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3159 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3164 POST_MEM_WRITE(ARG4, sizeof(long));
3165 // GrP fixme be specific about d_name?
3166 POST_MEM_WRITE(ARG2, RES);
3170 PRE(getdirentries64)
3172 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3173 PRE_REG_READ4(vki_ssize_t, "getdirentries",
3174 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3175 PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t));
3176 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3178 POST(getdirentries64)
3180 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3181 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3182 POST_MEM_WRITE(ARG2, RES);
3188 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3189 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3190 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3191 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3195 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3201 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3202 PRE_REG_READ2(long, "fstatfs64",
3203 unsigned int, fd, struct statfs *, buf);
3204 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3208 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3213 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
3214 PRE_REG_READ4(int, "csops",
3215 vki_pid_t, pid, uint32_t, ops,
3216 void *, useraddr, vki_size_t, usersize);
3218 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
3220 // If the pid is ours, don't mark the program as KILL or HARD
3221 // Maybe we should keep track of this for later calls to STATUS
3222 if (!ARG1 || VG_(getpid)() == ARG1) {
3224 case VKI_CS_OPS_MARKINVALID:
3225 case VKI_CS_OPS_MARKHARD:
3226 case VKI_CS_OPS_MARKKILL:
3227 SET_STATUS_Success(0);
3233 POST_MEM_WRITE( ARG3, ARG4 );
3238 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
3239 PRE_REG_READ3(int,"auditon",
3240 int,"cmd", void*,"data", unsigned int,"length");
3244 case VKI_A_SETPOLICY:
3245 case VKI_A_SETKMASK:
3246 case VKI_A_SETQCTRL:
3248 case VKI_A_SETCLASS:
3249 case VKI_A_SETPMASK:
3250 case VKI_A_SETFSIZE:
3251 // kernel reads data..data+length
3252 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3255 case VKI_A_GETKMASK:
3256 case VKI_A_GETPOLICY:
3257 case VKI_A_GETQCTRL:
3258 case VKI_A_GETFSIZE:
3260 // kernel writes data..data+length
3261 // GrP fixme be precise about what gets written
3262 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3266 case VKI_A_GETCLASS:
3267 case VKI_A_GETPINFO:
3268 case VKI_A_GETPINFO_ADDR:
3269 // kernel reads and writes data..data+length
3270 // GrP fixme be precise about what gets read and written
3271 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3272 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3275 case VKI_A_SETKAUDIT:
3277 case VKI_A_SETUMASK:
3278 case VKI_A_SETSMASK:
3279 case VKI_A_GETKAUDIT:
3283 // unimplemented on darwin
3287 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1);
3295 case VKI_A_SETPOLICY:
3296 case VKI_A_SETKMASK:
3297 case VKI_A_SETQCTRL:
3299 case VKI_A_SETCLASS:
3300 case VKI_A_SETPMASK:
3301 case VKI_A_SETFSIZE:
3302 // kernel reads data..data+length
3305 case VKI_A_GETKMASK:
3306 case VKI_A_GETPOLICY:
3307 case VKI_A_GETQCTRL:
3308 case VKI_A_GETFSIZE:
3310 // kernel writes data..data+length
3311 // GrP fixme be precise about what gets written
3312 POST_MEM_WRITE(ARG2, ARG3);
3316 case VKI_A_GETCLASS:
3317 case VKI_A_GETPINFO:
3318 case VKI_A_GETPINFO_ADDR:
3319 // kernel reads and writes data..data+length
3320 // GrP fixme be precise about what gets read and written
3321 POST_MEM_WRITE(ARG2, ARG3);
3324 case VKI_A_SETKAUDIT:
3326 case VKI_A_SETUMASK:
3327 case VKI_A_SETSMASK:
3328 case VKI_A_GETKAUDIT:
3332 // unimplemented on darwin
3345 #if VG_WORDSIZE == 4
3346 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
3347 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
3348 PRE_REG_READ7(Addr, "mmap",
3349 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3350 unsigned long,offset_hi, unsigned long,offset_lo);
3351 // GrP fixme V mmap and kernel mach_msg collided once - don't use
3352 // V's mechanism for now
3353 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
3354 // (Off64T)LOHI64(ARG6, ARG7) );
3356 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
3357 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3358 PRE_REG_READ6(long, "mmap",
3359 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3361 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3365 // SET_STATUS_from_SysRes(r);
3371 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
3372 // Try to load symbols from the region
3373 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/ );
3380 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
3381 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3383 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
3384 void*, oldp, vki_size_t *, oldlenp,
3385 void*, newp, vki_size_t *, newlenp);
3387 PRE_MEM_READ("sysctl(name)", ARG1, ARG2); // reads name[0..namelen-1]
3390 PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
3392 // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
3393 PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
3394 PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
3398 PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
3401 if (VG_(clo_trace_syscalls)) {
3403 int *name = (int *)ARG1;
3404 VG_(printf)(" mib: [ ");
3405 for (i = 0; i < ARG2; i++) {
3406 VG_(printf)("%d ", name[i]);
3411 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
3412 // (executable path and arguments and environment
3415 // Intercept sysctl(kern.usrstack). The kernel's reply would be
3416 // Valgrind's stack, not the client's stack.
3417 // GrP fixme kern_usrstack64
3418 if (ARG1 && ARG2 == 2 &&
3419 ((int *)ARG1)[0] == VKI_CTL_KERN &&
3420 #if VG_WORDSIZE == 4
3421 ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
3423 ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
3427 if (ARG5/*newp*/ || ARG6/*newlen*/) {
3428 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
3430 Addr *oldp = (Addr *)ARG3;
3431 size_t *oldlenp = (size_t *)ARG4;
3433 Addr stack_end = VG_(clstk_end)+1;
3434 size_t oldlen = *oldlenp;
3435 // always return actual size
3436 *oldlenp = sizeof(Addr);
3437 if (oldp && oldlen >= sizeof(Addr)) {
3438 // oldp is big enough
3439 // copy value and return 0
3441 SET_STATUS_Success(0);
3443 // oldp isn't big enough
3444 // copy as much as possible and return ENOMEM
3445 if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
3446 SET_STATUS_Failure(VKI_ENOMEM);
3453 if (!SUCCESS && !FAILURE) {
3454 // Don't set SfPostOnFail if we've already handled it locally.
3455 *flags |= SfPostOnFail;
3461 if (SUCCESS || ERR == VKI_ENOMEM) {
3462 // sysctl can write truncated data and return VKI_ENOMEM
3464 POST_MEM_WRITE(ARG4, sizeof(size_t));
3467 POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
3475 PRINT( "sigpending ( %#lx )", ARG1 );
3476 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
3477 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
3481 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
3488 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
3489 PRE_REG_READ3(long, "sigprocmask",
3490 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
3492 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
3494 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
3496 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
3497 value of 'how' is irrelevant, and it appears that Darwin's libc
3498 passes zero, which is not equal to any of
3499 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
3500 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
3501 value independently of the other args. Solution: in this case,
3502 simply pass a valid (but irrelevant) value for 'how'. */
3503 /* Also, in this case the new set is passed to the kernel by
3504 reference, not value, as in some other sigmask related Darwin
3507 if (ARG2 == 0 /* the new-set is NULL */
3508 && ARG1 != VKI_SIG_BLOCK
3509 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
3510 arg1 = VKI_SIG_SETMASK;
3512 SET_STATUS_from_SysRes(
3513 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
3514 (vki_sigset_t*)ARG3 )
3518 *flags |= SfPollAfter;
3524 if (RES == 0 && ARG3 != 0)
3525 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
3531 /* Just hand this off to the kernel. Is that really correct? And
3532 shouldn't we at least set SfPollAfter? These questions apply to
3533 all the Linux versions too. */
3534 /* I think the first arg is the 32-bit signal mask (by value), and
3535 the other two args are ignored. */
3536 *flags |= SfMayBlock;
3537 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
3538 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
3541 /* ---------------------------------------------------------------------
3543 ------------------------------------------------------------------ */
3545 // We must record the aiocbp for each aio_read() in a table so that when
3546 // aio_return() is called we can mark the memory written asynchronously by
3547 // aio_read() as having been written. We don't have to do this for
3548 // aio_write(). See bug 197227 for more details.
3549 static OSet* aiocbp_table = NULL;
3550 static Bool aio_init_done = False;
3552 static void aio_init(void)
3554 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
3555 aio_init_done = True;
3558 static Bool was_a_successful_aio_read = False;
3562 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3563 // This assumes that the kernel looks at the struct pointer, but not the
3564 // contents of the struct.
3565 PRINT( "aio_return ( %#lx )", ARG1 );
3566 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
3568 if (!aio_init_done) aio_init();
3569 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
3573 // If we found the aiocbp in our own table it must have been an aio_read(),
3574 // so mark the buffer as written. If we didn't find it, it must have been
3575 // an aio_write() or a bogus aio_return() (eg. a second one on the same
3576 // aiocbp). Either way, the buffer won't have been written so we don't
3577 // have to mark the buffer as written.
3578 if (was_a_successful_aio_read) {
3579 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3580 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3581 was_a_successful_aio_read = False;
3587 // This assumes that the kernel looks at the struct pointers in the list,
3588 // but not the contents of the structs.
3589 PRINT( "aio_suspend ( %#lx )", ARG1 );
3590 PRE_REG_READ3(long, "aio_suspend",
3591 const struct vki_aiocb *, aiocbp, int, nent,
3592 const struct vki_timespec *, timeout);
3594 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
3596 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
3601 // This assumes that the kernel looks at the struct pointer, but not the
3602 // contents of the struct.
3603 PRINT( "aio_error ( %#lx )", ARG1 );
3604 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
3609 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3611 PRINT( "aio_read ( %#lx )", ARG1 );
3612 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
3613 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3615 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3616 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
3617 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
3618 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3620 SET_STATUS_Failure( VKI_EBADF );
3623 SET_STATUS_Failure( VKI_EINVAL );
3628 // We have to record the fact that there is an asynchronous read request
3629 // pending. When a successful aio_return() occurs for this aiocb, then we
3630 // will mark the memory as having been defined.
3631 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3632 if (!aio_init_done) aio_init();
3633 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
3634 // should have caused the aio_read() to fail and we shouldn't have reached
3636 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
3641 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3643 PRINT( "aio_write ( %#lx )", ARG1 );
3644 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
3645 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
3647 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
3648 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
3649 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
3650 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3652 SET_STATUS_Failure( VKI_EBADF );
3655 SET_STATUS_Failure( VKI_EINVAL );
3659 /* ---------------------------------------------------------------------
3660 mach_msg: formatted messages
3661 ------------------------------------------------------------------ */
3663 static size_t desc_size(mach_msg_descriptor_t *desc)
3665 switch (desc->type.type) {
3666 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
3667 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
3668 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
3669 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
3671 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
3672 return sizeof(desc->type); // guess
3677 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
3681 mach_port_t *ports = (mach_port_t *)desc->address;
3682 for (i = 0; i < desc->count; i++) {
3683 assign_port_name(ports[i], name);
3688 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
3690 mach_msg_body_t *body;
3691 mach_msg_size_t count, i;
3693 mach_msg_descriptor_t *desc;
3695 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
3697 body = (mach_msg_body_t *)(mh+1);
3698 count = body->msgh_descriptor_count;
3699 p = (uint8_t *)(body+1);
3701 for (i = 0; i < count; i++) {
3702 desc = (mach_msg_descriptor_t *)p;
3703 p += desc_size(desc);
3705 switch (desc->type.type) {
3706 case MACH_MSG_PORT_DESCRIPTOR:
3708 record_unnamed_port(tid, desc->port.name, -1);
3709 record_port_insert_rights(desc->port.name, desc->port.disposition);
3710 PRINT("got port %s;\n", name_for_port(desc->port.name));
3713 case MACH_MSG_OOL_DESCRIPTOR:
3714 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3715 // out-of-line memory - map it
3716 // GrP fixme how is VOLATILE different? do we care?
3717 // GrP fixme do other flags tell us anything? assume shared for now
3718 // GrP fixme more SF_ flags marking mach_msg memory might be nice
3719 // GrP fixme protection
3720 if (desc->out_of_line.size > 0) {
3721 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
3722 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
3723 (Addr)desc->out_of_line.size);
3724 PRINT("got ool mem %p..%#lx;\n", desc->out_of_line.address,
3725 (Addr)desc->out_of_line.address+desc->out_of_line.size);
3727 ML_(notify_core_and_tool_of_mmap)(
3728 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3729 VKI_MAP_PRIVATE, -1, 0);
3731 // GrP fixme mark only un-rounded part as initialized
3734 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3735 // out-of-line array of ports - map it
3736 // GrP fixme see fixmes above
3737 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));
3739 if (desc->ool_ports.count > 0) {
3740 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
3741 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
3742 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
3744 ML_(notify_core_and_tool_of_mmap)(
3745 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
3746 VKI_MAP_PRIVATE, -1, 0);
3749 for (i = 0; i < desc->ool_ports.count; i++) {
3750 record_unnamed_port(tid, ports[i], -1);
3751 record_port_insert_rights(ports[i], desc->port.disposition);
3752 PRINT(" %s", name_for_port(ports[i]));
3759 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
3766 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
3771 mach_msg_size_t pad1;
3773 uint8_t disposition;
3775 } *desc = (void*)desc2;
3778 PRE_FIELD_READ("msg->desc.port.name", desc->name);
3779 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
3780 PRE_FIELD_READ("msg->desc.port.type", desc->type);
3784 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
3789 #if VG_WORDSIZE != 8
3790 mach_msg_size_t size;
3796 #if VG_WORDSIZE == 8
3797 mach_msg_size_t size;
3799 } *desc = (void*)desc2;
3802 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
3803 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
3804 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
3805 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
3806 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
3809 static void pre_oolports_desc_read(ThreadId tid,
3810 mach_msg_ool_ports_descriptor_t *desc2)
3815 #if VG_WORDSIZE != 8
3816 mach_msg_size_t size;
3820 uint8_t disposition;
3822 #if VG_WORDSIZE == 8
3823 mach_msg_size_t size;
3825 } *desc = (void*)desc2;
3828 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
3829 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
3830 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
3831 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
3832 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
3833 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
3837 // Returns the size of the descriptor area
3838 // (mach_msg_body_t + any mach_msg_descriptor_t)
3839 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
3841 mach_msg_body_t *body;
3842 mach_msg_size_t count, i;
3844 mach_msg_descriptor_t *desc;
3846 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
3848 body = (mach_msg_body_t *)(mh+1);
3849 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
3851 count = body->msgh_descriptor_count;
3852 p = (uint8_t *)(body+1);
3854 for (i = 0; i < count; i++) {
3855 desc = (mach_msg_descriptor_t *)p;
3856 p += desc_size(desc);
3858 switch (desc->type.type) {
3859 case MACH_MSG_PORT_DESCRIPTOR:
3860 // single port; no memory map effects
3861 pre_port_desc_read(tid, &desc->port);
3864 case MACH_MSG_OOL_DESCRIPTOR:
3865 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
3866 // out-of-line memory - unmap it if it's marked dealloc
3867 // GrP fixme need to remap if message fails?
3868 // GrP fixme how is VOLATILE different? do we care?
3869 // GrP fixme struct is different for lp64
3870 pre_ool_desc_read(tid, &desc->out_of_line);
3872 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
3873 vm_size_t size = desc->out_of_line.size;
3874 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
3875 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
3876 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
3877 (Addr)desc->out_of_line.address + size);
3878 ML_(notify_core_and_tool_of_munmap)(start, end - start);
3882 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
3883 // out-of-line array of ports - unmap it if it's marked dealloc
3884 // GrP fixme need to remap if message fails?
3885 // GrP fixme struct different for lp64
3886 pre_oolports_desc_read(tid, &desc->ool_ports);
3888 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
3889 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
3890 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
3891 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
3892 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
3893 (Addr)desc->ool_ports.address + size);
3894 ML_(notify_core_and_tool_of_munmap)(start, end - start);
3898 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
3903 return (size_t)((Addr)p - (Addr)body);
3907 /* ---------------------------------------------------------------------
3908 mach_msg: host-related messages
3909 ------------------------------------------------------------------ */
3916 mach_msg_header_t Head;
3918 kern_return_t RetCode;
3919 mach_msg_type_number_t host_info_outCnt;
3920 integer_t host_info_out[14];
3924 Reply *reply = (Reply *)ARG1;
3926 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
3933 mach_msg_header_t Head;
3935 host_flavor_t flavor;
3936 mach_msg_type_number_t host_info_outCnt;
3940 Request *req = (Request *)ARG1;
3942 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
3944 AFTER = POST_FN(host_info);
3948 POST(host_page_size)
3952 mach_msg_header_t Head;
3954 kern_return_t RetCode;
3955 vm_size_t out_page_size;
3959 Reply *reply = (Reply *)ARG1;
3961 if (!reply->RetCode) {
3962 PRINT("page size %u", reply->out_page_size);
3964 PRINT("mig return %d", reply->RetCode);
3970 PRINT("host_page_size(mach_host_self(), ...)");
3972 AFTER = POST_FN(host_page_size);
3976 POST(host_get_io_master)
3980 mach_msg_header_t Head;
3981 /* start of the kernel processed data */
3982 mach_msg_body_t msgh_body;
3983 mach_msg_port_descriptor_t io_master;
3984 /* end of the kernel processed data */
3988 Reply *reply = (Reply *)ARG1;
3990 assign_port_name(reply->io_master.name, "io_master-%p");
3991 PRINT("%s", name_for_port(reply->io_master.name));
3994 PRE(host_get_io_master)
3998 mach_msg_header_t Head;
4002 // Request *req = (Request *)ARG1;
4004 PRINT("host_get_io_master(mach_host_self())");
4006 AFTER = POST_FN(host_get_io_master);
4010 POST(host_get_clock_service)
4014 mach_msg_header_t Head;
4015 /* start of the kernel processed data */
4016 mach_msg_body_t msgh_body;
4017 mach_msg_port_descriptor_t clock_serv;
4018 /* end of the kernel processed data */
4022 Reply *reply = (Reply *)ARG1;
4024 assign_port_name(reply->clock_serv.name, "clock-%p");
4025 PRINT("%s", name_for_port(reply->clock_serv.name));
4028 PRE(host_get_clock_service)
4032 mach_msg_header_t Head;
4034 clock_id_t clock_id;
4038 Request *req = (Request *)ARG1;
4040 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4042 AFTER = POST_FN(host_get_clock_service);
4046 PRE(host_request_notification)
4050 mach_msg_header_t Head;
4051 /* start of the kernel processed data */
4052 mach_msg_body_t msgh_body;
4053 mach_msg_port_descriptor_t notify_port;
4054 /* end of the kernel processed data */
4056 host_flavor_t notify_type;
4060 Request *req = (Request *)ARG1;
4062 if (MACH_REMOTE == mach_task_self()) {
4063 if (req->notify_type == 0) {
4064 PRINT("host_request_notification(mach_host_self(), %s, %s)",
4065 "HOST_NOTIFY_CALENDAR_CHANGE",
4066 name_for_port(req->notify_port.name));
4068 PRINT("host_request_notification(mach_host_self(), %d, %s)",
4070 name_for_port(req->notify_port.name));
4073 PRINT("host_request_notification(%s, %d, %s)",
4074 name_for_port(MACH_REMOTE),
4076 name_for_port(req->notify_port.name));
4079 // GrP fixme only do this on success
4080 assign_port_name(req->notify_port.name, "host_notify-%p");
4084 /* ---------------------------------------------------------------------
4085 mach_msg: messages to a task
4086 ------------------------------------------------------------------ */
4093 mach_msg_header_t Head;
4095 mach_port_name_t name;
4099 Request *req = (Request *)ARG1;
4101 PRINT("mach_port_type(%s, %s, ...)",
4102 name_for_port(MACH_REMOTE), name_for_port(req->name));
4104 AFTER = POST_FN(mach_port_type);
4107 POST(mach_port_type)
4112 PRE(mach_port_extract_member)
4116 mach_msg_header_t Head;
4118 mach_port_name_t name;
4119 mach_port_name_t pset;
4123 Request *req = (Request *)ARG1;
4125 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
4126 name_for_port(MACH_REMOTE),
4127 req->name, req->pset);
4129 AFTER = POST_FN(mach_port_extract_member);
4131 // GrP fixme port tracker?
4134 POST(mach_port_extract_member)
4138 mach_msg_header_t Head;
4140 kern_return_t RetCode;
4144 Reply *reply = (Reply *)ARG1;
4146 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4150 PRE(mach_port_allocate)
4154 mach_msg_header_t Head;
4156 mach_port_right_t right;
4160 Request *req = (Request *)ARG1;
4162 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
4164 MACH_ARG(mach_port_allocate.right) = req->right;
4166 AFTER = POST_FN(mach_port_allocate);
4169 POST(mach_port_allocate)
4173 mach_msg_header_t Head;
4175 kern_return_t RetCode;
4176 mach_port_name_t name;
4180 Reply *reply = (Reply *)ARG1;
4182 if (!reply->RetCode) {
4183 if (MACH_REMOTE == vg_task_port) {
4184 // GrP fixme port tracking is too imprecise
4185 // vg_assert(!port_exists(reply->name));
4186 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
4187 PRINT("got port 0x%x", reply->name);
4189 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
4192 PRINT("mig return %d", reply->RetCode);
4197 PRE(mach_port_deallocate)
4201 mach_msg_header_t Head;
4203 mach_port_name_t name;
4207 Request *req = (Request *)ARG1;
4209 PRINT("mach_port_deallocate(%s, %s)",
4210 name_for_port(MACH_REMOTE),
4211 name_for_port(req->name));
4213 MACH_ARG(mach_port.port) = req->name;
4215 AFTER = POST_FN(mach_port_deallocate);
4217 // Must block to prevent race (other thread allocates and
4218 // notifies after we deallocate but before we notify)
4219 *flags &= ~SfMayBlock;
4222 POST(mach_port_deallocate)
4226 mach_msg_header_t Head;
4228 kern_return_t RetCode;
4232 Reply *reply = (Reply *)ARG1;
4234 if (!reply->RetCode) {
4235 if (MACH_REMOTE == vg_task_port) {
4236 // Must have cleared SfMayBlock in PRE to prevent race
4237 record_port_dealloc(MACH_ARG(mach_port.port));
4239 VG_(printf)("UNKNOWN remote port dealloc\n");
4242 PRINT("mig return %d", reply->RetCode);
4247 PRE(mach_port_get_refs)
4251 mach_msg_header_t Head;
4253 mach_port_name_t name;
4254 mach_port_right_t right;
4258 Request *req = (Request *)ARG1;
4260 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
4261 name_for_port(MACH_REMOTE),
4262 name_for_port(req->name), req->right);
4264 MACH_ARG(mach_port_mod_refs.port) = req->name;
4265 MACH_ARG(mach_port_mod_refs.right) = req->right;
4267 AFTER = POST_FN(mach_port_get_refs);
4270 POST(mach_port_get_refs)
4274 mach_msg_header_t Head;
4276 kern_return_t RetCode;
4277 mach_port_urefs_t refs;
4281 Reply *reply = (Reply *)ARG1;
4283 if (!reply->RetCode) {
4284 PRINT("got refs=%d", reply->refs);
4286 PRINT("mig return %d", reply->RetCode);
4291 PRE(mach_port_mod_refs)
4295 mach_msg_header_t Head;
4297 mach_port_name_t name;
4298 mach_port_right_t right;
4299 mach_port_delta_t delta;
4303 Request *req = (Request *)ARG1;
4305 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
4306 name_for_port(MACH_REMOTE),
4307 name_for_port(req->name), req->right, req->delta);
4309 MACH_ARG(mach_port_mod_refs.port) = req->name;
4310 MACH_ARG(mach_port_mod_refs.right) = req->right;
4311 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
4313 AFTER = POST_FN(mach_port_mod_refs);
4315 // Must block to prevent race (other thread allocates and
4316 // notifies after we deallocate but before we notify)
4317 *flags &= ~SfMayBlock;
4320 POST(mach_port_mod_refs)
4324 mach_msg_header_t Head;
4326 kern_return_t RetCode;
4330 Reply *reply = (Reply *)ARG1;
4332 if (!reply->RetCode) {
4333 if (MACH_REMOTE == vg_task_port) {
4334 // Must have cleared SfMayBlock in PRE to prevent race
4335 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
4336 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
4337 MACH_ARG(mach_port_mod_refs.delta));
4339 VG_(printf)("UNKNOWN remote port mod refs\n");
4342 PRINT("mig return %d", reply->RetCode);
4347 PRE(mach_port_get_set_status)
4351 mach_msg_header_t Head;
4353 mach_port_name_t name;
4357 Request *req = (Request *)ARG1;
4359 PRINT("mach_port_get_set_status(%s, %s)",
4360 name_for_port(MACH_REMOTE),
4361 name_for_port(req->name));
4363 AFTER = POST_FN(mach_port_get_set_status);
4366 POST(mach_port_get_set_status)
4370 mach_msg_header_t Head;
4371 /* start of the kernel processed data */
4372 mach_msg_body_t msgh_body;
4373 mach_msg_ool_descriptor_t members;
4374 /* end of the kernel processed data */
4376 mach_msg_type_number_t membersCnt;
4377 mach_msg_trailer_t trailer;
4381 // Reply *reply = (Reply *)ARG1;
4383 // GrP fixme nothing to do?
4387 PRE(mach_port_destroy)
4391 mach_msg_header_t Head;
4393 mach_port_name_t name;
4397 Request *req = (Request *)ARG1;
4399 PRINT("mach_port_destroy(%s, %s)",
4400 name_for_port(MACH_REMOTE),
4401 name_for_port(req->name));
4403 MACH_ARG(mach_port.port) = req->name;
4405 AFTER = POST_FN(mach_port_destroy);
4407 // Must block to prevent race (other thread allocates and
4408 // notifies after we deallocate but before we notify)
4409 *flags &= ~SfMayBlock;
4412 POST(mach_port_destroy)
4416 mach_msg_header_t Head;
4418 kern_return_t RetCode;
4422 Reply *reply = (Reply *)ARG1;
4424 if (!reply->RetCode) {
4425 if (MACH_REMOTE == vg_task_port) {
4426 // Must have cleared SfMayBlock in PRE to prevent race
4427 record_port_destroy(MACH_ARG(mach_port.port));
4429 VG_(printf)("UNKNOWN remote port destroy\n");
4432 PRINT("mig return %d", reply->RetCode);
4437 PRE(mach_port_request_notification)
4441 mach_msg_header_t Head;
4442 /* start of the kernel processed data */
4443 mach_msg_body_t msgh_body;
4444 mach_msg_port_descriptor_t notify;
4445 /* end of the kernel processed data */
4447 mach_port_name_t name;
4448 mach_msg_id_t msgid;
4449 mach_port_mscount_t sync;
4453 Request *req = (Request *)ARG1;
4455 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
4456 name_for_port(MACH_REMOTE),
4457 name_for_port(req->name), req->msgid, req->sync,
4458 req->notify.name, req->notify.disposition);
4460 AFTER = POST_FN(mach_port_request_notification);
4463 POST(mach_port_request_notification)
4465 // GrP fixme port tracker? not sure
4469 PRE(mach_port_insert_right)
4473 mach_msg_header_t Head;
4474 /* start of the kernel processed data */
4475 mach_msg_body_t msgh_body;
4476 mach_msg_port_descriptor_t poly;
4477 /* end of the kernel processed data */
4479 mach_port_name_t name;
4483 Request *req = (Request *)ARG1;
4485 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
4486 name_for_port(MACH_REMOTE),
4487 name_for_port(req->name), req->poly.name, req->poly.disposition);
4489 AFTER = POST_FN(mach_port_insert_right);
4491 if (MACH_REMOTE == mach_task_self()) {
4492 // GrP fixme import_complex_message handles everything?
4493 // what about export_complex_message for MOVE variants?
4495 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
4496 // GrP fixme also may remove rights from this task?
4499 // GrP fixme port tracker?
4502 POST(mach_port_insert_right)
4507 PRE(mach_port_get_attributes)
4511 mach_msg_header_t Head;
4513 mach_port_name_t name;
4514 mach_port_flavor_t flavor;
4515 mach_msg_type_number_t port_info_outCnt;
4519 Request *req = (Request *)ARG1;
4521 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
4522 name_for_port(MACH_REMOTE),
4523 name_for_port(req->name), req->flavor, req->port_info_outCnt);
4525 AFTER = POST_FN(mach_port_get_attributes);
4528 POST(mach_port_get_attributes)
4533 PRE(mach_port_set_attributes)
4537 mach_msg_header_t Head;
4539 mach_port_name_t name;
4540 mach_port_flavor_t flavor;
4541 mach_msg_type_number_t port_infoCnt;
4542 integer_t port_info[10];
4546 Request *req = (Request *)ARG1;
4548 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
4549 name_for_port(MACH_REMOTE),
4550 name_for_port(req->name), req->flavor, req->port_infoCnt);
4552 AFTER = POST_FN(mach_port_set_attributes);
4555 POST(mach_port_set_attributes)
4560 PRE(mach_port_insert_member)
4564 mach_msg_header_t Head;
4566 mach_port_name_t name;
4567 mach_port_name_t pset;
4571 Request *req = (Request *)ARG1;
4573 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
4574 name_for_port(MACH_REMOTE), req->name, req->pset);
4576 AFTER = POST_FN(mach_port_insert_member);
4578 // GrP fixme port tracker?
4581 POST(mach_port_insert_member)
4586 PRE(task_get_special_port)
4590 mach_msg_header_t Head;
4596 Request *req = (Request *)ARG1;
4598 switch (req->which_port) {
4599 case TASK_KERNEL_PORT:
4600 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
4601 name_for_port(MACH_REMOTE));
4603 case TASK_HOST_PORT:
4604 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
4605 name_for_port(MACH_REMOTE));
4607 case TASK_BOOTSTRAP_PORT:
4608 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
4609 name_for_port(MACH_REMOTE));
4611 case TASK_WIRED_LEDGER_PORT:
4612 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
4613 name_for_port(MACH_REMOTE));
4615 case TASK_PAGED_LEDGER_PORT:
4616 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
4617 name_for_port(MACH_REMOTE));
4620 PRINT("task_get_special_port(%s, %d)",
4621 name_for_port(MACH_REMOTE), req->which_port);
4625 MACH_ARG(task_get_special_port.which_port) = req->which_port;
4627 AFTER = POST_FN(task_get_special_port);
4630 POST(task_get_special_port)
4634 mach_msg_header_t Head;
4635 /* start of the kernel processed data */
4636 mach_msg_body_t msgh_body;
4637 mach_msg_port_descriptor_t special_port;
4638 /* end of the kernel processed data */
4642 Reply *reply = (Reply *)ARG1;
4644 PRINT("got port %#x ", reply->special_port.name);
4646 switch (MACH_ARG(task_get_special_port.which_port)) {
4647 case TASK_BOOTSTRAP_PORT:
4648 vg_bootstrap_port = reply->special_port.name;
4649 assign_port_name(reply->special_port.name, "bootstrap");
4651 case TASK_KERNEL_PORT:
4652 assign_port_name(reply->special_port.name, "kernel");
4654 case TASK_HOST_PORT:
4655 assign_port_name(reply->special_port.name, "host");
4657 case TASK_WIRED_LEDGER_PORT:
4658 assign_port_name(reply->special_port.name, "wired-ledger");
4660 case TASK_PAGED_LEDGER_PORT:
4661 assign_port_name(reply->special_port.name, "paged-ledger");
4664 assign_port_name(reply->special_port.name, "special-%p");
4668 PRINT("%s", name_for_port(reply->special_port.name));
4672 PRE(semaphore_create)
4676 mach_msg_header_t Head;
4683 Request *req = (Request *)ARG1;
4685 PRINT("semaphore_create(%s, ..., %d, %d)",
4686 name_for_port(MACH_REMOTE), req->policy, req->value);
4688 AFTER = POST_FN(semaphore_create);
4691 POST(semaphore_create)
4695 mach_msg_header_t Head;
4696 /* start of the kernel processed data */
4697 mach_msg_body_t msgh_body;
4698 mach_msg_port_descriptor_t semaphore;
4699 /* end of the kernel processed data */
4700 mach_msg_trailer_t trailer;
4704 Reply *reply = (Reply *)ARG1;
4706 assign_port_name(reply->semaphore.name, "semaphore-%p");
4707 PRINT("%s", name_for_port(reply->semaphore.name));
4711 PRE(semaphore_destroy)
4715 mach_msg_header_t Head;
4716 /* start of the kernel processed data */
4717 mach_msg_body_t msgh_body;
4718 mach_msg_port_descriptor_t semaphore;
4719 /* end of the kernel processed data */
4720 mach_msg_trailer_t trailer;
4724 Request *req = (Request *)ARG1;
4726 PRINT("semaphore_destroy(%s, %s)",
4727 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
4729 record_port_destroy(req->semaphore.name);
4731 AFTER = POST_FN(semaphore_destroy);
4734 POST(semaphore_destroy)
4738 mach_msg_header_t Head;
4740 kern_return_t RetCode;
4741 mach_msg_trailer_t trailer;
4745 Reply *reply = (Reply *)ARG1;
4746 if (!reply->RetCode) {
4748 PRINT("mig return %d", reply->RetCode);
4753 PRE(mach_ports_lookup)
4757 mach_msg_header_t Head;
4761 // Request *req = (Request *)ARG1;
4763 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
4765 AFTER = POST_FN(mach_ports_lookup);
4768 POST(mach_ports_lookup)
4772 mach_msg_header_t Head;
4773 /* start of the kernel processed data */
4774 mach_msg_body_t msgh_body;
4775 mach_msg_ool_ports_descriptor_t init_port_set;
4776 /* end of the kernel processed data */
4778 mach_msg_type_number_t init_port_setCnt;
4782 // Reply *reply = (Reply *)ARG1;
4790 mach_msg_header_t Head;
4794 // Request *req = (Request *)ARG1;
4796 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
4798 AFTER = POST_FN(task_threads);
4805 mach_msg_header_t Head;
4806 /* start of the kernel processed data */
4807 mach_msg_body_t msgh_body;
4808 mach_msg_ool_ports_descriptor_t act_list;
4809 /* end of the kernel processed data */
4811 mach_msg_type_number_t act_listCnt;
4812 mach_msg_trailer_t trailer;
4816 Reply *reply = (Reply *)ARG1;
4818 if (MACH_REMOTE == vg_task_port) {
4819 assign_port_names(&reply->act_list, "thread-%p");
4821 assign_port_names(&reply->act_list, "remote-thread-%p");
4828 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
4830 if (MACH_REMOTE == vg_task_port) {
4831 // GrP fixme self-suspend
4834 // suspend other - no problem
4837 AFTER = POST_FN(task_suspend);
4847 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
4849 if (MACH_REMOTE == vg_task_port) {
4850 // GrP fixme self-resume
4853 // resume other - no problem
4856 AFTER = POST_FN(task_resume);
4868 mach_msg_header_t Head;
4870 vm_address_t address;
4876 Request *req = (Request *)ARG1;
4878 PRINT("vm_allocate (%s, at %#x, size %d, flags %#x)",
4879 name_for_port(MACH_REMOTE),
4880 req->address, req->size, req->flags);
4882 MACH_ARG(vm_allocate.size) = req->size;
4883 MACH_ARG(vm_allocate.flags) = req->flags;
4885 AFTER = POST_FN(vm_allocate);
4892 mach_msg_header_t Head;
4894 kern_return_t RetCode;
4895 vm_address_t address;
4896 mach_msg_trailer_t trailer;
4900 Reply *reply = (Reply *)ARG1;
4902 if (!reply->RetCode) {
4903 if (MACH_REMOTE == vg_task_port) {
4904 PRINT("allocated at %#x", reply->address);
4905 // requesting 0 bytes returns address 0 with no error
4906 if (MACH_ARG(vm_allocate.size)) {
4907 ML_(notify_core_and_tool_of_mmap)(
4908 reply->address, MACH_ARG(vm_allocate.size),
4909 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
4912 PRINT("allocated at %#x in remote task %s", reply->address,
4913 name_for_port(MACH_REMOTE));
4916 PRINT("mig return %d", reply->RetCode);
4925 mach_msg_header_t Head;
4927 vm_address_t address;
4932 Request *req = (Request *)ARG1;
4934 PRINT("vm_deallocate(%s, at %#x, size %d)",
4935 name_for_port(MACH_REMOTE),
4936 req->address, req->size);
4938 MACH_ARG(vm_deallocate.address) = req->address;
4939 MACH_ARG(vm_deallocate.size) = req->size;
4941 AFTER = POST_FN(vm_deallocate);
4943 // Must block to prevent race (other thread allocates and
4944 // notifies after we deallocate but before we notify)
4945 *flags &= ~SfMayBlock;
4952 mach_msg_header_t Head;
4954 kern_return_t RetCode;
4955 mach_msg_trailer_t trailer;
4959 Reply *reply = (Reply *)ARG1;
4961 if (!reply->RetCode) {
4962 if (MACH_REMOTE == vg_task_port) {
4963 if (MACH_ARG(vm_deallocate.size)) {
4964 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
4965 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
4966 MACH_ARG(vm_deallocate.size));
4967 // Must have cleared SfMayBlock in PRE to prevent race
4968 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4972 PRINT("mig return %d", reply->RetCode);
4981 mach_msg_header_t Head;
4983 vm_address_t address;
4985 boolean_t set_maximum;
4986 vm_prot_t new_protection;
4990 Request *req = (Request *)ARG1;
4992 PRINT("vm_protect(%s, at %#x, size %d, set_max %d, prot %d)",
4993 name_for_port(MACH_REMOTE), req->address, req->size,
4994 req->set_maximum, req->new_protection);
4996 MACH_ARG(vm_protect.address) = req->address;
4997 MACH_ARG(vm_protect.size) = req->size;
4998 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
4999 MACH_ARG(vm_protect.new_protection) = req->new_protection;
5001 AFTER = POST_FN(vm_protect);
5008 mach_msg_header_t Head;
5010 kern_return_t RetCode;
5011 mach_msg_trailer_t trailer;
5015 Reply *reply = (Reply *)ARG1;
5017 if (!reply->RetCode) {
5018 if (MACH_REMOTE == vg_task_port) {
5019 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
5020 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
5021 MACH_ARG(vm_protect.size));
5022 UInt prot = MACH_ARG(vm_protect.new_protection);
5023 if (MACH_ARG(vm_protect.set_maximum)) {
5024 // GrP fixme mprotect max
5025 VG_(printf)("UNKNOWN vm_protect set maximum");
5026 //VG_(mprotect_max_range)(start, end-start, prot);
5028 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5032 PRINT("mig return %d", reply->RetCode);
5041 mach_msg_header_t Head;
5043 vm_address_t address;
5045 vm_inherit_t new_inheritance;
5049 Request *req = (Request *)ARG1;
5051 PRINT("vm_inherit(%s, at %#x, size %d, value %d)",
5052 name_for_port(MACH_REMOTE),
5053 req->address, req->size,
5054 req->new_inheritance);
5056 AFTER = POST_FN(vm_inherit);
5063 mach_msg_header_t Head;
5065 kern_return_t RetCode;
5066 mach_msg_trailer_t trailer;
5070 Reply *reply = (Reply *)ARG1;
5072 if (!reply->RetCode) {
5073 if (MACH_REMOTE == vg_task_port) {
5074 // GrP fixme do something?
5077 PRINT("mig return %d", reply->RetCode);
5086 mach_msg_header_t Head;
5088 vm_address_t address;
5093 Request *req = (Request *)ARG1;
5095 PRINT("vm_read(from %s at %#x size %u)",
5096 name_for_port(MACH_REMOTE), req->address, req->size);
5098 MACH_ARG(vm_read.addr) = req->address;
5099 MACH_ARG(vm_read.size) = req->size;
5101 AFTER = POST_FN(vm_read);
5108 mach_msg_header_t Head;
5109 /* start of the kernel processed data */
5110 mach_msg_body_t msgh_body;
5111 mach_msg_ool_descriptor_t data;
5112 /* end of the kernel processed data */
5114 mach_msg_type_number_t dataCnt;
5118 // Reply *reply = (Reply *)ARG1;
5120 if (MACH_REMOTE == vg_task_port) {
5121 // vm_read from self
5122 // GrP fixme copy initialized state
5132 mach_msg_header_t Head;
5134 mach_vm_address_t address;
5135 mach_vm_size_t size;
5139 Request *req = (Request *)ARG1;
5141 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
5142 name_for_port(MACH_REMOTE), req->address, req->size);
5144 MACH_ARG(mach_vm_read.addr) = req->address;
5145 MACH_ARG(mach_vm_read.size) = req->size;
5147 AFTER = POST_FN(mach_vm_read);
5154 mach_msg_header_t Head;
5155 /* start of the kernel processed data */
5156 mach_msg_body_t msgh_body;
5157 mach_msg_ool_descriptor_t data;
5158 /* end of the kernel processed data */
5160 mach_msg_type_number_t dataCnt;
5164 // Reply *reply = (Reply *)ARG1;
5166 if (MACH_REMOTE == vg_task_port) {
5167 // vm_read from self
5168 // GrP fixme copy initialized state
5173 PRE(vm_read_overwrite)
5177 mach_msg_header_t Head;
5179 vm_address_t address;
5185 Request *req = (Request *)ARG1;
5187 PRINT("vm_read_overwrite(from %s at %#x size %u to %#x)",
5188 name_for_port(MACH_REMOTE), req->address, req->size, req->data);
5190 MACH_ARG(vm_read_overwrite.addr) = req->address;
5191 MACH_ARG(vm_read_overwrite.size) = req->size;
5192 MACH_ARG(vm_read_overwrite.data) = req->data;
5194 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
5196 AFTER = POST_FN(vm_read_overwrite);
5199 POST(vm_read_overwrite)
5203 mach_msg_header_t Head;
5205 kern_return_t RetCode;
5210 Reply *reply = (Reply *)ARG1;
5212 if (reply->RetCode) {
5213 PRINT("mig return %d", reply->RetCode);
5215 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
5216 if (MACH_REMOTE == vg_task_port) {
5217 // vm_read_overwrite from self
5218 // GrP fixme copy initialized state
5219 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5221 // vm_read_overwrite from remote
5222 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5232 mach_msg_header_t Head;
5234 vm_address_t source_address;
5236 vm_address_t dest_address;
5240 Request *req = (Request *)ARG1;
5242 PRINT("vm_copy(%s, %#x, %d, %#x)",
5243 name_for_port(MACH_REMOTE),
5244 req->source_address, req->size, req->dest_address);
5246 MACH_ARG(vm_copy.src) = req->source_address;
5247 MACH_ARG(vm_copy.dst) = req->dest_address;
5248 MACH_ARG(vm_copy.size) = req->size;
5250 AFTER = POST_FN(vm_copy);
5257 mach_msg_header_t Head;
5259 kern_return_t RetCode;
5260 mach_msg_trailer_t trailer;
5264 Reply *reply = (Reply *)ARG1;
5266 if (!reply->RetCode) {
5267 if (MACH_REMOTE == vg_task_port) {
5268 // GrP fixme set dst's initialization equal to src's
5269 // and wipe any symbols or translations in dst
5272 PRINT("mig return %d", reply->RetCode);
5281 mach_msg_header_t Head;
5282 /* start of the kernel processed data */
5283 mach_msg_body_t msgh_body;
5284 mach_msg_port_descriptor_t object;
5285 /* end of the kernel processed data */
5287 vm_address_t address;
5293 vm_prot_t cur_protection;
5294 vm_prot_t max_protection;
5295 vm_inherit_t inheritance;
5299 Request *req = (Request *)ARG1;
5301 // GrP fixme check these
5302 PRINT("vm_map(in %s, at %#x, size %d, from %s ...)",
5303 name_for_port(MACH_REMOTE),
5304 req->address, req->size,
5305 name_for_port(req->object.name));
5307 MACH_ARG(vm_map.size) = req->size;
5308 MACH_ARG(vm_map.copy) = req->copy;
5309 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
5311 AFTER = POST_FN(vm_map);
5318 mach_msg_header_t Head;
5320 kern_return_t RetCode;
5321 vm_address_t address;
5322 mach_msg_trailer_t trailer;
5326 Reply *reply = (Reply *)ARG1;
5328 if (!reply->RetCode) {
5329 // GrP fixme check src and dest tasks
5330 PRINT("mapped at %#x", reply->address);
5331 // GrP fixme max prot
5332 ML_(notify_core_and_tool_of_mmap)(
5333 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
5334 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
5335 // GrP fixme VKI_MAP_PRIVATE if !copy?
5337 PRINT("mig return %d", reply->RetCode);
5346 mach_msg_header_t Head;
5347 /* start of the kernel processed data */
5348 mach_msg_body_t msgh_body;
5349 mach_msg_port_descriptor_t src_task;
5350 /* end of the kernel processed data */
5352 vm_address_t target_address;
5356 vm_address_t src_address;
5358 vm_inherit_t inheritance;
5362 Request *req = (Request *)ARG1;
5364 // GrP fixme check src and dest tasks
5366 if (VG_(clo_trace_syscalls)) {
5367 mach_port_name_t source_task = req->src_task.name;
5368 if (source_task == mach_task_self()) {
5369 PRINT("vm_remap(mach_task_self(), "
5370 "to %#x size %d, from mach_task_self() at %#x, ...)",
5371 req->target_address, req->size, req->src_address);
5373 PRINT("vm_remap(mach_task_self(), "
5374 "to %#x size %d, from task %u at %#x, ...)",
5375 req->target_address, req->size,
5376 source_task, req->src_address);
5381 // vt->syscall_arg2 = req->target_address;
5382 MACH_ARG(vm_remap.size) = req->size;
5383 // vt->syscall_arg4 = req->copy;
5385 AFTER = POST_FN(vm_remap);
5392 mach_msg_header_t Head;
5394 kern_return_t RetCode;
5395 vm_address_t target_address;
5396 vm_prot_t cur_protection;
5397 vm_prot_t max_protection;
5398 mach_msg_trailer_t trailer;
5402 Reply *reply = (Reply *)ARG1;
5404 if (!reply->RetCode) {
5405 // GrP fixme check src and dest tasks
5406 UInt prot = reply->cur_protection & reply->max_protection;
5407 // GrP fixme max prot
5408 PRINT("mapped at %#x", reply->target_address);
5409 ML_(notify_core_and_tool_of_mmap)(
5410 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
5411 prot, VKI_MAP_SHARED, -1, 0);
5412 // GrP fixme VKI_MAP_FIXED if !copy?
5413 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
5415 PRINT("mig return %d", reply->RetCode);
5420 PRE(mach_make_memory_entry_64)
5424 mach_msg_header_t Head;
5425 /* start of the kernel processed data */
5426 mach_msg_body_t msgh_body;
5427 mach_msg_port_descriptor_t parent_entry;
5428 /* end of the kernel processed data */
5430 memory_object_size_t size;
5431 memory_object_offset_t offset;
5432 vm_prot_t permission;
5436 Request *req = (Request *)ARG1;
5438 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
5439 name_for_port(MACH_REMOTE),
5440 req->size, req->offset, req->permission, req->parent_entry.type);
5442 AFTER = POST_FN(mach_make_memory_entry_64);
5445 POST(mach_make_memory_entry_64)
5449 mach_msg_header_t Head;
5450 mach_msg_body_t msgh_body;
5451 mach_msg_port_descriptor_t object;
5453 memory_object_size_t size;
5457 Reply *reply = (Reply *)ARG1;
5459 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
5460 assign_port_name(reply->object.name, "memory-%p");
5461 PRINT("%s", name_for_port(reply->object.name));
5466 PRE(vm_purgable_control)
5470 mach_msg_header_t Head;
5472 vm_address_t address;
5473 vm_purgable_t control;
5478 Request *req = (Request *)ARG1;
5480 PRINT("vm_purgable_control(%s, %#x, %d, %d)",
5481 name_for_port(MACH_REMOTE),
5482 req->address, req->control, req->state);
5484 // GrP fixme verify address?
5486 AFTER = POST_FN(vm_purgable_control);
5489 POST(vm_purgable_control)
5493 mach_msg_header_t Head;
5495 kern_return_t RetCode;
5500 Reply *reply = (Reply *)ARG1;
5502 if (!reply->RetCode) {
5504 PRINT("mig return %d", reply->RetCode);
5509 PRE(mach_vm_purgable_control)
5513 mach_msg_header_t Head;
5515 mach_vm_address_t address;
5516 vm_purgable_t control;
5521 Request *req = (Request *)ARG1;
5523 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
5524 name_for_port(MACH_REMOTE),
5525 (unsigned long long)req->address, req->control, req->state);
5527 // GrP fixme verify address?
5529 AFTER = POST_FN(mach_vm_purgable_control);
5532 POST(mach_vm_purgable_control)
5536 mach_msg_header_t Head;
5538 kern_return_t RetCode;
5543 Reply *reply = (Reply *)ARG1;
5545 if (!reply->RetCode) {
5547 PRINT("mig return %d", reply->RetCode);
5552 PRE(mach_vm_allocate)
5556 mach_msg_header_t Head;
5558 mach_vm_address_t address;
5559 mach_vm_size_t size;
5564 Request *req = (Request *)ARG1;
5566 PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
5567 name_for_port(MACH_REMOTE),
5568 req->address, req->size, req->flags);
5570 MACH_ARG(mach_vm_allocate.size) = req->size;
5571 MACH_ARG(mach_vm_allocate.flags) = req->flags;
5573 AFTER = POST_FN(mach_vm_allocate);
5576 POST(mach_vm_allocate)
5580 mach_msg_header_t Head;
5582 kern_return_t RetCode;
5583 mach_vm_address_t address;
5584 mach_msg_trailer_t trailer;
5588 Reply *reply = (Reply *)ARG1;
5590 if (!reply->RetCode) {
5591 if (MACH_REMOTE == vg_task_port) {
5592 PRINT("allocated at 0x%llx", reply->address);
5593 // requesting 0 bytes returns address 0 with no error
5594 if (MACH_ARG(mach_vm_allocate.size)) {
5595 ML_(notify_core_and_tool_of_mmap)(
5596 reply->address, MACH_ARG(mach_vm_allocate.size),
5597 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5600 PRINT("allocated at 0x%llx in remote task %s", reply->address,
5601 name_for_port(MACH_REMOTE));
5604 PRINT("mig return %d", reply->RetCode);
5609 PRE(mach_vm_deallocate)
5613 mach_msg_header_t Head;
5615 mach_vm_address_t address;
5616 mach_vm_size_t size;
5620 Request *req = (Request *)ARG1;
5622 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
5623 name_for_port(MACH_REMOTE),
5624 req->address, req->size);
5626 MACH_ARG(mach_vm_deallocate.address) = req->address;
5627 MACH_ARG(mach_vm_deallocate.size) = req->size;
5629 AFTER = POST_FN(mach_vm_deallocate);
5631 // Must block to prevent race (other thread allocates and
5632 // notifies after we deallocate but before we notify)
5633 *flags &= ~SfMayBlock;
5636 POST(mach_vm_deallocate)
5640 mach_msg_header_t Head;
5642 kern_return_t RetCode;
5643 mach_msg_trailer_t trailer;
5647 Reply *reply = (Reply *)ARG1;
5649 if (!reply->RetCode) {
5650 if (MACH_REMOTE == vg_task_port) {
5651 if (MACH_ARG(mach_vm_deallocate.size)) {
5652 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
5653 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
5654 MACH_ARG(mach_vm_deallocate.size));
5655 // Must have cleared SfMayBlock in PRE to prevent race
5656 ML_(notify_core_and_tool_of_munmap)(start, end - start);
5660 PRINT("mig return %d", reply->RetCode);
5665 PRE(mach_vm_protect)
5669 mach_msg_header_t Head;
5671 mach_vm_address_t address;
5672 mach_vm_size_t size;
5673 boolean_t set_maximum;
5674 vm_prot_t new_protection;
5678 Request *req = (Request *)ARG1;
5680 PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
5681 name_for_port(MACH_REMOTE), req->address, req->size,
5682 req->set_maximum, req->new_protection);
5684 MACH_ARG(mach_vm_protect.address) = req->address;
5685 MACH_ARG(mach_vm_protect.size) = req->size;
5686 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
5687 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
5689 AFTER = POST_FN(mach_vm_protect);
5692 POST(mach_vm_protect)
5696 mach_msg_header_t Head;
5698 kern_return_t RetCode;
5699 mach_msg_trailer_t trailer;
5703 Reply *reply = (Reply *)ARG1;
5705 if (!reply->RetCode) {
5706 if (MACH_REMOTE == vg_task_port) {
5707 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
5708 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
5709 MACH_ARG(mach_vm_protect.size));
5710 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
5711 if (MACH_ARG(mach_vm_protect.set_maximum)) {
5712 // DDD: #warning GrP fixme mprotect max
5713 //VG_(mprotect_max_range)(start, end-start, prot);
5715 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5719 PRINT("mig return %d", reply->RetCode);
5724 PRE(mach_vm_inherit)
5728 mach_msg_header_t Head;
5730 mach_vm_address_t address;
5731 mach_vm_size_t size;
5732 vm_inherit_t new_inheritance;
5736 Request *req = (Request *)ARG1;
5738 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
5739 name_for_port(MACH_REMOTE),
5740 req->address, req->size, req->new_inheritance);
5742 AFTER = POST_FN(mach_vm_inherit);
5745 POST(mach_vm_inherit)
5749 mach_msg_header_t Head;
5751 kern_return_t RetCode;
5752 mach_msg_trailer_t trailer;
5756 Reply *reply = (Reply *)ARG1;
5758 if (!reply->RetCode) {
5759 // no V-visible side effects
5760 // GrP fixme except maybe fork/exec
5762 PRINT("mig return %d", reply->RetCode);
5771 mach_msg_header_t Head;
5773 mach_vm_address_t source_address;
5774 mach_vm_size_t size;
5775 mach_vm_address_t dest_address;
5779 Request *req = (Request *)ARG1;
5781 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
5782 name_for_port(MACH_REMOTE),
5783 req->source_address, req->size, req->dest_address);
5786 // vt->syscall_arg2 = req->source_address;
5787 // vt->syscall_arg3 = req->size;
5788 // vt->syscall_arg4 = req->dest_address;
5790 AFTER = POST_FN(mach_vm_copy);
5797 mach_msg_header_t Head;
5799 kern_return_t RetCode;
5800 mach_msg_trailer_t trailer;
5804 Reply *reply = (Reply *)ARG1;
5806 if (!reply->RetCode) {
5807 if (MACH_REMOTE == vg_task_port) {
5808 // GrP fixme set dest's initialization equal to src's
5809 // BUT vm_copy allocates no memory
5812 PRINT("mig return %d", reply->RetCode);
5821 mach_msg_header_t Head;
5822 /* start of the kernel processed data */
5823 mach_msg_body_t msgh_body;
5824 mach_msg_port_descriptor_t object;
5825 /* end of the kernel processed data */
5827 mach_vm_address_t address;
5828 mach_vm_size_t size;
5829 mach_vm_address_t mask;
5831 memory_object_offset_t offset;
5833 vm_prot_t cur_protection;
5834 vm_prot_t max_protection;
5835 vm_inherit_t inheritance;
5839 Request *req = (Request *)ARG1;
5841 // GrP fixme check these
5842 PRINT("mach_vm_map(in %s, at 0x%llx, size %llu, from %s ...)",
5843 name_for_port(MACH_REMOTE),
5844 req->address, req->size,
5845 name_for_port(req->object.name));
5847 MACH_ARG(mach_vm_map.size) = req->size;
5848 MACH_ARG(mach_vm_map.copy) = req->copy;
5849 MACH_ARG(mach_vm_map.protection) =
5850 (req->cur_protection & req->max_protection);
5852 AFTER = POST_FN(mach_vm_map);
5859 mach_msg_header_t Head;
5861 kern_return_t RetCode;
5862 mach_vm_address_t address;
5863 mach_msg_trailer_t trailer;
5867 Reply *reply = (Reply *)ARG1;
5869 if (!reply->RetCode) {
5870 // GrP fixme check src and dest tasks
5871 PRINT("mapped at 0x%llx", reply->address);
5872 // GrP fixme max prot
5873 ML_(notify_core_and_tool_of_mmap)(
5874 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
5875 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
5876 // GrP fixme VKI_MAP_PRIVATE if !copy?
5878 PRINT("mig return %d", reply->RetCode);
5883 PRE(mach_vm_region_recurse)
5887 mach_msg_header_t Head;
5889 mach_vm_address_t address;
5890 natural_t nesting_depth;
5891 mach_msg_type_number_t infoCnt;
5895 Request *req = (Request *)ARG1;
5897 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
5898 name_for_port(MACH_REMOTE),
5899 req->address, req->nesting_depth, req->infoCnt);
5901 AFTER = POST_FN(mach_vm_region_recurse);
5904 POST(mach_vm_region_recurse)
5908 mach_msg_header_t Head;
5910 kern_return_t RetCode;
5911 mach_vm_address_t address;
5912 mach_vm_size_t size;
5913 natural_t nesting_depth;
5914 mach_msg_type_number_t infoCnt;
5919 Reply *reply = (Reply *)ARG1;
5921 if (!reply->RetCode) {
5922 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
5923 reply->address, reply->size,
5924 reply->nesting_depth, reply->infoCnt);
5925 // GrP fixme mark info contents beyond infoCnt as bogus
5927 PRINT("mig return %d", reply->RetCode);
5932 /* ---------------------------------------------------------------------
5933 mach_msg: messages to thread
5934 ------------------------------------------------------------------ */
5938 POST(thread_terminate)
5943 PRE(thread_terminate)
5945 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
5946 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
5948 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
5950 AFTER = POST_FN(thread_terminate);
5952 if (self_terminate) {
5953 // Terminating this thread.
5954 // Copied from sys_exit.
5955 ThreadState *tst = VG_(get_ThreadState)(tid);
5956 tst->exitreason = VgSrc_ExitThread;
5957 tst->os_state.exitcode = 0; // GrP fixme anything better?
5958 // What we would like to do is:
5959 // SET_STATUS_Success(0);
5960 // but that doesn't work, because this is a MACH-class syscall,
5961 // and SET_STATUS_Success creates a UNIX-class syscall result.
5962 // Hence we have to laboriously construct the full SysRes "by hand"
5963 // and use that to set the syscall return status.
5964 SET_STATUS_from_SysRes(
5965 VG_(mk_SysRes_x86_darwin)(
5966 VG_DARWIN_SYSCALL_CLASS_MACH,
5967 False/*success*/, 0, 0
5970 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
5972 // Terminating some other thread.
5973 // Do keep the scheduler lock while terminating any other thread.
5974 // Otherwise we might halt the other thread while it holds the lock,
5975 // which would deadlock the process.
5976 // GrP fixme good enough?
5977 // GrP fixme need to clean up other thread's valgrind data?
5989 PRINT("thread_create(mach_task_self(), ...)");
5991 AFTER = POST_FN(thread_create);
5994 VG_(core_panic)("thread_create() unimplemented");
5998 PRE(thread_create_running)
6002 mach_msg_header_t Head;
6004 thread_state_flavor_t flavor;
6005 mach_msg_type_number_t new_stateCnt;
6006 natural_t new_state[144];
6011 thread_state_t regs;
6012 ThreadState *new_thread;
6014 PRINT("thread_create_running(mach_task_self(), ...)");
6016 // The new thread will immediately begin execution,
6017 // so we need to hijack the register state here.
6019 req = (Request *)ARG1;
6020 regs = (thread_state_t)req->new_state;
6022 // Build virtual thread.
6023 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
6025 // Edit the thread state to send to the real kernel.
6026 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
6028 AFTER = POST_FN(thread_create_running);
6032 POST(thread_create_running)
6036 mach_msg_header_t Head;
6037 /* start of the kernel processed data */
6038 mach_msg_body_t msgh_body;
6039 mach_msg_port_descriptor_t child_act;
6040 /* end of the kernel processed data */
6044 Reply *reply = (Reply *)ARG1;
6046 assign_port_name(reply->child_act.name, "thread-%p");
6047 PRINT("%s", name_for_port(reply->child_act.name));
6051 PRE(bsdthread_create)
6055 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
6056 ARG1, ARG2, ARG3, ARG4, ARG5);
6057 PRE_REG_READ5(pthread_t,"bsdthread_create",
6058 void *,"func", void *,"func_arg", void *,"stack",
6059 pthread_t,"thread", unsigned int,"flags");
6061 // The kernel will call V's pthread_hijack() to launch the thread.
6062 // Here we allocate the thread state and pass it to pthread_hijack()
6063 // via the func_arg parameter.
6065 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
6066 allocstack(tst->tid);
6068 tst->os_state.func_arg = (Addr)ARG2;
6071 // Create a semaphore that pthread_hijack will signal once it starts
6072 // POST(bsdthread_create) needs to wait for the new memory map to appear
6073 semaphore_create(mach_task_self(), &tst->os_state.child_go,
6074 SYNC_POLICY_FIFO, 0);
6075 semaphore_create(mach_task_self(), &tst->os_state.child_done,
6076 SYNC_POLICY_FIFO, 0);
6079 POST(bsdthread_create)
6081 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
6082 // We hold V's lock on the child's behalf.
6083 // If we return before letting pthread_hijack do its thing, V thinks
6084 // the new pthread struct is still unmapped when we return to libc,
6085 // causing false errors.
6087 ThreadState *tst = (ThreadState *)ARG2;
6088 semaphore_signal(tst->os_state.child_go);
6089 semaphore_wait(tst->os_state.child_done);
6090 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
6091 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
6093 // GrP fixme semaphore destroy needed when thread creation fails
6094 // GrP fixme probably other cleanup too
6096 // DDD: I'm not at all sure this is the right spot for this. It probably
6097 // should be in pthread_hijack instead, just before the call to
6098 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
6099 // parent tid value there...
6100 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
6104 PRE(bsdthread_terminate)
6108 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
6109 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
6110 PRE_REG_READ4(int,"bsdthread_terminate",
6111 void *,"freeaddr", size_t,"freesize",
6112 mach_port_t,"kport", mach_port_t,"joinsem");
6114 // Free memory and signal semaphore.
6115 // GrP fixme errors?
6116 if (ARG4) semaphore_signal((semaphore_t)ARG4);
6118 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
6119 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
6122 // Tell V to terminate the thread.
6123 // Copied from sys_exit.
6124 tst = VG_(get_ThreadState)(tid);
6125 tst->exitreason = VgSrc_ExitThread;
6126 tst->os_state.exitcode = 0; // GrP fixme anything better?
6127 SET_STATUS_Success(0);
6131 POST(thread_suspend)
6137 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6138 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
6140 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
6142 AFTER = POST_FN(thread_suspend);
6145 // Don't keep the scheduler lock while self-suspending.
6146 // Otherwise we might halt while still holding the lock,
6147 // which would deadlock the process.
6148 *flags |= SfMayBlock;
6150 // Do keep the scheduler lock while suspending any other thread.
6151 // Otherwise we might halt the other thread while it holds the lock,
6152 // which would deadlock the process.
6157 POST(thread_get_state)
6161 mach_msg_header_t Head;
6163 kern_return_t RetCode;
6164 mach_msg_type_number_t old_stateCnt;
6165 natural_t old_state[144];
6166 mach_msg_trailer_t trailer;
6170 Reply *reply = (Reply *)ARG1;
6171 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
6172 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
6174 if (!reply->RetCode) {
6175 thread_state_from_vex((thread_state_t)reply->old_state,
6176 flavor, reply->old_stateCnt,
6177 &VG_(get_ThreadState)(tid)->arch.vex);
6179 PRINT("mig return %d", reply->RetCode);
6183 PRE(thread_get_state)
6187 mach_msg_header_t Head;
6189 thread_state_flavor_t flavor;
6190 mach_msg_type_number_t old_stateCnt;
6194 Request *req = (Request *)ARG1;
6195 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
6197 // GrP fixme if (self) {
6198 PRINT("thread_get_state(%s, %d)",
6199 name_for_port(req->Head.msgh_request_port), req->flavor);
6201 PRINT("thread_get_state(0x%x, %d)",
6202 req->Head.msgh_request_port, req->flavor);
6205 // Hack the thread state after making the real call.
6206 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
6207 MACH_ARG(thread_get_state.flavor) = req->flavor;
6209 AFTER = POST_FN(thread_get_state);
6219 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6220 // Bool self = (mh->msgh_request_port == MACH_THREAD);
6222 // GrP fixme if (self) {
6223 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
6225 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
6228 AFTER = POST_FN(thread_policy);
6234 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6236 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
6237 // GrP fixme does any thread info need to be hijacked?
6239 AFTER = POST_FN(thread_info);
6244 // GrP fixme mark unused parts of thread_info_out as uninitialized?
6249 /* ---------------------------------------------------------------------
6250 mach_msg: messages to bootstrap port
6251 ------------------------------------------------------------------ */
6254 POST(bootstrap_register)
6258 mach_msg_header_t Head;
6260 kern_return_t RetCode;
6261 mach_msg_trailer_t trailer;
6265 Reply *reply = (Reply *)ARG1;
6267 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
6270 PRE(bootstrap_register)
6274 mach_msg_header_t Head;
6275 /* start of the kernel processed data */
6276 mach_msg_body_t msgh_body;
6277 mach_msg_port_descriptor_t service_port;
6278 /* end of the kernel processed data */
6280 name_t service_name;
6284 Request *req = (Request *)ARG1;
6286 PRINT("bootstrap_register(port 0x%x, \"%s\")",
6287 req->service_port.name, req->service_name);
6289 assign_port_name(req->service_port.name, req->service_name);
6291 AFTER = POST_FN(bootstrap_register);
6295 POST(bootstrap_look_up)
6299 mach_msg_header_t Head;
6300 /* start of the kernel processed data */
6301 mach_msg_body_t msgh_body;
6302 mach_msg_port_descriptor_t service_port;
6303 /* end of the kernel processed data */
6304 mach_msg_trailer_t trailer;
6308 Reply *reply = (Reply *)ARG1;
6310 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
6311 reply->service_port.name)
6313 assign_port_name(reply->service_port.name,
6314 MACH_ARG(bootstrap_look_up.service_name));
6315 PRINT("%s", name_for_port(reply->service_port.name));
6319 VG_(arena_free)(VG_AR_CORE, MACH_ARG(bootstrap_look_up.service_name));
6322 PRE(bootstrap_look_up)
6326 mach_msg_header_t Head;
6328 name_t service_name;
6332 Request *req = (Request *)ARG1;
6334 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
6336 MACH_ARG(bootstrap_look_up.service_name) =
6337 VG_(arena_strdup)(VG_AR_CORE, "syswrap-darwin.bootstrap-name",
6340 AFTER = POST_FN(bootstrap_look_up);
6344 /* ---------------------------------------------------------------------
6345 mach_msg: receiver-specific handlers
6346 ------------------------------------------------------------------ */
6349 POST(mach_msg_receive)
6351 // mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6353 // GrP fixme don't know of anything interesting here currently
6354 // import_complex_message handles everything
6355 // PRINT("UNHANDLED reply %d", mh->msgh_id);
6357 // Assume the call may have mapped or unmapped memory
6358 ML_(sync_mappings)("after", "mach_msg_receive", 0);
6361 PRE(mach_msg_receive)
6363 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6365 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
6367 AFTER = POST_FN(mach_msg_receive);
6369 // no message sent, only listening for a reply
6370 // assume message may block
6371 *flags |= SfMayBlock;
6375 PRE(mach_msg_bootstrap)
6377 // message to bootstrap port
6379 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6381 switch (mh->msgh_id) {
6383 CALL_PRE(bootstrap_register);
6386 CALL_PRE(bootstrap_look_up);
6390 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
6391 mh->msgh_id, name_for_port(mh->msgh_request_port),
6392 mh->msgh_reply_port);
6400 // message to host self - check for host-level kernel calls
6402 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6404 switch (mh->msgh_id) {
6406 CALL_PRE(host_info);
6409 CALL_PRE(host_page_size);
6412 CALL_PRE(host_get_io_master);
6415 CALL_PRE(host_get_clock_service);
6418 CALL_PRE(host_request_notification);
6422 // unknown message to host self
6423 VG_(printf)("UNKNOWN host message [id %d, to %s, reply 0x%x]\n",
6424 mh->msgh_id, name_for_port(mh->msgh_request_port),
6425 mh->msgh_reply_port);
6432 // message to a task port
6434 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6436 switch (mh->msgh_id) {
6438 CALL_PRE(mach_port_type);
6441 CALL_PRE(mach_port_allocate);
6444 CALL_PRE(mach_port_destroy);
6447 CALL_PRE(mach_port_deallocate);
6450 CALL_PRE(mach_port_get_refs);
6453 CALL_PRE(mach_port_mod_refs);
6456 CALL_PRE(mach_port_get_set_status);
6459 CALL_PRE(mach_port_request_notification);
6462 CALL_PRE(mach_port_insert_right);
6465 CALL_PRE(mach_port_get_attributes);
6468 CALL_PRE(mach_port_set_attributes);
6471 CALL_PRE(mach_port_insert_member);
6474 CALL_PRE(mach_port_extract_member);
6478 CALL_PRE(task_threads);
6481 CALL_PRE(mach_ports_lookup);
6485 CALL_PRE(task_suspend);
6488 CALL_PRE(task_resume);
6492 CALL_PRE(task_get_special_port);
6495 CALL_PRE(thread_create);
6498 CALL_PRE(thread_create_running);
6502 CALL_PRE(semaphore_create);
6505 CALL_PRE(semaphore_destroy);
6509 CALL_PRE(vm_allocate);
6512 CALL_PRE(vm_deallocate);
6515 CALL_PRE(vm_protect);
6518 CALL_PRE(vm_inherit);
6527 CALL_PRE(vm_read_overwrite);
6536 CALL_PRE(mach_make_memory_entry_64);
6539 CALL_PRE(vm_purgable_control);
6543 CALL_PRE(mach_vm_allocate);
6546 CALL_PRE(mach_vm_deallocate);
6549 CALL_PRE(mach_vm_protect);
6552 CALL_PRE(mach_vm_inherit);
6555 CALL_PRE(mach_vm_read);
6558 CALL_PRE(mach_vm_copy);
6561 CALL_PRE(mach_vm_map);
6564 CALL_PRE(mach_vm_region_recurse);
6567 CALL_PRE(mach_make_memory_entry_64);
6570 CALL_PRE(mach_vm_purgable_control);
6574 // unknown message to task self
6575 VG_(printf)("UNKNOWN task message [id %d, to %s, reply 0x%x]\n",
6576 mh->msgh_id, name_for_port(mh->msgh_remote_port),
6577 mh->msgh_reply_port);
6583 PRE(mach_msg_thread)
6585 // message to local thread - check for thread-level kernel calls
6587 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6589 switch (mh->msgh_id) {
6591 CALL_PRE(thread_terminate);
6594 CALL_PRE(thread_get_state);
6597 CALL_PRE(thread_suspend);
6600 CALL_PRE(thread_info);
6603 CALL_PRE(thread_policy);
6606 // unknown message to a thread
6607 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
6608 mh->msgh_id, name_for_port(mh->msgh_request_port),
6609 mh->msgh_reply_port);
6615 static int is_thread_port(mach_port_t port)
6617 if (port == 0) return False;
6619 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
6623 static int is_task_port(mach_port_t port)
6625 if (port == 0) return False;
6627 if (port == vg_task_port) return True;
6629 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
6633 /* ---------------------------------------------------------------------
6634 mach_msg: base handlers
6635 ------------------------------------------------------------------ */
6639 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6640 mach_msg_option_t option = (mach_msg_option_t)ARG2;
6641 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
6642 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
6643 // mach_port_t rcv_name = (mach_port_t)ARG5;
6644 size_t complex_header_size = 0;
6646 PRE_REG_READ7(long, "mach_msg",
6647 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
6648 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
6649 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
6650 mach_port_t,"notify");
6652 // Assume default POST handler until specified otherwise
6655 // Assume call may block unless specified otherwise
6656 *flags |= SfMayBlock;
6658 if (option & MACH_SEND_MSG) {
6659 // Validate outgoing message header
6660 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
6661 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
6662 // msgh_size not required, use parameter instead
6663 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
6664 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
6665 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
6666 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
6667 // msgh_reserved not required
6668 PRE_MEM_READ("mach_msg(msg.msgh_id)",
6669 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
6671 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6672 // Validate typed message data and handle memory map changes.
6673 complex_header_size = export_complex_message(tid, mh);
6676 // GrP fixme handle sender-specified message trailer
6677 // (but is this only for too-secure processes?)
6678 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
6680 MACH_REMOTE = mh->msgh_remote_port;
6681 MACH_MSGH_ID = mh->msgh_id;
6684 if (option & MACH_RCV_MSG) {
6685 // Pre-validate receive buffer
6686 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
6689 // Call a PRE handler. The PRE handler may set an AFTER handler.
6691 if (!(option & MACH_SEND_MSG)) {
6692 // no message sent, receive only
6693 CALL_PRE(mach_msg_receive);
6696 else if (mh->msgh_request_port == vg_host_port) {
6697 // message sent to mach_host_self()
6698 CALL_PRE(mach_msg_host);
6701 else if (is_task_port(mh->msgh_request_port)) {
6702 // message sent to a task
6703 CALL_PRE(mach_msg_task);
6706 else if (mh->msgh_request_port == vg_bootstrap_port) {
6707 // message sent to bootstrap port
6708 CALL_PRE(mach_msg_bootstrap);
6711 else if (is_thread_port(mh->msgh_request_port)) {
6712 // message sent to one of this process's threads
6713 CALL_PRE(mach_msg_thread);
6717 // arbitrary message to arbitrary port
6718 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
6719 mh->msgh_id, name_for_port(mh->msgh_request_port),
6720 mh->msgh_reply_port);
6722 AFTER = POST_FN(mach_msg_unhandled);
6724 // Assume the entire message body may be read.
6725 // GrP fixme generates false positives for unknown protocols
6727 PRE_MEM_READ("mach_msg(payload)",
6728 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
6729 send_size - sizeof(mach_msg_header_t) - complex_header_size);
6737 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6738 mach_msg_option_t option = (mach_msg_option_t)ARG2;
6740 if (option & MACH_RCV_MSG) {
6742 // error during send or receive
6743 // GrP fixme need to clean up port rights?
6745 mach_msg_trailer_t *mt =
6746 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
6748 // Assume the entire received message and trailer is initialized
6749 // GrP fixme would being more specific catch any bugs?
6750 POST_MEM_WRITE((Addr)mh,
6751 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
6753 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6754 // Update memory map for out-of-line message data
6755 import_complex_message(tid, mh);
6760 // Call handler chosen by PRE(mach_msg)
6762 (*AFTER)(tid, arrghs, status);
6767 POST(mach_msg_unhandled)
6769 ML_(sync_mappings)("after", "mach_msg_unhandled", 0);
6773 /* ---------------------------------------------------------------------
6775 ------------------------------------------------------------------ */
6777 PRE(mach_reply_port)
6779 PRINT("mach_reply_port()");
6782 POST(mach_reply_port)
6784 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
6785 PRINT("reply port %s", name_for_port(RES));
6789 PRE(mach_thread_self)
6791 PRINT("mach_thread_self()");
6794 POST(mach_thread_self)
6796 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
6797 PRINT("thread %#lx", RES);
6803 PRINT("mach_host_self()");
6806 POST(mach_host_self)
6809 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
6810 PRINT("host %#lx", RES);
6816 PRINT("mach_task_self()");
6819 POST(mach_task_self)
6822 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
6823 PRINT("task %#lx", RES);
6827 PRE(syscall_thread_switch)
6829 PRINT("syscall_thread_switch(%s, %ld, %ld)",
6830 name_for_port(ARG1), ARG2, ARG3);
6831 PRE_REG_READ3(long, "syscall_thread_switch",
6832 mach_port_t,"thread", int,"option", natural_t,"timeout");
6834 *flags |= SfMayBlock;
6838 PRE(semaphore_signal)
6840 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
6841 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
6845 PRE(semaphore_signal_all)
6847 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
6848 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
6852 PRE(semaphore_signal_thread)
6854 PRINT("semaphore_signal_thread(%s, %s)",
6855 name_for_port(ARG1), name_for_port(ARG2));
6856 PRE_REG_READ2(long, "semaphore_signal_thread",
6857 semaphore_t,"semaphore", mach_port_t,"thread");
6863 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
6864 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
6866 *flags |= SfMayBlock;
6870 PRE(semaphore_wait_signal)
6872 PRINT("semaphore_wait_signal(%s, %s)",
6873 name_for_port(ARG1), name_for_port(ARG2));
6874 PRE_REG_READ2(long, "semaphore_wait_signal",
6875 semaphore_t,"wait_semaphore",
6876 semaphore_t,"signal_semaphore");
6878 *flags |= SfMayBlock;
6882 PRE(semaphore_timedwait)
6884 PRINT("semaphore_timedwait(%s, %g seconds)",
6885 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
6886 PRE_REG_READ3(long, "semaphore_wait_signal",
6887 semaphore_t,"semaphore",
6889 int,"wait_time_lo");
6891 *flags |= SfMayBlock;
6895 PRE(semaphore_timedwait_signal)
6897 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
6898 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
6899 PRE_REG_READ4(long, "semaphore_wait_signal",
6900 semaphore_t,"wait_semaphore",
6901 semaphore_t,"signal_semaphore",
6903 int,"wait_time_lo");
6905 *flags |= SfMayBlock;
6909 PRE(__semwait_signal)
6911 /* args: int cond_sem, int mutex_sem,
6912 int timeout, int relative,
6913 time_t tv_sec, time_t tv_nsec */
6914 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
6915 name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
6916 PRE_REG_READ6(long, "__semwait_signal",
6917 int,"cond_sem", int,"mutex_sem",
6918 int,"timeout", int,"relative",
6919 vki_time_t,"tv_sec", int,"tv_nsec");
6921 *flags |= SfMayBlock;
6927 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
6928 PRE_REG_READ3(long, "task_for_pid",
6929 mach_port_t,"target",
6930 vki_pid_t, "pid", mach_port_t *,"task");
6931 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
6938 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
6940 task = *(mach_port_t *)ARG3;
6941 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
6942 PRINT("task 0x%x", task);
6948 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
6949 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
6950 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
6957 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
6959 pid = *(vki_pid_t *)ARG2;
6960 PRINT("pid %u", pid);
6964 PRE(mach_timebase_info)
6966 PRINT("mach_timebase_info(%#lx)", ARG1);
6967 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
6968 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
6971 POST(mach_timebase_info)
6973 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
6977 PRE(mach_wait_until)
6979 #if VG_WORDSIZE == 8
6980 PRINT("mach_wait_until(%llu)", ARG1);
6981 PRE_REG_READ1(long, "mach_wait_until",
6982 unsigned long long,"deadline");
6984 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
6985 PRE_REG_READ2(long, "mach_wait_until",
6986 int,"deadline_hi", int,"deadline_lo");
6988 *flags |= SfMayBlock;
6992 PRE(mk_timer_create)
6994 PRINT("mk_timer_create()");
6995 PRE_REG_READ0(long, "mk_timer_create");
6998 POST(mk_timer_create)
7000 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
7004 PRE(mk_timer_destroy)
7006 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
7007 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
7009 // Must block to prevent race (other thread allocates and
7010 // notifies after we deallocate but before we notify)
7011 *flags &= ~SfMayBlock;
7014 POST(mk_timer_destroy)
7016 // Must have cleared SfMayBlock in PRE to prevent race
7017 record_port_destroy(ARG1);
7023 #if VG_WORDSIZE == 8
7024 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), ARG2);
7025 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
7026 unsigned long,"expire_time");
7028 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
7029 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
7030 int,"expire_time_hi", int,"expire_time_lo");
7035 PRE(mk_timer_cancel)
7037 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
7038 PRE_REG_READ2(long, "mk_timer_cancel",
7039 mach_port_t,"name", Addr,"result_time");
7041 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
7045 POST(mk_timer_cancel)
7048 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
7053 PRE(iokit_user_client_trap)
7055 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
7056 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
7057 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
7058 mach_port_t,connect, unsigned int,index,
7059 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
7060 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
7062 // can't do anything else with this in general
7063 // might be able to use connect+index to choose something sometimes
7066 POST(iokit_user_client_trap)
7068 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
7075 PRE_REG_READ0(long, "swtch");
7077 *flags |= SfMayBlock;
7083 PRINT("swtch_pri ( %ld )", ARG1);
7084 PRE_REG_READ1(long, "swtch_pri", int,"pri");
7086 *flags |= SfMayBlock;
7092 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
7093 an explanation of what follows. */
7094 /* This handles the fake signal-return system call created by
7095 sigframe-x86-darwin.c. */
7096 /* See also comments just below on PRE(sigreturn). */
7098 PRINT("FAKE_SIGRETURN ( )");
7100 vg_assert(VG_(is_valid_tid)(tid));
7101 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7102 vg_assert(VG_(is_running_thread)(tid));
7104 /* Remove the signal frame from this thread's (guest) stack,
7105 in the process restoring the pre-signal guest state. */
7106 VG_(sigframe_destroy)(tid, True);
7108 /* Tell the driver not to update the guest state with the "result",
7109 and set a bogus result to keep it happy. */
7110 *flags |= SfNoWriteResult;
7111 SET_STATUS_Success(0);
7113 /* Check to see if any signals arose as a result of this. */
7114 *flags |= SfPollAfter;
7120 /* This is the "real" sigreturn. But because we construct all the
7121 signal frames ourselves (of course, in m_sigframe), this cannot
7122 happen as a result of normal signal delivery. I think it
7123 happens only when doing siglongjmp, in which case Darwin's Libc
7124 appears to use it for two different purposes: to mess with the
7125 per-thread sigaltstack flags (as per arg 2), or to restore the
7126 thread's state from a ucontext* (as per arg 1). */
7128 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
7130 vg_assert(VG_(is_valid_tid)(tid));
7131 vg_assert(tid >= 1 && tid < VG_N_THREADS);
7132 vg_assert(VG_(is_running_thread)(tid));
7134 if (ARG2 == VKI_UC_SET_ALT_STACK) {
7135 /* This is confusing .. the darwin kernel sources imply there is
7136 a per-thread on-altstack/not-on-altstack flag, which is set
7137 by this flag. Just ignore it and claim success for the time
7139 VG_(debugLog)(0, "syswrap-darwin",
7140 "WARNING: Ignoring sigreturn( ..., "
7141 "UC_SET_ALT_STACK );\n");
7142 SET_STATUS_Success(0);
7145 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
7147 VG_(debugLog)(0, "syswrap-darwin",
7148 "WARNING: Ignoring sigreturn( ..., "
7149 "UC_RESET_ALT_STACK );\n");
7150 SET_STATUS_Success(0);
7154 /* Otherwise claim this isn't supported. (Could be
7157 What do we have to do if we do need to support it?
7159 1. Change the second argument of VG_(sigframe_destroy) from
7160 "Bool isRT" to "UInt sysno", so we can pass the syscall
7161 number, so it can distinguish this case from the
7162 __NR_DARWIN_FAKE_SIGRETURN case.
7164 2. In VG_(sigframe_destroy), look at sysno to distinguish the
7165 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
7166 For this case, restore the thread's CPU state (or at least
7167 the integer regs) from the ucontext in ARG1 (and do all the
7168 other "signal-returns" stuff too).
7170 3. For (2), how do we know where the ucontext is? One way is to
7171 temporarily copy ARG1 into this thread's guest_EBX (or any
7172 other int reg), and have VG_(sigframe_destroy) read
7173 guest_EBX. Why is it ok to trash guest_EBX (or any other int
7174 reg)? Because VG_(sigframe_destroy) is just about to
7175 overwrite all the regs anyway -- since the primary purpose of
7176 calling it is to restore the register state from the ucontext
7179 Hey, it's uggerly. But at least it's documented.
7181 /* But in the meantime ... */
7182 VG_(debugLog)(0, "syswrap-darwin",
7183 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
7184 VG_(debugLog)(0, "syswrap-darwin",
7185 "WARNING: Thread/program/Valgrind "
7186 "will likely segfault now.\n");
7187 VG_(debugLog)(0, "syswrap-darwin",
7188 "WARNING: Please file a bug report at "
7189 "http://www.valgrind.org.\n");
7190 SET_STATUS_Failure( VKI_ENOSYS );
7194 /* ---------------------------------------------------------------------
7195 machine-dependent traps
7196 ------------------------------------------------------------------ */
7198 #if defined(VGA_x86)
7199 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
7201 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
7202 return VG_(arena_calloc)(VG_AR_CORE, "syswrap-darwin.ldt", nbytes, 1);
7206 PRE(thread_fast_set_cthread_self)
7208 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
7209 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
7211 #if defined(VGA_x86)
7212 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
7214 VexGuestX86SegDescr *ldt;
7215 ThreadState *tst = VG_(get_ThreadState)(tid);
7216 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
7218 ldt = alloc_zeroed_x86_LDT();
7219 tst->arch.vex.guest_LDT = (HWord)ldt;
7221 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
7222 ldt[6].LdtEnt.Bits.LimitLow = 1;
7223 ldt[6].LdtEnt.Bits.LimitHi = 0;
7224 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
7225 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
7226 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
7227 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
7228 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
7229 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
7230 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
7231 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
7233 tst->os_state.pthread = ARG1;
7234 tst->arch.vex.guest_GS = 0x37;
7236 // What we would like to do is:
7237 // SET_STATUS_Success(0x37);
7238 // but that doesn't work, because this is a MDEP-class syscall,
7239 // and SET_STATUS_Success creates a UNIX-class syscall result.
7240 // Hence we have to laboriously construct the full SysRes "by hand"
7241 // and use that to set the syscall return status.
7242 SET_STATUS_from_SysRes(
7243 VG_(mk_SysRes_x86_darwin)(
7244 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7250 #elif defined(VGA_amd64)
7251 // GrP fixme bigger hack than x86
7253 ThreadState *tst = VG_(get_ThreadState)(tid);
7254 tst->os_state.pthread = ARG1;
7255 tst->arch.vex.guest_GS_0x60 = ARG1;
7256 // SET_STATUS_Success(0x60);
7257 // see comments on x86 case just above
7258 SET_STATUS_from_SysRes(
7259 VG_(mk_SysRes_amd64_darwin)(
7260 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
7267 #error unknown architecture
7272 /* ---------------------------------------------------------------------
7274 ------------------------------------------------------------------ */
7276 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
7277 #define MACX_(sysno, name) WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7278 #define MACXY(sysno, name) WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
7279 #define _____(sysno) GENX_(sysno, sys_ni_syscall)
7282 _____ : unsupported by the kernel (sys_ni_syscall)
7283 // _____ : unimplemented in valgrind
7284 GEN : handlers are in syswrap-generic.c
7285 MAC : handlers are in this file
7286 X_ : PRE handler only
7287 XY : PRE and POST handlers
7289 const SyscallTableEntry ML_(syscall_table)[] = {
7290 // _____(__NR_syscall), // 0
7291 MACX_(__NR_exit, exit),
7292 GENX_(__NR_fork, sys_fork),
7293 GENXY(__NR_read, sys_read),
7294 GENX_(__NR_write, sys_write),
7295 GENXY(__NR_open, sys_open),
7296 GENXY(__NR_close, sys_close),
7297 GENXY(__NR_wait4, sys_wait4),
7298 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
7299 GENX_(__NR_link, sys_link),
7300 GENX_(__NR_unlink, sys_unlink),
7301 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
7302 GENX_(__NR_chdir, sys_chdir),
7303 GENX_(__NR_fchdir, sys_fchdir),
7304 GENX_(__NR_mknod, sys_mknod),
7305 GENX_(__NR_chmod, sys_chmod),
7306 GENX_(__NR_chown, sys_chown),
7307 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
7308 MACXY(__NR_getfsstat, getfsstat),
7309 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
7310 GENX_(__NR_getpid, sys_getpid), // 20
7311 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
7312 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
7313 GENX_(__NR_setuid, sys_setuid),
7314 GENX_(__NR_getuid, sys_getuid),
7315 GENX_(__NR_geteuid, sys_geteuid),
7316 MACX_(__NR_ptrace, ptrace),
7317 MACXY(__NR_recvmsg, recvmsg),
7318 MACX_(__NR_sendmsg, sendmsg),
7319 MACXY(__NR_recvfrom, recvfrom),
7320 MACXY(__NR_accept, accept),
7321 MACXY(__NR_getpeername, getpeername),
7322 MACXY(__NR_getsockname, getsockname),
7323 GENX_(__NR_access, sys_access),
7324 MACX_(__NR_chflags, chflags),
7325 MACX_(__NR_fchflags, fchflags),
7326 GENX_(__NR_sync, sys_sync),
7327 GENX_(__NR_kill, sys_kill),
7328 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
7329 GENX_(__NR_getppid, sys_getppid),
7330 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
7331 GENXY(__NR_dup, sys_dup),
7332 MACXY(__NR_pipe, pipe),
7333 GENX_(__NR_getegid, sys_getegid),
7334 // _____(__NR_profil),
7335 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
7336 MACXY(__NR_sigaction, sigaction),
7337 GENX_(__NR_getgid, sys_getgid),
7338 MACXY(__NR_sigprocmask, sigprocmask),
7339 MACXY(__NR_getlogin, getlogin),
7340 // _____(__NR_setlogin),
7341 // _____(__NR_acct),
7342 MACXY(__NR_sigpending, sigpending),
7343 GENXY(__NR_sigaltstack, sys_sigaltstack),
7344 MACXY(__NR_ioctl, ioctl),
7345 // _____(__NR_reboot),
7346 // _____(__NR_revoke),
7347 // _____(__NR_symlink),
7348 GENX_(__NR_readlink, sys_readlink),
7349 GENX_(__NR_execve, sys_execve),
7350 GENX_(__NR_umask, sys_umask), // 60
7351 GENX_(__NR_chroot, sys_chroot),
7352 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
7353 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
7354 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
7355 GENX_(__NR_msync, sys_msync),
7356 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
7357 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
7358 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
7359 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
7360 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
7361 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
7362 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
7363 GENXY(__NR_munmap, sys_munmap),
7364 GENXY(__NR_mprotect, sys_mprotect),
7365 GENX_(__NR_madvise, sys_madvise),
7366 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
7367 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
7368 GENXY(__NR_mincore, sys_mincore),
7369 GENXY(__NR_getgroups, sys_getgroups),
7370 // _____(__NR_setgroups), // 80
7371 GENX_(__NR_getpgrp, sys_getpgrp),
7372 GENX_(__NR_setpgid, sys_setpgid),
7373 GENXY(__NR_setitimer, sys_setitimer),
7374 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
7375 // _____(__NR_swapon),
7376 GENXY(__NR_getitimer, sys_getitimer),
7377 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
7378 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
7379 MACXY(__NR_getdtablesize, getdtablesize),
7380 GENXY(__NR_dup2, sys_dup2),
7381 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
7382 MACXY(__NR_fcntl, fcntl),
7383 GENX_(__NR_select, sys_select),
7384 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
7385 GENX_(__NR_fsync, sys_fsync),
7386 GENX_(__NR_setpriority, sys_setpriority),
7387 MACXY(__NR_socket, socket),
7388 MACX_(__NR_connect, connect),
7389 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
7390 GENX_(__NR_getpriority, sys_getpriority), // 100
7391 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
7392 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
7393 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
7394 MACX_(__NR_bind, bind),
7395 MACX_(__NR_setsockopt, setsockopt),
7396 MACX_(__NR_listen, listen),
7397 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
7398 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
7399 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
7400 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
7401 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
7402 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
7403 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
7404 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
7405 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
7406 GENXY(__NR_gettimeofday, sys_gettimeofday),
7407 GENXY(__NR_getrusage, sys_getrusage),
7408 MACXY(__NR_getsockopt, getsockopt),
7409 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
7410 GENXY(__NR_readv, sys_readv), // 120
7411 GENX_(__NR_writev, sys_writev),
7412 // _____(__NR_settimeofday),
7413 GENX_(__NR_fchown, sys_fchown),
7414 GENX_(__NR_fchmod, sys_fchmod),
7415 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
7416 // _____(__NR_setreuid),
7417 // _____(__NR_setregid),
7418 GENX_(__NR_rename, sys_rename),
7419 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
7420 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
7421 GENX_(__NR_flock, sys_flock),
7422 // _____(__NR_mkfifo),
7423 MACX_(__NR_sendto, sendto),
7424 MACX_(__NR_shutdown, shutdown),
7425 MACXY(__NR_socketpair, socketpair),
7426 GENX_(__NR_mkdir, sys_mkdir),
7427 GENX_(__NR_rmdir, sys_rmdir),
7428 GENX_(__NR_utimes, sys_utimes),
7429 MACX_(__NR_futimes, futimes),
7430 // _____(__NR_adjtime), // 140
7431 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
7432 MACXY(__NR_gethostuuid, gethostuuid),
7433 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
7434 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
7435 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
7436 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
7437 GENX_(__NR_setsid, sys_setsid),
7438 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
7439 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
7440 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
7441 // _____(__NR_getpgid),
7442 // _____(__NR_setprivexec),
7443 GENXY(__NR_pread, sys_pread64),
7444 GENX_(__NR_pwrite, sys_pwrite64),
7445 // _____(__NR_nfssvc),
7446 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
7447 GENXY(__NR_statfs, sys_statfs),
7448 GENXY(__NR_fstatfs, sys_fstatfs),
7449 // _____(__NR_unmount),
7450 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
7451 // _____(__NR_getfh),
7452 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
7453 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
7454 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
7455 // _____(__NR_quotactl),
7456 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
7457 MACX_(__NR_mount, mount),
7458 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
7459 MACXY(__NR_csops, csops), // code-signing ops
7460 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
7461 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
7462 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
7463 // _____(__NR_waitid),
7464 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
7465 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
7466 // _____(__NR_add_profil),
7467 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
7468 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
7469 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
7470 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
7471 GENX_(__NR_setgid, sys_setgid),
7472 MACX_(__NR_setegid, setegid),
7473 MACX_(__NR_seteuid, seteuid),
7474 MACX_(__NR_sigreturn, sigreturn),
7475 // _____(__NR_chud),
7476 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
7477 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
7478 GENXY(__NR_stat, sys_newstat),
7479 GENXY(__NR_fstat, sys_newfstat),
7480 GENXY(__NR_lstat, sys_newlstat),
7481 MACX_(__NR_pathconf, pathconf),
7482 MACX_(__NR_fpathconf, fpathconf),
7483 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
7484 GENXY(__NR_getrlimit, sys_getrlimit),
7485 GENX_(__NR_setrlimit, sys_setrlimit),
7486 MACXY(__NR_getdirentries, getdirentries),
7487 MACXY(__NR_mmap, mmap),
7488 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
7489 MACX_(__NR_lseek, lseek),
7490 GENX_(__NR_truncate, sys_truncate64), // 200
7491 GENX_(__NR_ftruncate, sys_ftruncate64),
7492 MACXY(__NR___sysctl, __sysctl),
7493 GENX_(__NR_mlock, sys_mlock),
7494 GENX_(__NR_munlock, sys_munlock),
7495 // _____(__NR_undelete),
7496 // _____(__NR_ATsocket),
7497 // _____(__NR_ATgetmsg),
7498 // _____(__NR_ATputmsg),
7499 // _____(__NR_ATPsndreq),
7500 // _____(__NR_ATPsndrsp),
7501 // _____(__NR_ATPgetreq),
7502 // _____(__NR_ATPgetrsp),
7503 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
7504 // _____(__NR_kqueue_from_portset_np),
7505 // _____(__NR_kqueue_portset_np),
7506 // _____(__NR_mkcomplex),
7507 // _____(__NR_statv),
7508 // _____(__NR_lstatv),
7509 // _____(__NR_fstatv),
7510 MACXY(__NR_getattrlist, getattrlist), // 220
7511 MACX_(__NR_setattrlist, setattrlist),
7512 MACXY(__NR_getdirentriesattr, getdirentriesattr),
7513 MACX_(__NR_exchangedata, exchangedata),
7514 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
7515 // _____(__NR_searchfs),
7516 GENX_(__NR_delete, sys_unlink),
7517 // _____(__NR_copyfile),
7518 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
7519 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
7520 GENXY(__NR_poll, sys_poll),
7521 MACX_(__NR_watchevent, watchevent),
7522 MACXY(__NR_waitevent, waitevent),
7523 MACX_(__NR_modwatch, modwatch),
7524 MACXY(__NR_getxattr, getxattr),
7525 MACXY(__NR_fgetxattr, fgetxattr),
7526 MACX_(__NR_setxattr, setxattr),
7527 MACX_(__NR_fsetxattr, fsetxattr),
7528 // _____(__NR_removexattr),
7529 // _____(__NR_fremovexattr),
7530 MACXY(__NR_listxattr, listxattr), // 240
7531 MACXY(__NR_flistxattr, flistxattr),
7532 MACXY(__NR_fsctl, fsctl),
7533 MACX_(__NR_initgroups, initgroups),
7534 MACXY(__NR_posix_spawn, posix_spawn),
7535 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
7536 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
7537 // _____(__NR_nfsclnt),
7538 // _____(__NR_fhopen),
7539 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
7540 // _____(__NR_minherit),
7541 // _____(__NR_semsys),
7542 // _____(__NR_msgsys),
7543 // _____(__NR_shmsys),
7544 MACXY(__NR_semctl, semctl),
7545 MACX_(__NR_semget, semget),
7546 MACX_(__NR_semop, semop),
7547 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
7548 // _____(__NR_msgctl),
7549 // _____(__NR_msgget),
7550 // _____(__NR_msgsnd), // 260
7551 // _____(__NR_msgrcv),
7552 MACXY(__NR_shmat, shmat),
7553 MACXY(__NR_shmctl, shmctl),
7554 MACXY(__NR_shmdt, shmdt),
7555 MACX_(__NR_shmget, shmget),
7556 MACXY(__NR_shm_open, shm_open),
7557 // _____(__NR_shm_unlink),
7558 MACX_(__NR_sem_open, sem_open),
7559 MACX_(__NR_sem_close, sem_close),
7560 MACX_(__NR_sem_unlink, sem_unlink),
7561 MACX_(__NR_sem_wait, sem_wait),
7562 MACX_(__NR_sem_trywait, sem_trywait),
7563 MACX_(__NR_sem_post, sem_post),
7564 // _____(__NR_sem_getvalue),
7565 MACXY(__NR_sem_init, sem_init),
7566 MACX_(__NR_sem_destroy, sem_destroy),
7567 // _____(__NR_open_extended),
7568 // _____(__NR_umask_extended),
7569 MACXY(__NR_stat_extended, stat_extended),
7570 MACXY(__NR_lstat_extended, lstat_extended), // 280
7571 MACXY(__NR_fstat_extended, fstat_extended),
7572 MACX_(__NR_chmod_extended, chmod_extended),
7573 MACX_(__NR_fchmod_extended,fchmod_extended),
7574 MACXY(__NR_access_extended,access_extended),
7575 MACX_(__NR_settid, settid),
7576 // _____(__NR_gettid),
7577 // _____(__NR_setsgroups),
7578 // _____(__NR_getsgroups),
7579 // _____(__NR_setwgroups),
7580 // _____(__NR_getwgroups),
7581 // _____(__NR_mkfifo_extended),
7582 // _____(__NR_mkdir_extended),
7583 // _____(__NR_identitysvc),
7584 // _____(__NR_shared_region_check_np),
7585 // _____(__NR_shared_region_map_np),
7586 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
7587 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
7588 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
7589 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
7590 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
7591 // _____(__NR___pthread_mutex_destroy),
7592 // _____(__NR___pthread_mutex_init),
7593 // _____(__NR___pthread_mutex_lock),
7594 // _____(__NR___pthread_mutex_trylock),
7595 // _____(__NR___pthread_mutex_unlock),
7596 // _____(__NR___pthread_cond_init),
7597 // _____(__NR___pthread_cond_destroy),
7598 // _____(__NR___pthread_cond_broadcast),
7599 // _____(__NR___pthread_cond_signal),
7600 // _____(__NR_getsid),
7601 // _____(__NR_settid_with_pid),
7602 // _____(__NR___pthread_cond_timedwait),
7603 // _____(__NR_aio_fsync),
7604 MACXY(__NR_aio_return, aio_return),
7605 MACX_(__NR_aio_suspend, aio_suspend),
7606 // _____(__NR_aio_cancel),
7607 MACX_(__NR_aio_error, aio_error),
7608 MACXY(__NR_aio_read, aio_read),
7609 MACX_(__NR_aio_write, aio_write),
7610 // _____(__NR_lio_listio), // 320
7611 // _____(__NR___pthread_cond_wait),
7612 // _____(__NR_iopolicysys),
7613 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
7614 // _____(__NR_mlockall),
7615 // _____(__NR_munlockall),
7616 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
7617 MACX_(__NR_issetugid, issetugid),
7618 MACX_(__NR___pthread_kill, __pthread_kill),
7619 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
7620 // _____(__NR___sigwait),
7621 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
7622 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
7623 MACX_(__NR___pthread_canceled, __pthread_canceled),
7624 MACX_(__NR___semwait_signal, __semwait_signal),
7625 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
7626 // _____(__NR_proc_info),
7627 MACXY(__NR_sendfile, sendfile),
7628 MACXY(__NR_stat64, stat64),
7629 MACXY(__NR_fstat64, fstat64),
7630 MACXY(__NR_lstat64, lstat64), // 340
7631 MACXY(__NR_stat64_extended, stat64_extended),
7632 MACXY(__NR_lstat64_extended, lstat64_extended),
7633 MACXY(__NR_fstat64_extended, fstat64_extended),
7634 MACXY(__NR_getdirentries64, getdirentries64),
7635 MACXY(__NR_statfs64, statfs64),
7636 MACXY(__NR_fstatfs64, fstatfs64),
7637 MACXY(__NR_getfsstat64, getfsstat64),
7638 // _____(__NR___pthread_chdir),
7639 // _____(__NR___pthread_fchdir),
7640 // _____(__NR_audit),
7641 MACXY(__NR_auditon, auditon),
7642 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
7643 // _____(__NR_getauid),
7644 // _____(__NR_setauid),
7645 // _____(__NR_getaudit),
7646 // _____(__NR_setaudit),
7647 // _____(__NR_getaudit_addr),
7648 // _____(__NR_setaudit_addr),
7649 // _____(__NR_auditctl),
7650 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
7651 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
7652 MACXY(__NR_kqueue, kqueue),
7653 MACXY(__NR_kevent, kevent),
7654 // _____(__NR_lchown),
7655 // _____(__NR_stack_snapshot),
7656 MACX_(__NR_bsdthread_register, bsdthread_register),
7657 MACX_(__NR_workq_open, workq_open),
7658 MACXY(__NR_workq_ops, workq_ops),
7659 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
7660 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // ???
7661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // ???
7662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
7663 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
7664 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
7665 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
7666 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
7667 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
7668 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
7669 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
7670 // _____(__NR___mac_execve), // 380
7671 MACX_(__NR___mac_syscall, __mac_syscall),
7672 // _____(__NR___mac_get_file),
7673 // _____(__NR___mac_set_file),
7674 // _____(__NR___mac_get_link),
7675 // _____(__NR___mac_set_link),
7676 // _____(__NR___mac_get_proc),
7677 // _____(__NR___mac_set_proc),
7678 // _____(__NR___mac_get_fd),
7679 // _____(__NR___mac_set_fd),
7680 // _____(__NR___mac_get_pid),
7681 // _____(__NR___mac_get_lcid),
7682 // _____(__NR___mac_get_lctx),
7683 // _____(__NR___mac_set_lctx),
7684 // _____(__NR_setlcid),
7685 // _____(__NR_getlcid),
7686 // GrP fixme need any special nocancel handling?
7687 GENXY(__NR_read_nocancel, sys_read),
7688 GENX_(__NR_write_nocancel, sys_write),
7689 GENXY(__NR_open_nocancel, sys_open),
7690 GENXY(__NR_close_nocancel, sys_close),
7691 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
7692 MACXY(__NR_recvmsg_nocancel, recvmsg),
7693 MACX_(__NR_sendmsg_nocancel, sendmsg),
7694 MACXY(__NR_recvfrom_nocancel, recvfrom),
7695 MACXY(__NR_accept_nocancel, accept),
7696 GENX_(__NR_msync_nocancel, sys_msync),
7697 MACXY(__NR_fcntl_nocancel, fcntl),
7698 GENX_(__NR_select_nocancel, sys_select),
7699 GENX_(__NR_fsync_nocancel, sys_fsync),
7700 MACX_(__NR_connect_nocancel, connect),
7701 // _____(__NR_sigsuspend_nocancel),
7702 GENXY(__NR_readv_nocancel, sys_readv),
7703 GENX_(__NR_writev_nocancel, sys_writev),
7704 MACX_(__NR_sendto_nocancel, sendto),
7705 GENXY(__NR_pread_nocancel, sys_pread64),
7706 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
7707 // _____(__NR_waitid_nocancel),
7708 GENXY(__NR_poll_nocancel, sys_poll),
7709 // _____(__NR_msgsnd_nocancel),
7710 // _____(__NR_msgrcv_nocancel),
7711 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
7712 // _____(__NR_aio_suspend_nocancel),
7713 // _____(__NR___sigwait_nocancel),
7714 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
7715 // _____(__NR___mac_mount),
7716 // _____(__NR___mac_get_mount),
7717 // _____(__NR___mac_getfsstat),
7718 // _____(__NR_MAXSYSCALL)
7719 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
7723 // Mach traps use negative syscall numbers.
7724 // Use ML_(mach_trap_table)[-mach_trap_number] .
7726 const SyscallTableEntry ML_(mach_trap_table)[] = {
7727 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
7728 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
7729 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
7730 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
7731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
7732 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
7733 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
7734 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
7735 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
7736 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
7737 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
7738 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
7739 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
7740 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
7741 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
7742 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
7743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
7744 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
7745 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
7746 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
7747 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)), // -20
7748 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
7749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
7750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
7751 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
7752 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
7753 MACXY(__NR_mach_reply_port, mach_reply_port),
7754 MACXY(__NR_thread_self_trap, mach_thread_self),
7755 MACXY(__NR_task_self_trap, mach_task_self),
7756 MACXY(__NR_host_self_trap, mach_host_self),
7757 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
7758 MACXY(__NR_mach_msg_trap, mach_msg),
7759 // _____(__NR_mach_msg_overwrite_trap),
7760 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
7761 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
7762 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
7763 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
7764 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
7765 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
7766 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
7767 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
7768 #if defined(VGA_x86)
7769 // _____(__NR_init_process),
7770 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
7771 // _____(__NR_map_fd),
7773 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
7774 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
7775 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
7777 // _____(__NR_task_name_for_pid),
7778 MACXY(__NR_task_for_pid, task_for_pid),
7779 MACXY(__NR_pid_for_task, pid_for_task),
7780 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
7781 #if defined(VGA_x86)
7782 // _____(__NR_macx_swapon),
7783 // _____(__NR_macx_swapoff),
7784 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
7785 // _____(__NR_macx_triggers),
7786 // _____(__NR_macx_backing_store_suspend),
7787 // _____(__NR_macx_backing_store_recovery),
7789 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
7790 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
7791 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
7792 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
7793 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
7794 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
7796 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
7797 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
7798 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
7799 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
7800 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
7801 MACX_(__NR_swtch_pri, swtch_pri),
7802 MACX_(__NR_swtch, swtch), // -60
7803 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
7804 // _____(__NR_clock_sleep_trap),
7805 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
7806 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
7807 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
7808 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
7809 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
7810 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
7811 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
7812 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
7813 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
7814 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
7815 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
7816 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
7817 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
7818 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
7819 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
7820 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
7821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
7822 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
7823 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
7824 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
7825 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
7826 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
7827 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
7828 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
7829 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
7830 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
7831 MACXY(__NR_mach_timebase_info, mach_timebase_info),
7832 MACX_(__NR_mach_wait_until, mach_wait_until),
7833 MACXY(__NR_mk_timer_create, mk_timer_create),
7834 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
7835 MACX_(__NR_mk_timer_arm, mk_timer_arm),
7836 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
7837 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
7838 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
7839 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
7840 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
7841 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
7842 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
7846 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
7847 // calling convention instead of the syscall convention.
7848 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
7850 #if defined(VGA_x86)
7851 const SyscallTableEntry ML_(mdep_trap_table)[] = {
7852 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
7854 #elif defined(VGA_amd64)
7855 const SyscallTableEntry ML_(mdep_trap_table)[] = {
7856 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
7859 #error unknown architecture
7862 const UInt ML_(syscall_table_size) =
7863 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
7865 const UInt ML_(mach_trap_table_size) =
7866 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
7868 const UInt ML_(mdep_trap_table_size) =
7869 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
7871 #endif // defined(VGO_darwin)
7873 /*--------------------------------------------------------------------*/
7875 /*--------------------------------------------------------------------*/