syswrap-darwin.c revision d7d4acffb954f581bdbf847e8f8571538294bbf1
1
2/*--------------------------------------------------------------------*/
3/*--- Darwin-specific syscalls, etc.              syswrap-darwin.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2005-2013 Apple Inc.
11      Greg Parker  gparker@apple.com
12
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.
17
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.
22
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
26   02111-1307, USA.
27
28   The GNU General Public License is contained in the file COPYING.
29*/
30
31#if defined(VGO_darwin)
32
33#include "pub_core_basics.h"
34#include "pub_core_vki.h"
35#include "pub_core_vkiscnums.h"
36#include "pub_core_libcsetjmp.h"   // to keep _threadstate.h happy
37#include "pub_core_threadstate.h"
38#include "pub_core_aspacemgr.h"
39#include "pub_core_xarray.h"
40#include "pub_core_clientstate.h"
41#include "pub_core_debuglog.h"
42#include "pub_core_debuginfo.h"    // VG_(di_notify_*)
43#include "pub_core_transtab.h"     // VG_(discard_translations)
44#include "pub_core_libcbase.h"
45#include "pub_core_libcassert.h"
46#include "pub_core_libcfile.h"
47#include "pub_core_libcprint.h"
48#include "pub_core_libcproc.h"
49#include "pub_core_libcsignal.h"
50#include "pub_core_machine.h"      // VG_(get_SP)
51#include "pub_core_mallocfree.h"
52#include "pub_core_options.h"
53#include "pub_core_oset.h"
54#include "pub_core_scheduler.h"
55#include "pub_core_sigframe.h"      // For VG_(sigframe_destroy)()
56#include "pub_core_signals.h"
57#include "pub_core_syscall.h"
58#include "pub_core_syswrap.h"
59#include "pub_core_tooliface.h"
60
61#include "priv_types_n_macros.h"
62#include "priv_syswrap-generic.h"   /* for decls of generic wrappers */
63#include "priv_syswrap-darwin.h"    /* for decls of darwin-ish wrappers */
64#include "priv_syswrap-main.h"
65
66/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
67#include <mach/mach.h>
68#include <mach/mach_vm.h>
69#include <semaphore.h>
70/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
71
72#define msgh_request_port      msgh_remote_port
73#define msgh_reply_port        msgh_local_port
74#define BOOTSTRAP_MAX_NAME_LEN                  128
75typedef HChar name_t[BOOTSTRAP_MAX_NAME_LEN];
76
77typedef uint64_t mig_addr_t;
78
79
80// Saved ports
81static mach_port_t vg_host_port = 0;
82static mach_port_t vg_task_port = 0;
83static mach_port_t vg_bootstrap_port = 0;
84
85// Run a thread from beginning to end and return the thread's
86// scheduler-return-code.
87static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
88{
89   VgSchedReturnCode ret;
90   ThreadId     tid = (ThreadId)tidW;
91   ThreadState* tst = VG_(get_ThreadState)(tid);
92
93   VG_(debugLog)(1, "syswrap-darwin",
94                    "thread_wrapper(tid=%lld): entry\n",
95                    (ULong)tidW);
96
97   vg_assert(tst->status == VgTs_Init);
98
99   /* make sure we get the CPU lock before doing anything significant */
100   VG_(acquire_BigLock)(tid, "thread_wrapper");
101
102   if (0)
103      VG_(printf)("thread tid %d started: stack = %p\n",
104                  tid, &tid);
105
106   /* Make sure error reporting is enabled in the new thread. */
107   tst->err_disablement_level = 0;
108
109   VG_TRACK(pre_thread_first_insn, tid);
110
111   tst->os_state.lwpid = VG_(gettid)();
112   tst->os_state.threadgroup = VG_(getpid)();
113
114   /* Thread created with all signals blocked; scheduler will set the
115      appropriate mask */
116
117   ret = VG_(scheduler)(tid);
118
119   vg_assert(VG_(is_exiting)(tid));
120
121   vg_assert(tst->status == VgTs_Runnable);
122   vg_assert(VG_(is_running_thread)(tid));
123
124   VG_(debugLog)(1, "syswrap-darwin",
125                    "thread_wrapper(tid=%lld): done\n",
126                    (ULong)tidW);
127
128   /* Return to caller, still holding the lock. */
129   return ret;
130}
131
132
133
134/* Allocate a stack for this thread, if it doesn't already have one.
135   Returns the initial stack pointer value to use, or 0 if allocation
136   failed. */
137
138Addr allocstack ( ThreadId tid )
139{
140   ThreadState* tst = VG_(get_ThreadState)(tid);
141   VgStack*     stack;
142   Addr         initial_SP;
143
144   /* Either the stack_base and stack_init_SP are both zero (in which
145      case a stack hasn't been allocated) or they are both non-zero,
146      in which case it has. */
147
148   if (tst->os_state.valgrind_stack_base == 0)
149      vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
150
151   if (tst->os_state.valgrind_stack_base != 0)
152      vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
153
154   /* If no stack is present, allocate one. */
155
156   if (tst->os_state.valgrind_stack_base == 0) {
157      stack = VG_(am_alloc_VgStack)( &initial_SP );
158      if (stack) {
159         tst->os_state.valgrind_stack_base    = (Addr)stack;
160         tst->os_state.valgrind_stack_init_SP = initial_SP;
161      }
162   }
163
164   VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
165                   tid,
166                   (void*)tst->os_state.valgrind_stack_base,
167                   (void*)tst->os_state.valgrind_stack_init_SP );
168
169   vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
170
171   return tst->os_state.valgrind_stack_init_SP;
172}
173
174
175void find_stack_segment(ThreadId tid, Addr sp)
176{
177   /* We don't really know where the client stack is, because it's
178      allocated by the client.  The best we can do is look at the
179      memory mappings and try to derive some useful information.  We
180      assume that esp starts near its highest possible value, and can
181      only go down to the start of the mmaped segment. */
182   ThreadState *tst = VG_(get_ThreadState)(tid);
183   const NSegment *seg = VG_(am_find_nsegment)(sp);
184   if (seg && seg->kind != SkResvn) {
185      tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
186      tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
187
188      if (1)
189         VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
190                     tid, seg->start, VG_PGROUNDUP(sp));
191   } else {
192       VG_(printf)("couldn't find user stack\n");
193      VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
194                   tid, sp);
195      tst->client_stack_szB  = 0;
196   }
197}
198
199
200/* Run a thread all the way to the end, then do appropriate exit actions
201   (this is the last-one-out-turn-off-the-lights bit).
202*/
203static void run_a_thread_NORETURN ( Word tidW )
204{
205   Int               c;
206   VgSchedReturnCode src;
207   ThreadId          tid = (ThreadId)tidW;
208   ThreadState*      tst;
209
210   VG_(debugLog)(1, "syswrap-darwin",
211                    "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
212                    (ULong)tidW);
213
214   tst = VG_(get_ThreadState)(tid);
215   vg_assert(tst);
216
217   /* Run the thread all the way through. */
218   src = thread_wrapper(tid);
219
220   VG_(debugLog)(1, "syswrap-darwin",
221                    "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
222                    (ULong)tidW);
223
224   c = VG_(count_living_threads)();
225   vg_assert(c >= 1); /* stay sane */
226
227   // Tell the tool this thread is exiting
228   VG_TRACK( pre_thread_ll_exit, tid );
229
230   /* If the thread is exiting with errors disabled, complain loudly;
231      doing so is bad (does the user know this has happened?)  Also,
232      in all cases, be paranoid and clear the flag anyway so that the
233      thread slot is safe in this respect if later reallocated.  This
234      should be unnecessary since the flag should be cleared when the
235      slot is reallocated, in thread_wrapper(). */
236   if (tst->err_disablement_level > 0) {
237      VG_(umsg)(
238         "WARNING: exiting thread has error reporting disabled.\n"
239         "WARNING: possibly as a result of some mistake in the use\n"
240         "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
241      );
242      VG_(debugLog)(
243         1, "syswrap-linux",
244            "run_a_thread_NORETURN(tid=%lld): "
245            "WARNING: exiting thread has err_disablement_level = %u\n",
246            (ULong)tidW, tst->err_disablement_level
247      );
248   }
249   tst->err_disablement_level = 0;
250
251   if (c == 1) {
252
253      VG_(debugLog)(1, "syswrap-darwin",
254                       "run_a_thread_NORETURN(tid=%lld): "
255                          "last one standing\n",
256                          (ULong)tidW);
257
258      /* We are the last one standing.  Keep hold of the lock and
259         carry on to show final tool results, then exit the entire system.
260         Use the continuation pointer set at startup in m_main. */
261      ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
262
263   } else {
264
265      mach_msg_header_t msg;
266
267      VG_(debugLog)(1, "syswrap-darwin",
268                       "run_a_thread_NORETURN(tid=%lld): "
269                          "not last one standing\n",
270                          (ULong)tidW);
271
272      /* OK, thread is dead, but others still exist.  Just exit. */
273
274      /* This releases the run lock */
275      VG_(exit_thread)(tid);
276      vg_assert(tst->status == VgTs_Zombie);
277
278      /* tid is now invalid. */
279
280      // GrP fixme exit race
281      msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
282      msg.msgh_request_port = VG_(gettid)();
283      msg.msgh_reply_port = 0;
284      msg.msgh_id = 3600;  // thread_terminate
285
286      tst->status = VgTs_Empty;
287      // GrP fixme race here! new thread may claim this V thread stack
288      // before we get out here!
289      // GrP fixme use bsdthread_terminate for safe cleanup?
290      mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
291               sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
292
293      // DDD: This is reached sometimes on none/tests/manythreads, maybe
294      // because of the race above.
295      VG_(core_panic)("Thread exit failed?\n");
296   }
297
298   /*NOTREACHED*/
299   vg_assert(0);
300}
301
302
303/* Allocate a stack for the main thread, and run it all the way to the
304   end.  Although we already have a working VgStack
305   (VG_(interim_stack)) it's better to allocate a new one, so that
306   overflow detection works uniformly for all threads.
307*/
308void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
309{
310   Addr sp;
311   VG_(debugLog)(1, "syswrap-darwin",
312                    "entering VG_(main_thread_wrapper_NORETURN)\n");
313
314   sp = allocstack(tid);
315
316   /* If we can't even allocate the first thread's stack, we're hosed.
317      Give up. */
318   vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
319
320   /* shouldn't be any other threads around yet */
321   vg_assert( VG_(count_living_threads)() == 1 );
322
323   call_on_new_stack_0_1(
324      (Addr)sp,             /* stack */
325      0,                     /*bogus return address*/
326      run_a_thread_NORETURN,  /* fn to call */
327      (Word)tid              /* arg to give it */
328   );
329
330   /*NOTREACHED*/
331   vg_assert(0);
332}
333
334
335void start_thread_NORETURN ( Word arg )
336{
337   ThreadState* tst = (ThreadState*)arg;
338   ThreadId     tid = tst->tid;
339
340   run_a_thread_NORETURN ( (Word)tid );
341   /*NOTREACHED*/
342   vg_assert(0);
343}
344
345
346void VG_(cleanup_thread) ( ThreadArchState* arch )
347{
348}
349
350
351/* ---------------------------------------------------------------------
352   Mach port tracking (based on syswrap-generic's fd tracker)
353   ------------------------------------------------------------------ */
354
355/* One of these is allocated for each open port.  */
356typedef struct OpenPort
357{
358   mach_port_t port;
359   mach_port_type_t type;         /* right type(s) */
360   Int send_count;                /* number of send rights */
361   HChar *name;                   /* bootstrap name or NULL */
362   ExeContext *where;             /* first allocation only */
363   struct OpenPort *next, *prev;
364} OpenPort;
365
366// strlen("0x12345678")
367#define PORT_STRLEN (2+2*sizeof(mach_port_t))
368
369/* List of allocated ports. */
370static OpenPort *allocated_ports;
371
372/* Count of open ports. */
373static Int allocated_port_count = 0;
374
375/* Create an entry for |port|, with no other info.  Assumes it doesn't
376   already exist. */
377static void port_create_vanilla(mach_port_t port)
378{
379   OpenPort* op
380     = VG_(arena_calloc)(VG_AR_CORE, "syswrap-darwin.port_create_vanilla",
381			 sizeof(OpenPort), 1);
382   op->port = port;
383   /* Add it to the list. */
384   op->next = allocated_ports;
385   if (allocated_ports) allocated_ports->prev = op;
386   allocated_ports = op;
387   allocated_port_count++;
388}
389
390__attribute__((unused))
391static Bool port_exists(mach_port_t port)
392{
393   OpenPort *i;
394
395   /* Check to see if this port is already open. */
396   i = allocated_ports;
397   while (i) {
398      if (i->port == port) {
399         return True;
400      }
401      i = i->next;
402   }
403
404   return False;
405}
406
407static OpenPort *info_for_port(mach_port_t port)
408{
409   OpenPort *i;
410   if (!port) return NULL;
411
412   i = allocated_ports;
413   while (i) {
414      if (i->port == port) {
415         return i;
416      }
417      i = i->next;
418   }
419
420   return NULL;
421}
422
423
424// Give a port a name, without changing its refcount
425// GrP fixme don't override name if it already has a specific one
426__private_extern__ void assign_port_name(mach_port_t port, const HChar *name)
427{
428   OpenPort *i;
429   if (!port) return;
430   vg_assert(name);
431
432   i = info_for_port(port);
433   vg_assert(i);
434
435   if (i->name) VG_(arena_free)(VG_AR_CORE, i->name);
436   i->name =
437       VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name",
438                         VG_(strlen)(name) + PORT_STRLEN + 1);
439   VG_(sprintf)(i->name, name, port);
440}
441
442
443// Return the name of the given port or "UNKNOWN 0x1234" if not known.
444static const HChar *name_for_port(mach_port_t port)
445{
446   static HChar buf[8 + PORT_STRLEN + 1];
447   OpenPort *i;
448
449   // hack
450   if (port == VG_(gettid)()) return "mach_thread_self()";
451   if (port == 0) return "NULL";
452
453   i = allocated_ports;
454   while (i) {
455      if (i->port == port) {
456         return i->name;
457      }
458      i = i->next;
459   }
460
461   VG_(sprintf)(buf, "NONPORT-%#x", port);
462   return buf;
463}
464
465/* Note the fact that a port was just deallocated. */
466
467static
468void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
469{
470   OpenPort *i = allocated_ports;
471   if (!port) return;
472
473   while(i) {
474      if(i->port == port) {
475         vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
476         if (right & MACH_PORT_TYPE_SEND) {
477            // send rights are refcounted
478            if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
479            i->send_count += delta;
480            if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
481            else i->type &= ~MACH_PORT_TYPE_SEND;
482         }
483         right = right & ~MACH_PORT_TYPE_SEND;
484         if (right) {
485            // other rights are not refcounted
486            if (delta > 0) {
487               i->type |= right;
488            } else if (delta < 0) {
489               i->type &= ~right;
490            }
491         }
492
493         if (i->type != 0) return;
494
495         // Port has no rights left. Kill it.
496         // VG_(printf)("deleting port %p %s", i->port, i->name);
497         if(i->prev)
498            i->prev->next = i->next;
499         else
500            allocated_ports = i->next;
501         if(i->next)
502            i->next->prev = i->prev;
503         if(i->name)
504            VG_(arena_free) (VG_AR_CORE, i->name);
505         VG_(arena_free) (VG_AR_CORE, i);
506         allocated_port_count--;
507         return;
508      }
509      i = i->next;
510   }
511
512   VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
513}
514
515static
516void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
517{
518   switch (type) {
519   case MACH_MSG_TYPE_PORT_NAME:
520      // this task has no rights for the name
521      break;
522   case MACH_MSG_TYPE_PORT_RECEIVE:
523      // this task gets receive rights
524      record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
525      break;
526   case MACH_MSG_TYPE_PORT_SEND:
527      // this task gets a send right
528      record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
529      break;
530   case MACH_MSG_TYPE_PORT_SEND_ONCE:
531      // this task gets send-once rights
532      record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
533      break;
534   default:
535      vg_assert(0);
536      break;
537   }
538}
539
540static
541void record_port_dealloc(mach_port_t port)
542{
543   // deletes 1 send or send-once right (port can't have both)
544   record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
545}
546
547static
548void record_port_destroy(mach_port_t port)
549{
550   // deletes all rights to port
551   record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
552}
553
554
555/* Note the fact that a Mach port was just allocated or transferred.
556   If the port is already known, increment its reference count. */
557void record_named_port(ThreadId tid, mach_port_t port,
558                       mach_port_right_t right, const HChar *name)
559{
560   OpenPort *i;
561   if (!port) return;
562
563   /* Check to see if this port is already open. */
564   i = allocated_ports;
565   while (i) {
566      if (i->port == port) {
567         if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
568         return;
569      }
570      i = i->next;
571   }
572
573   /* Not already one: allocate an OpenPort */
574   if (i == NULL) {
575      i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port",
576                            sizeof(OpenPort));
577
578      i->prev = NULL;
579      i->next = allocated_ports;
580      if(allocated_ports) allocated_ports->prev = i;
581      allocated_ports = i;
582      allocated_port_count++;
583
584      i->port = port;
585      i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
586      i->name = NULL;
587      if (right != -1) {
588         i->type = MACH_PORT_TYPE(right);
589         i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
590      } else {
591         i->type = 0;
592         i->send_count = 0;
593      }
594
595      assign_port_name(port, name);
596   }
597}
598
599
600// Record opening of a nameless port.
601static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
602{
603   record_named_port(tid, port, right, "unnamed-%p");
604}
605
606
607/* Dump summary of open Mach ports, like VG_(show_open_fds) */
608void VG_(show_open_ports)(void)
609{
610   OpenPort *i;
611
612   VG_(message)(Vg_UserMsg,
613                "MACH PORTS: %d open at exit.", allocated_port_count);
614
615   for (i = allocated_ports; i; i = i->next) {
616      if (i->name) {
617         VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name);
618      } else {
619         VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port);
620      }
621
622      if (i->where) {
623         VG_(pp_ExeContext)(i->where);
624         VG_(message)(Vg_UserMsg, "");
625      }
626   }
627
628   VG_(message)(Vg_UserMsg, "");
629}
630
631
632/* ---------------------------------------------------------------------
633   sync_mappings
634   ------------------------------------------------------------------ */
635
636Bool ML_(sync_mappings)(const HChar *when, const HChar *where, Int num)
637{
638   // Usually the number of segments added/removed in a single calls is very
639   // small e.g. 1.  But it sometimes gets up to at least 100 or so (eg. for
640   // Quicktime).  So we use a repeat-with-bigger-buffers-until-success model,
641   // because we can't do dynamic allocation within VG_(get_changed_segments),
642   // because it's in m_aspacemgr.
643   ChangedSeg* css = NULL;
644   Int         css_size;
645   Int         css_used;
646   Int         i;
647   Bool        ok;
648
649   if (VG_(clo_trace_syscalls)) {
650       VG_(debugLog)(0, "syswrap-darwin",
651                     "sync_mappings(\"%s\", \"%s\", %d)\n",
652                     when, where, num);
653   }
654
655   // 16 is enough for most cases, but small enough that overflow happens
656   // occasionally and thus the overflow path gets some test coverage.
657   css_size = 16;
658   ok = False;
659   while (!ok) {
660      VG_(free)(css);   // css is NULL on first iteration;  that's ok.
661      css = VG_(calloc)("sys_wrap.sync_mappings", css_size, sizeof(ChangedSeg));
662      ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
663      css_size *= 2;
664   }
665
666   // Now add/remove them.
667   for (i = 0; i < css_used; i++) {
668      ChangedSeg* cs = &css[i];
669      if (cs->is_added) {
670         ML_(notify_core_and_tool_of_mmap)(
671               cs->start, cs->end - cs->start + 1,
672               cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
673         // should this call VG_(di_notify_mmap) also?
674      } else {
675         ML_(notify_core_and_tool_of_munmap)(
676               cs->start, cs->end - cs->start + 1);
677      }
678      if (VG_(clo_trace_syscalls)) {
679          if (cs->is_added) {
680             VG_(debugLog)(0, "syswrap-darwin",
681                "  added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
682                cs->start, cs->end + 1, (UInt)cs->prot, where, when);
683	  } else {
684             VG_(debugLog)(0, "syswrap-darwin",
685                "  removed region 0x%010lx..0x%010lx at %s (%s)\n",
686                cs->start, cs->end + 1, where, when);
687	  }
688      }
689   }
690
691   VG_(free)(css);
692
693   return css_used > 0;
694}
695
696/* ---------------------------------------------------------------------
697   wrappers
698   ------------------------------------------------------------------ */
699
700#define PRE(name)       DEFN_PRE_TEMPLATE(darwin, name)
701#define POST(name)      DEFN_POST_TEMPLATE(darwin, name)
702
703#define PRE_FN(name)    vgSysWrap_darwin_##name##_before
704#define POST_FN(name)   vgSysWrap_darwin_##name##_after
705
706#define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
707#define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
708
709#if VG_WORDSIZE == 4
710// Combine two 32-bit values into a 64-bit value
711// Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
712# if defined(VGA_x86)
713#  define LOHI64(lo,hi)   ( (lo) | ((ULong)(hi) << 32) )
714# else
715#  error unknown architecture
716# endif
717#endif
718
719// Retrieve the current Mach thread
720#define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
721
722// Set the POST handler for a mach_msg derivative
723#define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
724
725// Set or get values saved from Mach messages
726#define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
727#define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
728#define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
729
730/* ---------------------------------------------------------------------
731   darwin ioctl wrapper
732   ------------------------------------------------------------------ */
733
734PRE(ioctl)
735{
736   *flags |= SfMayBlock;
737
738   /* Handle ioctls that don't take an arg first */
739   switch (ARG2 /* request */) {
740   case VKI_TIOCSCTTY:
741   case VKI_TIOCEXCL:
742   case VKI_TIOCPTYGRANT:
743   case VKI_TIOCPTYUNLK:
744   case VKI_DTRACEHIOC_REMOVE:
745      PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
746      PRE_REG_READ2(long, "ioctl",
747                    unsigned int, fd, unsigned int, request);
748      return;
749   default:
750      PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
751      PRE_REG_READ3(long, "ioctl",
752                    unsigned int, fd, unsigned int, request, unsigned long, arg);
753   }
754
755   switch (ARG2 /* request */) {
756   case VKI_TIOCGWINSZ:
757      PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
758      break;
759   case VKI_TIOCSWINSZ:
760      PRE_MEM_READ( "ioctl(TIOCSWINSZ)",  ARG3, sizeof(struct vki_winsize) );
761      break;
762   case VKI_TIOCMBIS:
763      PRE_MEM_READ( "ioctl(TIOCMBIS)",    ARG3, sizeof(unsigned int) );
764      break;
765   case VKI_TIOCMBIC:
766      PRE_MEM_READ( "ioctl(TIOCMBIC)",    ARG3, sizeof(unsigned int) );
767      break;
768   case VKI_TIOCMSET:
769      PRE_MEM_READ( "ioctl(TIOCMSET)",    ARG3, sizeof(unsigned int) );
770      break;
771   case VKI_TIOCMGET:
772      PRE_MEM_WRITE( "ioctl(TIOCMGET)",   ARG3, sizeof(unsigned int) );
773      break;
774   case VKI_TIOCGPGRP:
775      /* Get process group ID for foreground processing group. */
776      PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
777      break;
778   case VKI_TIOCSPGRP:
779      /* Set a process group ID? */
780      PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
781      break;
782   case VKI_FIONBIO:
783      PRE_MEM_READ( "ioctl(FIONBIO)",    ARG3, sizeof(int) );
784      break;
785   case VKI_FIOASYNC:
786      PRE_MEM_READ( "ioctl(FIOASYNC)",   ARG3, sizeof(int) );
787      break;
788   case VKI_FIONREAD:                /* identical to SIOCINQ */
789      PRE_MEM_WRITE( "ioctl(FIONREAD)",  ARG3, sizeof(int) );
790      break;
791
792
793      /* These all use struct ifreq AFAIK */
794      /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
795   case VKI_SIOCGIFFLAGS:        /* get flags                    */
796      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
797                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
798      PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
799      break;
800   case VKI_SIOCGIFMTU:          /* get MTU size                 */
801      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
802                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
803      PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
804      break;
805   case VKI_SIOCGIFADDR:         /* get PA address               */
806      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
807                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
808      PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
809      break;
810   case VKI_SIOCGIFNETMASK:      /* get network PA mask          */
811      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
812                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
813      PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
814      break;
815   case VKI_SIOCGIFMETRIC:       /* get metric                   */
816      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
817                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
818      PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
819      break;
820   case VKI_SIOCGIFDSTADDR:      /* get remote PA address        */
821      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
822                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
823      PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
824      break;
825   case VKI_SIOCGIFBRDADDR:      /* get broadcast PA address     */
826      PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
827                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
828      PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
829      break;
830   case VKI_SIOCGIFCONF:         /* get iface list               */
831      /* WAS:
832         PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
833         KERNEL_DO_SYSCALL(tid,RES);
834         if (!VG_(is_kerror)(RES) && RES == 0)
835         POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
836      */
837      PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
838                    (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
839                    sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
840      PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
841                    (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
842                    sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
843      if ( ARG3 ) {
844         // TODO len must be readable and writable
845         // buf pointer only needs to be readable
846         struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
847         PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
848                        (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
849      }
850      break;
851
852   case VKI_SIOCSIFFLAGS:        /* set flags                    */
853      PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
854                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
855      PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
856                     (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
857                     sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
858      break;
859   case VKI_SIOCSIFADDR:         /* set PA address               */
860   case VKI_SIOCSIFDSTADDR:      /* set remote PA address        */
861   case VKI_SIOCSIFBRDADDR:      /* set broadcast PA address     */
862   case VKI_SIOCSIFNETMASK:      /* set network PA mask          */
863      PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
864                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
865      PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
866                     (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
867                     sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
868      break;
869   case VKI_SIOCSIFMETRIC:       /* set metric                   */
870      PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
871                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
872      PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
873                     (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
874                     sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
875      break;
876   case VKI_SIOCSIFMTU:          /* set MTU size                 */
877      PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
878                     (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
879      PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
880                     (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
881                     sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
882      break;
883      /* Routing table calls.  */
884#ifdef VKI_SIOCADDRT
885   case VKI_SIOCADDRT:           /* add routing table entry      */
886   case VKI_SIOCDELRT:           /* delete routing table entry   */
887      PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
888                    sizeof(struct vki_rtentry));
889      break;
890#endif
891
892   case VKI_SIOCGPGRP:
893      PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
894      break;
895   case VKI_SIOCSPGRP:
896      PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
897      //tst->sys_flags &= ~SfMayBlock;
898      break;
899
900   case VKI_FIODTYPE:
901      PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
902      break;
903
904   case VKI_DTRACEHIOC_ADDDOF:
905       break;
906
907       // ttycom.h
908   case VKI_TIOCGETA:
909       PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
910       break;
911   case VKI_TIOCSETA:
912       PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
913       break;
914   case VKI_TIOCGETD:
915       PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
916       break;
917   case VKI_TIOCSETD:
918       PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
919       break;
920   case VKI_TIOCPTYGNAME:
921       PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
922       break;
923
924   // filio.h
925   case VKI_FIOCLEX:
926       break;
927   case VKI_FIONCLEX:
928       break;
929
930   default:
931      ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
932      break;
933   }
934}
935
936
937POST(ioctl)
938{
939   vg_assert(SUCCESS);
940   switch (ARG2 /* request */) {
941   case VKI_TIOCGWINSZ:
942      POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
943      break;
944   case VKI_TIOCSWINSZ:
945   case VKI_TIOCMBIS:
946   case VKI_TIOCMBIC:
947   case VKI_TIOCMSET:
948      break;
949   case VKI_TIOCMGET:
950      POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
951      break;
952   case VKI_TIOCGPGRP:
953      /* Get process group ID for foreground processing group. */
954      POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
955      break;
956   case VKI_TIOCSPGRP:
957      /* Set a process group ID? */
958      POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
959      break;
960   case VKI_TIOCSCTTY:
961      break;
962   case VKI_FIONBIO:
963      break;
964   case VKI_FIOASYNC:
965      break;
966   case VKI_FIONREAD:                /* identical to SIOCINQ */
967      POST_MEM_WRITE( ARG3, sizeof(int) );
968      break;
969
970      /* These all use struct ifreq AFAIK */
971   case VKI_SIOCGIFFLAGS:        /* get flags                    */
972      POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
973                      sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
974      break;
975   case VKI_SIOCGIFMTU:          /* get MTU size                 */
976      POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
977                      sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
978      break;
979   case VKI_SIOCGIFADDR:         /* get PA address               */
980   case VKI_SIOCGIFDSTADDR:      /* get remote PA address        */
981   case VKI_SIOCGIFBRDADDR:      /* get broadcast PA address     */
982   case VKI_SIOCGIFNETMASK:      /* get network PA mask          */
983      POST_MEM_WRITE(
984                (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
985                sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
986      break;
987   case VKI_SIOCGIFMETRIC:       /* get metric                   */
988      POST_MEM_WRITE(
989                (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
990                sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
991      break;
992   case VKI_SIOCGIFCONF:         /* get iface list               */
993      /* WAS:
994         PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
995         KERNEL_DO_SYSCALL(tid,RES);
996         if (!VG_(is_kerror)(RES) && RES == 0)
997         POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
998      */
999      if (RES == 0 && ARG3 ) {
1000         struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1001         if (ifc->vki_ifc_buf != NULL)
1002            POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1003      }
1004      break;
1005
1006   case VKI_SIOCSIFFLAGS:        /* set flags                    */
1007   case VKI_SIOCSIFDSTADDR:      /* set remote PA address        */
1008   case VKI_SIOCSIFBRDADDR:      /* set broadcast PA address     */
1009   case VKI_SIOCSIFNETMASK:      /* set network PA mask          */
1010   case VKI_SIOCSIFMETRIC:       /* set metric                   */
1011   case VKI_SIOCSIFADDR:         /* set PA address               */
1012   case VKI_SIOCSIFMTU:          /* set MTU size                 */
1013      break;
1014
1015#ifdef VKI_SIOCADDRT
1016      /* Routing table calls.  */
1017   case VKI_SIOCADDRT:           /* add routing table entry      */
1018   case VKI_SIOCDELRT:           /* delete routing table entry   */
1019      break;
1020#endif
1021
1022   case VKI_SIOCGPGRP:
1023      POST_MEM_WRITE(ARG3, sizeof(int));
1024      break;
1025   case VKI_SIOCSPGRP:
1026      break;
1027
1028   case VKI_FIODTYPE:
1029      POST_MEM_WRITE( ARG3, sizeof(int) );
1030      break;
1031
1032   case VKI_DTRACEHIOC_REMOVE:
1033   case VKI_DTRACEHIOC_ADDDOF:
1034       break;
1035
1036       // ttycom.h
1037   case VKI_TIOCGETA:
1038       POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1039       break;
1040   case VKI_TIOCSETA:
1041       break;
1042   case VKI_TIOCGETD:
1043       POST_MEM_WRITE( ARG3, sizeof(int) );
1044       break;
1045   case VKI_TIOCSETD:
1046       break;
1047   case VKI_TIOCPTYGNAME:
1048       POST_MEM_WRITE( ARG3, 128);
1049       break;
1050   case VKI_TIOCPTYGRANT:
1051   case VKI_TIOCPTYUNLK:
1052       break;
1053
1054   default:
1055      break;
1056   }
1057}
1058
1059
1060/* ---------------------------------------------------------------------
1061   darwin fcntl wrapper
1062   ------------------------------------------------------------------ */
1063static const HChar *name_for_fcntl(UWord cmd) {
1064#define F(n) case VKI_##n: return #n
1065   switch (cmd) {
1066      F(F_CHKCLEAN);
1067      F(F_RDAHEAD);
1068      F(F_NOCACHE);
1069      F(F_FULLFSYNC);
1070      F(F_FREEZE_FS);
1071      F(F_THAW_FS);
1072      F(F_GLOBAL_NOCACHE);
1073      F(F_PREALLOCATE);
1074      F(F_SETSIZE);
1075      F(F_RDADVISE);
1076#     if DARWIN_VERS < DARWIN_10_9
1077      F(F_READBOOTSTRAP);
1078      F(F_WRITEBOOTSTRAP);
1079#     endif
1080      F(F_LOG2PHYS);
1081      F(F_GETPATH);
1082      F(F_PATHPKG_CHECK);
1083      F(F_ADDSIGS);
1084#     if DARWIN_VERS >= DARWIN_10_9
1085      F(F_ADDFILESIGS);
1086#     endif
1087   default:
1088      return "UNKNOWN";
1089   }
1090#undef F
1091}
1092
1093PRE(fcntl)
1094{
1095   switch (ARG2) {
1096   // These ones ignore ARG3.
1097   case VKI_F_GETFD:
1098   case VKI_F_GETFL:
1099   case VKI_F_GETOWN:
1100      PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1101      PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1102      break;
1103
1104   // These ones use ARG3 as "arg".
1105   case VKI_F_DUPFD:
1106   case VKI_F_SETFD:
1107   case VKI_F_SETFL:
1108   case VKI_F_SETOWN:
1109      PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1110      PRE_REG_READ3(long, "fcntl",
1111                    unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1112      break;
1113
1114   // These ones use ARG3 as "lock".
1115   case VKI_F_GETLK:
1116   case VKI_F_SETLK:
1117   case VKI_F_SETLKW:
1118      PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1119      PRE_REG_READ3(long, "fcntl",
1120                    unsigned int, fd, unsigned int, cmd,
1121                    struct flock64 *, lock);
1122      // GrP fixme mem read sizeof(flock64)
1123      if (ARG2 == VKI_F_SETLKW)
1124         *flags |= SfMayBlock;
1125      break;
1126
1127       // none
1128   case VKI_F_CHKCLEAN:
1129   case VKI_F_RDAHEAD:
1130   case VKI_F_NOCACHE:
1131   case VKI_F_FULLFSYNC:
1132   case VKI_F_FREEZE_FS:
1133   case VKI_F_THAW_FS:
1134   case VKI_F_GLOBAL_NOCACHE:
1135      PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1136      PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1137      break;
1138
1139       // struct fstore
1140   case VKI_F_PREALLOCATE:
1141      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1142      PRE_REG_READ3(long, "fcntl",
1143                    unsigned int, fd, unsigned int, cmd,
1144                    struct fstore *, fstore);
1145      {
1146         struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1147         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1148                         fstore->fst_flags );
1149         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1150                         fstore->fst_posmode );
1151         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1152                         fstore->fst_offset );
1153         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1154                         fstore->fst_length );
1155         PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1156                          fstore->fst_bytesalloc);
1157      }
1158      break;
1159
1160       // off_t
1161   case VKI_F_SETSIZE:
1162      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1163      PRE_REG_READ3(long, "fcntl",
1164                    unsigned int, fd, unsigned int, cmd,
1165                    vki_off_t *, offset);
1166      break;
1167
1168       // struct radvisory
1169   case VKI_F_RDADVISE:
1170      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1171      PRE_REG_READ3(long, "fcntl",
1172                    unsigned int, fd, unsigned int, cmd,
1173                    struct vki_radvisory *, radvisory);
1174      {
1175         struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1176         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1177                         radvisory->ra_offset );
1178         PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1179                         radvisory->ra_count );
1180      }
1181      break;
1182
1183#  if DARWIN_VERS < DARWIN_10_9
1184       // struct fbootstraptransfer
1185   case VKI_F_READBOOTSTRAP:
1186   case VKI_F_WRITEBOOTSTRAP:
1187      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1188      PRE_REG_READ3(long, "fcntl",
1189                    unsigned int, fd, unsigned int, cmd,
1190                    struct fbootstraptransfer *, bootstrap);
1191      PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1192                    ARG3, sizeof(struct vki_fbootstraptransfer) );
1193      break;
1194#  endif
1195
1196       // struct log2phys (out)
1197   case VKI_F_LOG2PHYS:
1198      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1199      PRE_REG_READ3(long, "fcntl",
1200                    unsigned int, fd, unsigned int, cmd,
1201                    struct log2phys *, l2p);
1202      PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1203                     ARG3, sizeof(struct vki_log2phys) );
1204      break;
1205
1206       // char[maxpathlen] (out)
1207   case VKI_F_GETPATH:
1208      PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1209      PRE_REG_READ3(long, "fcntl",
1210                    unsigned int, fd, unsigned int, cmd,
1211                    char *, pathbuf);
1212      PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1213                     ARG3, VKI_MAXPATHLEN );
1214      break;
1215
1216       // char[maxpathlen] (in)
1217   case VKI_F_PATHPKG_CHECK:
1218      PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1219          (char *)ARG3);
1220      PRE_REG_READ3(long, "fcntl",
1221                    unsigned int, fd, unsigned int, cmd,
1222                    char *, pathbuf);
1223      PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1224      break;
1225
1226   case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1227      PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1228      PRE_REG_READ3(long, "fcntl",
1229                    unsigned int, fd, unsigned int, cmd,
1230                    vki_fsignatures_t *, sigs);
1231
1232      {
1233         vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1234         PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1235                         fsigs->fs_blob_start);
1236         PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1237                         fsigs->fs_blob_size);
1238
1239         if (fsigs->fs_blob_start)
1240            PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1241                          (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1242      }
1243      break;
1244
1245   case VKI_F_ADDFILESIGS: /* Add signature from same file (used by dyld for shared libs) */
1246      PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1247      PRE_REG_READ3(long, "fcntl",
1248                    unsigned int, fd, unsigned int, cmd,
1249                    vki_fsignatures_t *, sigs);
1250
1251      {
1252         vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1253         PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1254                         fsigs->fs_blob_start);
1255         PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1256                         fsigs->fs_blob_size);
1257      }
1258      break;
1259
1260   default:
1261      PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1262      VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
1263      break;
1264   }
1265}
1266
1267POST(fcntl)
1268{
1269   vg_assert(SUCCESS);
1270   switch (ARG2) {
1271   case VKI_F_DUPFD:
1272      if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1273         VG_(close)(RES);
1274         SET_STATUS_Failure( VKI_EMFILE );
1275      } else {
1276         if (VG_(clo_track_fds))
1277            ML_(record_fd_open_named)(tid, RES);
1278      }
1279      break;
1280
1281   case VKI_F_GETFD:
1282   case VKI_F_GETFL:
1283   case VKI_F_GETOWN:
1284   case VKI_F_SETFD:
1285   case VKI_F_SETFL:
1286   case VKI_F_SETOWN:
1287   case VKI_F_GETLK:
1288   case VKI_F_SETLK:
1289   case VKI_F_SETLKW:
1290       break;
1291
1292   case VKI_F_PREALLOCATE:
1293      {
1294         struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1295         POST_FIELD_WRITE( fstore->fst_bytesalloc );
1296      }
1297      break;
1298
1299   case VKI_F_LOG2PHYS:
1300      POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1301      break;
1302
1303   case VKI_F_GETPATH:
1304      POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1305      PRINT("\"%s\"", (char*)ARG3);
1306      break;
1307
1308   default:
1309      // DDD: ugh, missing lots of cases here, not nice
1310      break;
1311   }
1312}
1313
1314/* ---------------------------------------------------------------------
1315   unix syscalls
1316   ------------------------------------------------------------------ */
1317
1318PRE(futimes)
1319{
1320   PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
1321   PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1322   if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1323      SET_STATUS_Failure( VKI_EBADF );
1324   } else if (ARG2 != 0) {
1325      PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1326      PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1327   }
1328}
1329
1330PRE(semget)
1331{
1332   PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1333   PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1334}
1335
1336PRE(semop)
1337{
1338   *flags |= SfMayBlock;
1339   PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
1340   PRE_REG_READ3(long, "semop",
1341                 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1342   ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1343}
1344
1345PRE(semctl)
1346{
1347   switch (ARG3) {
1348   case VKI_IPC_STAT:
1349   case VKI_IPC_SET:
1350      PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1351      PRE_REG_READ4(long, "semctl",
1352                    int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1353      break;
1354   case VKI_GETALL:
1355   case VKI_SETALL:
1356      PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1357      PRE_REG_READ4(long, "semctl",
1358                    int, semid, int, semnum, int, cmd, unsigned short *, arg);
1359      break;
1360   case VKI_SETVAL:
1361      PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1362      PRE_REG_READ4(long, "semctl",
1363                    int, semid, int, semnum, int, cmd, int, arg);
1364      break;
1365   default:
1366      PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1367      PRE_REG_READ3(long, "semctl",
1368                    int, semid, int, semnum, int, cmd);
1369      break;
1370   }
1371   ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1372}
1373POST(semctl)
1374{
1375   ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1376}
1377
1378PRE(sem_open)
1379{
1380   if (ARG2 & VKI_O_CREAT) {
1381      // 4-arg version
1382      PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1383            ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1384      PRE_REG_READ4(vki_sem_t *, "sem_open",
1385                    const char *, name, int, oflag, vki_mode_t, mode,
1386                    unsigned int, value);
1387   } else {
1388      // 2-arg version
1389      PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1390      PRE_REG_READ2(vki_sem_t *, "sem_open",
1391                    const char *, name, int, oflag);
1392   }
1393   PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1394
1395   /* Otherwise handle normally */
1396   *flags |= SfMayBlock;
1397}
1398
1399PRE(sem_close)
1400{
1401   PRINT("sem_close( %#lx )", ARG1);
1402   PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1403}
1404
1405PRE(sem_unlink)
1406{
1407   PRINT("sem_unlink(  %#lx(%s) )", ARG1,(char*)ARG1);
1408   PRE_REG_READ1(int, "sem_unlink", const char *, name);
1409   PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1410}
1411
1412PRE(sem_post)
1413{
1414   PRINT("sem_post( %#lx )", ARG1);
1415   PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1416   *flags |= SfMayBlock;
1417}
1418
1419PRE(sem_destroy)
1420{
1421  PRINT("sem_destroy( %#lx )", ARG1);
1422  PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1423  PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1424}
1425
1426PRE(sem_init)
1427{
1428  PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
1429  PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1430                int, pshared, unsigned int, value);
1431  PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1432}
1433
1434POST(sem_init)
1435{
1436  POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1437}
1438
1439PRE(sem_wait)
1440{
1441   PRINT("sem_wait( %#lx )", ARG1);
1442   PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1443   *flags |= SfMayBlock;
1444}
1445
1446PRE(sem_trywait)
1447{
1448   PRINT("sem_trywait( %#lx )", ARG1);
1449   PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1450   *flags |= SfMayBlock;
1451}
1452
1453PRE(kqueue)
1454{
1455    PRINT("kqueue()");
1456}
1457
1458POST(kqueue)
1459{
1460   if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1461      VG_(close)(RES);
1462      SET_STATUS_Failure( VKI_EMFILE );
1463   } else {
1464      if (VG_(clo_track_fds)) {
1465         ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1466      }
1467   }
1468}
1469
1470PRE(fileport_makeport)
1471{
1472    PRINT("guarded_open_np(fd:%#lx, portnamep:%#lx) FIXME",
1473      ARG1, ARG2);
1474}
1475
1476PRE(guarded_open_np)
1477{
1478    PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1479      ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1480}
1481
1482PRE(guarded_kqueue_np)
1483{
1484    PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1485      ARG1, ARG2);
1486}
1487
1488POST(guarded_kqueue_np)
1489{
1490   if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1491      VG_(close)(RES);
1492      SET_STATUS_Failure( VKI_EMFILE );
1493   } else {
1494      if (VG_(clo_track_fds)) {
1495         ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1496      }
1497   }
1498}
1499
1500PRE(guarded_close_np)
1501{
1502    PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1503      ARG1, ARG2);
1504}
1505
1506PRE(change_fdguard_np)
1507{
1508    PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
1509      ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1510}
1511
1512PRE(connectx)
1513{
1514    PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
1515      ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
1516}
1517
1518PRE(disconnectx)
1519{
1520    PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
1521      ARG1, ARG2, ARG3);
1522}
1523
1524
1525PRE(kevent)
1526{
1527   PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1528         ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1529   PRE_REG_READ6(int,"kevent", int,kq,
1530                 const struct vki_kevent *,changelist, int,nchanges,
1531                 struct vki_kevent *,eventlist, int,nevents,
1532                 const struct vki_timespec *,timeout);
1533
1534   if (ARG3) PRE_MEM_READ ("kevent(changelist)",
1535                           ARG2, ARG3 * sizeof(struct vki_kevent));
1536   if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
1537                           ARG4, ARG5 * sizeof(struct vki_kevent));
1538   if (ARG6) PRE_MEM_READ ("kevent(timeout)",
1539                           ARG6, sizeof(struct vki_timespec));
1540
1541   *flags |= SfMayBlock;
1542}
1543
1544POST(kevent)
1545{
1546   PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
1547   if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
1548}
1549
1550
1551PRE(kevent64)
1552{
1553   PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1554         ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1555   PRE_REG_READ6(int,"kevent64", int,kq,
1556                 const struct vki_kevent64 *,changelist, int,nchanges,
1557                 struct vki_kevent64 *,eventlist, int,nevents,
1558                 const struct vki_timespec *,timeout);
1559
1560   if (ARG3) PRE_MEM_READ ("kevent64(changelist)",
1561                           ARG2, ARG3 * sizeof(struct vki_kevent64));
1562   if (ARG5) PRE_MEM_WRITE("kevent64(eventlist)",
1563                           ARG4, ARG5 * sizeof(struct vki_kevent64));
1564   if (ARG6) PRE_MEM_READ ("kevent64(timeout)",
1565                           ARG6, sizeof(struct vki_timespec));
1566
1567   *flags |= SfMayBlock;
1568}
1569
1570POST(kevent64)
1571{
1572   PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
1573   if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
1574}
1575
1576
1577Addr pthread_starter = 0;
1578Addr wqthread_starter = 0;
1579SizeT pthread_structsize = 0;
1580
1581PRE(bsdthread_register)
1582{
1583   PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
1584   PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
1585                 void *,"wqthread", size_t,"pthsize");
1586
1587   pthread_starter = ARG1;
1588   wqthread_starter = ARG2;
1589   pthread_structsize = ARG3;
1590   ARG1 = (Word)&pthread_hijack_asm;
1591   ARG2 = (Word)&wqthread_hijack_asm;
1592}
1593
1594PRE(workq_open)
1595{
1596   PRINT("workq_open()");
1597   PRE_REG_READ0(int, "workq_open");
1598
1599   // This creates lots of threads and thread stacks under the covers,
1600   // but we ignore them all until some work item starts running on it.
1601}
1602
1603static const HChar *workqop_name(int op)
1604{
1605   switch (op) {
1606   case VKI_WQOPS_QUEUE_ADD:        return "QUEUE_ADD";
1607   case VKI_WQOPS_QUEUE_REMOVE:     return "QUEUE_REMOVE";
1608   case VKI_WQOPS_THREAD_RETURN:    return "THREAD_RETURN";
1609   case VKI_WQOPS_THREAD_SETCONC:   return "THREAD_SETCONC";
1610   case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
1611   case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
1612   default: return "?";
1613   }
1614}
1615
1616
1617PRE(workq_ops)
1618{
1619   PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
1620      ARG3);
1621   PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
1622                 int,"priority");
1623
1624   switch (ARG1) {
1625   case VKI_WQOPS_QUEUE_ADD:
1626   case VKI_WQOPS_QUEUE_REMOVE:
1627      // GrP fixme need anything here?
1628      // GrP fixme may block?
1629      break;
1630   case VKI_WQOPS_QUEUE_NEWSPISUPP:
1631      // JRS don't think we need to do anything here -- this just checks
1632      // whether some newer functionality is supported
1633      break;
1634   case VKI_WQOPS_QUEUE_REQTHREADS:
1635      // JRS uh, looks like it queues up a bunch of threads, or some such?
1636      *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
1637      break;
1638   case VKI_WQOPS_THREAD_RETURN: {
1639      // The interesting case. The kernel will do one of two things:
1640      // 1. Return normally. We continue; libc proceeds to stop the thread.
1641      //    V does nothing special here.
1642      // 2. Jump to wqthread_hijack. This wipes the stack and runs a
1643      //    new work item, and never returns from workq_ops.
1644      //    V handles this by longjmp() from wqthread_hijack back to the
1645      //    scheduler, which continues at the new client SP/IP/state.
1646      //    This works something like V's signal handling.
1647      //    To the tool, this looks like workq_ops() sometimes returns
1648      //    to a strange address.
1649      ThreadState *tst = VG_(get_ThreadState)(tid);
1650      tst->os_state.wq_jmpbuf_valid = True;
1651      *flags |= SfMayBlock;  // GrP fixme true?
1652      break;
1653   }
1654   default:
1655      VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
1656      break;
1657   }
1658}
1659POST(workq_ops)
1660{
1661   ThreadState *tst = VG_(get_ThreadState)(tid);
1662   tst->os_state.wq_jmpbuf_valid = False;
1663}
1664
1665
1666
1667PRE(__mac_syscall)
1668{
1669   PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
1670   PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
1671                 int,"call", void *,"arg");
1672
1673   // GrP fixme check call's arg?
1674   // GrP fixme check policy?
1675}
1676
1677
1678/* Not like syswrap-generic's sys_exit, which exits only one thread.
1679   More like syswrap-generic's sys_exit_group. */
1680PRE(exit)
1681{
1682   ThreadId     t;
1683   ThreadState* tst;
1684
1685   PRINT("darwin exit( %ld )", ARG1);
1686   PRE_REG_READ1(void, "exit", int, status);
1687
1688   tst = VG_(get_ThreadState)(tid);
1689
1690   /* A little complex; find all the threads with the same threadgroup
1691      as this one (including this one), and mark them to exit */
1692   for (t = 1; t < VG_N_THREADS; t++) {
1693      if ( /* not alive */
1694           VG_(threads)[t].status == VgTs_Empty
1695           /* GrP fixme zombie? */
1696         )
1697         continue;
1698
1699      VG_(threads)[t].exitreason = VgSrc_ExitProcess;
1700      VG_(threads)[t].os_state.exitcode = ARG1;
1701
1702      if (t != tid)
1703         VG_(get_thread_out_of_syscall)(t);     /* unblock it, if blocked */
1704   }
1705
1706   /* We have to claim the syscall already succeeded. */
1707   SET_STATUS_Success(0);
1708}
1709
1710
1711PRE(sigaction)
1712{
1713   PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
1714   PRE_REG_READ3(long, "sigaction",
1715                 int, signum, vki_sigaction_toK_t *, act,
1716                 vki_sigaction_fromK_t *, oldact);
1717
1718   if (ARG2 != 0) {
1719      vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
1720      PRE_MEM_READ( "sigaction(act->sa_handler)",
1721                    (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1722      PRE_MEM_READ( "sigaction(act->sa_mask)",
1723                    (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1724      PRE_MEM_READ( "sigaction(act->sa_flags)",
1725                    (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
1726   }
1727   if (ARG3 != 0)
1728      PRE_MEM_WRITE( "sigaction(oldact)",
1729                     ARG3, sizeof(vki_sigaction_fromK_t));
1730
1731   SET_STATUS_from_SysRes(
1732      VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
1733                                  (vki_sigaction_fromK_t *)ARG3)
1734   );
1735}
1736POST(sigaction)
1737{
1738   vg_assert(SUCCESS);
1739   if (RES == 0 && ARG3 != 0)
1740      POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
1741}
1742
1743
1744PRE(__pthread_kill)
1745{
1746   PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
1747   PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
1748}
1749
1750
1751PRE(__pthread_sigmask)
1752{
1753   // GrP fixme
1754   // JRS: arguments are identical to sigprocmask
1755   // (how, sigset_t*, sigset_t*).  Perhaps behave identically?
1756   static Bool warned;
1757   if (!warned) {
1758      VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. "
1759                  "This warning will not be repeated.\n");
1760      warned = True;
1761   }
1762   SET_STATUS_Success( 0 );
1763}
1764
1765
1766PRE(__pthread_canceled)
1767{
1768   *flags |= SfMayBlock; /* might kill this thread??? */
1769   /* I don't think so -- I think it just changes the cancellation
1770      state.  But taking no chances. */
1771   PRINT("__pthread_canceled ( %ld )", ARG1);
1772   PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
1773}
1774
1775
1776PRE(__pthread_markcancel)
1777{
1778   *flags |= SfMayBlock; /* might kill this thread??? */
1779   PRINT("__pthread_markcancel ( %#lx )", ARG1);
1780   PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
1781   /* Just let it go through.  No idea if this is correct. */
1782}
1783
1784
1785PRE(__disable_threadsignal)
1786{
1787   vki_sigset_t set;
1788   PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
1789   /* I don't think this really looks at its arguments.  So don't
1790      bother to check them. */
1791
1792   VG_(sigfillset)( &set );
1793   SET_STATUS_from_SysRes(
1794      VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
1795   );
1796
1797   /* We don't expect that blocking all signals for this thread could
1798      cause any more to be delivered (how could it?), but just in case
1799      .. */
1800   if (SUCCESS)
1801      *flags |= SfPollAfter;
1802}
1803
1804
1805PRE(kdebug_trace)
1806{
1807   PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
1808         ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1809   /*
1810     Don't check anything - some clients pass fewer arguments.
1811   PRE_REG_READ6(long, "kdebug_trace",
1812                 int,"code", int,"arg1", int,"arg2",
1813                 int,"arg3", int,"arg4", int,"arg5");
1814   */
1815}
1816
1817
1818PRE(seteuid)
1819{
1820    PRINT("seteuid(%ld)", ARG1);
1821    PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
1822}
1823
1824
1825PRE(setegid)
1826{
1827    PRINT("setegid(%ld)", ARG1);
1828    PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
1829}
1830
1831PRE(settid)
1832{
1833    PRINT("settid(%ld, %ld)", ARG1, ARG2);
1834    PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
1835}
1836
1837PRE(gettid)
1838{
1839    PRINT("gettid()");
1840    PRE_REG_READ0(long, gettid);
1841}
1842
1843/* XXX need to check whether we need POST operations for
1844 * waitevent, watchevent, modwatch -- jpeach
1845 */
1846PRE(watchevent)
1847{
1848    PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
1849    PRE_REG_READ2(long, "watchevent",
1850        vki_eventreq *, "event", unsigned int, "eventmask");
1851
1852    PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
1853    PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
1854    *flags |= SfMayBlock;
1855}
1856
1857#define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
1858PRE(waitevent)
1859{
1860   PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
1861   PRE_REG_READ2(long, "waitevent",
1862      vki_eventreq *, "event", struct timeval *, "timeout");
1863   PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
1864
1865   if (ARG2  &&  ARG2 != WAITEVENT_FAST_POLL) {
1866      PRE_timeval_READ("waitevent(timeout)", ARG2);
1867   }
1868
1869   /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
1870   *flags |= SfMayBlock;
1871}
1872
1873POST(waitevent)
1874{
1875   POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
1876}
1877
1878PRE(modwatch)
1879{
1880   PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
1881   PRE_REG_READ2(long, "modwatch",
1882      vki_eventreq *, "event", unsigned int, "eventmask");
1883
1884   PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
1885   PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
1886}
1887
1888PRE(getxattr)
1889{
1890   PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
1891         ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1892
1893   PRE_REG_READ6(vki_ssize_t, "getxattr",
1894                const char *, path, char *, name, void *, value,
1895                vki_size_t, size, uint32_t, position, int, options);
1896   PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
1897   PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1898   if (ARG3)
1899      PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1900}
1901
1902POST(getxattr)
1903{
1904   vg_assert((vki_ssize_t)RES >= 0);
1905   if (ARG3)
1906      POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1907}
1908
1909PRE(fgetxattr)
1910{
1911   PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
1912      ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
1913
1914   PRE_REG_READ6(vki_ssize_t, "fgetxattr",
1915                 int, fd, char *, name, void *, value,
1916                 vki_size_t, size, uint32_t, position, int, options);
1917   PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
1918   PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
1919}
1920
1921POST(fgetxattr)
1922{
1923   vg_assert((vki_ssize_t)RES >= 0);
1924   POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
1925}
1926
1927PRE(setxattr)
1928{
1929   PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
1930         ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1931   PRE_REG_READ6(int, "setxattr",
1932                 const char *,"path", char *,"name", void *,"value",
1933                 vki_size_t,"size", uint32_t,"position", int,"options" );
1934
1935   PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
1936   PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
1937   PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
1938}
1939
1940
1941PRE(fsetxattr)
1942{
1943   PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
1944          ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
1945   PRE_REG_READ6(int, "fsetxattr",
1946                 int,"fd", char *,"name", void *,"value",
1947                 vki_size_t,"size", uint32_t,"position", int,"options" );
1948
1949   PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
1950   PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
1951}
1952
1953
1954PRE(removexattr)
1955{
1956   PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
1957          ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 );
1958   PRE_REG_READ3(int, "removexattr",
1959                 const char*, "path", char*, "attrname", int, "options");
1960   PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
1961   PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
1962}
1963
1964
1965PRE(fremovexattr)
1966{
1967   PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
1968          ARG1, ARG2, (HChar*)ARG2, ARG3 );
1969   PRE_REG_READ3(int, "fremovexattr",
1970                 int, "fd", char*, "attrname", int, "options");
1971   PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
1972}
1973
1974
1975PRE(listxattr)
1976{
1977   PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
1978          ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
1979   PRE_REG_READ4 (long, "listxattr",
1980                 const char *,"path", char *,"namebuf",
1981                 vki_size_t,"size", int,"options" );
1982
1983   PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
1984   PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
1985   *flags |= SfMayBlock;
1986}
1987POST(listxattr)
1988{
1989   vg_assert(SUCCESS);
1990   vg_assert((vki_ssize_t)RES >= 0);
1991   POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
1992}
1993
1994
1995PRE(flistxattr)
1996{
1997   PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
1998          ARG1, ARG2, ARG3, ARG4 );
1999   PRE_REG_READ4 (long, "flistxattr",
2000                  int, "fd", char *,"namebuf",
2001                 vki_size_t,"size", int,"options" );
2002   PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2003   *flags |= SfMayBlock;
2004}
2005POST(flistxattr)
2006{
2007   vg_assert(SUCCESS);
2008   vg_assert((vki_ssize_t)RES >= 0);
2009   POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2010}
2011
2012
2013PRE(shmat)
2014{
2015   UWord arg2tmp;
2016   PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2017   PRE_REG_READ3(long, "shmat",
2018                 int, shmid, const void *, shmaddr, int, shmflg);
2019   arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2020   if (arg2tmp == 0)
2021      SET_STATUS_Failure( VKI_EINVAL );
2022   else
2023      ARG2 = arg2tmp;  // used in POST
2024}
2025POST(shmat)
2026{
2027   ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2028}
2029
2030PRE(shmctl)
2031{
2032   PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
2033   PRE_REG_READ3(long, "shmctl",
2034                 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2035   ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2036}
2037POST(shmctl)
2038{
2039   ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2040}
2041
2042PRE(shmdt)
2043{
2044   PRINT("shmdt ( %#lx )",ARG1);
2045   PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2046   if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2047      SET_STATUS_Failure( VKI_EINVAL );
2048}
2049POST(shmdt)
2050{
2051   ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2052}
2053
2054PRE(shmget)
2055{
2056   PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2057   PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2058}
2059
2060PRE(shm_open)
2061{
2062   PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
2063   PRE_REG_READ3(long, "shm_open",
2064                 const char *,"name", int,"flags", vki_mode_t,"mode");
2065
2066   PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2067
2068   *flags |= SfMayBlock;
2069}
2070POST(shm_open)
2071{
2072   vg_assert(SUCCESS);
2073   if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2074      VG_(close)(RES);
2075      SET_STATUS_Failure( VKI_EMFILE );
2076   } else {
2077      if (VG_(clo_track_fds))
2078         ML_(record_fd_open_with_given_name)(tid, RES, (char*)ARG1);
2079   }
2080}
2081
2082PRE(shm_unlink)
2083{
2084   *flags |= SfMayBlock;
2085   PRINT("shm_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
2086   PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2087   PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2088}
2089POST(shm_unlink)
2090{
2091   /* My reading of the man page suggests that a call may cause memory
2092      mappings to change: "if no references exist at the time of the
2093      call to shm_unlink(), the resources are reclaimed immediately".
2094      So we need to resync here, sigh. */
2095   ML_(sync_mappings)("after", "shm_unlink", 0);
2096}
2097
2098PRE(stat_extended)
2099{
2100   PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2101      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2102   PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2103                 void *, fsacl, vki_size_t *, fsacl_size);
2104   PRE_MEM_RASCIIZ( "stat_extended(file_name)",  ARG1 );
2105   PRE_MEM_WRITE(   "stat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
2106   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2107      PRE_MEM_WRITE("stat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
2108   PRE_MEM_READ(    "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2109}
2110POST(stat_extended)
2111{
2112   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2113   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2114      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2115   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2116}
2117
2118
2119PRE(lstat_extended)
2120{
2121   PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2122      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2123   PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2124                 void *, fsacl, vki_size_t *, fsacl_size);
2125   PRE_MEM_RASCIIZ( "lstat_extended(file_name)",  ARG1 );
2126   PRE_MEM_WRITE(   "lstat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
2127   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2128      PRE_MEM_WRITE("lstat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
2129   PRE_MEM_READ(    "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2130}
2131POST(lstat_extended)
2132{
2133   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2134   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2135      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2136   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2137}
2138
2139
2140PRE(fstat_extended)
2141{
2142   PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2143      ARG1, ARG2, ARG3, ARG4);
2144   PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2145                 void *, fsacl, vki_size_t *, fsacl_size);
2146   PRE_MEM_WRITE(   "fstat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
2147   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2148      PRE_MEM_WRITE("fstat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
2149   PRE_MEM_READ(    "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2150}
2151POST(fstat_extended)
2152{
2153   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2154   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2155      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2156   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2157}
2158
2159
2160PRE(stat64_extended)
2161{
2162   PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2163      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2164   PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2165                 void *, fsacl, vki_size_t *, fsacl_size);
2166   PRE_MEM_RASCIIZ( "stat64_extended(file_name)",  ARG1 );
2167   PRE_MEM_WRITE(   "stat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
2168   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2169      PRE_MEM_WRITE("stat64_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
2170   PRE_MEM_READ(    "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2171}
2172POST(stat64_extended)
2173{
2174   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2175   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2176      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2177   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2178}
2179
2180
2181PRE(lstat64_extended)
2182{
2183   PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2184      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2185   PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2186                 void *, fsacl, vki_size_t *, fsacl_size);
2187   PRE_MEM_RASCIIZ( "lstat64_extended(file_name)",  ARG1 );
2188   PRE_MEM_WRITE(   "lstat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
2189   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2190      PRE_MEM_WRITE(   "lstat64_extended(fsacl)",   ARG3, *(vki_size_t *)ARG4 );
2191   PRE_MEM_READ(    "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2192}
2193POST(lstat64_extended)
2194{
2195   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2196   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2197      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2198   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2199}
2200
2201
2202PRE(fstat64_extended)
2203{
2204   PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2205      ARG1, ARG2, ARG3, ARG4);
2206   PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2207                 void *, fsacl, vki_size_t *, fsacl_size);
2208   PRE_MEM_WRITE(   "fstat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
2209   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2210      PRE_MEM_WRITE("fstat64_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
2211   PRE_MEM_READ(    "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2212}
2213POST(fstat64_extended)
2214{
2215   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2216   if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2217      POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2218   POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2219}
2220
2221
2222PRE(fchmod_extended)
2223{
2224   /* DDD: Note: this is not really correct.  Handling of
2225      chmod_extended is broken in the same way. */
2226   PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2227         ARG1, ARG2, ARG3, ARG4, ARG5);
2228   PRE_REG_READ5(long, "fchmod_extended",
2229                 unsigned int, fildes,
2230                 uid_t, uid,
2231                 gid_t, gid,
2232                 vki_mode_t, mode,
2233                 void* /*really,user_addr_t*/, xsecurity);
2234   /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2235      is just way wrong.  [The trouble is with the size, which depends on a
2236      non-trival kernel computation] */
2237   if (ARG5) {
2238      PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2239                    sizeof(struct vki_kauth_filesec) );
2240   }
2241}
2242
2243PRE(chmod_extended)
2244{
2245   /* DDD: Note: this is not really correct.  Handling of
2246      fchmod_extended is broken in the same way. */
2247   PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2248         ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2249   PRE_REG_READ5(long, "chmod_extended",
2250                 unsigned int, fildes,
2251                 uid_t, uid,
2252                 gid_t, gid,
2253                 vki_mode_t, mode,
2254                 void* /*really,user_addr_t*/, xsecurity);
2255   PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2256   /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2257      is just way wrong.  [The trouble is with the size, which depends on a
2258      non-trival kernel computation] */
2259   if (ARG5) {
2260      PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2261                    sizeof(struct vki_kauth_filesec) );
2262   }
2263}
2264
2265PRE(open_extended)
2266{
2267   /* DDD: Note: this is not really correct.  Handling of
2268      {,f}chmod_extended is broken in the same way. */
2269   PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )",
2270         ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2271	 ARG2, ARG3, ARG4, ARG5, ARG6);
2272   PRE_REG_READ6(long, "open_extended",
2273                 char*, path,
2274                 int,   flags,
2275                 uid_t, uid,
2276                 gid_t, gid,
2277                 vki_mode_t, mode,
2278                 void* /*really,user_addr_t*/, xsecurity);
2279   PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2280   /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2281      is just way wrong.  [The trouble is with the size, which depends on a
2282      non-trival kernel computation] */
2283   if (ARG6)
2284      PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2285                    sizeof(struct vki_kauth_filesec) );
2286}
2287
2288// This is a ridiculous syscall.  Specifically, the 'entries' argument points
2289// to a buffer that contains one or more 'accessx_descriptor' structs followed
2290// by one or more strings.  Each accessx_descriptor contains a field,
2291// 'ad_name_offset', which points to one of the strings (or it can contain
2292// zero which means "reuse the string from the previous accessx_descriptor").
2293//
2294// What's really ridiculous is that we are only given the size of the overall
2295// buffer, not the number of accessx_descriptors, nor the number of strings.
2296// The kernel determines the number of accessx_descriptors by walking through
2297// them one by one, checking that the ad_name_offset points within the buffer,
2298// past the current point (or that it's a zero, unless its the first
2299// descriptor);  if so, we assume that this really is an accessx_descriptor,
2300// if not, we assume we've hit the strings section.  Gah.
2301//
2302// This affects us here because number of entries in the 'results' buffer is
2303// determined by the number of accessx_descriptors.  So we have to know that
2304// number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'.  In
2305// practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2306// computation after the syscall has succeeded, because the kernel will have
2307// checked for all the zillion different ways this syscall can fail, and we'll
2308// know we have a well-formed 'entries' buffer.  This means we might miss some
2309// uses of unaddressable memory but oh well.
2310//
2311PRE(access_extended)
2312{
2313   PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2314      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2315   // XXX: the accessx_descriptor struct contains padding, so this can cause
2316   // unnecessary undefined value errors.  But you arguably shouldn't be
2317   // passing undefined values to the kernel anyway...
2318   PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2319                 vki_errno_t *, results, vki_uid_t *, uid);
2320   PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2321
2322   // XXX: as mentioned above, this check is too hard to do before the
2323   // syscall.
2324   //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2325}
2326POST(access_extended)
2327{
2328   // 'n_descs' is the number of descriptors we think are in the buffer.  We
2329   // start with the maximum possible value, which occurs if we have the
2330   // shortest possible string section.  The shortest string section allowed
2331   // consists of a single one-char string (plus the NUL char).  Hence the
2332   // '2'.
2333   struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2334   SizeT size = ARG2;
2335   Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2336   Int i;         // Current position in the descriptors section array.
2337   Int u;         // Upper bound on the length of the descriptors array
2338                  //   (recomputed each time around the loop)
2339   vg_assert(n_descs > 0);
2340
2341   // Step through the descriptors, lowering 'n_descs' until we know we've
2342   // reached the string section.
2343   for (i = 0; True; i++) {
2344      // If we're past our estimate, we must be one past the end of the
2345      // descriptors section (ie. at the start of the string section).  Stop.
2346      if (i >= n_descs)
2347         break;
2348
2349      // Get the array index for the string, but pretend momentarily that it
2350      // is actually another accessx_descriptor.  That gives us an upper bound
2351      // on the length of the descriptors section.  (Unless the index is zero,
2352      // in which case we have no new info.)
2353      u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2354      if (u == 0) {
2355         vg_assert(i != 0);
2356         continue;
2357      }
2358
2359      // If the upper bound is below our current estimate, revise that
2360      // estimate downwards.
2361      if (u < n_descs)
2362         n_descs = u;
2363   }
2364
2365   // Sanity check.
2366   vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2367
2368   POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2369}
2370
2371
2372PRE(chflags)
2373{
2374   PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2375   PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2376   PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2377
2378   // GrP fixme sanity-check flags value?
2379}
2380
2381PRE(fchflags)
2382{
2383   PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2384   PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2385
2386   // GrP fixme sanity-check flags value?
2387}
2388
2389PRE(stat64)
2390{
2391   PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2392   PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2393   PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2394   PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2395}
2396POST(stat64)
2397{
2398   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2399}
2400
2401PRE(lstat64)
2402{
2403   PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2404   PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2405   PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2406   PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2407}
2408POST(lstat64)
2409{
2410   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2411}
2412
2413PRE(fstat64)
2414{
2415   PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2416   PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2417   PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2418}
2419POST(fstat64)
2420{
2421   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2422}
2423
2424PRE(getfsstat)
2425{
2426   PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2427   PRE_REG_READ3(int, "getfsstat",
2428                 struct vki_statfs *, buf, int, bufsize, int, flags);
2429   if (ARG1) {
2430      // ARG2 is a BYTE SIZE
2431      PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2432   }
2433}
2434POST(getfsstat)
2435{
2436   if (ARG1) {
2437      // RES is a STRUCT COUNT
2438      POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2439   }
2440}
2441
2442PRE(getfsstat64)
2443{
2444   PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2445   PRE_REG_READ3(int, "getfsstat64",
2446                 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2447   if (ARG1) {
2448      // ARG2 is a BYTE SIZE
2449      PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2450   }
2451}
2452POST(getfsstat64)
2453{
2454   if (ARG1) {
2455      // RES is a STRUCT COUNT
2456      POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2457   }
2458}
2459
2460PRE(mount)
2461{
2462   // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2463   // We are conservative and check everything, except the memory pointed to
2464   // by 'data'.
2465   *flags |= SfMayBlock;
2466   PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2467         ARG1,(char*)ARG1, ARG2,(char*)ARG2, ARG3, ARG4);
2468   PRE_REG_READ4(long, "mount",
2469                 const char *, type, const char *, dir,
2470                 int, flags, void *, data);
2471   PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2472   PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2473}
2474
2475
2476static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2477                          void *attrBuf, SizeT attrBufSize,
2478                          void (*fn)(ThreadId, void *attrData, SizeT size)
2479                          )
2480{
2481   typedef struct {
2482      uint32_t attrBit;
2483      int32_t attrSize;
2484   } attrspec;
2485   static const attrspec commonattr[] = {
2486      // This order is important.
2487#if DARWIN_VERS >= DARWIN_10_6
2488      { ATTR_CMN_RETURNED_ATTRS,  sizeof(attribute_set_t) },
2489#endif
2490      { ATTR_CMN_NAME,            -1 },
2491      { ATTR_CMN_DEVID,           sizeof(dev_t) },
2492      { ATTR_CMN_FSID,            sizeof(fsid_t) },
2493      { ATTR_CMN_OBJTYPE,         sizeof(fsobj_type_t) },
2494      { ATTR_CMN_OBJTAG,          sizeof(fsobj_tag_t) },
2495      { ATTR_CMN_OBJID,           sizeof(fsobj_id_t) },
2496      { ATTR_CMN_OBJPERMANENTID,  sizeof(fsobj_id_t) },
2497      { ATTR_CMN_PAROBJID,        sizeof(fsobj_id_t) },
2498      { ATTR_CMN_SCRIPT,          sizeof(text_encoding_t) },
2499      { ATTR_CMN_CRTIME,          sizeof(struct timespec) },
2500      { ATTR_CMN_MODTIME,         sizeof(struct timespec) },
2501      { ATTR_CMN_CHGTIME,         sizeof(struct timespec) },
2502      { ATTR_CMN_ACCTIME,         sizeof(struct timespec) },
2503      { ATTR_CMN_BKUPTIME,        sizeof(struct timespec) },
2504      { ATTR_CMN_FNDRINFO,        32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2505      { ATTR_CMN_OWNERID,         sizeof(uid_t) },
2506      { ATTR_CMN_GRPID,           sizeof(gid_t) },
2507      { ATTR_CMN_ACCESSMASK,      sizeof(uint32_t) },
2508      { ATTR_CMN_NAMEDATTRCOUNT,  sizeof(uint32_t) },
2509      { ATTR_CMN_NAMEDATTRLIST,   -1 },
2510      { ATTR_CMN_FLAGS,           sizeof(uint32_t) },
2511      { ATTR_CMN_USERACCESS,      sizeof(uint32_t) },
2512      { ATTR_CMN_EXTENDED_SECURITY, -1 },
2513      { ATTR_CMN_UUID,            sizeof(guid_t) },
2514      { ATTR_CMN_GRPUUID,         sizeof(guid_t) },
2515      { ATTR_CMN_FILEID,          sizeof(uint64_t) },
2516      { ATTR_CMN_PARENTID,        sizeof(uint64_t) },
2517#if DARWIN_VERS >= DARWIN_10_6
2518      { ATTR_CMN_FULLPATH,        -1 },
2519#endif
2520      { 0,                        0 }
2521   };
2522   static const attrspec volattr[] = {
2523      // This order is important.
2524      { ATTR_VOL_INFO,            0 },
2525      { ATTR_VOL_FSTYPE,          sizeof(uint32_t) },
2526      { ATTR_VOL_SIGNATURE,       sizeof(uint32_t) },
2527      { ATTR_VOL_SIZE,            sizeof(off_t) },
2528      { ATTR_VOL_SPACEFREE,       sizeof(off_t) },
2529      { ATTR_VOL_SPACEAVAIL,      sizeof(off_t) },
2530      { ATTR_VOL_MINALLOCATION,   sizeof(off_t) },
2531      { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2532      { ATTR_VOL_IOBLOCKSIZE,     sizeof(uint32_t) },
2533      { ATTR_VOL_OBJCOUNT,        sizeof(uint32_t) },
2534      { ATTR_VOL_FILECOUNT,       sizeof(uint32_t) },
2535      { ATTR_VOL_DIRCOUNT,        sizeof(uint32_t) },
2536      { ATTR_VOL_MAXOBJCOUNT,     sizeof(uint32_t) },
2537      { ATTR_VOL_MOUNTPOINT,      -1 },
2538      { ATTR_VOL_NAME,            -1 },
2539      { ATTR_VOL_MOUNTFLAGS,      sizeof(uint32_t) },
2540      { ATTR_VOL_MOUNTEDDEVICE,   -1 },
2541      { ATTR_VOL_ENCODINGSUSED,   sizeof(uint64_t) },
2542      { ATTR_VOL_CAPABILITIES,    sizeof(vol_capabilities_attr_t) },
2543#if DARWIN_VERS >= DARWIN_10_6
2544      { ATTR_VOL_UUID,            sizeof(uuid_t) },
2545#endif
2546      { ATTR_VOL_ATTRIBUTES,      sizeof(vol_attributes_attr_t) },
2547      { 0,                        0 }
2548   };
2549   static const attrspec dirattr[] = {
2550      // This order is important.
2551      { ATTR_DIR_LINKCOUNT,       sizeof(uint32_t) },
2552      { ATTR_DIR_ENTRYCOUNT,      sizeof(uint32_t) },
2553      { ATTR_DIR_MOUNTSTATUS,     sizeof(uint32_t) },
2554      { 0,                        0 }
2555   };
2556   static const attrspec fileattr[] = {
2557      // This order is important.
2558      { ATTR_FILE_LINKCOUNT,      sizeof(uint32_t) },
2559      { ATTR_FILE_TOTALSIZE,      sizeof(off_t) },
2560      { ATTR_FILE_ALLOCSIZE,      sizeof(off_t) },
2561      { ATTR_FILE_IOBLOCKSIZE,    sizeof(uint32_t) },
2562      { ATTR_FILE_CLUMPSIZE,      sizeof(uint32_t) },
2563      { ATTR_FILE_DEVTYPE,        sizeof(uint32_t) },
2564      { ATTR_FILE_FILETYPE,       sizeof(uint32_t) },
2565      { ATTR_FILE_FORKCOUNT,      sizeof(uint32_t) },
2566      { ATTR_FILE_FORKLIST,       -1 },
2567      { ATTR_FILE_DATALENGTH,     sizeof(off_t) },
2568      { ATTR_FILE_DATAALLOCSIZE,  sizeof(off_t) },
2569      { ATTR_FILE_DATAEXTENTS,    sizeof(extentrecord) },
2570      { ATTR_FILE_RSRCLENGTH,     sizeof(off_t) },
2571      { ATTR_FILE_RSRCALLOCSIZE,  sizeof(off_t) },
2572      { ATTR_FILE_RSRCEXTENTS,    sizeof(extentrecord) },
2573      { 0,                        0 }
2574   };
2575   static const attrspec forkattr[] = {
2576      // This order is important.
2577      { ATTR_FORK_TOTALSIZE,      sizeof(off_t) },
2578      { ATTR_FORK_ALLOCSIZE,      sizeof(off_t) },
2579      { 0,                        0 }
2580   };
2581
2582   static const attrspec *attrdefs[5] = {
2583      commonattr, volattr, dirattr, fileattr, forkattr
2584   };
2585   attrgroup_t a[5];
2586   uint8_t *d, *dend;
2587   int g, i;
2588
2589   vg_assert(attrList->bitmapcount == 5);
2590   VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
2591   d = attrBuf;
2592   dend = d + attrBufSize;
2593
2594#if DARWIN_VERS >= DARWIN_10_6
2595   // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
2596   if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
2597       // fixme range check this?
2598       a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
2599       fn(tid, d, sizeof(attribute_set_t));
2600       VG_(memcpy)(a, d, sizeof(a));
2601   }
2602#endif
2603
2604   for (g = 0; g < 5; g++) {
2605      for (i = 0; attrdefs[g][i].attrBit; i++) {
2606         uint32_t bit = attrdefs[g][i].attrBit;
2607         int32_t size = attrdefs[g][i].attrSize;
2608
2609         if (a[g] & bit) {
2610             a[g] &= ~bit;  // clear bit for error check later
2611            if (size == -1) {
2612               attrreference_t *ref = (attrreference_t *)d;
2613               size = MIN(sizeof(attrreference_t), dend - d);
2614               fn(tid, d, size);
2615               if (size >= sizeof(attrreference_t)  &&
2616                   d + ref->attr_dataoffset < dend)
2617               {
2618                  fn(tid, d + ref->attr_dataoffset,
2619                     MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
2620               }
2621               d += size;
2622            }
2623            else {
2624               size = MIN(size, dend - d);
2625               fn(tid, d, size);
2626               d += size;
2627            }
2628
2629            if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
2630            if (d > dend) d = dend;
2631         }
2632      }
2633
2634      // Known bits are cleared. Die if any bits are left.
2635      if (a[g] != 0) {
2636         VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
2637      }
2638   }
2639}
2640
2641static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2642{
2643   POST_MEM_WRITE((Addr)attrData, attrDataSize);
2644}
2645
2646static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
2647{
2648   PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
2649}
2650
2651PRE(getattrlist)
2652{
2653   PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2654         ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2655   PRE_REG_READ5(int, "getattrlist",
2656                 const char *,path, struct vki_attrlist *,attrList,
2657                 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2658   PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
2659   PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2660   PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
2661}
2662
2663POST(getattrlist)
2664{
2665   if (ARG4 > sizeof(vki_uint32_t)) {
2666      // attrBuf is uint32_t size followed by attr data
2667      vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
2668      POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
2669      if (ARG5 & FSOPT_REPORT_FULLSIZE) {
2670         // *sizep is bytes required for return value, including *sizep
2671      } else {
2672         // *sizep is actual bytes returned, including *sizep
2673      }
2674      scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
2675   }
2676}
2677
2678
2679PRE(setattrlist)
2680{
2681   PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
2682         ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
2683   PRE_REG_READ5(int, "setattrlist",
2684                 const char *,path, struct vki_attrlist *,attrList,
2685                 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
2686   PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
2687   PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
2688   scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
2689}
2690
2691
2692PRE(getdirentriesattr)
2693{
2694   PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
2695         ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2696   PRE_REG_READ8(int, "getdirentriesattr",
2697                 int,fd, struct vki_attrlist *,attrList,
2698                 void *,attrBuf, size_t,attrBufSize,
2699                 unsigned int *,count, unsigned int *,basep,
2700                 unsigned int *,newState, unsigned int,options);
2701   PRE_MEM_READ("getdirentriesattr(attrList)",
2702                ARG2, sizeof(struct vki_attrlist));
2703   PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
2704   PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2705   PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
2706   PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
2707   PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
2708}
2709POST(getdirentriesattr)
2710{
2711   char *p, *end;
2712   unsigned int count;
2713   unsigned int i;
2714
2715   POST_MEM_WRITE(ARG5, sizeof(unsigned int));
2716   POST_MEM_WRITE(ARG6, sizeof(unsigned int));
2717   POST_MEM_WRITE(ARG7, sizeof(unsigned int));
2718
2719   // return buffer is concatenation of variable-size structs
2720   count = *(unsigned int *)ARG5;
2721   p = (char *)ARG3;
2722   end = (char *)ARG3 + ARG4;
2723   for (i = 0; i < count; i++) {
2724      vg_assert(p < end);  // failure is kernel bug or Valgrind bug
2725      p += *(unsigned int *)p;
2726   }
2727
2728   POST_MEM_WRITE(ARG3, p - (char *)ARG3);
2729
2730   PRINT("got %d records, %ld/%lu bytes\n",
2731         count, (Addr)p-(Addr)ARG3, ARG4);
2732}
2733
2734
2735PRE(fsgetpath)
2736{
2737#if VG_WORDSIZE == 4
2738   PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
2739         ARG1, ARG2, ARG3,
2740         ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
2741         LOHI64(ARG4, ARG5));
2742   PRE_REG_READ5(ssize_t, "fsgetpath",
2743                 void*,"buf", size_t,"bufsize",
2744                 fsid_t *,"fsid",
2745                 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
2746#else
2747   PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
2748         ARG1, ARG2, ARG3,
2749         ((unsigned int *)ARG3)[0],
2750         ((unsigned int *)ARG3)[1], ARG4);
2751   PRE_REG_READ4(ssize_t, "fsgetpath",
2752                 void*,"buf", size_t,"bufsize",
2753                 fsid_t *,"fsid", uint64_t,"objid");
2754#endif
2755   PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
2756   PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
2757}
2758
2759POST(fsgetpath)
2760{
2761   POST_MEM_WRITE(ARG1, RES);
2762}
2763
2764PRE(audit_session_self)
2765{
2766  PRINT("audit_session_self()");
2767}
2768
2769POST(audit_session_self)
2770{
2771  record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
2772  PRINT("audit-session %#lx", RES);
2773}
2774
2775PRE(exchangedata)
2776{
2777   PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
2778         ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
2779   PRE_REG_READ3(int, "exchangedata",
2780                 char *, path1, char *, path2, unsigned long, options);
2781   PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
2782   PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
2783}
2784
2785PRE(fsctl)
2786{
2787   PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
2788      ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2789   PRE_REG_READ4( long, "fsctl",
2790                  char *,"path", unsigned int,"request",
2791                  void *,"data", unsigned int,"options");
2792
2793   PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
2794
2795   switch (ARG2) {
2796   case VKI_afpfsByteRangeLock2FSCTL: {
2797      struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2798      PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
2799                     pb->offset);
2800      PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
2801                     pb->length);
2802      PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
2803                     pb->unLockFlag);
2804      PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
2805                     pb->startEndFlag);
2806      PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
2807                     pb->fd);
2808
2809      PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
2810                      pb->retRangeStart);
2811
2812      // GrP fixme check fd
2813      break;
2814   }
2815   case VKI_FSIOC_SYNC_VOLUME:
2816       PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
2817       break;
2818
2819   default:
2820      // fsctl requests use ioctl encoding
2821      ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
2822      break;
2823   }
2824}
2825
2826POST(fsctl)
2827{
2828   switch (ARG2) {
2829   case VKI_afpfsByteRangeLock2FSCTL: {
2830      struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
2831      POST_FIELD_WRITE(pb->retRangeStart);
2832      break;
2833   }
2834   case VKI_FSIOC_SYNC_VOLUME:
2835       break;
2836
2837   default:
2838      // fsctl requests use ioctl encoding
2839      ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
2840      break;
2841   }
2842}
2843
2844PRE(initgroups)
2845{
2846    PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
2847    PRE_REG_READ3(long, "initgroups",
2848        int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
2849    PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
2850}
2851
2852
2853//--------- posix_spawn ---------//
2854/* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
2855   the simpler AIX equivalent (syswrap-aix5.c). */
2856// Pre_read a char** argument.
2857static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
2858{
2859   while (True) {
2860      Addr a_deref;
2861      Addr* a_p = (Addr*)a;
2862      PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2863      a_deref = *a_p;
2864      if (0 == a_deref)
2865         break;
2866      PRE_MEM_RASCIIZ( s2, a_deref );
2867      a += sizeof(char*);
2868   }
2869}
2870static SysRes simple_pre_exec_check ( const HChar* exe_name,
2871                                      Bool trace_this_child )
2872{
2873   Int fd, ret;
2874   SysRes res;
2875   Bool setuid_allowed;
2876
2877   // Check it's readable
2878   res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
2879   if (sr_isError(res)) {
2880      return res;
2881   }
2882   fd = sr_Res(res);
2883   VG_(close)(fd);
2884
2885   // Check we have execute permissions.  We allow setuid executables
2886   // to be run only in the case when we are not simulating them, that
2887   // is, they to be run natively.
2888   setuid_allowed = trace_this_child  ? False  : True;
2889   ret = VG_(check_executable)(NULL/*&is_setuid*/,
2890                               exe_name, setuid_allowed);
2891   if (0 != ret) {
2892      return VG_(mk_SysRes_Error)(ret);
2893   }
2894   return VG_(mk_SysRes_Success)(0);
2895}
2896PRE(posix_spawn)
2897{
2898   HChar*       path = NULL;       /* path to executable */
2899   HChar**      envp = NULL;
2900   HChar**      argv = NULL;
2901   HChar**      arg2copy;
2902   HChar*       launcher_basename = NULL;
2903   Int          i, j, tot_args;
2904   SysRes       res;
2905   Bool         trace_this_child;
2906
2907   /* args: pid_t* pid
2908            char*  path
2909            posix_spawn_file_actions_t* file_actions
2910            char** argv
2911            char** envp
2912   */
2913   PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
2914         ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2915
2916   /* Standard pre-syscall checks */
2917
2918   PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
2919                 void*, file_actions, char**, argv, char**, envp );
2920   PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
2921   PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
2922   // DDD: check file_actions
2923   if (ARG4 != 0)
2924      pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
2925                                "posix_spawn(argv[i])" );
2926   if (ARG5 != 0)
2927      pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
2928                                "posix_spawn(envp[i])" );
2929
2930   if (0)
2931   VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
2932         ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
2933
2934   /* Now follows a bunch of logic copied from PRE(sys_execve) in
2935      syswrap-generic.c. */
2936
2937   /* Check that the name at least begins in client-accessible storage. */
2938   if (ARG2 == 0 /* obviously bogus */
2939       || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
2940      SET_STATUS_Failure( VKI_EFAULT );
2941      return;
2942   }
2943
2944   // Decide whether or not we want to follow along
2945   { // Make 'child_argv' be a pointer to the child's arg vector
2946     // (skipping the exe name)
2947     HChar** child_argv = (HChar**)ARG4;
2948     if (child_argv && child_argv[0] == NULL)
2949        child_argv = NULL;
2950     trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
2951   }
2952
2953   // Do the important checks:  it is a file, is executable, permissions are
2954   // ok, etc.  We allow setuid executables to run only in the case when
2955   // we are not simulating them, that is, they to be run natively.
2956   res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
2957   if (sr_isError(res)) {
2958      SET_STATUS_Failure( sr_Err(res) );
2959      return;
2960   }
2961
2962   /* If we're tracing the child, and the launcher name looks bogus
2963      (possibly because launcher.c couldn't figure it out, see
2964      comments therein) then we have no option but to fail. */
2965   if (trace_this_child
2966       && (VG_(name_of_launcher) == NULL
2967           || VG_(name_of_launcher)[0] != '/')) {
2968      SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2969      return;
2970   }
2971
2972   /* Ok.  So let's give it a try. */
2973   VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
2974
2975   /* posix_spawn on Darwin is combining the fork and exec in one syscall.
2976      So, we should not terminate gdbserver : this is still the parent
2977      running, which will terminate its gdbserver when exiting.
2978      If the child process is traced, it will start a fresh gdbserver
2979      after posix_spawn. */
2980
2981   // Set up the child's exe path.
2982   //
2983   if (trace_this_child) {
2984
2985      // We want to exec the launcher.  Get its pre-remembered path.
2986      path = VG_(name_of_launcher);
2987      // VG_(name_of_launcher) should have been acquired by m_main at
2988      // startup.  The following two assertions should be assured by
2989      // the "If we're tracking the child .." test just above here.
2990      vg_assert(path);
2991      vg_assert(path[0] == '/');
2992      launcher_basename = path;
2993
2994   } else {
2995      path = (HChar*)ARG2;
2996   }
2997
2998   // Set up the child's environment.
2999   //
3000   // Remove the valgrind-specific stuff from the environment so the
3001   // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3002   // This is done unconditionally, since if we are tracing the child,
3003   // the child valgrind will set up the appropriate client environment.
3004   // Nb: we make a copy of the environment before trying to mangle it
3005   // as it might be in read-only memory (this was bug #101881).
3006   //
3007   // Then, if tracing the child, set VALGRIND_LIB for it.
3008   //
3009   if (ARG5 == 0) {
3010      envp = NULL;
3011   } else {
3012      envp = VG_(env_clone)( (HChar**)ARG5 );
3013      vg_assert(envp);
3014      VG_(env_remove_valgrind_env_stuff)( envp );
3015   }
3016
3017   if (trace_this_child) {
3018      // Set VALGRIND_LIB in ARG5 (the environment)
3019      VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3020   }
3021
3022   // Set up the child's args.  If not tracing it, they are
3023   // simply ARG4.  Otherwise, they are
3024   //
3025   // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3026   //
3027   // except that the first VG_(args_for_valgrind_noexecpass) args
3028   // are omitted.
3029   //
3030   if (!trace_this_child) {
3031      argv = (HChar**)ARG4;
3032   } else {
3033      vg_assert( VG_(args_for_valgrind) );
3034      vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3035      vg_assert( VG_(args_for_valgrind_noexecpass)
3036                   <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3037      /* how many args in total will there be? */
3038      // launcher basename
3039      tot_args = 1;
3040      // V's args
3041      tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3042      tot_args -= VG_(args_for_valgrind_noexecpass);
3043      // name of client exe
3044      tot_args++;
3045      // args for client exe, skipping [0]
3046      arg2copy = (HChar**)ARG4;
3047      if (arg2copy && arg2copy[0]) {
3048         for (i = 1; arg2copy[i]; i++)
3049            tot_args++;
3050      }
3051      // allocate
3052      argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3053                          (tot_args+1) * sizeof(HChar*) );
3054      vg_assert(argv);
3055      // copy
3056      j = 0;
3057      argv[j++] = launcher_basename;
3058      for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3059         if (i < VG_(args_for_valgrind_noexecpass))
3060            continue;
3061         argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3062      }
3063      argv[j++] = (HChar*)ARG2;
3064      if (arg2copy && arg2copy[0])
3065         for (i = 1; arg2copy[i]; i++)
3066            argv[j++] = arg2copy[i];
3067      argv[j++] = NULL;
3068      // check
3069      vg_assert(j == tot_args+1);
3070   }
3071
3072   /* DDD: sort out the signal state.  What signal
3073      state does the child inherit from the parent?  */
3074
3075   if (0) {
3076      HChar **cpp;
3077      VG_(printf)("posix_spawn: %s\n", path);
3078      for (cpp = argv; cpp && *cpp; cpp++)
3079         VG_(printf)("argv: %s\n", *cpp);
3080      if (1)
3081         for (cpp = envp; cpp && *cpp; cpp++)
3082            VG_(printf)("env: %s\n", *cpp);
3083   }
3084
3085   /* Let the call go through as usual.  However, we have to poke
3086      the altered arguments back into the argument slots. */
3087   ARG2 = (UWord)path;
3088   ARG4 = (UWord)argv;
3089   ARG5 = (UWord)envp;
3090
3091   /* not to mention .. */
3092   *flags |= SfMayBlock;
3093}
3094POST(posix_spawn)
3095{
3096   vg_assert(SUCCESS);
3097   if (ARG1 != 0) {
3098      POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3099   }
3100}
3101
3102
3103PRE(socket)
3104{
3105   PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
3106   PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3107}
3108
3109POST(socket)
3110{
3111   SysRes r;
3112   vg_assert(SUCCESS);
3113   r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3114   SET_STATUS_from_SysRes(r);
3115}
3116
3117
3118PRE(setsockopt)
3119{
3120   PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3121      ARG1,ARG2,ARG3,ARG4,ARG5);
3122   PRE_REG_READ5(long, "setsockopt",
3123                 int, s, int, level, int, optname,
3124                 const void *, optval, vki_socklen_t, optlen);
3125   ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3126}
3127
3128
3129PRE(getsockopt)
3130{
3131   Addr optval_p = ARG4;
3132   Addr optlen_p = ARG5;
3133   PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3134      ARG1,ARG2,ARG3,ARG4,ARG5);
3135   PRE_REG_READ5(long, "getsockopt",
3136                 int, s, int, level, int, optname,
3137                 void *, optval, vki_socklen_t *, optlen);
3138   /* int getsockopt(int socket, int level, int option_name,
3139                     void *restrict option_value,
3140                     socklen_t *restrict option_len); */
3141   /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3142   if (optval_p != (Addr)NULL) {
3143      ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3144                                   "socketcall.getsockopt(optval)",
3145                                   "socketcall.getsockopt(optlen)" );
3146   }
3147   // DDD: #warning GrP fixme darwin-specific sockopts
3148}
3149
3150POST(getsockopt)
3151{
3152   Addr optval_p = ARG4;
3153   Addr optlen_p = ARG5;
3154   vg_assert(SUCCESS);
3155   if (optval_p != (Addr)NULL) {
3156      ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3157                                    optval_p, optlen_p,
3158                                    "socketcall.getsockopt(optlen_out)" );
3159   // DDD: #warning GrP fixme darwin-specific sockopts
3160   }
3161}
3162
3163
3164PRE(connect)
3165{
3166   *flags |= SfMayBlock;
3167   PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3168   PRE_REG_READ3(long, "connect",
3169                 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3170   ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3171}
3172
3173
3174PRE(accept)
3175{
3176   *flags |= SfMayBlock;
3177   PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3178   PRE_REG_READ3(long, "accept",
3179                 int, s, struct sockaddr *, addr, int, *addrlen);
3180   ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3181}
3182
3183POST(accept)
3184{
3185   SysRes r;
3186   vg_assert(SUCCESS);
3187   r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3188                                         ARG1,ARG2,ARG3);
3189   SET_STATUS_from_SysRes(r);
3190}
3191
3192
3193PRE(sendto)
3194{
3195   *flags |= SfMayBlock;
3196   PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3197      ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
3198   PRE_REG_READ6(long, "sendto",
3199                 int, s, const void *, msg, int, len,
3200                 unsigned int, flags,
3201                 const struct sockaddr *, to, int, tolen);
3202   ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3203}
3204
3205PRE(sendfile)
3206{
3207#if VG_WORDSIZE == 4
3208   PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3209         ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
3210
3211   PRE_REG_READ7(long, "sendfile",
3212      int, fromfd, int, tofd,
3213      vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3214      vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3215   PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3216   if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3217#else
3218   PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
3219      ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
3220
3221   PRE_REG_READ6(long, "sendfile",
3222      int, fromfd, int, tofd,
3223      vki_uint64_t, offset,
3224      vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3225   PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3226   if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3227#endif
3228
3229   *flags |= SfMayBlock;
3230}
3231POST(sendfile)
3232{
3233#if VG_WORDSIZE == 4
3234   POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3235   if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3236#else
3237   POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3238   if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3239#endif
3240}
3241
3242PRE(recvfrom)
3243{
3244   *flags |= SfMayBlock;
3245   PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3246      ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3247   PRE_REG_READ6(long, "recvfrom",
3248                 int, s, void *, buf, int, len, unsigned int, flags,
3249                 struct sockaddr *, from, int *, fromlen);
3250   ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3251}
3252
3253POST(recvfrom)
3254{
3255   vg_assert(SUCCESS);
3256   ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3257                                       ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3258}
3259
3260
3261PRE(sendmsg)
3262{
3263   *flags |= SfMayBlock;
3264   PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3265   PRE_REG_READ3(long, "sendmsg",
3266                 int, s, const struct msghdr *, msg, int, flags);
3267   ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3268}
3269
3270
3271PRE(recvmsg)
3272{
3273   *flags |= SfMayBlock;
3274   PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3275   PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3276   ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3277}
3278
3279POST(recvmsg)
3280{
3281   ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3282}
3283
3284
3285PRE(shutdown)
3286{
3287   *flags |= SfMayBlock;
3288   PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
3289   PRE_REG_READ2(int, "shutdown", int, s, int, how);
3290}
3291
3292
3293PRE(bind)
3294{
3295   PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3296   PRE_REG_READ3(long, "bind",
3297                 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3298   ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3299}
3300
3301
3302PRE(listen)
3303{
3304   PRINT("listen ( %ld, %ld )",ARG1,ARG2);
3305   PRE_REG_READ2(long, "listen", int, s, int, backlog);
3306}
3307
3308
3309PRE(getsockname)
3310{
3311   PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3312   PRE_REG_READ3(long, "getsockname",
3313                 int, s, struct sockaddr *, name, int *, namelen);
3314   ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3315}
3316
3317POST(getsockname)
3318{
3319   vg_assert(SUCCESS);
3320   ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3321                                          ARG1,ARG2,ARG3);
3322}
3323
3324
3325PRE(getpeername)
3326{
3327   PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3328   PRE_REG_READ3(long, "getpeername",
3329                 int, s, struct sockaddr *, name, int *, namelen);
3330   ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3331}
3332
3333POST(getpeername)
3334{
3335   vg_assert(SUCCESS);
3336   ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3337                                          ARG1,ARG2,ARG3);
3338}
3339
3340
3341PRE(socketpair)
3342{
3343   PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3344   PRE_REG_READ4(long, "socketpair",
3345                 int, d, int, type, int, protocol, int *, sv);
3346   ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3347}
3348
3349POST(socketpair)
3350{
3351   vg_assert(SUCCESS);
3352   ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3353                                         ARG1,ARG2,ARG3,ARG4);
3354}
3355
3356
3357PRE(gethostuuid)
3358{
3359   PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3360   PRE_REG_READ2(int,"gethostuuid",
3361                 char *,"uuid_buf",
3362                 const struct vki_timespec *,"timeout");
3363
3364   PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3365   PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3366
3367   *flags |= SfMayBlock;
3368}
3369
3370
3371POST(gethostuuid)
3372{
3373   POST_MEM_WRITE(ARG1, 16);
3374}
3375
3376/* Darwin pipe() returns the two descriptors in two registers. */
3377PRE(pipe)
3378{
3379   PRINT("pipe ( )");
3380   PRE_REG_READ0(int, "pipe");
3381}
3382
3383POST(pipe)
3384{
3385   Int p0, p1;
3386   vg_assert(SUCCESS);
3387   p0 = RES;
3388   p1 = RESHI;
3389
3390   if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3391       !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3392      VG_(close)(p0);
3393      VG_(close)(p1);
3394      SET_STATUS_Failure( VKI_EMFILE );
3395   } else {
3396      if (VG_(clo_track_fds)) {
3397         ML_(record_fd_open_nameless)(tid, p0);
3398         ML_(record_fd_open_nameless)(tid, p1);
3399      }
3400   }
3401}
3402
3403
3404PRE(getlogin)
3405{
3406   PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3407   PRE_REG_READ2(long, "getlogin",
3408                 char *,"namebuf", unsigned int,"namelen");
3409
3410   PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3411}
3412
3413POST(getlogin)
3414{
3415   POST_MEM_WRITE(ARG1, ARG2);
3416}
3417
3418
3419PRE(ptrace)
3420{
3421   PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3422   PRE_REG_READ4(long, "ptrace",
3423                 int,"request", vki_pid_t,"pid",
3424                 vki_caddr_t,"addr", int,"data");
3425
3426   // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3427
3428   // GrP fixme anything needed?
3429}
3430
3431
3432PRE(issetugid)
3433{
3434   PRINT("issetugid ( )");
3435   PRE_REG_READ0(long, "issetugid");
3436}
3437
3438
3439PRE(getdtablesize)
3440{
3441   PRINT("getdtablesize ( )");
3442   PRE_REG_READ0(long, "getdtablesize");
3443}
3444
3445POST(getdtablesize)
3446{
3447   // Subtract Valgrind's fd range from client's dtable
3448   if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3449}
3450
3451PRE(lseek)
3452{
3453   PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3454   PRE_REG_READ4(vki_off_t, "lseek",
3455                 unsigned int,fd, int,offset_hi, int,offset_lo,
3456                 unsigned int,whence);
3457}
3458
3459
3460PRE(pathconf)
3461{
3462   PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3463   PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3464   PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3465}
3466
3467
3468PRE(fpathconf)
3469{
3470   PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3471   PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3472
3473   if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3474      SET_STATUS_Failure( VKI_EBADF );
3475}
3476
3477
3478PRE(getdirentries)
3479{
3480   PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3481   PRE_REG_READ4(int, "getdirentries",
3482                 int, fd, char *, buf, int, nbytes, long *, basep);
3483   PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3484   PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3485}
3486
3487POST(getdirentries)
3488{
3489   POST_MEM_WRITE(ARG4, sizeof(long));
3490   // GrP fixme be specific about d_name?
3491   POST_MEM_WRITE(ARG2, RES);
3492}
3493
3494
3495PRE(getdirentries64)
3496{
3497   PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3498   PRE_REG_READ4(vki_ssize_t, "getdirentries",
3499                 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3500   PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t));
3501   PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3502}
3503POST(getdirentries64)
3504{
3505   POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3506   // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3507   POST_MEM_WRITE(ARG2, RES);
3508}
3509
3510
3511PRE(statfs64)
3512{
3513   PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3514   PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3515   PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3516   PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3517}
3518POST(statfs64)
3519{
3520   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3521}
3522
3523
3524PRE(fstatfs64)
3525{
3526   PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3527   PRE_REG_READ2(long, "fstatfs64",
3528                 unsigned int, fd, struct statfs *, buf);
3529   PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3530}
3531POST(fstatfs64)
3532{
3533   POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3534}
3535
3536PRE(csops)
3537{
3538   PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
3539   PRE_REG_READ4(int, "csops",
3540                 vki_pid_t, pid, uint32_t, ops,
3541                 void *, useraddr, vki_size_t, usersize);
3542
3543   PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
3544
3545   // If the pid is ours, don't mark the program as KILL or HARD
3546   // Maybe we should keep track of this for later calls to STATUS
3547   if (!ARG1 || VG_(getpid)() == ARG1) {
3548      switch (ARG2) {
3549      case VKI_CS_OPS_MARKINVALID:
3550      case VKI_CS_OPS_MARKHARD:
3551      case VKI_CS_OPS_MARKKILL:
3552         SET_STATUS_Success(0);
3553      }
3554   }
3555}
3556POST(csops)
3557{
3558   POST_MEM_WRITE( ARG3, ARG4 );
3559}
3560
3561PRE(auditon)
3562{
3563   PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
3564   PRE_REG_READ3(int,"auditon",
3565                 int,"cmd", void*,"data", unsigned int,"length");
3566
3567   switch (ARG1) {
3568
3569   case VKI_A_SETPOLICY:
3570   case VKI_A_SETKMASK:
3571   case VKI_A_SETQCTRL:
3572   case VKI_A_SETCOND:
3573   case VKI_A_SETCLASS:
3574   case VKI_A_SETPMASK:
3575   case VKI_A_SETFSIZE:
3576#if DARWIN_VERS >= DARWIN_10_6
3577   case VKI_A_SENDTRIGGER:
3578#endif
3579      // kernel reads data..data+length
3580      PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3581      break;
3582
3583   case VKI_A_GETKMASK:
3584   case VKI_A_GETPOLICY:
3585   case VKI_A_GETQCTRL:
3586   case VKI_A_GETFSIZE:
3587   case VKI_A_GETCOND:
3588      // kernel writes data..data+length
3589      // GrP fixme be precise about what gets written
3590      PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3591      break;
3592
3593
3594   case VKI_A_GETCLASS:
3595   case VKI_A_GETPINFO:
3596   case VKI_A_GETPINFO_ADDR:
3597#if DARWIN_VERS >= DARWIN_10_6
3598   case VKI_A_GETSINFO_ADDR:
3599#endif
3600      // kernel reads and writes data..data+length
3601      // GrP fixme be precise about what gets read and written
3602      PRE_MEM_READ("auditon(data)", ARG2, ARG3);
3603      PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
3604      break;
3605
3606   case VKI_A_SETKAUDIT:
3607   case VKI_A_SETSTAT:
3608   case VKI_A_SETUMASK:
3609   case VKI_A_SETSMASK:
3610   case VKI_A_GETKAUDIT:
3611   case VKI_A_GETCWD:
3612   case VKI_A_GETCAR:
3613   case VKI_A_GETSTAT:
3614      // unimplemented on darwin
3615      break;
3616
3617   default:
3618      VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1);
3619      break;
3620   }
3621}
3622POST(auditon)
3623{
3624   switch (ARG1) {
3625
3626   case VKI_A_SETPOLICY:
3627   case VKI_A_SETKMASK:
3628   case VKI_A_SETQCTRL:
3629   case VKI_A_SETCOND:
3630   case VKI_A_SETCLASS:
3631   case VKI_A_SETPMASK:
3632   case VKI_A_SETFSIZE:
3633#if DARWIN_VERS >= DARWIN_10_6
3634   case VKI_A_SENDTRIGGER:
3635#endif
3636      // kernel reads data..data+length
3637      break;
3638
3639   case VKI_A_GETKMASK:
3640   case VKI_A_GETPOLICY:
3641   case VKI_A_GETQCTRL:
3642   case VKI_A_GETFSIZE:
3643   case VKI_A_GETCOND:
3644      // kernel writes data..data+length
3645      // GrP fixme be precise about what gets written
3646      POST_MEM_WRITE(ARG2, ARG3);
3647      break;
3648
3649
3650   case VKI_A_GETCLASS:
3651   case VKI_A_GETPINFO:
3652   case VKI_A_GETPINFO_ADDR:
3653#if DARWIN_VERS >= DARWIN_10_6
3654   case VKI_A_GETSINFO_ADDR:
3655#endif
3656      // kernel reads and writes data..data+length
3657      // GrP fixme be precise about what gets read and written
3658      POST_MEM_WRITE(ARG2, ARG3);
3659      break;
3660
3661   case VKI_A_SETKAUDIT:
3662   case VKI_A_SETSTAT:
3663   case VKI_A_SETUMASK:
3664   case VKI_A_SETSMASK:
3665   case VKI_A_GETKAUDIT:
3666   case VKI_A_GETCWD:
3667   case VKI_A_GETCAR:
3668   case VKI_A_GETSTAT:
3669      // unimplemented on darwin
3670      break;
3671
3672   default:
3673      break;
3674   }
3675}
3676
3677
3678PRE(mmap)
3679{
3680   // SysRes r;
3681   if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
3682
3683#if VG_WORDSIZE == 4
3684   PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
3685         ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
3686   PRE_REG_READ7(Addr, "mmap",
3687                 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3688                 unsigned long,offset_hi, unsigned long,offset_lo);
3689   // GrP fixme V mmap and kernel mach_msg collided once - don't use
3690   // V's mechanism for now
3691   // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
3692   // (Off64T)LOHI64(ARG6, ARG7) );
3693#else
3694   PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
3695         ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3696   PRE_REG_READ6(long, "mmap",
3697                 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
3698                 Off64T,offset);
3699   // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3700
3701#endif
3702
3703   // SET_STATUS_from_SysRes(r);
3704}
3705
3706POST(mmap)
3707{
3708   if (RES != -1) {
3709      ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
3710      // Try to load symbols from the region
3711      VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
3712                           -1/*don't use_fd*/ );
3713   }
3714}
3715
3716
3717PRE(__sysctl)
3718{
3719   PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
3720          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
3721
3722   PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
3723                 void*, oldp, vki_size_t *, oldlenp,
3724                 void*, newp, vki_size_t *, newlenp);
3725
3726   PRE_MEM_READ("sysctl(name)", ARG1, ARG2);  // reads name[0..namelen-1]
3727   if (ARG4) {
3728      // writes *ARG4
3729      PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
3730      if (ARG3) {
3731         // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
3732         PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
3733         PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
3734      }
3735   }
3736   if (ARG5) {
3737      PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
3738   }
3739
3740   if (VG_(clo_trace_syscalls)) {
3741      unsigned int i;
3742      int *name = (int *)ARG1;
3743      VG_(printf)(" mib: [ ");
3744      for (i = 0; i < ARG2; i++) {
3745         VG_(printf)("%d ", name[i]);
3746      }
3747      VG_(printf)("]");
3748   }
3749
3750   // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
3751   // (executable path and arguments and environment
3752
3753   {
3754      // Intercept sysctl(kern.usrstack). The kernel's reply would be
3755      // Valgrind's stack, not the client's stack.
3756      // GrP fixme kern_usrstack64
3757      if (ARG1  &&  ARG2 == 2  &&
3758          ((int *)ARG1)[0] == VKI_CTL_KERN  &&
3759#if VG_WORDSIZE == 4
3760          ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
3761#else
3762          ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
3763#endif
3764          )
3765      {
3766         if (ARG5/*newp*/  ||  ARG6/*newlen*/) {
3767            SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
3768         } else {
3769            Addr *oldp = (Addr *)ARG3;
3770            size_t *oldlenp = (size_t *)ARG4;
3771            if (oldlenp) {
3772               Addr stack_end = VG_(clstk_end)+1;
3773               size_t oldlen = *oldlenp;
3774               // always return actual size
3775               *oldlenp = sizeof(Addr);
3776               if (oldp  &&  oldlen >= sizeof(Addr)) {
3777                  // oldp is big enough
3778                  // copy value and return 0
3779                  *oldp = stack_end;
3780                  SET_STATUS_Success(0);
3781               } else {
3782                  // oldp isn't big enough
3783                  // copy as much as possible and return ENOMEM
3784                  if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
3785                  SET_STATUS_Failure(VKI_ENOMEM);
3786               }
3787            }
3788         }
3789      }
3790   }
3791
3792   if (!SUCCESS  &&  !FAILURE) {
3793      // Don't set SfPostOnFail if we've already handled it locally.
3794      *flags |= SfPostOnFail;
3795   }
3796}
3797
3798POST(__sysctl)
3799{
3800   if (SUCCESS  ||  ERR == VKI_ENOMEM) {
3801      // sysctl can write truncated data and return VKI_ENOMEM
3802      if (ARG4) {
3803         POST_MEM_WRITE(ARG4, sizeof(size_t));
3804      }
3805      if (ARG3  &&  ARG4) {
3806         POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
3807      }
3808   }
3809}
3810
3811
3812PRE(sigpending)
3813{
3814   PRINT( "sigpending ( %#lx )", ARG1 );
3815   PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
3816   PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
3817}
3818POST(sigpending)
3819{
3820   POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
3821}
3822
3823
3824PRE(sigprocmask)
3825{
3826   UWord arg1;
3827   PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
3828   PRE_REG_READ3(long, "sigprocmask",
3829                 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
3830   if (ARG2 != 0)
3831      PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
3832   if (ARG3 != 0)
3833      PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
3834
3835   /* Massage ARG1 ('how').  If ARG2 (the new mask) is NULL then the
3836      value of 'how' is irrelevant, and it appears that Darwin's libc
3837      passes zero, which is not equal to any of
3838      SIG_{BLOCK,UNBLOCK,SETMASK}.  This causes
3839      VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
3840      value independently of the other args.  Solution: in this case,
3841      simply pass a valid (but irrelevant) value for 'how'. */
3842   /* Also, in this case the new set is passed to the kernel by
3843      reference, not value, as in some other sigmask related Darwin
3844      syscalls. */
3845   arg1 = ARG1;
3846   if (ARG2 == 0  /* the new-set is NULL */
3847       && ARG1 != VKI_SIG_BLOCK
3848       && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
3849      arg1 = VKI_SIG_SETMASK;
3850   }
3851   SET_STATUS_from_SysRes(
3852      VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
3853                                           (vki_sigset_t*)ARG3 )
3854   );
3855
3856   if (SUCCESS)
3857      *flags |= SfPollAfter;
3858}
3859
3860POST(sigprocmask)
3861{
3862   vg_assert(SUCCESS);
3863   if (RES == 0 && ARG3 != 0)
3864      POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
3865}
3866
3867
3868PRE(sigsuspend)
3869{
3870   /* Just hand this off to the kernel.  Is that really correct?  And
3871      shouldn't we at least set SfPollAfter?  These questions apply to
3872      all the Linux versions too. */
3873   /* I think the first arg is the 32-bit signal mask (by value), and
3874      the other two args are ignored. */
3875   *flags |= SfMayBlock;
3876   PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
3877   PRE_REG_READ1(int, "sigsuspend", int, sigmask);
3878}
3879
3880
3881/* Be careful about the 4th arg, since that is a uint64_t.  Hence 64-
3882   and 32-bit wrappers are different.
3883
3884   ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
3885   length in the usual way.  I have seen values NULL, 0 passed in some
3886   cases.  I left the calls to PRE_MEM_WRITE/READ unconditional on the
3887   basis that they don't do anything if the length is zero, so it's OK
3888   for the buffer pointer to be NULL in that case (meaning they don't
3889   complain).
3890
3891   int proc_info(int32_t callnum, int32_t pid,
3892                 uint32_t flavor, uint64_t arg,
3893                 user_addr_t buffer, int32_t buffersize)
3894*/
3895#if DARWIN_VERS >= DARWIN_10_6
3896PRE(proc_info)
3897{
3898#if VG_WORDSIZE == 4
3899   PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3900         (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
3901   PRE_REG_READ7(int, "proc_info",
3902                 int, callnum, int, pid, unsigned int, flavor,
3903                 vki_uint32_t, arg_low32,
3904                 vki_uint32_t, arg_high32,
3905                 void*, buffer, int, buffersize);
3906   PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
3907#else
3908   PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
3909         (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
3910   PRE_REG_READ6(int, "proc_info",
3911                 int, callnum, int, pid, unsigned int, flavor,
3912                 unsigned long long int, arg,
3913                 void*, buffer, int, buffersize);
3914   PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
3915#endif
3916}
3917
3918POST(proc_info)
3919{
3920#if VG_WORDSIZE == 4
3921   vg_assert(SUCCESS);
3922   POST_MEM_WRITE(ARG6, ARG7);
3923#else
3924   vg_assert(SUCCESS);
3925   POST_MEM_WRITE(ARG5, ARG6);
3926#endif
3927}
3928
3929#endif /* DARWIN_VERS >= DARWIN_10_6 */
3930
3931/* ---------------------------------------------------------------------
3932   aio_*
3933   ------------------------------------------------------------------ */
3934
3935// We must record the aiocbp for each aio_read() in a table so that when
3936// aio_return() is called we can mark the memory written asynchronously by
3937// aio_read() as having been written.  We don't have to do this for
3938// aio_write().  See bug 197227 for more details.
3939static OSet* aiocbp_table = NULL;
3940static Bool aio_init_done = False;
3941
3942static void aio_init(void)
3943{
3944   aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
3945   aio_init_done = True;
3946}
3947
3948static Bool was_a_successful_aio_read = False;
3949
3950PRE(aio_return)
3951{
3952   struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3953   // This assumes that the kernel looks at the struct pointer, but not the
3954   // contents of the struct.
3955   PRINT( "aio_return ( %#lx )", ARG1 );
3956   PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
3957
3958   if (!aio_init_done) aio_init();
3959   was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
3960}
3961POST(aio_return)
3962{
3963   // If we found the aiocbp in our own table it must have been an aio_read(),
3964   // so mark the buffer as written.  If we didn't find it, it must have been
3965   // an aio_write() or a bogus aio_return() (eg. a second one on the same
3966   // aiocbp).  Either way, the buffer won't have been written so we don't
3967   // have to mark the buffer as written.
3968   if (was_a_successful_aio_read) {
3969      struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
3970      POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
3971      was_a_successful_aio_read = False;
3972   }
3973}
3974
3975PRE(aio_suspend)
3976{
3977   // This assumes that the kernel looks at the struct pointers in the list,
3978   // but not the contents of the structs.
3979   PRINT( "aio_suspend ( %#lx )", ARG1 );
3980   PRE_REG_READ3(long, "aio_suspend",
3981                 const struct vki_aiocb *, aiocbp, int, nent,
3982                 const struct vki_timespec *, timeout);
3983   if (ARG2 > 0)
3984      PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
3985   if (ARG3)
3986      PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
3987}
3988
3989PRE(aio_error)
3990{
3991   // This assumes that the kernel looks at the struct pointer, but not the
3992   // contents of the struct.
3993   PRINT( "aio_error ( %#lx )", ARG1 );
3994   PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
3995}
3996
3997PRE(aio_read)
3998{
3999   struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4000
4001   PRINT( "aio_read ( %#lx )", ARG1 );
4002   PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4003   PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4004
4005   if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4006      if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4007         PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4008                       (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4009      } else {
4010         SET_STATUS_Failure( VKI_EBADF );
4011      }
4012   } else {
4013      SET_STATUS_Failure( VKI_EINVAL );
4014   }
4015}
4016POST(aio_read)
4017{
4018   // We have to record the fact that there is an asynchronous read request
4019   // pending.  When a successful aio_return() occurs for this aiocb, then we
4020   // will mark the memory as having been defined.
4021   struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4022   if (!aio_init_done) aio_init();
4023   // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4024   // should have caused the aio_read() to fail and we shouldn't have reached
4025   // here.
4026   VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4027}
4028
4029PRE(aio_write)
4030{
4031   struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4032
4033   PRINT( "aio_write ( %#lx )", ARG1 );
4034   PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4035   PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4036
4037   if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4038      if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4039         PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4040                      (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4041      } else {
4042         SET_STATUS_Failure( VKI_EBADF );
4043      }
4044   } else {
4045      SET_STATUS_Failure( VKI_EINVAL );
4046   }
4047}
4048
4049/* ---------------------------------------------------------------------
4050   mach_msg: formatted messages
4051   ------------------------------------------------------------------ */
4052
4053static size_t desc_size(mach_msg_descriptor_t *desc)
4054{
4055   switch (desc->type.type) {
4056   case MACH_MSG_PORT_DESCRIPTOR:          return sizeof(desc->port);
4057   case MACH_MSG_OOL_DESCRIPTOR:           return sizeof(desc->out_of_line);
4058   case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:  return sizeof(desc->out_of_line);
4059   case MACH_MSG_OOL_PORTS_DESCRIPTOR:     return sizeof(desc->ool_ports);
4060   default:
4061      VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4062      return sizeof(desc->type); // guess
4063   }
4064}
4065
4066
4067static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4068                              const char *name)
4069{
4070   mach_msg_size_t i;
4071   mach_port_t *ports = (mach_port_t *)desc->address;
4072   for (i = 0; i < desc->count; i++) {
4073      assign_port_name(ports[i], name);
4074   }
4075}
4076
4077
4078static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4079{
4080   mach_msg_body_t *body;
4081   mach_msg_size_t count, i;
4082   uint8_t *p;
4083   mach_msg_descriptor_t *desc;
4084
4085   vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4086
4087   body = (mach_msg_body_t *)(mh+1);
4088   count = body->msgh_descriptor_count;
4089   p = (uint8_t *)(body+1);
4090
4091   for (i = 0; i < count; i++) {
4092      desc = (mach_msg_descriptor_t *)p;
4093      p += desc_size(desc);
4094
4095      switch (desc->type.type) {
4096      case MACH_MSG_PORT_DESCRIPTOR:
4097         // single port
4098         record_unnamed_port(tid, desc->port.name, -1);
4099         record_port_insert_rights(desc->port.name, desc->port.disposition);
4100         PRINT("got port %s;\n", name_for_port(desc->port.name));
4101         break;
4102
4103      case MACH_MSG_OOL_DESCRIPTOR:
4104      case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4105         // out-of-line memory - map it
4106         // GrP fixme how is VOLATILE different? do we care?
4107         // GrP fixme do other flags tell us anything? assume shared for now
4108         // GrP fixme more SF_ flags marking mach_msg memory might be nice
4109         // GrP fixme protection
4110         if (desc->out_of_line.size > 0) {
4111            Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4112            Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4113                                    (Addr)desc->out_of_line.size);
4114            PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4115                  (char*)desc->out_of_line.address+desc->out_of_line.size);
4116
4117            ML_(notify_core_and_tool_of_mmap)(
4118               start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4119               VKI_MAP_PRIVATE, -1, 0);
4120         }
4121         // GrP fixme mark only un-rounded part as initialized
4122         break;
4123
4124      case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4125         // out-of-line array of ports - map it
4126         // GrP fixme see fixmes above
4127         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));
4128
4129         if (desc->ool_ports.count > 0) {
4130            Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4131            Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4132            mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4133
4134            ML_(notify_core_and_tool_of_mmap)(
4135               start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4136               VKI_MAP_PRIVATE, -1, 0);
4137
4138            PRINT(":");
4139            for (i = 0; i < desc->ool_ports.count; i++) {
4140               record_unnamed_port(tid, ports[i], -1);
4141               record_port_insert_rights(ports[i], desc->port.disposition);
4142               PRINT(" %s", name_for_port(ports[i]));
4143            }
4144         }
4145         PRINT(";\n");
4146         break;
4147
4148      default:
4149         VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4150         break;
4151      }
4152   }
4153}
4154
4155
4156static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4157{
4158#pragma pack(4)
4159   struct {
4160      mach_port_t name;
4161      mach_msg_size_t pad1;
4162      uint16_t pad2;
4163      uint8_t disposition;
4164      uint8_t type;
4165   } *desc = (void*)desc2;
4166#pragma pack()
4167
4168   PRE_FIELD_READ("msg->desc.port.name",        desc->name);
4169   PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4170   PRE_FIELD_READ("msg->desc.port.type",        desc->type);
4171}
4172
4173
4174static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4175{
4176#pragma pack(4)
4177   struct {
4178      Addr address;
4179#if VG_WORDSIZE != 8
4180      mach_msg_size_t size;
4181#endif
4182      uint8_t deallocate;
4183      uint8_t copy;
4184      uint8_t pad1;
4185      uint8_t type;
4186#if VG_WORDSIZE == 8
4187      mach_msg_size_t size;
4188#endif
4189   } *desc = (void*)desc2;
4190#pragma pack()
4191
4192   PRE_FIELD_READ("msg->desc.out_of_line.address",    desc->address);
4193   PRE_FIELD_READ("msg->desc.out_of_line.size",       desc->size);
4194   PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4195   PRE_FIELD_READ("msg->desc.out_of_line.copy",       desc->copy);
4196   PRE_FIELD_READ("msg->desc.out_of_line.type",       desc->type);
4197}
4198
4199static void pre_oolports_desc_read(ThreadId tid,
4200                                   mach_msg_ool_ports_descriptor_t *desc2)
4201{
4202#pragma pack(4)
4203   struct {
4204      Addr address;
4205#if VG_WORDSIZE != 8
4206      mach_msg_size_t size;
4207#endif
4208      uint8_t deallocate;
4209      uint8_t copy;
4210      uint8_t disposition;
4211      uint8_t type;
4212#if VG_WORDSIZE == 8
4213      mach_msg_size_t size;
4214#endif
4215   } *desc = (void*)desc2;
4216#pragma pack()
4217
4218   PRE_FIELD_READ("msg->desc.ool_ports.address",     desc->address);
4219   PRE_FIELD_READ("msg->desc.ool_ports.size",        desc->size);
4220   PRE_FIELD_READ("msg->desc.ool_ports.deallocate",  desc->deallocate);
4221   PRE_FIELD_READ("msg->desc.ool_ports.copy",        desc->copy);
4222   PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4223   PRE_FIELD_READ("msg->desc.ool_ports.type",        desc->type);
4224}
4225
4226
4227// Returns the size of the descriptor area
4228// (mach_msg_body_t + any mach_msg_descriptor_t)
4229static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4230{
4231   mach_msg_body_t *body;
4232   mach_msg_size_t count, i;
4233   uint8_t *p;
4234   mach_msg_descriptor_t *desc;
4235
4236   vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4237
4238   body = (mach_msg_body_t *)(mh+1);
4239   PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4240
4241   count = body->msgh_descriptor_count;
4242   p = (uint8_t *)(body+1);
4243
4244   for (i = 0; i < count; i++) {
4245      desc = (mach_msg_descriptor_t *)p;
4246      p += desc_size(desc);
4247
4248      switch (desc->type.type) {
4249      case MACH_MSG_PORT_DESCRIPTOR:
4250         // single port; no memory map effects
4251         pre_port_desc_read(tid, &desc->port);
4252         break;
4253
4254      case MACH_MSG_OOL_DESCRIPTOR:
4255      case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4256         // out-of-line memory - unmap it if it's marked dealloc
4257         // GrP fixme need to remap if message fails?
4258         // GrP fixme how is VOLATILE different? do we care?
4259         // GrP fixme struct is different for lp64
4260         pre_ool_desc_read(tid, &desc->out_of_line);
4261
4262         if (desc->out_of_line.deallocate  &&  desc->out_of_line.size > 0) {
4263            vm_size_t size = desc->out_of_line.size;
4264            Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4265            Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4266            PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4267                  (Addr)desc->out_of_line.address + size);
4268            ML_(notify_core_and_tool_of_munmap)(start, end - start);
4269         }
4270         break;
4271
4272      case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4273         // out-of-line array of ports - unmap it if it's marked dealloc
4274         // GrP fixme need to remap if message fails?
4275         // GrP fixme struct different for lp64
4276         pre_oolports_desc_read(tid, &desc->ool_ports);
4277
4278         if (desc->ool_ports.deallocate  &&  desc->ool_ports.count > 0) {
4279            vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4280            Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4281            Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4282            PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4283                  (Addr)desc->ool_ports.address + size);
4284            ML_(notify_core_and_tool_of_munmap)(start, end - start);
4285         }
4286         break;
4287      default:
4288         VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4289         break;
4290      }
4291   }
4292
4293   return (size_t)((Addr)p - (Addr)body);
4294}
4295
4296
4297/* ---------------------------------------------------------------------
4298   mach_msg: host-related messages
4299   ------------------------------------------------------------------ */
4300
4301
4302POST(host_info)
4303{
4304#pragma pack(4)
4305   typedef struct {
4306      mach_msg_header_t Head;
4307      NDR_record_t NDR;
4308      kern_return_t RetCode;
4309      mach_msg_type_number_t host_info_outCnt;
4310      integer_t host_info_out[14];
4311   } Reply;
4312#pragma pack()
4313
4314   Reply *reply = (Reply *)ARG1;
4315
4316   if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4317}
4318
4319PRE(host_info)
4320{
4321#pragma pack(4)
4322   typedef struct {
4323      mach_msg_header_t Head;
4324      NDR_record_t NDR;
4325      host_flavor_t flavor;
4326      mach_msg_type_number_t host_info_outCnt;
4327   } Request;
4328#pragma pack()
4329
4330   Request *req = (Request *)ARG1;
4331
4332   PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4333
4334   AFTER = POST_FN(host_info);
4335}
4336
4337
4338POST(host_page_size)
4339{
4340#pragma pack(4)
4341   typedef struct {
4342      mach_msg_header_t Head;
4343      NDR_record_t NDR;
4344      kern_return_t RetCode;
4345      vm_size_t out_page_size;
4346   } Reply;
4347#pragma pack()
4348
4349   Reply *reply = (Reply *)ARG1;
4350
4351   if (!reply->RetCode) {
4352     PRINT("page size %llu", (ULong)reply->out_page_size);
4353   } else {
4354      PRINT("mig return %d", reply->RetCode);
4355   }
4356}
4357
4358PRE(host_page_size)
4359{
4360   PRINT("host_page_size(mach_host_self(), ...)");
4361
4362   AFTER = POST_FN(host_page_size);
4363}
4364
4365
4366POST(host_get_io_master)
4367{
4368#pragma pack(4)
4369   typedef struct {
4370      mach_msg_header_t Head;
4371      /* start of the kernel processed data */
4372      mach_msg_body_t msgh_body;
4373      mach_msg_port_descriptor_t io_master;
4374      /* end of the kernel processed data */
4375   } Reply;
4376#pragma pack()
4377
4378   Reply *reply = (Reply *)ARG1;
4379
4380   assign_port_name(reply->io_master.name, "io_master-%p");
4381   PRINT("%s", name_for_port(reply->io_master.name));
4382}
4383
4384PRE(host_get_io_master)
4385{
4386#pragma pack(4)
4387   typedef struct {
4388      mach_msg_header_t Head;
4389   } Request;
4390#pragma pack()
4391
4392   // Request *req = (Request *)ARG1;
4393
4394   PRINT("host_get_io_master(mach_host_self())");
4395
4396   AFTER = POST_FN(host_get_io_master);
4397}
4398
4399
4400POST(host_get_clock_service)
4401{
4402#pragma pack(4)
4403   typedef struct {
4404      mach_msg_header_t Head;
4405      /* start of the kernel processed data */
4406      mach_msg_body_t msgh_body;
4407      mach_msg_port_descriptor_t clock_serv;
4408      /* end of the kernel processed data */
4409   } Reply;
4410#pragma pack()
4411
4412   Reply *reply = (Reply *)ARG1;
4413
4414   assign_port_name(reply->clock_serv.name, "clock-%p");
4415   PRINT("%s", name_for_port(reply->clock_serv.name));
4416}
4417
4418PRE(host_get_clock_service)
4419{
4420#pragma pack(4)
4421   typedef struct {
4422      mach_msg_header_t Head;
4423      NDR_record_t NDR;
4424      clock_id_t clock_id;
4425   } Request;
4426#pragma pack()
4427
4428   Request *req = (Request *)ARG1;
4429
4430   PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4431
4432   AFTER = POST_FN(host_get_clock_service);
4433}
4434
4435
4436PRE(host_request_notification)
4437{
4438#pragma pack(4)
4439   typedef struct {
4440      mach_msg_header_t Head;
4441      /* start of the kernel processed data */
4442      mach_msg_body_t msgh_body;
4443      mach_msg_port_descriptor_t notify_port;
4444      /* end of the kernel processed data */
4445      NDR_record_t NDR;
4446      host_flavor_t notify_type;
4447   } Request;
4448#pragma pack()
4449
4450   Request *req = (Request *)ARG1;
4451
4452   if (MACH_REMOTE == mach_task_self()) {
4453      if (req->notify_type == 0) {
4454         PRINT("host_request_notification(mach_host_self(), %s, %s)",
4455               "HOST_NOTIFY_CALENDAR_CHANGE",
4456               name_for_port(req->notify_port.name));
4457      } else {
4458         PRINT("host_request_notification(mach_host_self(), %d, %s)",
4459               req->notify_type,
4460               name_for_port(req->notify_port.name));
4461      }
4462   } else {
4463      PRINT("host_request_notification(%s, %d, %s)",
4464            name_for_port(MACH_REMOTE),
4465            req->notify_type,
4466            name_for_port(req->notify_port.name));
4467   }
4468
4469    // GrP fixme only do this on success
4470   assign_port_name(req->notify_port.name, "host_notify-%p");
4471}
4472
4473
4474/* ---------------------------------------------------------------------
4475   mach_msg: messages to a task
4476   ------------------------------------------------------------------ */
4477
4478// JRS 2011-Aug-25: just guessing here.  I have no clear idea how
4479// these structs are derived.  They obviously relate to the various
4480// .def files in the xnu sources, and can also be found in some
4481// form in /usr/include/mach/*.h, but not sure how these all
4482// relate to each other.
4483
4484PRE(mach_port_set_context)
4485{
4486#pragma pack(4)
4487   typedef struct {
4488      mach_msg_header_t Head;
4489      NDR_record_t NDR;
4490      mach_port_name_t name;
4491      mach_vm_address_t context;
4492   } Request;
4493#pragma pack()
4494
4495   Request *req = (Request *)ARG1;
4496
4497   PRINT("mach_port_set_context(%s, %s, 0x%llx)",
4498        name_for_port(MACH_REMOTE),
4499        name_for_port(req->name), req->context);
4500
4501   AFTER = POST_FN(mach_port_set_context);
4502}
4503
4504POST(mach_port_set_context)
4505{
4506#pragma pack(4)
4507   typedef struct {
4508      mach_msg_header_t Head;
4509      NDR_record_t NDR;
4510      kern_return_t RetCode;
4511   } Reply;
4512#pragma pack()
4513}
4514
4515
4516// JRS 2011-Aug-25 FIXME completely bogus
4517PRE(task_get_exception_ports)
4518{
4519#pragma pack(4)
4520   typedef struct {
4521      mach_msg_header_t Head;
4522      NDR_record_t NDR;
4523      exception_mask_t exception_mask;
4524   } Request;
4525#pragma pack()
4526
4527   PRINT("task_get_exception_ports(BOGUS)");
4528   AFTER = POST_FN(task_get_exception_ports);
4529}
4530
4531POST(task_get_exception_ports)
4532{
4533#pragma pack(4)
4534   typedef struct {
4535      mach_msg_header_t Head;
4536      /* start of the kernel processed data */
4537      mach_msg_body_t msgh_body;
4538      mach_msg_port_descriptor_t old_handlers[32];
4539      /* end of the kernel processed data */
4540      NDR_record_t NDR;
4541      mach_msg_type_number_t masksCnt;
4542      exception_mask_t masks[32];
4543      exception_behavior_t old_behaviors[32];
4544      thread_state_flavor_t old_flavors[32];
4545   } Reply;
4546#pragma pack()
4547}
4548
4549
4550///////////////////////////////////////////////////
4551
4552PRE(mach_port_type)
4553{
4554#pragma pack(4)
4555   typedef struct {
4556      mach_msg_header_t Head;
4557      NDR_record_t NDR;
4558      mach_port_name_t name;
4559   } Request;
4560#pragma pack()
4561
4562   Request *req = (Request *)ARG1;
4563
4564   PRINT("mach_port_type(%s, %s, ...)",
4565         name_for_port(MACH_REMOTE), name_for_port(req->name));
4566
4567   AFTER = POST_FN(mach_port_type);
4568}
4569
4570POST(mach_port_type)
4571{
4572}
4573
4574
4575PRE(mach_port_extract_member)
4576{
4577#pragma pack(4)
4578   typedef struct {
4579      mach_msg_header_t Head;
4580      NDR_record_t NDR;
4581      mach_port_name_t name;
4582      mach_port_name_t pset;
4583   } Request;
4584#pragma pack()
4585
4586   Request *req = (Request *)ARG1;
4587
4588   PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
4589         name_for_port(MACH_REMOTE),
4590         req->name, req->pset);
4591
4592   AFTER = POST_FN(mach_port_extract_member);
4593
4594   // GrP fixme port tracker?
4595}
4596
4597POST(mach_port_extract_member)
4598{
4599#pragma pack(4)
4600   typedef struct {
4601      mach_msg_header_t Head;
4602      NDR_record_t NDR;
4603      kern_return_t RetCode;
4604   } Reply;
4605#pragma pack()
4606
4607   Reply *reply = (Reply *)ARG1;
4608
4609   if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4610}
4611
4612
4613PRE(mach_port_allocate)
4614{
4615#pragma pack(4)
4616   typedef struct {
4617      mach_msg_header_t Head;
4618      NDR_record_t NDR;
4619      mach_port_right_t right;
4620   } Request;
4621#pragma pack()
4622
4623   Request *req = (Request *)ARG1;
4624
4625   PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
4626
4627   MACH_ARG(mach_port_allocate.right) = req->right;
4628
4629   AFTER = POST_FN(mach_port_allocate);
4630}
4631
4632POST(mach_port_allocate)
4633{
4634#pragma pack(4)
4635   typedef struct {
4636      mach_msg_header_t Head;
4637      NDR_record_t NDR;
4638      kern_return_t RetCode;
4639      mach_port_name_t name;
4640   } Reply;
4641#pragma pack()
4642
4643   Reply *reply = (Reply *)ARG1;
4644
4645   if (!reply->RetCode) {
4646      if (MACH_REMOTE == vg_task_port) {
4647         // GrP fixme port tracking is too imprecise
4648         // vg_assert(!port_exists(reply->name));
4649         record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
4650         PRINT("got port 0x%x", reply->name);
4651      } else {
4652         VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
4653      }
4654   } else {
4655      PRINT("mig return %d", reply->RetCode);
4656   }
4657}
4658
4659
4660PRE(mach_port_deallocate)
4661{
4662#pragma pack(4)
4663   typedef struct {
4664      mach_msg_header_t Head;
4665      NDR_record_t NDR;
4666      mach_port_name_t name;
4667   } Request;
4668#pragma pack()
4669
4670   Request *req = (Request *)ARG1;
4671
4672   PRINT("mach_port_deallocate(%s, %s)",
4673         name_for_port(MACH_REMOTE),
4674         name_for_port(req->name));
4675
4676   MACH_ARG(mach_port.port) = req->name;
4677
4678   AFTER = POST_FN(mach_port_deallocate);
4679
4680   // Must block to prevent race (other thread allocates and
4681   // notifies after we deallocate but before we notify)
4682   *flags &= ~SfMayBlock;
4683}
4684
4685POST(mach_port_deallocate)
4686{
4687#pragma pack(4)
4688   typedef struct {
4689      mach_msg_header_t Head;
4690      NDR_record_t NDR;
4691      kern_return_t RetCode;
4692   } Reply;
4693#pragma pack()
4694
4695   Reply *reply = (Reply *)ARG1;
4696
4697   if (!reply->RetCode) {
4698      if (MACH_REMOTE == vg_task_port) {
4699         // Must have cleared SfMayBlock in PRE to prevent race
4700         record_port_dealloc(MACH_ARG(mach_port.port));
4701      } else {
4702         VG_(printf)("UNKNOWN remote port dealloc\n");
4703      }
4704   } else {
4705      PRINT("mig return %d", reply->RetCode);
4706   }
4707}
4708
4709
4710PRE(mach_port_get_refs)
4711{
4712#pragma pack(4)
4713   typedef struct {
4714      mach_msg_header_t Head;
4715      NDR_record_t NDR;
4716      mach_port_name_t name;
4717      mach_port_right_t right;
4718   } Request;
4719#pragma pack()
4720
4721   Request *req = (Request *)ARG1;
4722
4723   PRINT("mach_port_get_refs(%s, %s, 0x%x)",
4724         name_for_port(MACH_REMOTE),
4725         name_for_port(req->name), req->right);
4726
4727   MACH_ARG(mach_port_mod_refs.port) = req->name;
4728   MACH_ARG(mach_port_mod_refs.right) = req->right;
4729
4730   AFTER = POST_FN(mach_port_get_refs);
4731}
4732
4733POST(mach_port_get_refs)
4734{
4735#pragma pack(4)
4736   typedef struct {
4737      mach_msg_header_t Head;
4738      NDR_record_t NDR;
4739      kern_return_t RetCode;
4740      mach_port_urefs_t refs;
4741   } Reply;
4742#pragma pack()
4743
4744   Reply *reply = (Reply *)ARG1;
4745
4746   if (!reply->RetCode) {
4747      PRINT("got refs=%d", reply->refs);
4748   } else {
4749      PRINT("mig return %d", reply->RetCode);
4750   }
4751}
4752
4753
4754PRE(mach_port_mod_refs)
4755{
4756#pragma pack(4)
4757   typedef struct {
4758      mach_msg_header_t Head;
4759      NDR_record_t NDR;
4760      mach_port_name_t name;
4761      mach_port_right_t right;
4762      mach_port_delta_t delta;
4763   } Request;
4764#pragma pack()
4765
4766   Request *req = (Request *)ARG1;
4767
4768   PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
4769         name_for_port(MACH_REMOTE),
4770         name_for_port(req->name), req->right, req->delta);
4771
4772   MACH_ARG(mach_port_mod_refs.port) = req->name;
4773   MACH_ARG(mach_port_mod_refs.right) = req->right;
4774   MACH_ARG(mach_port_mod_refs.delta) = req->delta;
4775
4776   AFTER = POST_FN(mach_port_mod_refs);
4777
4778   // Must block to prevent race (other thread allocates and
4779   // notifies after we deallocate but before we notify)
4780   *flags &= ~SfMayBlock;
4781}
4782
4783POST(mach_port_mod_refs)
4784{
4785#pragma pack(4)
4786   typedef struct {
4787      mach_msg_header_t Head;
4788      NDR_record_t NDR;
4789      kern_return_t RetCode;
4790   } Reply;
4791#pragma pack()
4792
4793   Reply *reply = (Reply *)ARG1;
4794
4795   if (!reply->RetCode) {
4796      if (MACH_REMOTE == vg_task_port) {
4797         // Must have cleared SfMayBlock in PRE to prevent race
4798         record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
4799                              MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
4800                              MACH_ARG(mach_port_mod_refs.delta));
4801      } else {
4802         VG_(printf)("UNKNOWN remote port mod refs\n");
4803      }
4804   } else {
4805      PRINT("mig return %d", reply->RetCode);
4806   }
4807}
4808
4809
4810PRE(mach_port_get_set_status)
4811{
4812#pragma pack(4)
4813   typedef struct {
4814      mach_msg_header_t Head;
4815      NDR_record_t NDR;
4816      mach_port_name_t name;
4817   } Request;
4818#pragma pack()
4819
4820   Request *req = (Request *)ARG1;
4821
4822   PRINT("mach_port_get_set_status(%s, %s)",
4823         name_for_port(MACH_REMOTE),
4824         name_for_port(req->name));
4825
4826   AFTER = POST_FN(mach_port_get_set_status);
4827}
4828
4829POST(mach_port_get_set_status)
4830{
4831#pragma pack(4)
4832   typedef struct {
4833      mach_msg_header_t Head;
4834      /* start of the kernel processed data */
4835      mach_msg_body_t msgh_body;
4836      mach_msg_ool_descriptor_t members;
4837      /* end of the kernel processed data */
4838      NDR_record_t NDR;
4839      mach_msg_type_number_t membersCnt;
4840      mach_msg_trailer_t trailer;
4841   } Reply;
4842#pragma pack()
4843
4844   // Reply *reply = (Reply *)ARG1;
4845
4846   // GrP fixme nothing to do?
4847}
4848
4849
4850PRE(mach_port_move_member)
4851{
4852#pragma pack(4)
4853    typedef struct {
4854        mach_msg_header_t Head;
4855        NDR_record_t NDR;
4856        mach_port_name_t member;
4857        mach_port_name_t after;
4858    } Request;
4859#pragma pack()
4860
4861    Request *req = (Request *)ARG1;
4862
4863    PRINT("mach_port_move_member(%s, %s, %s)",
4864          name_for_port(MACH_REMOTE),
4865          name_for_port(req->member),
4866          name_for_port(req->after));
4867    /*
4868    MACH_ARG(mach_port_move_member.member) = req->member;
4869    MACH_ARG(mach_port_move_member.after) = req->after;
4870    */
4871    AFTER = POST_FN(mach_port_move_member);
4872}
4873
4874POST(mach_port_move_member)
4875{
4876#pragma pack(4)
4877   typedef struct {
4878      mach_msg_header_t Head;
4879      NDR_record_t NDR;
4880      kern_return_t RetCode;
4881      mach_msg_trailer_t trailer;
4882   } Reply;
4883#pragma pack()
4884
4885   Reply *reply = (Reply *)ARG1;
4886
4887   if (!reply->RetCode) {
4888      // fixme port set tracker?
4889   } else {
4890      PRINT("mig return %d", reply->RetCode);
4891   }
4892}
4893
4894
4895PRE(mach_port_destroy)
4896{
4897#pragma pack(4)
4898   typedef struct {
4899      mach_msg_header_t Head;
4900      NDR_record_t NDR;
4901      mach_port_name_t name;
4902   } Request;
4903#pragma pack()
4904
4905   Request *req = (Request *)ARG1;
4906
4907   PRINT("mach_port_destroy(%s, %s)",
4908         name_for_port(MACH_REMOTE),
4909         name_for_port(req->name));
4910
4911   MACH_ARG(mach_port.port) = req->name;
4912
4913   AFTER = POST_FN(mach_port_destroy);
4914
4915   // Must block to prevent race (other thread allocates and
4916   // notifies after we deallocate but before we notify)
4917   *flags &= ~SfMayBlock;
4918}
4919
4920POST(mach_port_destroy)
4921{
4922#pragma pack(4)
4923   typedef struct {
4924      mach_msg_header_t Head;
4925      NDR_record_t NDR;
4926      kern_return_t RetCode;
4927   } Reply;
4928#pragma pack()
4929
4930   Reply *reply = (Reply *)ARG1;
4931
4932   if (!reply->RetCode) {
4933      if (MACH_REMOTE == vg_task_port) {
4934         // Must have cleared SfMayBlock in PRE to prevent race
4935         record_port_destroy(MACH_ARG(mach_port.port));
4936      } else {
4937         VG_(printf)("UNKNOWN remote port destroy\n");
4938      }
4939   } else {
4940      PRINT("mig return %d", reply->RetCode);
4941   }
4942}
4943
4944
4945PRE(mach_port_request_notification)
4946{
4947#pragma pack(4)
4948   typedef struct {
4949      mach_msg_header_t Head;
4950      /* start of the kernel processed data */
4951      mach_msg_body_t msgh_body;
4952      mach_msg_port_descriptor_t notify;
4953      /* end of the kernel processed data */
4954      NDR_record_t NDR;
4955      mach_port_name_t name;
4956      mach_msg_id_t msgid;
4957      mach_port_mscount_t sync;
4958   } Request;
4959#pragma pack()
4960
4961   Request *req = (Request *)ARG1;
4962
4963   PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
4964         name_for_port(MACH_REMOTE),
4965         name_for_port(req->name), req->msgid, req->sync,
4966         req->notify.name, req->notify.disposition);
4967
4968   AFTER = POST_FN(mach_port_request_notification);
4969}
4970
4971POST(mach_port_request_notification)
4972{
4973   // GrP fixme port tracker? not sure
4974}
4975
4976
4977PRE(mach_port_insert_right)
4978{
4979#pragma pack(4)
4980   typedef struct {
4981      mach_msg_header_t Head;
4982      /* start of the kernel processed data */
4983      mach_msg_body_t msgh_body;
4984      mach_msg_port_descriptor_t poly;
4985      /* end of the kernel processed data */
4986      NDR_record_t NDR;
4987      mach_port_name_t name;
4988   } Request;
4989#pragma pack()
4990
4991   Request *req = (Request *)ARG1;
4992
4993   PRINT("mach_port_insert_right(%s, %s, %d, %d)",
4994         name_for_port(MACH_REMOTE),
4995         name_for_port(req->name), req->poly.name, req->poly.disposition);
4996
4997   AFTER = POST_FN(mach_port_insert_right);
4998
4999   if (MACH_REMOTE == mach_task_self()) {
5000      // GrP fixme import_complex_message handles everything?
5001      // what about export_complex_message for MOVE variants?
5002   } else {
5003      VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5004      // GrP fixme also may remove rights from this task?
5005   }
5006
5007   // GrP fixme port tracker?
5008}
5009
5010POST(mach_port_insert_right)
5011{
5012}
5013
5014
5015PRE(mach_port_extract_right)
5016{
5017#pragma pack(4)
5018   typedef struct {
5019      mach_msg_header_t Head;
5020      NDR_record_t NDR;
5021      mach_port_name_t name;
5022      mach_msg_type_name_t msgt_name;
5023   } Request;
5024#pragma pack()
5025
5026   Request *req = (Request *)ARG1;
5027
5028   PRINT("mach_port_extract_right(%s, %s, %d)",
5029         name_for_port(MACH_REMOTE),
5030         name_for_port(req->name), req->msgt_name);
5031
5032   AFTER = POST_FN(mach_port_extract_right);
5033
5034   // fixme port tracker?
5035}
5036
5037POST(mach_port_extract_right)
5038{
5039   // fixme import_complex_message handles the returned result, right?
5040}
5041
5042
5043PRE(mach_port_get_attributes)
5044{
5045#pragma pack(4)
5046   typedef struct {
5047      mach_msg_header_t Head;
5048      NDR_record_t NDR;
5049      mach_port_name_t name;
5050      mach_port_flavor_t flavor;
5051      mach_msg_type_number_t port_info_outCnt;
5052   } Request;
5053#pragma pack()
5054
5055   Request *req = (Request *)ARG1;
5056
5057   PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5058         name_for_port(MACH_REMOTE),
5059         name_for_port(req->name), req->flavor, req->port_info_outCnt);
5060
5061   AFTER = POST_FN(mach_port_get_attributes);
5062}
5063
5064POST(mach_port_get_attributes)
5065{
5066}
5067
5068
5069PRE(mach_port_set_attributes)
5070{
5071#pragma pack(4)
5072   typedef struct {
5073      mach_msg_header_t Head;
5074      NDR_record_t NDR;
5075      mach_port_name_t name;
5076      mach_port_flavor_t flavor;
5077      mach_msg_type_number_t port_infoCnt;
5078      integer_t port_info[10];
5079   } Request;
5080#pragma pack()
5081
5082   Request *req = (Request *)ARG1;
5083
5084   PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5085        name_for_port(MACH_REMOTE),
5086        name_for_port(req->name), req->flavor, req->port_infoCnt);
5087
5088   AFTER = POST_FN(mach_port_set_attributes);
5089}
5090
5091POST(mach_port_set_attributes)
5092{
5093}
5094
5095
5096PRE(mach_port_insert_member)
5097{
5098#pragma pack(4)
5099   typedef struct {
5100      mach_msg_header_t Head;
5101      NDR_record_t NDR;
5102      mach_port_name_t name;
5103      mach_port_name_t pset;
5104   } Request;
5105#pragma pack()
5106
5107   Request *req = (Request *)ARG1;
5108
5109   PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5110         name_for_port(MACH_REMOTE), req->name, req->pset);
5111
5112   AFTER = POST_FN(mach_port_insert_member);
5113
5114   // GrP fixme port tracker?
5115}
5116
5117POST(mach_port_insert_member)
5118{
5119}
5120
5121
5122PRE(task_get_special_port)
5123{
5124#pragma pack(4)
5125   typedef struct {
5126      mach_msg_header_t Head;
5127      NDR_record_t NDR;
5128      int which_port;
5129   } Request;
5130#pragma pack()
5131
5132   Request *req = (Request *)ARG1;
5133
5134   switch (req->which_port) {
5135   case TASK_KERNEL_PORT:
5136      PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5137            name_for_port(MACH_REMOTE));
5138      break;
5139   case TASK_HOST_PORT:
5140      PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5141            name_for_port(MACH_REMOTE));
5142      break;
5143   case TASK_BOOTSTRAP_PORT:
5144      PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5145            name_for_port(MACH_REMOTE));
5146      break;
5147#if DARWIN_VERS < DARWIN_10_8
5148   /* These disappeared in 10.8 */
5149   case TASK_WIRED_LEDGER_PORT:
5150      PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5151            name_for_port(MACH_REMOTE));
5152      break;
5153   case TASK_PAGED_LEDGER_PORT:
5154      PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5155            name_for_port(MACH_REMOTE));
5156      break;
5157#endif
5158   default:
5159      PRINT("task_get_special_port(%s, %d)",
5160            name_for_port(MACH_REMOTE), req->which_port);
5161      break;
5162   }
5163
5164   MACH_ARG(task_get_special_port.which_port) = req->which_port;
5165
5166   AFTER = POST_FN(task_get_special_port);
5167}
5168
5169POST(task_get_special_port)
5170{
5171#pragma pack(4)
5172   typedef struct {
5173      mach_msg_header_t Head;
5174      /* start of the kernel processed data */
5175      mach_msg_body_t msgh_body;
5176      mach_msg_port_descriptor_t special_port;
5177      /* end of the kernel processed data */
5178   } Reply;
5179#pragma pack()
5180
5181   Reply *reply = (Reply *)ARG1;
5182
5183   PRINT("got port %#x ", reply->special_port.name);
5184
5185   switch (MACH_ARG(task_get_special_port.which_port)) {
5186   case TASK_BOOTSTRAP_PORT:
5187      vg_bootstrap_port = reply->special_port.name;
5188      assign_port_name(reply->special_port.name, "bootstrap");
5189      break;
5190   case TASK_KERNEL_PORT:
5191      assign_port_name(reply->special_port.name, "kernel");
5192      break;
5193   case TASK_HOST_PORT:
5194      assign_port_name(reply->special_port.name, "host");
5195      break;
5196#if DARWIN_VERS < DARWIN_10_8
5197   /* These disappeared in 10.8 */
5198   case TASK_WIRED_LEDGER_PORT:
5199      assign_port_name(reply->special_port.name, "wired-ledger");
5200      break;
5201   case TASK_PAGED_LEDGER_PORT:
5202      assign_port_name(reply->special_port.name, "paged-ledger");
5203      break;
5204#endif
5205   default:
5206      assign_port_name(reply->special_port.name, "special-%p");
5207      break;
5208   }
5209
5210   PRINT("%s", name_for_port(reply->special_port.name));
5211}
5212
5213
5214PRE(semaphore_create)
5215{
5216#pragma pack(4)
5217   typedef struct {
5218      mach_msg_header_t Head;
5219      NDR_record_t NDR;
5220      int policy;
5221      int value;
5222   } Request;
5223#pragma pack()
5224
5225   Request *req = (Request *)ARG1;
5226
5227   PRINT("semaphore_create(%s, ..., %d, %d)",
5228         name_for_port(MACH_REMOTE), req->policy, req->value);
5229
5230   AFTER = POST_FN(semaphore_create);
5231}
5232
5233POST(semaphore_create)
5234{
5235#pragma pack(4)
5236   typedef struct {
5237      mach_msg_header_t Head;
5238      /* start of the kernel processed data */
5239      mach_msg_body_t msgh_body;
5240      mach_msg_port_descriptor_t semaphore;
5241      /* end of the kernel processed data */
5242      mach_msg_trailer_t trailer;
5243   } Reply;
5244#pragma pack()
5245
5246   Reply *reply = (Reply *)ARG1;
5247
5248   assign_port_name(reply->semaphore.name, "semaphore-%p");
5249   PRINT("%s", name_for_port(reply->semaphore.name));
5250}
5251
5252
5253PRE(semaphore_destroy)
5254{
5255#pragma pack(4)
5256   typedef struct {
5257      mach_msg_header_t Head;
5258      /* start of the kernel processed data */
5259      mach_msg_body_t msgh_body;
5260      mach_msg_port_descriptor_t semaphore;
5261      /* end of the kernel processed data */
5262      mach_msg_trailer_t trailer;
5263   } Request;
5264#pragma pack()
5265
5266   Request *req = (Request *)ARG1;
5267
5268   PRINT("semaphore_destroy(%s, %s)",
5269         name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
5270
5271   record_port_destroy(req->semaphore.name);
5272
5273   AFTER = POST_FN(semaphore_destroy);
5274}
5275
5276POST(semaphore_destroy)
5277{
5278#pragma pack(4)
5279   typedef struct {
5280      mach_msg_header_t Head;
5281      NDR_record_t NDR;
5282      kern_return_t RetCode;
5283      mach_msg_trailer_t trailer;
5284   } Reply;
5285#pragma pack()
5286
5287   Reply *reply = (Reply *)ARG1;
5288   if (!reply->RetCode) {
5289   } else {
5290      PRINT("mig return %d", reply->RetCode);
5291   }
5292}
5293
5294PRE(task_policy_set)
5295{
5296#pragma pack(4)
5297   typedef struct {
5298      mach_msg_header_t Head;
5299      NDR_record_t NDR;
5300      task_policy_flavor_t flavor;
5301      mach_msg_type_number_t policy_infoCnt;
5302      integer_t policy_info[16];
5303   } Request;
5304#pragma pack()
5305
5306   Request *req = (Request *)ARG1;
5307
5308   PRINT("task_policy_set(%s) flacor:%d", name_for_port(MACH_REMOTE), req->flavor);
5309
5310   AFTER = POST_FN(task_policy_set);
5311}
5312
5313POST(task_policy_set)
5314{
5315#pragma pack(4)
5316   typedef struct {
5317      mach_msg_header_t Head;
5318      NDR_record_t NDR;
5319      kern_return_t RetCode;
5320   } Reply;
5321#pragma pack()
5322
5323   Reply *reply = (Reply *)ARG1;
5324   if (!reply->RetCode) {
5325   } else {
5326      PRINT("mig return %d", reply->RetCode);
5327   }
5328}
5329
5330PRE(mach_ports_lookup)
5331{
5332#pragma pack(4)
5333   typedef struct {
5334       mach_msg_header_t Head;
5335   } Request;
5336#pragma pack()
5337
5338   // Request *req = (Request *)ARG1;
5339
5340   PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
5341
5342   AFTER = POST_FN(mach_ports_lookup);
5343}
5344
5345POST(mach_ports_lookup)
5346{
5347#pragma pack(4)
5348   typedef struct {
5349      mach_msg_header_t Head;
5350      /* start of the kernel processed data */
5351      mach_msg_body_t msgh_body;
5352      mach_msg_ool_ports_descriptor_t init_port_set;
5353      /* end of the kernel processed data */
5354      NDR_record_t NDR;
5355      mach_msg_type_number_t init_port_setCnt;
5356   } Reply;
5357#pragma pack()
5358
5359    // Reply *reply = (Reply *)ARG1;
5360}
5361
5362
5363PRE(task_threads)
5364{
5365#pragma pack(4)
5366   typedef struct {
5367      mach_msg_header_t Head;
5368   } Request;
5369#pragma pack()
5370
5371   // Request *req = (Request *)ARG1;
5372
5373   PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
5374
5375   AFTER = POST_FN(task_threads);
5376}
5377
5378POST(task_threads)
5379{
5380#pragma pack(4)
5381   typedef struct {
5382      mach_msg_header_t Head;
5383      /* start of the kernel processed data */
5384      mach_msg_body_t msgh_body;
5385      mach_msg_ool_ports_descriptor_t act_list;
5386      /* end of the kernel processed data */
5387      NDR_record_t NDR;
5388      mach_msg_type_number_t act_listCnt;
5389      mach_msg_trailer_t trailer;
5390   } Reply;
5391#pragma pack()
5392
5393   Reply *reply = (Reply *)ARG1;
5394
5395   if (MACH_REMOTE == vg_task_port) {
5396      assign_port_names(&reply->act_list, "thread-%p");
5397   } else {
5398      assign_port_names(&reply->act_list, "remote-thread-%p");
5399   }
5400}
5401
5402
5403PRE(task_suspend)
5404{
5405   PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
5406
5407   if (MACH_REMOTE == vg_task_port) {
5408      // GrP fixme self-suspend
5409      vg_assert(0);
5410   } else {
5411      // suspend other - no problem
5412   }
5413
5414   AFTER = POST_FN(task_suspend);
5415}
5416
5417POST(task_suspend)
5418{
5419}
5420
5421
5422PRE(task_resume)
5423{
5424   PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
5425
5426   if (MACH_REMOTE == vg_task_port) {
5427      // GrP fixme self-resume
5428      vg_assert(0);
5429   } else {
5430      // resume other - no problem
5431   }
5432
5433   AFTER = POST_FN(task_resume);
5434}
5435
5436POST(task_resume)
5437{
5438}
5439
5440
5441PRE(vm_allocate)
5442{
5443#pragma pack(4)
5444   typedef struct {
5445      mach_msg_header_t Head;
5446      NDR_record_t NDR;
5447      vm_address_t address;
5448      vm_size_t size;
5449      int flags;
5450   } Request;
5451#pragma pack()
5452
5453   Request *req = (Request *)ARG1;
5454
5455   PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
5456         name_for_port(MACH_REMOTE),
5457         (ULong)req->address, (ULong)req->size, req->flags);
5458
5459   MACH_ARG(vm_allocate.size) = req->size;
5460   MACH_ARG(vm_allocate.flags) = req->flags;
5461
5462   AFTER = POST_FN(vm_allocate);
5463}
5464
5465POST(vm_allocate)
5466{
5467#pragma pack(4)
5468   typedef struct {
5469      mach_msg_header_t Head;
5470      NDR_record_t NDR;
5471      kern_return_t RetCode;
5472      vm_address_t address;
5473      mach_msg_trailer_t trailer;
5474   } Reply;
5475#pragma pack()
5476
5477   Reply *reply = (Reply *)ARG1;
5478
5479   if (!reply->RetCode) {
5480      if (MACH_REMOTE == vg_task_port) {
5481        PRINT("allocated at %#llx", (ULong)reply->address);
5482         // requesting 0 bytes returns address 0 with no error
5483         if (MACH_ARG(vm_allocate.size)) {
5484            ML_(notify_core_and_tool_of_mmap)(
5485                  reply->address, MACH_ARG(vm_allocate.size),
5486                  VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
5487         }
5488      } else {
5489         PRINT("allocated at %#llx in remote task %s",
5490               (ULong)reply->address,
5491               name_for_port(MACH_REMOTE));
5492      }
5493   } else {
5494      PRINT("mig return %d", reply->RetCode);
5495   }
5496}
5497
5498
5499PRE(vm_deallocate)
5500{
5501#pragma pack(4)
5502   typedef struct {
5503      mach_msg_header_t Head;
5504      NDR_record_t NDR;
5505      vm_address_t address;
5506      vm_size_t size;
5507   } Request;
5508#pragma pack()
5509
5510   Request *req = (Request *)ARG1;
5511
5512   PRINT("vm_deallocate(%s, at %#llx, size %lld)",
5513         name_for_port(MACH_REMOTE),
5514         (ULong)req->address, (ULong)req->size);
5515
5516   MACH_ARG(vm_deallocate.address) = req->address;
5517   MACH_ARG(vm_deallocate.size) = req->size;
5518
5519   AFTER = POST_FN(vm_deallocate);
5520
5521   // Must block to prevent race (other thread allocates and
5522   // notifies after we deallocate but before we notify)
5523   *flags &= ~SfMayBlock;
5524}
5525
5526POST(vm_deallocate)
5527{
5528#pragma pack(4)
5529   typedef struct {
5530      mach_msg_header_t Head;
5531      NDR_record_t NDR;
5532      kern_return_t RetCode;
5533      mach_msg_trailer_t trailer;
5534   } Reply;
5535#pragma pack()
5536
5537   Reply *reply = (Reply *)ARG1;
5538
5539   if (!reply->RetCode) {
5540      if (MACH_REMOTE == vg_task_port) {
5541         if (MACH_ARG(vm_deallocate.size)) {
5542            Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
5543            Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
5544                                    MACH_ARG(vm_deallocate.size));
5545            // Must have cleared SfMayBlock in PRE to prevent race
5546            ML_(notify_core_and_tool_of_munmap)(start, end - start);
5547         }
5548      }
5549   } else {
5550      PRINT("mig return %d", reply->RetCode);
5551   }
5552}
5553
5554
5555PRE(vm_protect)
5556{
5557#pragma pack(4)
5558   typedef struct {
5559      mach_msg_header_t Head;
5560      NDR_record_t NDR;
5561      vm_address_t address;
5562      vm_size_t size;
5563      boolean_t set_maximum;
5564      vm_prot_t new_protection;
5565   } Request;
5566#pragma pack()
5567
5568   Request *req = (Request *)ARG1;
5569
5570   PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
5571         name_for_port(MACH_REMOTE),
5572         (ULong)req->address, (ULong)req->size,
5573         req->set_maximum, req->new_protection);
5574
5575   MACH_ARG(vm_protect.address) = req->address;
5576   MACH_ARG(vm_protect.size) = req->size;
5577   MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
5578   MACH_ARG(vm_protect.new_protection) = req->new_protection;
5579
5580   AFTER = POST_FN(vm_protect);
5581}
5582
5583POST(vm_protect)
5584{
5585#pragma pack(4)
5586   typedef struct {
5587      mach_msg_header_t Head;
5588      NDR_record_t NDR;
5589      kern_return_t RetCode;
5590      mach_msg_trailer_t trailer;
5591   } Reply;
5592#pragma pack()
5593
5594   Reply *reply = (Reply *)ARG1;
5595
5596   if (!reply->RetCode) {
5597      if (MACH_REMOTE == vg_task_port) {
5598         Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
5599         Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
5600                                 MACH_ARG(vm_protect.size));
5601         UInt prot = MACH_ARG(vm_protect.new_protection);
5602         if (MACH_ARG(vm_protect.set_maximum)) {
5603             // GrP fixme mprotect max
5604             VG_(printf)("UNKNOWN vm_protect set maximum");
5605            //VG_(mprotect_max_range)(start, end-start, prot);
5606         } else {
5607            ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
5608            VG_(di_notify_vm_protect)(start, end-start, prot);
5609         }
5610      }
5611   } else {
5612      PRINT("mig return %d", reply->RetCode);
5613   }
5614}
5615
5616
5617PRE(vm_inherit)
5618{
5619#pragma pack(4)
5620   typedef struct {
5621      mach_msg_header_t Head;
5622      NDR_record_t NDR;
5623      vm_address_t address;
5624      vm_size_t size;
5625      vm_inherit_t new_inheritance;
5626   } Request;
5627#pragma pack()
5628
5629   Request *req = (Request *)ARG1;
5630
5631   PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
5632         name_for_port(MACH_REMOTE),
5633         (ULong)req->address, (ULong)req->size,
5634         req->new_inheritance);
5635
5636   AFTER = POST_FN(vm_inherit);
5637}
5638
5639POST(vm_inherit)
5640{
5641#pragma pack(4)
5642   typedef struct {
5643      mach_msg_header_t Head;
5644      NDR_record_t NDR;
5645      kern_return_t RetCode;
5646      mach_msg_trailer_t trailer;
5647   } Reply;
5648#pragma pack()
5649
5650   Reply *reply = (Reply *)ARG1;
5651
5652   if (!reply->RetCode) {
5653      if (MACH_REMOTE == vg_task_port) {
5654         // GrP fixme do something?
5655      }
5656   } else {
5657      PRINT("mig return %d", reply->RetCode);
5658   }
5659}
5660
5661
5662PRE(vm_read)
5663{
5664#pragma pack(4)
5665   typedef struct {
5666      mach_msg_header_t Head;
5667      NDR_record_t NDR;
5668      vm_address_t address;
5669      vm_size_t size;
5670   } Request;
5671#pragma pack()
5672
5673   Request *req = (Request *)ARG1;
5674
5675   PRINT("vm_read(from %s at %#llx size %llu)",
5676         name_for_port(MACH_REMOTE),
5677         (ULong)req->address, (ULong)req->size);
5678
5679   MACH_ARG(vm_read.addr) = req->address;
5680   MACH_ARG(vm_read.size) = req->size;
5681
5682   AFTER = POST_FN(vm_read);
5683}
5684
5685POST(vm_read)
5686{
5687#pragma pack(4)
5688   typedef struct {
5689      mach_msg_header_t Head;
5690      /* start of the kernel processed data */
5691      mach_msg_body_t msgh_body;
5692      mach_msg_ool_descriptor_t data;
5693      /* end of the kernel processed data */
5694      NDR_record_t NDR;
5695      mach_msg_type_number_t dataCnt;
5696   } Reply;
5697#pragma pack()
5698
5699   // Reply *reply = (Reply *)ARG1;
5700
5701   if (MACH_REMOTE == vg_task_port) {
5702      // vm_read from self
5703      // GrP fixme copy initialized state
5704   }
5705}
5706
5707
5708
5709PRE(mach_vm_read)
5710{
5711#pragma pack(4)
5712   typedef struct {
5713      mach_msg_header_t Head;
5714      NDR_record_t NDR;
5715      mach_vm_address_t address;
5716      mach_vm_size_t size;
5717   } Request;
5718#pragma pack()
5719
5720   Request *req = (Request *)ARG1;
5721
5722   PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
5723         name_for_port(MACH_REMOTE), req->address, req->size);
5724
5725   MACH_ARG(mach_vm_read.addr) = req->address;
5726   MACH_ARG(mach_vm_read.size) = req->size;
5727
5728   AFTER = POST_FN(mach_vm_read);
5729}
5730
5731POST(mach_vm_read)
5732{
5733#pragma pack(4)
5734   typedef struct {
5735      mach_msg_header_t Head;
5736      /* start of the kernel processed data */
5737      mach_msg_body_t msgh_body;
5738      mach_msg_ool_descriptor_t data;
5739      /* end of the kernel processed data */
5740      NDR_record_t NDR;
5741      mach_msg_type_number_t dataCnt;
5742   } Reply;
5743#pragma pack()
5744
5745   // Reply *reply = (Reply *)ARG1;
5746
5747   if (MACH_REMOTE == vg_task_port) {
5748      // vm_read from self
5749      // GrP fixme copy initialized state
5750   }
5751}
5752
5753
5754PRE(vm_read_overwrite)
5755{
5756#pragma pack(4)
5757   typedef struct {
5758      mach_msg_header_t Head;
5759      NDR_record_t NDR;
5760      vm_address_t address;
5761      vm_size_t size;
5762      vm_address_t data;
5763   } Request;
5764#pragma pack()
5765
5766   Request *req = (Request *)ARG1;
5767
5768   PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
5769         name_for_port(MACH_REMOTE),
5770         (ULong)req->address, (ULong)req->size, (ULong)req->data);
5771
5772   MACH_ARG(vm_read_overwrite.addr) = req->address;
5773   MACH_ARG(vm_read_overwrite.size) = req->size;
5774   MACH_ARG(vm_read_overwrite.data) = req->data;
5775
5776   PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
5777
5778   AFTER = POST_FN(vm_read_overwrite);
5779}
5780
5781POST(vm_read_overwrite)
5782{
5783#pragma pack(4)
5784   typedef struct {
5785      mach_msg_header_t Head;
5786      NDR_record_t NDR;
5787      kern_return_t RetCode;
5788      vm_size_t outsize;
5789   } Reply;
5790#pragma pack()
5791
5792   Reply *reply = (Reply *)ARG1;
5793
5794   if (reply->RetCode) {
5795       PRINT("mig return %d", reply->RetCode);
5796   } else {
5797      PRINT("read %llu bytes", (unsigned long long)reply->outsize);
5798      if (MACH_REMOTE == vg_task_port) {
5799         // vm_read_overwrite from self
5800         // GrP fixme copy initialized state
5801         POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5802      } else {
5803         // vm_read_overwrite from remote
5804         POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
5805      }
5806   }
5807}
5808
5809
5810PRE(vm_copy)
5811{
5812#pragma pack(4)
5813   typedef struct {
5814      mach_msg_header_t Head;
5815      NDR_record_t NDR;
5816      vm_address_t source_address;
5817      vm_size_t size;
5818      vm_address_t dest_address;
5819   } Request;
5820#pragma pack()
5821
5822   Request *req = (Request *)ARG1;
5823
5824   PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
5825         name_for_port(MACH_REMOTE),
5826         (ULong)req->source_address,
5827         (ULong)req->size, (ULong)req->dest_address);
5828
5829   MACH_ARG(vm_copy.src) = req->source_address;
5830   MACH_ARG(vm_copy.dst) = req->dest_address;
5831   MACH_ARG(vm_copy.size) = req->size;
5832
5833   AFTER = POST_FN(vm_copy);
5834}
5835
5836POST(vm_copy)
5837{
5838#pragma pack(4)
5839   typedef struct {
5840      mach_msg_header_t Head;
5841      NDR_record_t NDR;
5842      kern_return_t RetCode;
5843      mach_msg_trailer_t trailer;
5844   } Reply;
5845#pragma pack()
5846
5847   Reply *reply = (Reply *)ARG1;
5848
5849   if (!reply->RetCode) {
5850      if (MACH_REMOTE == vg_task_port) {
5851         // GrP fixme set dst's initialization equal to src's
5852         // and wipe any symbols or translations in dst
5853      }
5854   } else {
5855      PRINT("mig return %d", reply->RetCode);
5856   }
5857}
5858
5859
5860PRE(vm_map)
5861{
5862#pragma pack(4)
5863   typedef struct {
5864      mach_msg_header_t Head;
5865      /* start of the kernel processed data */
5866      mach_msg_body_t msgh_body;
5867      mach_msg_port_descriptor_t object;
5868      /* end of the kernel processed data */
5869      NDR_record_t NDR;
5870      vm_address_t address;
5871      vm_size_t size;
5872      vm_address_t mask;
5873      int flags;
5874      vm_offset_t offset;
5875      boolean_t copy;
5876      vm_prot_t cur_protection;
5877      vm_prot_t max_protection;
5878      vm_inherit_t inheritance;
5879   } Request;
5880#pragma pack()
5881
5882   Request *req = (Request *)ARG1;
5883
5884   // GrP fixme check these
5885   PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)",
5886         name_for_port(MACH_REMOTE),
5887         (ULong)req->address, (ULong)req->size,
5888         name_for_port(req->object.name));
5889
5890   MACH_ARG(vm_map.size) = req->size;
5891   MACH_ARG(vm_map.copy) = req->copy;
5892   MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
5893
5894   AFTER = POST_FN(vm_map);
5895}
5896
5897POST(vm_map)
5898{
5899#pragma pack(4)
5900   typedef struct {
5901      mach_msg_header_t Head;
5902      NDR_record_t NDR;
5903      kern_return_t RetCode;
5904      vm_address_t address;
5905      mach_msg_trailer_t trailer;
5906   } Reply;
5907#pragma pack()
5908
5909   Reply *reply = (Reply *)ARG1;
5910
5911   if (!reply->RetCode) {
5912      // GrP fixme check src and dest tasks
5913     PRINT("mapped at %#llx", (ULong)reply->address);
5914      // GrP fixme max prot
5915      ML_(notify_core_and_tool_of_mmap)(
5916            reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
5917            MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
5918      // GrP fixme VKI_MAP_PRIVATE if !copy?
5919   } else {
5920      PRINT("mig return %d", reply->RetCode);
5921   }
5922}
5923
5924
5925PRE(vm_remap)
5926{
5927#pragma pack(4)
5928   typedef struct {
5929      mach_msg_header_t Head;
5930      /* start of the kernel processed data */
5931      mach_msg_body_t msgh_body;
5932      mach_msg_port_descriptor_t src_task;
5933      /* end of the kernel processed data */
5934      NDR_record_t NDR;
5935      vm_address_t target_address;
5936      vm_size_t size;
5937      vm_address_t mask;
5938      boolean_t anywhere;
5939      vm_address_t src_address;
5940      boolean_t copy;
5941      vm_inherit_t inheritance;
5942   } Request;
5943#pragma pack()
5944
5945   Request *req = (Request *)ARG1;
5946
5947   // GrP fixme check src and dest tasks
5948
5949   if (VG_(clo_trace_syscalls)) {
5950      mach_port_name_t source_task = req->src_task.name;
5951      if (source_task == mach_task_self()) {
5952         PRINT("vm_remap(mach_task_self(), "
5953               "to %#llx size %lld, from mach_task_self() at %#llx, ...)",
5954               (ULong)req->target_address,
5955               (ULong)req->size, (ULong)req->src_address);
5956      } else {
5957         PRINT("vm_remap(mach_task_self(), "
5958               "to %#llx size %lld, from task %u at %#llx, ...)",
5959               (ULong)req->target_address, (ULong)req->size,
5960               source_task, (ULong)req->src_address);
5961      }
5962   }
5963
5964   // arg1 is task
5965   // vt->syscall_arg2 = req->target_address;
5966   MACH_ARG(vm_remap.size) = req->size;
5967   // vt->syscall_arg4 = req->copy;
5968
5969   AFTER = POST_FN(vm_remap);
5970}
5971
5972POST(vm_remap)
5973{
5974#pragma pack(4)
5975   typedef struct {
5976      mach_msg_header_t Head;
5977      NDR_record_t NDR;
5978      kern_return_t RetCode;
5979      vm_address_t target_address;
5980      vm_prot_t cur_protection;
5981      vm_prot_t max_protection;
5982      mach_msg_trailer_t trailer;
5983   } Reply;
5984#pragma pack()
5985
5986   Reply *reply = (Reply *)ARG1;
5987
5988   if (!reply->RetCode) {
5989      // GrP fixme check src and dest tasks
5990      UInt prot = reply->cur_protection & reply->max_protection;
5991      // GrP fixme max prot
5992      PRINT("mapped at %#llx", (ULong)reply->target_address);
5993      ML_(notify_core_and_tool_of_mmap)(
5994            reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
5995            prot, VKI_MAP_SHARED, -1, 0);
5996      // GrP fixme VKI_MAP_FIXED if !copy?
5997      // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
5998   } else {
5999      PRINT("mig return %d", reply->RetCode);
6000   }
6001}
6002
6003
6004PRE(mach_make_memory_entry_64)
6005{
6006#pragma pack(4)
6007   typedef struct {
6008      mach_msg_header_t Head;
6009      /* start of the kernel processed data */
6010      mach_msg_body_t msgh_body;
6011      mach_msg_port_descriptor_t parent_entry;
6012      /* end of the kernel processed data */
6013      NDR_record_t NDR;
6014      memory_object_size_t size;
6015      memory_object_offset_t offset;
6016      vm_prot_t permission;
6017   } Request;
6018#pragma pack()
6019
6020   Request *req = (Request *)ARG1;
6021
6022   PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6023         name_for_port(MACH_REMOTE),
6024         req->size, req->offset, req->permission, req->parent_entry.type);
6025
6026   AFTER = POST_FN(mach_make_memory_entry_64);
6027}
6028
6029POST(mach_make_memory_entry_64)
6030{
6031#pragma pack(4)
6032   typedef struct {
6033      mach_msg_header_t Head;
6034      mach_msg_body_t msgh_body;
6035      mach_msg_port_descriptor_t object;
6036      NDR_record_t NDR;
6037      memory_object_size_t size;
6038   } Reply;
6039#pragma pack()
6040
6041   Reply *reply = (Reply *)ARG1;
6042
6043   if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6044      assign_port_name(reply->object.name, "memory-%p");
6045      PRINT("%s", name_for_port(reply->object.name));
6046   }
6047}
6048
6049
6050PRE(vm_purgable_control)
6051{
6052#pragma pack(4)
6053   typedef struct {
6054      mach_msg_header_t Head;
6055      NDR_record_t NDR;
6056      vm_address_t address;
6057      vm_purgable_t control;
6058      int state;
6059   } Request;
6060#pragma pack()
6061
6062   Request *req = (Request *)ARG1;
6063
6064   PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
6065         name_for_port(MACH_REMOTE),
6066         (ULong)req->address, req->control, req->state);
6067
6068   // GrP fixme verify address?
6069
6070   AFTER = POST_FN(vm_purgable_control);
6071}
6072
6073POST(vm_purgable_control)
6074{
6075#pragma pack(4)
6076   typedef struct {
6077      mach_msg_header_t Head;
6078      NDR_record_t NDR;
6079      kern_return_t RetCode;
6080      int state;
6081   } Reply;
6082#pragma pack()
6083
6084   Reply *reply = (Reply *)ARG1;
6085
6086   if (!reply->RetCode) {
6087   } else {
6088      PRINT("mig return %d", reply->RetCode);
6089   }
6090}
6091
6092
6093PRE(mach_vm_purgable_control)
6094{
6095#pragma pack(4)
6096   typedef struct {
6097      mach_msg_header_t Head;
6098      NDR_record_t NDR;
6099      mach_vm_address_t address;
6100      vm_purgable_t control;
6101      int state;
6102   } Request;
6103#pragma pack()
6104
6105   Request *req = (Request *)ARG1;
6106
6107   PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
6108         name_for_port(MACH_REMOTE),
6109         (unsigned long long)req->address, req->control, req->state);
6110
6111   // GrP fixme verify address?
6112
6113   AFTER = POST_FN(mach_vm_purgable_control);
6114}
6115
6116POST(mach_vm_purgable_control)
6117{
6118#pragma pack(4)
6119   typedef struct {
6120      mach_msg_header_t Head;
6121      NDR_record_t NDR;
6122      kern_return_t RetCode;
6123      int state;
6124   } Reply;
6125#pragma pack()
6126
6127   Reply *reply = (Reply *)ARG1;
6128
6129   if (!reply->RetCode) {
6130   } else {
6131      PRINT("mig return %d", reply->RetCode);
6132   }
6133}
6134
6135
6136PRE(mach_vm_allocate)
6137{
6138#pragma pack(4)
6139   typedef struct {
6140      mach_msg_header_t Head;
6141      NDR_record_t NDR;
6142      mach_vm_address_t address;
6143      mach_vm_size_t size;
6144      int flags;
6145   } Request;
6146#pragma pack()
6147
6148   Request *req = (Request *)ARG1;
6149
6150   PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
6151         name_for_port(MACH_REMOTE),
6152         req->address, req->size, req->flags);
6153
6154   MACH_ARG(mach_vm_allocate.size) = req->size;
6155   MACH_ARG(mach_vm_allocate.flags) = req->flags;
6156
6157   AFTER = POST_FN(mach_vm_allocate);
6158}
6159
6160POST(mach_vm_allocate)
6161{
6162#pragma pack(4)
6163   typedef struct {
6164      mach_msg_header_t Head;
6165      NDR_record_t NDR;
6166      kern_return_t RetCode;
6167      mach_vm_address_t address;
6168      mach_msg_trailer_t trailer;
6169   } Reply;
6170#pragma pack()
6171
6172   Reply *reply = (Reply *)ARG1;
6173
6174   if (!reply->RetCode) {
6175      if (MACH_REMOTE == vg_task_port) {
6176         PRINT("allocated at 0x%llx", reply->address);
6177         // requesting 0 bytes returns address 0 with no error
6178         if (MACH_ARG(mach_vm_allocate.size)) {
6179            ML_(notify_core_and_tool_of_mmap)(
6180                  reply->address, MACH_ARG(mach_vm_allocate.size),
6181                  VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6182         }
6183      } else {
6184         PRINT("allocated at 0x%llx in remote task %s", reply->address,
6185               name_for_port(MACH_REMOTE));
6186      }
6187   } else {
6188      PRINT("mig return %d", reply->RetCode);
6189   }
6190}
6191
6192
6193PRE(mach_vm_deallocate)
6194{
6195#pragma pack(4)
6196   typedef struct {
6197      mach_msg_header_t Head;
6198      NDR_record_t NDR;
6199      mach_vm_address_t address;
6200      mach_vm_size_t size;
6201   } Request;
6202#pragma pack()
6203
6204   Request *req = (Request *)ARG1;
6205
6206   PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
6207         name_for_port(MACH_REMOTE),
6208         req->address, req->size);
6209
6210   MACH_ARG(mach_vm_deallocate.address) = req->address;
6211   MACH_ARG(mach_vm_deallocate.size) = req->size;
6212
6213   AFTER = POST_FN(mach_vm_deallocate);
6214
6215   // Must block to prevent race (other thread allocates and
6216   // notifies after we deallocate but before we notify)
6217   *flags &= ~SfMayBlock;
6218}
6219
6220POST(mach_vm_deallocate)
6221{
6222#pragma pack(4)
6223   typedef struct {
6224      mach_msg_header_t Head;
6225      NDR_record_t NDR;
6226      kern_return_t RetCode;
6227      mach_msg_trailer_t trailer;
6228   } Reply;
6229#pragma pack()
6230
6231   Reply *reply = (Reply *)ARG1;
6232
6233   if (!reply->RetCode) {
6234      if (MACH_REMOTE == vg_task_port) {
6235         if (MACH_ARG(mach_vm_deallocate.size)) {
6236            Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
6237            Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
6238                                    MACH_ARG(mach_vm_deallocate.size));
6239            // Must have cleared SfMayBlock in PRE to prevent race
6240            ML_(notify_core_and_tool_of_munmap)(start, end - start);
6241         }
6242      }
6243   } else {
6244      PRINT("mig return %d", reply->RetCode);
6245   }
6246}
6247
6248
6249PRE(mach_vm_protect)
6250{
6251#pragma pack(4)
6252   typedef struct {
6253      mach_msg_header_t Head;
6254      NDR_record_t NDR;
6255      mach_vm_address_t address;
6256      mach_vm_size_t size;
6257      boolean_t set_maximum;
6258      vm_prot_t new_protection;
6259   } Request;
6260#pragma pack()
6261
6262   Request *req = (Request *)ARG1;
6263
6264   PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
6265         name_for_port(MACH_REMOTE), req->address, req->size,
6266         req->set_maximum, req->new_protection);
6267
6268   MACH_ARG(mach_vm_protect.address) = req->address;
6269   MACH_ARG(mach_vm_protect.size) = req->size;
6270   MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
6271   MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
6272
6273   AFTER = POST_FN(mach_vm_protect);
6274}
6275
6276POST(mach_vm_protect)
6277{
6278#pragma pack(4)
6279   typedef struct {
6280      mach_msg_header_t Head;
6281      NDR_record_t NDR;
6282      kern_return_t RetCode;
6283      mach_msg_trailer_t trailer;
6284   } Reply;
6285#pragma pack()
6286
6287   Reply *reply = (Reply *)ARG1;
6288
6289   if (!reply->RetCode) {
6290      if (MACH_REMOTE == vg_task_port) {
6291         Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
6292         Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
6293                                 MACH_ARG(mach_vm_protect.size));
6294         UInt prot = MACH_ARG(mach_vm_protect.new_protection);
6295         if (MACH_ARG(mach_vm_protect.set_maximum)) {
6296            // DDD: #warning GrP fixme mprotect max
6297            //VG_(mprotect_max_range)(start, end-start, prot);
6298         } else {
6299            ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6300         }
6301      }
6302   } else {
6303      PRINT("mig return %d", reply->RetCode);
6304   }
6305}
6306
6307
6308PRE(mach_vm_inherit)
6309{
6310#pragma pack(4)
6311   typedef struct {
6312      mach_msg_header_t Head;
6313      NDR_record_t NDR;
6314      mach_vm_address_t address;
6315      mach_vm_size_t size;
6316      vm_inherit_t new_inheritance;
6317   } Request;
6318#pragma pack()
6319
6320   Request *req = (Request *)ARG1;
6321
6322   PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
6323         name_for_port(MACH_REMOTE),
6324         req->address, req->size, req->new_inheritance);
6325
6326   AFTER = POST_FN(mach_vm_inherit);
6327}
6328
6329POST(mach_vm_inherit)
6330{
6331#pragma pack(4)
6332   typedef struct {
6333      mach_msg_header_t Head;
6334      NDR_record_t NDR;
6335      kern_return_t RetCode;
6336      mach_msg_trailer_t trailer;
6337   } Reply;
6338#pragma pack()
6339
6340   Reply *reply = (Reply *)ARG1;
6341
6342   if (!reply->RetCode) {
6343      // no V-visible side effects
6344      // GrP fixme except maybe fork/exec
6345   } else {
6346      PRINT("mig return %d", reply->RetCode);
6347   }
6348}
6349
6350
6351PRE(mach_vm_copy)
6352{
6353#pragma pack(4)
6354   typedef struct {
6355      mach_msg_header_t Head;
6356      NDR_record_t NDR;
6357      mach_vm_address_t source_address;
6358      mach_vm_size_t size;
6359      mach_vm_address_t dest_address;
6360   } Request;
6361#pragma pack()
6362
6363   Request *req = (Request *)ARG1;
6364
6365   PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
6366         name_for_port(MACH_REMOTE),
6367         req->source_address, req->size, req->dest_address);
6368
6369   // arg1 is task
6370   // vt->syscall_arg2 = req->source_address;
6371   // vt->syscall_arg3 = req->size;
6372   // vt->syscall_arg4 = req->dest_address;
6373
6374   AFTER = POST_FN(mach_vm_copy);
6375}
6376
6377POST(mach_vm_copy)
6378{
6379#pragma pack(4)
6380   typedef struct {
6381      mach_msg_header_t Head;
6382      NDR_record_t NDR;
6383      kern_return_t RetCode;
6384      mach_msg_trailer_t trailer;
6385   } Reply;
6386#pragma pack()
6387
6388   Reply *reply = (Reply *)ARG1;
6389
6390   if (!reply->RetCode) {
6391      if (MACH_REMOTE == vg_task_port) {
6392         // GrP fixme set dest's initialization equal to src's
6393         // BUT vm_copy allocates no memory
6394      }
6395   } else {
6396      PRINT("mig return %d", reply->RetCode);
6397   }
6398}
6399
6400PRE(mach_vm_read_overwrite)
6401{
6402#pragma pack(4)
6403   typedef struct {
6404      mach_msg_header_t Head;
6405      NDR_record_t NDR;
6406      mach_vm_address_t address;
6407      mach_vm_size_t size;
6408      mach_vm_address_t data;
6409   } Request;
6410#pragma pack()
6411
6412   Request *req = (Request *)ARG1;
6413
6414   PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
6415         name_for_port(MACH_REMOTE),
6416         req->address, req->size, req->data);
6417
6418   AFTER = POST_FN(mach_vm_read_overwrite);
6419}
6420
6421POST(mach_vm_read_overwrite)
6422{
6423#pragma pack(4)
6424   typedef struct {
6425      mach_msg_header_t Head;
6426      NDR_record_t NDR;
6427      kern_return_t RetCode;
6428      mach_vm_size_t outsize;
6429   } Reply;
6430#pragma pack()
6431
6432   Reply *reply = (Reply *)ARG1;
6433
6434   if (!reply->RetCode) {
6435      if (MACH_REMOTE == vg_task_port) {
6436         // GrP fixme set dest's initialization equal to src's
6437         // BUT vm_copy allocates no memory
6438      }
6439   } else {
6440      PRINT("mig return %d", reply->RetCode);
6441   }
6442}
6443
6444PRE(mach_vm_map)
6445{
6446#pragma pack(4)
6447   typedef struct {
6448      mach_msg_header_t Head;
6449      /* start of the kernel processed data */
6450      mach_msg_body_t msgh_body;
6451      mach_msg_port_descriptor_t object;
6452      /* end of the kernel processed data */
6453      NDR_record_t NDR;
6454      mach_vm_address_t address;
6455      mach_vm_size_t size;
6456      mach_vm_address_t mask;
6457      int flags;
6458      memory_object_offset_t offset;
6459      boolean_t copy;
6460      vm_prot_t cur_protection;
6461      vm_prot_t max_protection;
6462      vm_inherit_t inheritance;
6463   } Request;
6464#pragma pack()
6465
6466   Request *req = (Request *)ARG1;
6467
6468   // GrP fixme check these
6469   PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
6470         name_for_port(req->Head.msgh_remote_port),
6471         name_for_port(req->object.name),
6472         req->address, req->size,
6473         req->cur_protection,
6474         req->max_protection);
6475
6476   MACH_ARG(mach_vm_map.size) = req->size;
6477   MACH_ARG(mach_vm_map.copy) = req->copy;
6478   MACH_ARG(mach_vm_map.protection) =
6479      (req->cur_protection & req->max_protection);
6480
6481   AFTER = POST_FN(mach_vm_map);
6482}
6483
6484POST(mach_vm_map)
6485{
6486#pragma pack(4)
6487   typedef struct {
6488      mach_msg_header_t Head;
6489      NDR_record_t NDR;
6490      kern_return_t RetCode;
6491      mach_vm_address_t address;
6492      mach_msg_trailer_t trailer;
6493   } Reply;
6494#pragma pack()
6495
6496   Reply *reply = (Reply *)ARG1;
6497
6498   if (!reply->RetCode) {
6499      // GrP fixme check src and dest tasks
6500      PRINT("mapped at 0x%llx", reply->address);
6501      // GrP fixme max prot
6502      ML_(notify_core_and_tool_of_mmap)(
6503            reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
6504            MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
6505      // GrP fixme VKI_MAP_PRIVATE if !copy?
6506   } else {
6507      PRINT("mig return %d", reply->RetCode);
6508   }
6509}
6510
6511
6512PRE(mach_vm_remap)
6513{
6514#pragma pack(4)
6515   typedef struct {
6516      mach_msg_header_t Head;
6517      /* start of the kernel processed data */
6518      mach_msg_body_t msgh_body;
6519      mach_msg_port_descriptor_t src_task;
6520      /* end of the kernel processed data */
6521      NDR_record_t NDR;
6522      mach_vm_address_t target_address;
6523      mach_vm_size_t size;
6524      mach_vm_offset_t mask;
6525      int flags;
6526      mach_vm_address_t src_address;
6527      boolean_t copy;
6528      vm_inherit_t inheritance;
6529   } Request;
6530#pragma pack()
6531
6532   Request *req = (Request *)ARG1;
6533
6534   // GrP fixme check these
6535   PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
6536         name_for_port(MACH_REMOTE),
6537         req->target_address, req->size,
6538         name_for_port(req->src_task.name));
6539
6540   MACH_ARG(mach_vm_remap.size) = req->size;
6541   MACH_ARG(mach_vm_remap.copy) = req->copy;
6542
6543   AFTER = POST_FN(mach_vm_remap);
6544}
6545
6546POST(mach_vm_remap)
6547{
6548#pragma pack(4)
6549   typedef struct {
6550      mach_msg_header_t Head;
6551      NDR_record_t NDR;
6552      kern_return_t RetCode;
6553      mach_vm_address_t target_address;
6554      vm_prot_t cur_protection;
6555      vm_prot_t max_protection;
6556   } Reply;
6557#pragma pack()
6558
6559   Reply *reply = (Reply *)ARG1;
6560
6561   if (!reply->RetCode) {
6562      // GrP fixme check src and dest tasks
6563      PRINT("mapped at 0x%llx", reply->target_address);
6564      // GrP fixme max prot
6565      ML_(notify_core_and_tool_of_mmap)(
6566            reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
6567            reply->cur_protection, VKI_MAP_SHARED, -1, 0);
6568      // GrP fixme VKI_MAP_PRIVATE if !copy?
6569   } else {
6570      PRINT("mig return %d", reply->RetCode);
6571   }
6572}
6573
6574
6575PRE(mach_vm_region_recurse)
6576{
6577#pragma pack(4)
6578   typedef struct {
6579      mach_msg_header_t Head;
6580      NDR_record_t NDR;
6581      mach_vm_address_t address;
6582      natural_t nesting_depth;
6583      mach_msg_type_number_t infoCnt;
6584   } Request;
6585#pragma pack()
6586
6587   Request *req = (Request *)ARG1;
6588
6589   PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
6590         name_for_port(MACH_REMOTE),
6591         req->address, req->nesting_depth, req->infoCnt);
6592
6593   AFTER = POST_FN(mach_vm_region_recurse);
6594}
6595
6596POST(mach_vm_region_recurse)
6597{
6598#pragma pack(4)
6599   typedef struct {
6600      mach_msg_header_t Head;
6601      NDR_record_t NDR;
6602      kern_return_t RetCode;
6603      mach_vm_address_t address;
6604      mach_vm_size_t size;
6605      natural_t nesting_depth;
6606      mach_msg_type_number_t infoCnt;
6607      int info[19];
6608   } Reply;
6609#pragma pack()
6610
6611   Reply *reply = (Reply *)ARG1;
6612
6613   if (!reply->RetCode) {
6614       PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
6615             reply->address, reply->size,
6616             reply->nesting_depth, reply->infoCnt);
6617       // GrP fixme mark info contents beyond infoCnt as bogus
6618   } else {
6619      PRINT("mig return %d", reply->RetCode);
6620   }
6621}
6622
6623
6624/* ---------------------------------------------------------------------
6625   mach_msg: messages to thread
6626   ------------------------------------------------------------------ */
6627
6628
6629
6630POST(thread_terminate)
6631{
6632}
6633
6634
6635PRE(thread_terminate)
6636{
6637   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6638   Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
6639
6640   PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
6641
6642   AFTER = POST_FN(thread_terminate);
6643
6644   if (self_terminate) {
6645      // Terminating this thread.
6646      // Copied from sys_exit.
6647      ThreadState *tst = VG_(get_ThreadState)(tid);
6648      tst->exitreason = VgSrc_ExitThread;
6649      tst->os_state.exitcode = 0;  // GrP fixme anything better?
6650      // What we would like to do is:
6651      //   SET_STATUS_Success(0);
6652      // but that doesn't work, because this is a MACH-class syscall,
6653      // and SET_STATUS_Success creates a UNIX-class syscall result.
6654      // Hence we have to laboriously construct the full SysRes "by hand"
6655      // and use that to set the syscall return status.
6656      SET_STATUS_from_SysRes(
6657         VG_(mk_SysRes_x86_darwin)(
6658            VG_DARWIN_SYSCALL_CLASS_MACH,
6659            False/*success*/, 0, 0
6660         )
6661      );
6662      *flags &= ~SfMayBlock;  // clear flag set by PRE(mach_msg)
6663   } else {
6664      // Terminating some other thread.
6665      // Do keep the scheduler lock while terminating any other thread.
6666      // Otherwise we might halt the other thread while it holds the lock,
6667      // which would deadlock the process.
6668      // GrP fixme good enough?
6669      // GrP fixme need to clean up other thread's valgrind data?
6670   }
6671}
6672
6673
6674POST(thread_create)
6675{
6676}
6677
6678
6679PRE(thread_create)
6680{
6681   PRINT("thread_create(mach_task_self(), ...)");
6682
6683   AFTER = POST_FN(thread_create);
6684
6685   // GrP fixme
6686   VG_(core_panic)("thread_create() unimplemented");
6687}
6688
6689
6690PRE(thread_create_running)
6691{
6692#pragma pack(4)
6693   typedef struct {
6694      mach_msg_header_t Head;
6695      NDR_record_t NDR;
6696      thread_state_flavor_t flavor;
6697      mach_msg_type_number_t new_stateCnt;
6698      natural_t new_state[144];
6699   } Request;
6700#pragma pack()
6701
6702   Request *req;
6703   thread_state_t regs;
6704   ThreadState *new_thread;
6705
6706   PRINT("thread_create_running(mach_task_self(), ...)");
6707
6708   // The new thread will immediately begin execution,
6709   // so we need to hijack the register state here.
6710
6711   req = (Request *)ARG1;
6712   regs = (thread_state_t)req->new_state;
6713
6714   // Build virtual thread.
6715   new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
6716
6717   // Edit the thread state to send to the real kernel.
6718   hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
6719
6720   AFTER = POST_FN(thread_create_running);
6721}
6722
6723
6724POST(thread_create_running)
6725{
6726#pragma pack(4)
6727   typedef struct {
6728      mach_msg_header_t Head;
6729      /* start of the kernel processed data */
6730      mach_msg_body_t msgh_body;
6731      mach_msg_port_descriptor_t child_act;
6732      /* end of the kernel processed data */
6733   } Reply;
6734#pragma pack()
6735
6736   Reply *reply = (Reply *)ARG1;
6737
6738   assign_port_name(reply->child_act.name, "thread-%p");
6739   PRINT("%s", name_for_port(reply->child_act.name));
6740}
6741
6742
6743PRE(bsdthread_create)
6744{
6745   ThreadState *tst;
6746
6747   PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
6748         ARG1, ARG2, ARG3, ARG4, ARG5);
6749   PRE_REG_READ5(pthread_t,"bsdthread_create",
6750                 void *,"func", void *,"func_arg", void *,"stack",
6751                 pthread_t,"thread", unsigned int,"flags");
6752
6753   // The kernel will call V's pthread_hijack() to launch the thread.
6754   // Here we allocate the thread state and pass it to pthread_hijack()
6755   // via the func_arg parameter.
6756
6757   tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
6758   allocstack(tst->tid);
6759
6760   tst->os_state.func_arg = (Addr)ARG2;
6761   ARG2 = (Word)tst;
6762
6763   // Create a semaphore that pthread_hijack will signal once it starts
6764   // POST(bsdthread_create) needs to wait for the new memory map to appear
6765   semaphore_create(mach_task_self(), &tst->os_state.child_go,
6766                    SYNC_POLICY_FIFO, 0);
6767   semaphore_create(mach_task_self(), &tst->os_state.child_done,
6768                    SYNC_POLICY_FIFO, 0);
6769}
6770
6771POST(bsdthread_create)
6772{
6773   // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
6774   // We hold V's lock on the child's behalf.
6775   // If we return before letting pthread_hijack do its thing, V thinks
6776   // the new pthread struct is still unmapped when we return to libc,
6777   // causing false errors.
6778
6779   ThreadState *tst = (ThreadState *)ARG2;
6780   semaphore_signal(tst->os_state.child_go);
6781   semaphore_wait(tst->os_state.child_done);
6782   semaphore_destroy(mach_task_self(), tst->os_state.child_go);
6783   semaphore_destroy(mach_task_self(), tst->os_state.child_done);
6784
6785   // GrP fixme semaphore destroy needed when thread creation fails
6786   // GrP fixme probably other cleanup too
6787   // GrP fixme spinlocks might be good enough?
6788
6789   // DDD: I'm not at all sure this is the right spot for this.  It probably
6790   // should be in pthread_hijack instead, just before the call to
6791   // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
6792   // parent tid value there...
6793   vg_assert(VG_(owns_BigLock_LL)(tid));
6794   VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
6795}
6796
6797
6798PRE(bsdthread_terminate)
6799{
6800   ThreadState *tst;
6801
6802   PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
6803         ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
6804   PRE_REG_READ4(int,"bsdthread_terminate",
6805                 void *,"freeaddr", size_t,"freesize",
6806                 mach_port_t,"kport", mach_port_t,"joinsem");
6807
6808   // Free memory and signal semaphore.
6809   // GrP fixme errors?
6810   if (ARG4) semaphore_signal((semaphore_t)ARG4);
6811   if (ARG1  &&  ARG2) {
6812       ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
6813#      if DARWIN_VERS >= DARWIN_10_8
6814       /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
6815          the mig output.  Work around it for the time being. */
6816       VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
6817#      else
6818       vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
6819#      endif
6820   }
6821
6822   // Tell V to terminate the thread.
6823   // Copied from sys_exit.
6824   tst = VG_(get_ThreadState)(tid);
6825   tst->exitreason = VgSrc_ExitThread;
6826   tst->os_state.exitcode = 0;  // GrP fixme anything better?
6827   SET_STATUS_Success(0);
6828}
6829
6830
6831POST(thread_suspend)
6832{
6833}
6834
6835PRE(thread_suspend)
6836{
6837   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6838   Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
6839
6840   PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
6841
6842   AFTER = POST_FN(thread_suspend);
6843
6844   if (self_suspend) {
6845       // Don't keep the scheduler lock while self-suspending.
6846       // Otherwise we might halt while still holding the lock,
6847       // which would deadlock the process.
6848       *flags |= SfMayBlock;
6849   } else {
6850       // Do keep the scheduler lock while suspending any other thread.
6851       // Otherwise we might halt the other thread while it holds the lock,
6852       // which would deadlock the process.
6853   }
6854}
6855
6856
6857POST(thread_get_state)
6858{
6859#pragma pack(4)
6860   typedef struct {
6861      mach_msg_header_t Head;
6862      NDR_record_t NDR;
6863      kern_return_t RetCode;
6864      mach_msg_type_number_t old_stateCnt;
6865      natural_t old_state[144];
6866      mach_msg_trailer_t trailer;
6867   } Reply;
6868#pragma pack()
6869
6870   Reply *reply = (Reply *)ARG1;
6871   // mach_port_t thread = MACH_ARG(thread_get_state.thread);
6872   thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
6873
6874   if (!reply->RetCode) {
6875      thread_state_from_vex((thread_state_t)reply->old_state,
6876                             flavor, reply->old_stateCnt,
6877                             &VG_(get_ThreadState)(tid)->arch.vex);
6878   } else {
6879      PRINT("mig return %d", reply->RetCode);
6880   }
6881}
6882
6883PRE(thread_get_state)
6884{
6885#pragma pack(4)
6886   typedef struct {
6887      mach_msg_header_t Head;
6888      NDR_record_t NDR;
6889      thread_state_flavor_t flavor;
6890      mach_msg_type_number_t old_stateCnt;
6891   } Request;
6892#pragma pack()
6893
6894   Request *req = (Request *)ARG1;
6895   // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
6896
6897   // GrP fixme   if (self) {
6898   PRINT("thread_get_state(%s, %d)",
6899         name_for_port(req->Head.msgh_request_port), req->flavor);
6900       /*} else {
6901       PRINT("thread_get_state(0x%x, %d)",
6902             req->Head.msgh_request_port, req->flavor);
6903             }*/
6904
6905   // Hack the thread state after making the real call.
6906   MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
6907   MACH_ARG(thread_get_state.flavor) = req->flavor;
6908
6909   AFTER = POST_FN(thread_get_state);
6910}
6911
6912
6913PRE(thread_policy)
6914{
6915   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6916   // Bool self = (mh->msgh_request_port == MACH_THREAD);
6917
6918   // GrP fixme   if (self) {
6919      PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
6920      /*} else {
6921      PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
6922      }*/
6923
6924   AFTER = POST_FN(thread_policy);
6925}
6926
6927POST(thread_policy)
6928{
6929}
6930
6931
6932PRE(thread_policy_set)
6933{
6934   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6935
6936   PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
6937
6938   AFTER = POST_FN(thread_policy_set);
6939}
6940
6941POST(thread_policy_set)
6942{
6943}
6944
6945
6946PRE(thread_info)
6947{
6948   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
6949
6950   PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
6951   // GrP fixme does any thread info need to be hijacked?
6952
6953   AFTER = POST_FN(thread_info);
6954}
6955
6956POST(thread_info)
6957{
6958   // GrP fixme mark unused parts of thread_info_out as uninitialized?
6959}
6960
6961
6962
6963/* ---------------------------------------------------------------------
6964   mach_msg: messages to bootstrap port
6965   ------------------------------------------------------------------ */
6966
6967
6968POST(bootstrap_register)
6969{
6970#pragma pack(4)
6971   typedef struct {
6972      mach_msg_header_t Head;
6973      NDR_record_t NDR;
6974      kern_return_t RetCode;
6975      mach_msg_trailer_t trailer;
6976   } Reply;
6977#pragma pack()
6978
6979   Reply *reply = (Reply *)ARG1;
6980
6981   if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
6982}
6983
6984PRE(bootstrap_register)
6985{
6986#pragma pack(4)
6987   typedef struct {
6988      mach_msg_header_t Head;
6989      /* start of the kernel processed data */
6990      mach_msg_body_t msgh_body;
6991      mach_msg_port_descriptor_t service_port;
6992      /* end of the kernel processed data */
6993      NDR_record_t NDR;
6994      name_t service_name;
6995   } Request;
6996#pragma pack()
6997
6998   Request *req = (Request *)ARG1;
6999
7000   PRINT("bootstrap_register(port 0x%x, \"%s\")",
7001         req->service_port.name, req->service_name);
7002
7003   /* The required entry in the allocated_ports list (mapping) might
7004      not exist, due perhaps to broken syscall wrappers (mach__N etc).
7005      Create a minimal entry so that assign_port_name below doesn't
7006      cause an assertion. */
7007   if (!port_exists(req->service_port.name)) {
7008      port_create_vanilla(req->service_port.name);
7009   }
7010
7011   assign_port_name(req->service_port.name, req->service_name);
7012
7013   AFTER = POST_FN(bootstrap_register);
7014}
7015
7016
7017POST(bootstrap_look_up)
7018{
7019#pragma pack(4)
7020   typedef struct {
7021      mach_msg_header_t Head;
7022      /* start of the kernel processed data */
7023      mach_msg_body_t msgh_body;
7024      mach_msg_port_descriptor_t service_port;
7025      /* end of the kernel processed data */
7026      mach_msg_trailer_t trailer;
7027   } Reply;
7028#pragma pack()
7029
7030   Reply *reply = (Reply *)ARG1;
7031
7032   if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)  &&
7033       reply->service_port.name)
7034   {
7035       assign_port_name(reply->service_port.name,
7036                        MACH_ARG(bootstrap_look_up.service_name));
7037       PRINT("%s", name_for_port(reply->service_port.name));
7038   } else {
7039       PRINT("not found");
7040   }
7041   VG_(arena_free)(VG_AR_CORE, MACH_ARG(bootstrap_look_up.service_name));
7042}
7043
7044PRE(bootstrap_look_up)
7045{
7046#pragma pack(4)
7047   typedef struct {
7048      mach_msg_header_t Head;
7049      NDR_record_t NDR;
7050      name_t service_name;
7051   } Request;
7052#pragma pack()
7053
7054   Request *req = (Request *)ARG1;
7055
7056   PRINT("bootstrap_look_up(\"%s\")", req->service_name);
7057
7058   MACH_ARG(bootstrap_look_up.service_name) =
7059      VG_(arena_strdup)(VG_AR_CORE, "syswrap-darwin.bootstrap-name",
7060                        req->service_name);
7061
7062   AFTER = POST_FN(bootstrap_look_up);
7063}
7064
7065
7066/* ---------------------------------------------------------------------
7067   mach_msg: receiver-specific handlers
7068   ------------------------------------------------------------------ */
7069
7070
7071POST(mach_msg_receive)
7072{
7073   // mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7074
7075   // GrP fixme don't know of anything interesting here currently
7076   // import_complex_message handles everything
7077   // PRINT("UNHANDLED reply %d", mh->msgh_id);
7078
7079   // Assume the call may have mapped or unmapped memory
7080   ML_(sync_mappings)("after", "mach_msg_receive", 0);
7081}
7082
7083PRE(mach_msg_receive)
7084{
7085   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7086
7087   PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
7088
7089   AFTER = POST_FN(mach_msg_receive);
7090
7091   // no message sent, only listening for a reply
7092   // assume message may block
7093   *flags |= SfMayBlock;
7094}
7095
7096
7097PRE(mach_msg_bootstrap)
7098{
7099   // message to bootstrap port
7100
7101   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7102
7103   switch (mh->msgh_id) {
7104   case 403:
7105      CALL_PRE(bootstrap_register);
7106      return;
7107   case 404:
7108      CALL_PRE(bootstrap_look_up);
7109      return;
7110
7111   default:
7112      PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
7113            mh->msgh_id, name_for_port(mh->msgh_request_port),
7114            mh->msgh_reply_port);
7115      return;
7116   }
7117}
7118
7119
7120PRE(mach_msg_host)
7121{
7122   // message to host self - check for host-level kernel calls
7123
7124   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7125
7126   switch (mh->msgh_id) {
7127   case 200:
7128      CALL_PRE(host_info);
7129      return;
7130   case 202:
7131      CALL_PRE(host_page_size);
7132      return;
7133   case 205:
7134      CALL_PRE(host_get_io_master);
7135      return;
7136   case 206:
7137      CALL_PRE(host_get_clock_service);
7138      return;
7139   case 217:
7140      CALL_PRE(host_request_notification);
7141      return;
7142
7143   default:
7144      // unknown message to host self
7145      VG_(printf)("UNKNOWN host message [id %d, to %s, reply 0x%x]\n",
7146                  mh->msgh_id, name_for_port(mh->msgh_request_port),
7147                  mh->msgh_reply_port);
7148      return;
7149   }
7150}
7151
7152// JRS 2011-Aug-25: these magic numbers (3201 etc) come from
7153// /usr/include/mach/mach_port.h et al (grep in /usr/include
7154// for them)
7155PRE(mach_msg_task)
7156{
7157   // message to a task port
7158
7159   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7160
7161   switch (mh->msgh_id) {
7162   case 3201:
7163      CALL_PRE(mach_port_type);
7164      return;
7165   case 3204:
7166      CALL_PRE(mach_port_allocate);
7167      return;
7168   case 3205:
7169      CALL_PRE(mach_port_destroy);
7170      return;
7171   case 3206:
7172      CALL_PRE(mach_port_deallocate);
7173      return;
7174   case 3207:
7175      CALL_PRE(mach_port_get_refs);
7176      return;
7177   case 3208:
7178      CALL_PRE(mach_port_mod_refs);
7179      return;
7180   case 3211:
7181      CALL_PRE(mach_port_get_set_status);
7182      return;
7183   case 3212:
7184      CALL_PRE(mach_port_move_member);
7185      return;
7186   case 3213:
7187      CALL_PRE(mach_port_request_notification);
7188      return;
7189   case 3214:
7190      CALL_PRE(mach_port_insert_right);
7191      return;
7192   case 3215:
7193      CALL_PRE(mach_port_extract_right);
7194      return;
7195   case 3217:
7196      CALL_PRE(mach_port_get_attributes);
7197      return;
7198   case 3218:
7199      CALL_PRE(mach_port_set_attributes);
7200      return;
7201   case 3226:
7202      CALL_PRE(mach_port_insert_member);
7203      return;
7204   case 3227:
7205      CALL_PRE(mach_port_extract_member);
7206      return;
7207
7208   case 3229:
7209      CALL_PRE(mach_port_set_context);
7210      return;
7211
7212   case 3402:
7213      CALL_PRE(task_threads);
7214      return;
7215   case 3404:
7216      CALL_PRE(mach_ports_lookup);
7217      return;
7218
7219   case 3407:
7220      CALL_PRE(task_suspend);
7221      return;
7222   case 3408:
7223      CALL_PRE(task_resume);
7224      return;
7225
7226   case 3409:
7227      CALL_PRE(task_get_special_port);
7228      return;
7229   case 3411:
7230      CALL_PRE(thread_create);
7231      return;
7232   case 3412:
7233      CALL_PRE(thread_create_running);
7234      return;
7235
7236   case 3414:
7237      CALL_PRE(task_get_exception_ports);
7238      return;
7239
7240   case 3418:
7241      CALL_PRE(semaphore_create);
7242      return;
7243   case 3419:
7244      CALL_PRE(semaphore_destroy);
7245      return;
7246   case 3420:
7247      CALL_PRE(task_policy_set);
7248      return;
7249
7250   case 3801:
7251      CALL_PRE(vm_allocate);
7252      return;
7253   case 3802:
7254      CALL_PRE(vm_deallocate);
7255      return;
7256   case 3803:
7257      CALL_PRE(vm_protect);
7258      return;
7259   case 3804:
7260      CALL_PRE(vm_inherit);
7261      return;
7262   case 3805:
7263      CALL_PRE(vm_read);
7264      return;
7265   case 3808:
7266      CALL_PRE(vm_copy);
7267      return;
7268   case 3809:
7269      CALL_PRE(vm_read_overwrite);
7270      return;
7271   case 3812:
7272      CALL_PRE(vm_map);
7273      return;
7274   case 3814:
7275      CALL_PRE(vm_remap);
7276      return;
7277   case 3825:
7278      CALL_PRE(mach_make_memory_entry_64);
7279      return;
7280   case 3830:
7281      CALL_PRE(vm_purgable_control);
7282      return;
7283
7284   case 4800:
7285      CALL_PRE(mach_vm_allocate);
7286      return;
7287   case 4801:
7288      CALL_PRE(mach_vm_deallocate);
7289      return;
7290   case 4802:
7291      CALL_PRE(mach_vm_protect);
7292      return;
7293   case 4803:
7294      CALL_PRE(mach_vm_inherit);
7295      return;
7296   case 4804:
7297      CALL_PRE(mach_vm_read);
7298      return;
7299   case 4807:
7300      CALL_PRE(mach_vm_copy);
7301      return;
7302   case 4808:
7303      CALL_PRE(mach_vm_read_overwrite);
7304      return;
7305   case 4811:
7306      CALL_PRE(mach_vm_map);
7307      return;
7308   case 4813:
7309      CALL_PRE(mach_vm_remap);
7310      return;
7311   case 4815:
7312      CALL_PRE(mach_vm_region_recurse);
7313      return;
7314   case 4817:
7315      CALL_PRE(mach_make_memory_entry_64);
7316      return;
7317   case 4818:
7318      CALL_PRE(mach_vm_purgable_control);
7319      return;
7320
7321   default:
7322      // unknown message to task self
7323      VG_(printf)("UNKNOWN task message [id %d, to %s, reply 0x%x]\n",
7324                  mh->msgh_id, name_for_port(mh->msgh_remote_port),
7325                  mh->msgh_reply_port);
7326      return;
7327   }
7328}
7329
7330
7331PRE(mach_msg_thread)
7332{
7333   // message to local thread - check for thread-level kernel calls
7334
7335   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7336
7337   switch (mh->msgh_id) {
7338   case 3600:
7339      CALL_PRE(thread_terminate);
7340      return;
7341   case 3603:
7342      CALL_PRE(thread_get_state);
7343      return;
7344   case 3605:
7345      CALL_PRE(thread_suspend);
7346      return;
7347   case 3612:
7348      CALL_PRE(thread_info);
7349      return;
7350   case 3616:
7351      CALL_PRE(thread_policy);
7352      return;
7353   case 3617:
7354      CALL_PRE(thread_policy_set);
7355      return;
7356   default:
7357      // unknown message to a thread
7358      VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
7359                  mh->msgh_id, name_for_port(mh->msgh_request_port),
7360                  mh->msgh_reply_port);
7361      return;
7362   }
7363}
7364
7365
7366static int is_thread_port(mach_port_t port)
7367{
7368   if (port == 0) return False;
7369
7370   return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
7371}
7372
7373
7374static int is_task_port(mach_port_t port)
7375{
7376   if (port == 0) return False;
7377
7378   if (port == vg_task_port) return True;
7379
7380   return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
7381}
7382
7383
7384/* ---------------------------------------------------------------------
7385   mach_msg: base handlers
7386   ------------------------------------------------------------------ */
7387
7388PRE(mach_msg)
7389{
7390   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7391   mach_msg_option_t option = (mach_msg_option_t)ARG2;
7392   // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
7393   mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
7394   // mach_port_t rcv_name = (mach_port_t)ARG5;
7395   size_t complex_header_size = 0;
7396
7397   PRE_REG_READ7(long, "mach_msg",
7398                 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
7399                 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
7400                 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
7401                 mach_port_t,"notify");
7402
7403   // Assume default POST handler until specified otherwise
7404   AFTER = NULL;
7405
7406   // Assume call may block unless specified otherwise
7407   *flags |= SfMayBlock;
7408
7409   if (option & MACH_SEND_MSG) {
7410      // Validate outgoing message header
7411      PRE_MEM_READ("mach_msg(msg.msgh_bits)",
7412                   (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
7413      // msgh_size not required, use parameter instead
7414      PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
7415                   (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
7416      PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
7417                   (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
7418      // msgh_reserved not required
7419      PRE_MEM_READ("mach_msg(msg.msgh_id)",
7420                   (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
7421
7422      if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
7423         // Validate typed message data and handle memory map changes.
7424         complex_header_size = export_complex_message(tid, mh);
7425      }
7426
7427      // GrP fixme handle sender-specified message trailer
7428      // (but is this only for too-secure processes?)
7429      vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
7430
7431      MACH_REMOTE = mh->msgh_remote_port;
7432      MACH_MSGH_ID = mh->msgh_id;
7433   }
7434
7435   if (option & MACH_RCV_MSG) {
7436      // Pre-validate receive buffer
7437      PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
7438   }
7439
7440   // Call a PRE handler. The PRE handler may set an AFTER handler.
7441
7442   if (!(option & MACH_SEND_MSG)) {
7443      // no message sent, receive only
7444      CALL_PRE(mach_msg_receive);
7445      return;
7446   }
7447   else if (mh->msgh_request_port == vg_host_port) {
7448      // message sent to mach_host_self()
7449      CALL_PRE(mach_msg_host);
7450      return;
7451   }
7452   else if (is_task_port(mh->msgh_request_port)) {
7453      // message sent to a task
7454      CALL_PRE(mach_msg_task);
7455      return;
7456   }
7457   else if (mh->msgh_request_port == vg_bootstrap_port) {
7458      // message sent to bootstrap port
7459      CALL_PRE(mach_msg_bootstrap);
7460      return;
7461   }
7462   else if (is_thread_port(mh->msgh_request_port)) {
7463      // message sent to one of this process's threads
7464      CALL_PRE(mach_msg_thread);
7465      return;
7466   }
7467   else {
7468      // this is an attempt to optimize mapping sync
7469      // but there are always some cases hard to find
7470#if 0
7471      Bool do_mapping_update = False;
7472      // sorted by msgh_id, we suppose that msgh_id are different for each service,
7473      // which is obviously not true...
7474      switch (mh->msgh_id) {
7475         // com.apple.windowserver.active
7476         case 29008: // this one opens a port type 'a'
7477
7478         // com.apple.windowserver.active 'a' port
7479         case 29000:
7480         case 29822:
7481         case 29820: // adds a vm mapping
7482         case 29809: // contains a ool mem
7483         case 29800: // opens a port type 'b'
7484         case 29873:
7485         case 29876: // adds a vm mapping
7486
7487         // com.apple.windowserver.active 'b' port
7488         case 29624:
7489         case 29625:
7490         case 29506:
7491         case 29504:
7492         case 29509:
7493         case 29315:
7494         case 29236:
7495         case 29473:
7496         case 29268:
7497         case 29237: // contains a ool mem
7498         case 29360:
7499         case 29301:
7500         case 29287:
7501         case 29568:
7502         case 29570: // contains a ool mem
7503         case 29211:
7504         case 29569: // contains a ool mem
7505         case 29374:
7506         case 29246:
7507         case 29239:
7508         case 29272:
7509            if (mh->msgh_id == 29820 ||
7510               mh->msgh_id == 29876)
7511               do_mapping_update = True;
7512
7513            PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
7514               mh->msgh_id, name_for_port(mh->msgh_request_port),
7515               mh->msgh_reply_port);
7516            break;
7517
7518         // com.apple.FontServer
7519         case 13024:
7520            PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
7521               mh->msgh_id, name_for_port(mh->msgh_request_port),
7522               mh->msgh_reply_port);
7523            break;
7524
7525         // com.apple.system.notification_center
7526         case 78945698:
7527         case 78945701:
7528         case 78945695: // contains a ool mem
7529         case 78945694:
7530         case 78945700:
7531            if (mh->msgh_id == 78945695)
7532               do_mapping_update = False;
7533            PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
7534               mh->msgh_id, name_for_port(mh->msgh_request_port),
7535               mh->msgh_reply_port);
7536            break;
7537
7538         // com.apple.CoreServices.coreservicesd
7539         case 10000:
7540         case 10019:
7541         case 10002: // adds vm mappings
7542         case 10003: // adds vm mappings
7543         case 14007:
7544         case 13000:
7545         case 13001:
7546         case 13011:
7547         case 13016: // contains a ool mem
7548            if (mh->msgh_id == 10002||
7549                mh->msgh_id == 10003)
7550               do_mapping_update = True;
7551            PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
7552               mh->msgh_id, name_for_port(mh->msgh_request_port),
7553               mh->msgh_reply_port);
7554            break;
7555
7556         // com.apple.system.logger
7557         case 118:
7558            PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
7559               mh->msgh_id, name_for_port(mh->msgh_request_port),
7560               mh->msgh_reply_port);
7561            break;
7562
7563         // com.apple.coreservices.launchservicesd, and others
7564         case 1999646836: // might adds vm mapping
7565            if (mh->msgh_id == 1999646836)
7566               do_mapping_update = True;
7567            PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
7568               mh->msgh_id, name_for_port(mh->msgh_request_port),
7569               mh->msgh_reply_port);
7570            break;
7571
7572         // com.apple.ocspd
7573         case 33012:
7574            PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
7575               mh->msgh_id, name_for_port(mh->msgh_request_port),
7576               mh->msgh_reply_port);
7577
7578         default:
7579            // arbitrary message to arbitrary port
7580            do_mapping_update = True;
7581            PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
7582               mh->msgh_id, name_for_port(mh->msgh_request_port),
7583               mh->msgh_reply_port);
7584      }
7585
7586      // this is an optimization, don't check mapping on known mach_msg
7587      if (do_mapping_update)
7588         AFTER = POST_FN(mach_msg_unhandled);
7589      else
7590         AFTER = POST_FN(mach_msg_unhandled_check);
7591#else
7592      AFTER = POST_FN(mach_msg_unhandled);
7593#endif
7594
7595      // Assume the entire message body may be read.
7596      // GrP fixme generates false positives for unknown protocols
7597      /*
7598      PRE_MEM_READ("mach_msg(payload)",
7599                   (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
7600                   send_size - sizeof(mach_msg_header_t) - complex_header_size);
7601      */
7602      return;
7603   }
7604}
7605
7606POST(mach_msg)
7607{
7608   mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7609   mach_msg_option_t option = (mach_msg_option_t)ARG2;
7610
7611   if (option & MACH_RCV_MSG) {
7612      if (RES != 0) {
7613         // error during send or receive
7614         // GrP fixme need to clean up port rights?
7615      } else {
7616         mach_msg_trailer_t *mt =
7617             (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
7618
7619         // Assume the entire received message and trailer is initialized
7620         // GrP fixme would being more specific catch any bugs?
7621         POST_MEM_WRITE((Addr)mh,
7622                        round_msg(mh->msgh_size) + mt->msgh_trailer_size);
7623
7624         if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
7625             // Update memory map for out-of-line message data
7626             import_complex_message(tid, mh);
7627         }
7628      }
7629   }
7630
7631   // Call handler chosen by PRE(mach_msg)
7632   if (AFTER) {
7633      (*AFTER)(tid, arrghs, status);
7634   }
7635}
7636
7637
7638POST(mach_msg_unhandled)
7639{
7640   ML_(sync_mappings)("after", "mach_msg_receive (unhandled)", 0);
7641}
7642
7643POST(mach_msg_unhandled_check)
7644{
7645   if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
7646      PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
7647}
7648
7649
7650/* ---------------------------------------------------------------------
7651   other Mach traps
7652   ------------------------------------------------------------------ */
7653
7654PRE(mach_reply_port)
7655{
7656   PRINT("mach_reply_port()");
7657}
7658
7659POST(mach_reply_port)
7660{
7661   record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
7662   PRINT("reply port %s", name_for_port(RES));
7663}
7664
7665
7666PRE(mach_thread_self)
7667{
7668   PRINT("mach_thread_self()");
7669}
7670
7671POST(mach_thread_self)
7672{
7673   record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
7674   PRINT("thread %#lx", RES);
7675}
7676
7677
7678PRE(mach_host_self)
7679{
7680   PRINT("mach_host_self()");
7681}
7682
7683POST(mach_host_self)
7684{
7685   vg_host_port = RES;
7686   record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
7687   PRINT("host %#lx", RES);
7688}
7689
7690
7691PRE(mach_task_self)
7692{
7693   PRINT("mach_task_self()");
7694}
7695
7696POST(mach_task_self)
7697{
7698   vg_task_port = RES;
7699   record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
7700   PRINT("task %#lx", RES);
7701}
7702
7703
7704PRE(syscall_thread_switch)
7705{
7706   PRINT("syscall_thread_switch(%s, %ld, %ld)",
7707      name_for_port(ARG1), ARG2, ARG3);
7708   PRE_REG_READ3(long, "syscall_thread_switch",
7709                 mach_port_t,"thread", int,"option", natural_t,"timeout");
7710
7711   *flags |= SfMayBlock;
7712}
7713
7714
7715PRE(semaphore_signal)
7716{
7717   PRINT("semaphore_signal(%s)", name_for_port(ARG1));
7718   PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7719}
7720
7721
7722PRE(semaphore_signal_all)
7723{
7724   PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
7725   PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
7726}
7727
7728
7729PRE(semaphore_signal_thread)
7730{
7731   PRINT("semaphore_signal_thread(%s, %s)",
7732         name_for_port(ARG1), name_for_port(ARG2));
7733   PRE_REG_READ2(long, "semaphore_signal_thread",
7734                 semaphore_t,"semaphore", mach_port_t,"thread");
7735}
7736
7737
7738PRE(semaphore_wait)
7739{
7740   PRINT("semaphore_wait(%s)", name_for_port(ARG1));
7741   PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
7742
7743   *flags |= SfMayBlock;
7744}
7745
7746
7747PRE(semaphore_wait_signal)
7748{
7749   PRINT("semaphore_wait_signal(%s, %s)",
7750         name_for_port(ARG1), name_for_port(ARG2));
7751   PRE_REG_READ2(long, "semaphore_wait_signal",
7752                 semaphore_t,"wait_semaphore",
7753                 semaphore_t,"signal_semaphore");
7754
7755   *flags |= SfMayBlock;
7756}
7757
7758
7759PRE(semaphore_timedwait)
7760{
7761   PRINT("semaphore_timedwait(%s, %g seconds)",
7762         name_for_port(ARG1), ARG2+ARG3/1000000000.0);
7763   PRE_REG_READ3(long, "semaphore_wait_signal",
7764                 semaphore_t,"semaphore",
7765                 int,"wait_time_hi",
7766                 int,"wait_time_lo");
7767
7768   *flags |= SfMayBlock;
7769}
7770
7771
7772PRE(semaphore_timedwait_signal)
7773{
7774   PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
7775         name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
7776   PRE_REG_READ4(long, "semaphore_wait_signal",
7777                 semaphore_t,"wait_semaphore",
7778                 semaphore_t,"signal_semaphore",
7779                 int,"wait_time_hi",
7780                 int,"wait_time_lo");
7781
7782   *flags |= SfMayBlock;
7783}
7784
7785
7786PRE(__semwait_signal)
7787{
7788   /* 10.5 args: int cond_sem, int mutex_sem,
7789                 int timeout, int relative,
7790                 time_t tv_sec, time_t tv_nsec */
7791   PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
7792         name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
7793   PRE_REG_READ6(long, "__semwait_signal",
7794                 int,"cond_sem", int,"mutex_sem",
7795                 int,"timeout", int,"relative",
7796                 vki_time_t,"tv_sec", int,"tv_nsec");
7797
7798   *flags |= SfMayBlock;
7799}
7800// GrP provided this alternative version for 10.6, but NjN
7801// reckons the 10.5 is is still correct for 10.6.  So, retaining
7802// Greg's version as a comment just in case we need it later.
7803//PRE(__semwait_signal)
7804//{
7805//   /* 10.5 args: int cond_sem, int mutex_sem,
7806//                 int timeout, int relative,
7807//                 const timespec *ts */
7808//   PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
7809//         name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
7810//   PRE_REG_READ5(int, "__semwait_signal",
7811//                 int,cond_sem, int,mutex_sem,
7812//                 int,timeout, int,relative,
7813//                 const struct vki_timespec *,ts);
7814//
7815//   if (ARG5) PRE_MEM_READ ("__semwait_signal(ts)",
7816//                           ARG5, sizeof(struct vki_timespec));
7817//
7818//   *flags |= SfMayBlock;
7819//}
7820
7821
7822PRE(__thread_selfid)
7823{
7824   PRINT("__thread_selfid ()");
7825   PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
7826}
7827
7828PRE(task_for_pid)
7829{
7830   PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
7831   PRE_REG_READ3(long, "task_for_pid",
7832                 mach_port_t,"target",
7833                 vki_pid_t, "pid", mach_port_t *,"task");
7834   PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
7835}
7836
7837POST(task_for_pid)
7838{
7839   mach_port_t task;
7840
7841   POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
7842
7843   task = *(mach_port_t *)ARG3;
7844   record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
7845   PRINT("task 0x%x", task);
7846}
7847
7848
7849PRE(pid_for_task)
7850{
7851   PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
7852   PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
7853   PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
7854}
7855
7856POST(pid_for_task)
7857{
7858   vki_pid_t pid;
7859
7860   POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
7861
7862   pid = *(vki_pid_t *)ARG2;
7863   PRINT("pid %u", pid);
7864}
7865
7866
7867PRE(mach_timebase_info)
7868{
7869   PRINT("mach_timebase_info(%#lx)", ARG1);
7870   PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
7871   PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
7872}
7873
7874POST(mach_timebase_info)
7875{
7876   POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
7877}
7878
7879
7880PRE(mach_wait_until)
7881{
7882#if VG_WORDSIZE == 8
7883   PRINT("mach_wait_until(%lu)", ARG1);
7884   PRE_REG_READ1(long, "mach_wait_until",
7885                 unsigned long long,"deadline");
7886#else
7887   PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
7888   PRE_REG_READ2(long, "mach_wait_until",
7889                 int,"deadline_hi", int,"deadline_lo");
7890#endif
7891   *flags |= SfMayBlock;
7892}
7893
7894
7895PRE(mk_timer_create)
7896{
7897   PRINT("mk_timer_create()");
7898   PRE_REG_READ0(long, "mk_timer_create");
7899}
7900
7901POST(mk_timer_create)
7902{
7903   record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
7904}
7905
7906
7907PRE(mk_timer_destroy)
7908{
7909   PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
7910   PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
7911
7912   // Must block to prevent race (other thread allocates and
7913   // notifies after we deallocate but before we notify)
7914   *flags &= ~SfMayBlock;
7915}
7916
7917POST(mk_timer_destroy)
7918{
7919   // Must have cleared SfMayBlock in PRE to prevent race
7920   record_port_destroy(ARG1);
7921}
7922
7923
7924PRE(mk_timer_arm)
7925{
7926#if VG_WORDSIZE == 8
7927   PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
7928   PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
7929                 unsigned long,"expire_time");
7930#else
7931   PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
7932   PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
7933                 int,"expire_time_hi", int,"expire_time_lo");
7934#endif
7935}
7936
7937
7938PRE(mk_timer_cancel)
7939{
7940   PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
7941   PRE_REG_READ2(long, "mk_timer_cancel",
7942                 mach_port_t,"name", Addr,"result_time");
7943   if (ARG2) {
7944      PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
7945   }
7946}
7947
7948POST(mk_timer_cancel)
7949{
7950   if (ARG2) {
7951      POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
7952   }
7953}
7954
7955
7956PRE(iokit_user_client_trap)
7957{
7958   PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
7959         name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
7960   PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
7961                 mach_port_t,connect, unsigned int,index,
7962                 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
7963                 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
7964
7965   // can't do anything else with this in general
7966   // might be able to use connect+index to choose something sometimes
7967}
7968
7969POST(iokit_user_client_trap)
7970{
7971   ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
7972}
7973
7974
7975PRE(swtch)
7976{
7977   PRINT("swtch ( )");
7978   PRE_REG_READ0(long, "swtch");
7979
7980   *flags |= SfMayBlock;
7981}
7982
7983
7984PRE(swtch_pri)
7985{
7986   PRINT("swtch_pri ( %ld )", ARG1);
7987   PRE_REG_READ1(long, "swtch_pri", int,"pri");
7988
7989   *flags |= SfMayBlock;
7990}
7991
7992
7993PRE(FAKE_SIGRETURN)
7994{
7995   /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
7996      an explanation of what follows. */
7997   /* This handles the fake signal-return system call created by
7998      sigframe-x86-darwin.c. */
7999   /* See also comments just below on PRE(sigreturn). */
8000
8001   PRINT("FAKE_SIGRETURN ( )");
8002
8003   vg_assert(VG_(is_valid_tid)(tid));
8004   vg_assert(tid >= 1 && tid < VG_N_THREADS);
8005   vg_assert(VG_(is_running_thread)(tid));
8006
8007   /* Remove the signal frame from this thread's (guest) stack,
8008      in the process restoring the pre-signal guest state. */
8009   VG_(sigframe_destroy)(tid, True);
8010
8011   /* Tell the driver not to update the guest state with the "result",
8012      and set a bogus result to keep it happy. */
8013   *flags |= SfNoWriteResult;
8014   SET_STATUS_Success(0);
8015
8016   /* Check to see if any signals arose as a result of this. */
8017   *flags |= SfPollAfter;
8018}
8019
8020
8021PRE(sigreturn)
8022{
8023   /* This is the "real" sigreturn.  But because we construct all the
8024      signal frames ourselves (of course, in m_sigframe), this cannot
8025      happen as a result of normal signal delivery.  I think it
8026      happens only when doing siglongjmp, in which case Darwin's Libc
8027      appears to use it for two different purposes: to mess with the
8028      per-thread sigaltstack flags (as per arg 2), or to restore the
8029      thread's state from a ucontext* (as per arg 1). */
8030
8031   PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
8032
8033   vg_assert(VG_(is_valid_tid)(tid));
8034   vg_assert(tid >= 1 && tid < VG_N_THREADS);
8035   vg_assert(VG_(is_running_thread)(tid));
8036
8037   if (ARG2 == VKI_UC_SET_ALT_STACK) {
8038      /* This is confusing .. the darwin kernel sources imply there is
8039         a per-thread on-altstack/not-on-altstack flag, which is set
8040         by this flag.  Just ignore it and claim success for the time
8041         being. */
8042      VG_(debugLog)(0, "syswrap-darwin",
8043                       "WARNING: Ignoring sigreturn( ..., "
8044                       "UC_SET_ALT_STACK );\n");
8045      SET_STATUS_Success(0);
8046      return;
8047   }
8048   if (ARG2 == VKI_UC_RESET_ALT_STACK) {
8049      /* Ditto */
8050      VG_(debugLog)(0, "syswrap-darwin",
8051                       "WARNING: Ignoring sigreturn( ..., "
8052                       "UC_RESET_ALT_STACK );\n");
8053      SET_STATUS_Success(0);
8054      return;
8055   }
8056
8057   /* Otherwise claim this isn't supported.  (Could be
8058      catastrophic).
8059
8060      What do we have to do if we do need to support it?
8061
8062      1. Change the second argument of VG_(sigframe_destroy) from
8063         "Bool isRT" to "UInt sysno", so we can pass the syscall
8064         number, so it can distinguish this case from the
8065         __NR_DARWIN_FAKE_SIGRETURN case.
8066
8067      2. In VG_(sigframe_destroy), look at sysno to distinguish the
8068         cases.  For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
8069         For this case, restore the thread's CPU state (or at least
8070         the integer regs) from the ucontext in ARG1 (and do all the
8071         other "signal-returns" stuff too).
8072
8073      3. For (2), how do we know where the ucontext is?  One way is to
8074         temporarily copy ARG1 into this thread's guest_EBX (or any
8075         other int reg), and have VG_(sigframe_destroy) read
8076         guest_EBX.  Why is it ok to trash guest_EBX (or any other int
8077         reg)?  Because VG_(sigframe_destroy) is just about to
8078         overwrite all the regs anyway -- since the primary purpose of
8079         calling it is to restore the register state from the ucontext
8080         pointed to by ARG1.
8081
8082      Hey, it's uggerly.  But at least it's documented.
8083   */
8084   /* But in the meantime ... */
8085   VG_(debugLog)(0, "syswrap-darwin",
8086                    "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
8087   VG_(debugLog)(0, "syswrap-darwin",
8088                    "WARNING: Thread/program/Valgrind "
8089                    "will likely segfault now.\n");
8090   VG_(debugLog)(0, "syswrap-darwin",
8091                    "WARNING: Please file a bug report at "
8092                    "http://www.valgrind.org.\n");
8093   SET_STATUS_Failure( VKI_ENOSYS );
8094}
8095
8096
8097/* ---------------------------------------------------------------------
8098   machine-dependent traps
8099   ------------------------------------------------------------------ */
8100
8101#if defined(VGA_x86)
8102static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
8103{
8104   Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
8105   return VG_(arena_calloc)(VG_AR_CORE, "syswrap-darwin.ldt", nbytes, 1);
8106}
8107#endif
8108
8109PRE(thread_fast_set_cthread_self)
8110{
8111   PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
8112   PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
8113
8114#if defined(VGA_x86)
8115   // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
8116   {
8117      VexGuestX86SegDescr *ldt;
8118      ThreadState *tst = VG_(get_ThreadState)(tid);
8119      ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
8120      if (!ldt) {
8121         ldt = alloc_zeroed_x86_LDT();
8122         tst->arch.vex.guest_LDT = (HWord)ldt;
8123      }
8124      VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
8125      ldt[6].LdtEnt.Bits.LimitLow = 1;
8126      ldt[6].LdtEnt.Bits.LimitHi = 0;
8127      ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
8128      ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
8129      ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
8130      ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
8131      ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
8132      ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
8133      ldt[6].LdtEnt.Bits.Granularity = 1;  // SZ_G
8134      ldt[6].LdtEnt.Bits.Default_Big = 1;  // SZ_32
8135
8136      tst->os_state.pthread = ARG1;
8137      tst->arch.vex.guest_GS = 0x37;
8138
8139      // What we would like to do is:
8140      //   SET_STATUS_Success(0x37);
8141      // but that doesn't work, because this is a MDEP-class syscall,
8142      // and SET_STATUS_Success creates a UNIX-class syscall result.
8143      // Hence we have to laboriously construct the full SysRes "by hand"
8144      // and use that to set the syscall return status.
8145      SET_STATUS_from_SysRes(
8146         VG_(mk_SysRes_x86_darwin)(
8147            VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
8148            False, 0, 0x37
8149         )
8150      );
8151   }
8152
8153#elif defined(VGA_amd64)
8154   // GrP fixme bigger hack than x86
8155   {
8156      ThreadState *tst = VG_(get_ThreadState)(tid);
8157      tst->os_state.pthread = ARG1;
8158      tst->arch.vex.guest_GS_0x60 = ARG1;
8159      // SET_STATUS_Success(0x60);
8160      // see comments on x86 case just above
8161      SET_STATUS_from_SysRes(
8162         VG_(mk_SysRes_amd64_darwin)(
8163            VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
8164            False, 0, 0x60
8165         )
8166      );
8167   }
8168
8169#else
8170#error unknown architecture
8171#endif
8172}
8173
8174
8175/* ---------------------------------------------------------------------
8176   Added for OSX 10.7 (Lion)
8177   ------------------------------------------------------------------ */
8178
8179#if DARWIN_VERS >= DARWIN_10_7
8180
8181PRE(getaudit_addr)
8182{
8183   PRINT("getaudit_addr(%#lx, %lu)", ARG1, ARG2);
8184   PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
8185   PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
8186}
8187POST(getaudit_addr)
8188{
8189   POST_MEM_WRITE(ARG1, ARG2);
8190}
8191
8192PRE(psynch_mutexwait)
8193{
8194   PRINT("psynch_mutexwait(BOGUS)");
8195   *flags |= SfMayBlock;
8196}
8197POST(psynch_mutexwait)
8198{
8199}
8200
8201PRE(psynch_mutexdrop)
8202{
8203   PRINT("psynch_mutexdrop(BOGUS)");
8204   *flags |= SfMayBlock;
8205}
8206POST(psynch_mutexdrop)
8207{
8208}
8209
8210PRE(psynch_cvbroad)
8211{
8212   PRINT("psynch_cvbroad(BOGUS)");
8213}
8214POST(psynch_cvbroad)
8215{
8216}
8217
8218PRE(psynch_cvsignal)
8219{
8220   PRINT("psynch_cvsignal(BOGUS)");
8221}
8222POST(psynch_cvsignal)
8223{
8224}
8225
8226PRE(psynch_cvwait)
8227{
8228   PRINT("psynch_cvwait(BOGUS)");
8229   *flags |= SfMayBlock;
8230}
8231POST(psynch_cvwait)
8232{
8233}
8234
8235PRE(psynch_rw_rdlock)
8236{
8237   PRINT("psynch_rw_rdlock(BOGUS)");
8238   *flags |= SfMayBlock;
8239}
8240POST(psynch_rw_rdlock)
8241{
8242}
8243
8244PRE(psynch_rw_wrlock)
8245{
8246   PRINT("psynch_rw_wrlock(BOGUS)");
8247   *flags |= SfMayBlock;
8248}
8249POST(psynch_rw_wrlock)
8250{
8251}
8252
8253PRE(psynch_rw_unlock)
8254{
8255   PRINT("psynch_rw_unlock(BOGUS)");
8256}
8257POST(psynch_rw_unlock)
8258{
8259}
8260
8261PRE(psynch_cvclrprepost)
8262{
8263   PRINT("psynch_cvclrprepost(BOGUS)");
8264   *flags |= SfMayBlock;
8265}
8266POST(psynch_cvclrprepost)
8267{
8268}
8269
8270#endif /* DARWIN_VERS >= DARWIN_10_7 */
8271
8272
8273/* ---------------------------------------------------------------------
8274   Added for OSX 10.8 (Mountain Lion)
8275   ------------------------------------------------------------------ */
8276
8277#if DARWIN_VERS >= DARWIN_10_8
8278
8279PRE(kernelrpc_mach_vm_allocate_trap)
8280{
8281   PRINT("kernelrpc_mach_vm_allocate_trap(target:%s, address:%p, size:%#lx, flags:%#lx)", name_for_port(ARG1), *(void**)ARG2, ARG3, ARG4);
8282   if ((ARG4 & VM_FLAGS_ANYWHERE) == VM_FLAGS_FIXED)
8283      ML_(notify_core_and_tool_of_mmap)(*(mach_vm_address_t*)ARG2, ARG3, VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
8284}
8285POST(kernelrpc_mach_vm_allocate_trap)
8286{
8287   PRINT("address:%p size:%#lx", *(void**)ARG2, ARG3);
8288   if ((ARG4 & VM_FLAGS_ANYWHERE) != VM_FLAGS_FIXED)
8289      ML_(notify_core_and_tool_of_mmap)(*(mach_vm_address_t*)ARG2, ARG3, VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
8290}
8291
8292PRE(kernelrpc_mach_vm_deallocate_trap)
8293{
8294   PRINT("kernelrpc_mach_vm_deallocate_trap(target:%#lx, address:%#lx, size:%#lx)", ARG1, ARG2, ARG3);
8295}
8296POST(kernelrpc_mach_vm_deallocate_trap)
8297{
8298   // kernelrpc_mach_vm_deallocate_trap could be call with address == 0 && size == 0,
8299   // we shall not notify any unmap then
8300   if (ARG3)
8301      ML_(notify_core_and_tool_of_munmap)(ARG2, ARG3);
8302}
8303
8304PRE(kernelrpc_mach_vm_protect_trap)
8305{
8306   PRINT("kernelrpc_mach_vm_protect_trap(task:%#lx, address:%#lx, size:%#lx, set_maximum:%#lx, new_prot:%#lx)", ARG1, ARG2, ARG3, ARG4, ARG5);
8307   ML_(notify_core_and_tool_of_mprotect)(ARG2, ARG3, ARG5);
8308}
8309
8310#if DARWIN_VERS >= DARWIN_10_9
8311PRE(kernelrpc_mach_vm_map_trap)
8312{
8313   PRINT("kernelrpc_mach_vm_map_trap(target:%#lx, address:%p, size:%#lx, mask:%#lx, flags:%#lx, cur_prot:%#lx)",
8314    ARG1, *(void**)ARG2, ARG3, ARG4, ARG5, ARG6);
8315}
8316
8317POST(kernelrpc_mach_vm_map_trap)
8318{
8319   PRINT("-> address:%p", *(void**)ARG2);
8320   ML_(notify_core_and_tool_of_mmap)(*(mach_vm_address_t*)ARG2, ARG3, VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
8321  // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
8322}
8323#endif /* DARWIN_VERS >= DARWIN_10_9 */
8324
8325PRE(kernelrpc_mach_port_allocate_trap)
8326{
8327   PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)", ARG1, ARG2);
8328   PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)", ARG3, sizeof(mach_port_name_t));
8329}
8330
8331POST(kernelrpc_mach_port_allocate_trap)
8332{
8333   POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
8334   PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
8335   record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
8336}
8337
8338PRE(kernelrpc_mach_port_destroy_trap)
8339{
8340   PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
8341   record_port_destroy(ARG2);
8342}
8343
8344PRE(kernelrpc_mach_port_deallocate_trap)
8345{
8346   PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME", ARG1, ARG2);
8347}
8348
8349POST(kernelrpc_mach_port_deallocate_trap)
8350{
8351}
8352
8353PRE(kernelrpc_mach_port_mod_refs_trap)
8354{
8355   PRINT("kernelrpc_mach_port_mod_refs_trap(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
8356    ARG1, ARG2, ARG3, ARG4);
8357}
8358
8359PRE(kernelrpc_mach_port_move_member_trap)
8360{
8361   PRINT("kernelrpc_mach_port_move_member_trap(task:%#lx, name:%#lx, after:%#lx ) FIXME",
8362    ARG1, ARG2, ARG3);
8363}
8364
8365PRE(kernelrpc_mach_port_insert_right_trap)
8366{
8367   PRINT("kernelrpc_mach_port_insert_right_trap(FIXME,ARGUMENTS_UNKNOWN)");
8368}
8369
8370PRE(kernelrpc_mach_port_insert_member_trap)
8371{
8372   PRINT("kernelrpc_mach_port_insert_member_trap(FIXME,ARGUMENTS_UNKNOWN)");
8373}
8374
8375PRE(kernelrpc_mach_port_extract_member_trap)
8376{
8377   PRINT("kernelrpc_mach_port_extract_member_trap(FIXME,ARGUMENTS_UNKNOWN)");
8378}
8379
8380#if DARWIN_VERS >= DARWIN_10_9
8381PRE(kernelrpc_mach_port_construct_trap)
8382{
8383   PRINT("kernelrpc_mach_port_construct_trap(FIXME,ARGUMENTS_UNKNOWN)");
8384}
8385
8386PRE(kernelrpc_mach_port_destruct_trap)
8387{
8388   PRINT("kernelrpc_mach_port_destruct_trap(FIXME,ARGUMENTS_UNKNOWN)");
8389}
8390
8391PRE(kernelrpc_mach_port_guard_trap)
8392{
8393   PRINT("kernelrpc_mach_port_guard_trap(FIXME)");
8394}
8395
8396PRE(kernelrpc_mach_port_unguard_trap)
8397{
8398   PRINT("kernelrpc_mach_port_unguard_trap(FIXME)");
8399}
8400
8401#endif /* DARWIN_VERS >= DARWIN_10_9 */
8402
8403PRE(iopolicysys)
8404{
8405   PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
8406   /* mem effects unknown */
8407}
8408POST(iopolicysys)
8409{
8410}
8411
8412PRE(process_policy)
8413{
8414   PRINT("process_policy(FIXME)(scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx, attr:%lx, target_pid:%lx, target_threadid:%lx)",
8415    ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
8416   /* mem effects unknown */
8417}
8418POST(process_policy)
8419{
8420}
8421
8422#endif /* DARWIN_VERS >= DARWIN_10_8 */
8423
8424
8425/* ---------------------------------------------------------------------
8426   syscall tables
8427   ------------------------------------------------------------------ */
8428
8429/* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
8430#define MACX_(sysno, name)    WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
8431#define MACXY(sysno, name)    WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
8432#define _____(sysno) GENX_(sysno, sys_ni_syscall)  /* UNIX style only */
8433
8434/*
8435     _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
8436             unfortunately misused for Mach too, causing assertion failures
8437  // _____ : unimplemented in valgrind
8438     GEN   : handlers are in syswrap-generic.c
8439     MAC   : handlers are in this file
8440        X_ : PRE handler only
8441        XY : PRE and POST handlers
8442*/
8443const SyscallTableEntry ML_(syscall_table)[] = {
8444// _____(__NR_syscall),   // 0
8445   MACX_(__NR_exit,        exit),
8446   GENX_(__NR_fork,        sys_fork),
8447   GENXY(__NR_read,        sys_read),
8448   GENX_(__NR_write,       sys_write),
8449   GENXY(__NR_open,        sys_open),
8450   GENXY(__NR_close,       sys_close),
8451   GENXY(__NR_wait4,       sys_wait4),
8452   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)),     // old creat
8453   GENX_(__NR_link,        sys_link),
8454   GENX_(__NR_unlink,      sys_unlink),
8455   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)),    // old execv
8456   GENX_(__NR_chdir,       sys_chdir),
8457   GENX_(__NR_fchdir,      sys_fchdir),
8458   GENX_(__NR_mknod,       sys_mknod),
8459   GENX_(__NR_chmod,       sys_chmod),
8460   GENX_(__NR_chown,       sys_chown),
8461   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)),    // old break
8462   MACXY(__NR_getfsstat,   getfsstat),
8463   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)),    // old lseek
8464   GENX_(__NR_getpid,      sys_getpid),     // 20
8465   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)),    // old mount
8466   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)),    // old umount
8467   GENX_(__NR_setuid,      sys_setuid),
8468   GENX_(__NR_getuid,      sys_getuid),
8469   GENX_(__NR_geteuid,     sys_geteuid),
8470   MACX_(__NR_ptrace,      ptrace),
8471   MACXY(__NR_recvmsg,     recvmsg),
8472   MACX_(__NR_sendmsg,     sendmsg),
8473   MACXY(__NR_recvfrom,    recvfrom),
8474   MACXY(__NR_accept,      accept),
8475   MACXY(__NR_getpeername, getpeername),
8476   MACXY(__NR_getsockname, getsockname),
8477   GENX_(__NR_access,      sys_access),
8478   MACX_(__NR_chflags,     chflags),
8479   MACX_(__NR_fchflags,    fchflags),
8480   GENX_(__NR_sync,        sys_sync),
8481   GENX_(__NR_kill,        sys_kill),
8482   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)),    // old stat
8483   GENX_(__NR_getppid,     sys_getppid),
8484   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)),    // old lstat
8485   GENXY(__NR_dup,         sys_dup),
8486   MACXY(__NR_pipe,        pipe),
8487   GENX_(__NR_getegid,     sys_getegid),
8488// _____(__NR_profil),
8489   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)),    // old ktrace
8490   MACXY(__NR_sigaction,   sigaction),
8491   GENX_(__NR_getgid,      sys_getgid),
8492   MACXY(__NR_sigprocmask, sigprocmask),
8493   MACXY(__NR_getlogin,    getlogin),
8494// _____(__NR_setlogin),
8495// _____(__NR_acct),
8496   MACXY(__NR_sigpending,  sigpending),
8497   GENXY(__NR_sigaltstack, sys_sigaltstack),
8498   MACXY(__NR_ioctl,       ioctl),
8499// _____(__NR_reboot),
8500// _____(__NR_revoke),
8501   GENX_(__NR_symlink,     sys_symlink),   // 57
8502   GENX_(__NR_readlink,    sys_readlink),
8503   GENX_(__NR_execve,      sys_execve),
8504   GENX_(__NR_umask,       sys_umask),     // 60
8505   GENX_(__NR_chroot,      sys_chroot),
8506   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)),    // old fstat
8507   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)),    // used internally, reserved
8508   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)),    // old getpagesize
8509   GENX_(__NR_msync,       sys_msync),
8510   GENX_(__NR_vfork,       sys_fork),              // (We treat vfork as fork.)
8511   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)),    // old vread
8512   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)),    // old vwrite
8513   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)),    // old sbrk
8514   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)),    // old sstk
8515   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)),    // old mmap
8516   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)),    // old vadvise
8517   GENXY(__NR_munmap,      sys_munmap),
8518   GENXY(__NR_mprotect,    sys_mprotect),
8519   GENX_(__NR_madvise,     sys_madvise),
8520   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)),    // old vhangup
8521   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)),    // old vlimit
8522   GENXY(__NR_mincore,     sys_mincore),
8523   GENXY(__NR_getgroups,   sys_getgroups),
8524// _____(__NR_setgroups),   // 80
8525   GENX_(__NR_getpgrp,     sys_getpgrp),
8526   GENX_(__NR_setpgid,     sys_setpgid),
8527   GENXY(__NR_setitimer,   sys_setitimer),
8528   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)),    // old wait
8529// _____(__NR_swapon),
8530   GENXY(__NR_getitimer,   sys_getitimer),
8531   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)),    // old gethostname
8532   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)),    // old sethostname
8533   MACXY(__NR_getdtablesize, getdtablesize),
8534   GENXY(__NR_dup2,        sys_dup2),
8535   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)),    // old getdopt
8536   MACXY(__NR_fcntl,       fcntl),
8537   GENX_(__NR_select,      sys_select),
8538   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)),    // old setdopt
8539   GENX_(__NR_fsync,       sys_fsync),
8540   GENX_(__NR_setpriority, sys_setpriority),
8541   MACXY(__NR_socket,      socket),
8542   MACX_(__NR_connect,     connect),
8543   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)),    // old accept
8544   GENX_(__NR_getpriority, sys_getpriority),   // 100
8545   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)),   // old send
8546   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)),   // old recv
8547   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)),   // old sigreturn
8548   MACX_(__NR_bind,        bind),
8549   MACX_(__NR_setsockopt,  setsockopt),
8550   MACX_(__NR_listen,      listen),
8551   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)),   // old vtimes
8552   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)),   // old sigvec
8553   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)),   // old sigblock
8554   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)),   // old sigsetmask
8555   MACX_(__NR_sigsuspend,  sigsuspend),            // old sigsuspend
8556   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)),   // old sigstack
8557   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)),   // old recvmsg
8558   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)),   // old sendmsg
8559   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)),   // old vtrace
8560   GENXY(__NR_gettimeofday, sys_gettimeofday),
8561   GENXY(__NR_getrusage,   sys_getrusage),
8562   MACXY(__NR_getsockopt,  getsockopt),
8563   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)),   // old resuba
8564   GENXY(__NR_readv,       sys_readv),        // 120
8565   GENX_(__NR_writev,      sys_writev),
8566// _____(__NR_settimeofday),
8567   GENX_(__NR_fchown,      sys_fchown),
8568   GENX_(__NR_fchmod,      sys_fchmod),
8569   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)),   // old recvfrom
8570// _____(__NR_setreuid),
8571// _____(__NR_setregid),
8572   GENX_(__NR_rename,      sys_rename),
8573   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)),   // old truncate
8574   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)),   // old ftruncate
8575   GENX_(__NR_flock,       sys_flock),
8576// _____(__NR_mkfifo),
8577   MACX_(__NR_sendto,      sendto),
8578   MACX_(__NR_shutdown,    shutdown),
8579   MACXY(__NR_socketpair,  socketpair),
8580   GENX_(__NR_mkdir,       sys_mkdir),
8581   GENX_(__NR_rmdir,       sys_rmdir),
8582   GENX_(__NR_utimes,      sys_utimes),
8583   MACX_(__NR_futimes,     futimes),
8584// _____(__NR_adjtime),     // 140
8585   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)),   // old getpeername
8586   MACXY(__NR_gethostuuid, gethostuuid),
8587   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)),   // old sethostid
8588   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)),   // old getrlimit
8589   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)),   // old setrlimit
8590   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)),   // old killpg
8591   GENX_(__NR_setsid,      sys_setsid),
8592   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)),   // old setquota
8593   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)),   // old qquota
8594   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)),   // old getsockname
8595// _____(__NR_getpgid),
8596// _____(__NR_setprivexec),
8597   GENXY(__NR_pread,       sys_pread64),
8598   GENX_(__NR_pwrite,      sys_pwrite64),
8599// _____(__NR_nfssvc),
8600   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)),   // old getdirentries
8601   GENXY(__NR_statfs,      sys_statfs),
8602   GENXY(__NR_fstatfs,     sys_fstatfs),
8603// _____(__NR_unmount),
8604   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)),   // old async_daemon
8605// _____(__NR_getfh),
8606   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)),   // old getdomainname
8607   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)),   // old setdomainname
8608   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)),   // ???
8609// _____(__NR_quotactl),
8610   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)),   // old exportfs
8611   MACX_(__NR_mount,       mount),
8612   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)),   // old ustat
8613   MACXY(__NR_csops,       csops),                 // code-signing ops
8614   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)),   // old table
8615   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)),   // old wait3
8616   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)),   // old rpause
8617// _____(__NR_waitid),
8618   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)),   // old getdents
8619   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)),   // old gc_control
8620// _____(__NR_add_profil),
8621   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)),   // ???
8622   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)),   // ???
8623   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)),   // ???
8624   MACX_(__NR_kdebug_trace, kdebug_trace),     // 180
8625   GENX_(__NR_setgid,      sys_setgid),
8626   MACX_(__NR_setegid,     setegid),
8627   MACX_(__NR_seteuid,     seteuid),
8628   MACX_(__NR_sigreturn,   sigreturn),
8629// _____(__NR_chud),
8630   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)),   // ???
8631#if DARWIN_VERS >= DARWIN_10_6
8632// _____(__NR_fdatasync),
8633#else
8634   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)),   // ???
8635#endif
8636   GENXY(__NR_stat,        sys_newstat),
8637   GENXY(__NR_fstat,       sys_newfstat),
8638   GENXY(__NR_lstat,       sys_newlstat),
8639   MACX_(__NR_pathconf,    pathconf),
8640   MACX_(__NR_fpathconf,   fpathconf),
8641   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)),   // ???
8642   GENXY(__NR_getrlimit,   sys_getrlimit),
8643   GENX_(__NR_setrlimit,   sys_setrlimit),
8644   MACXY(__NR_getdirentries, getdirentries),
8645   MACXY(__NR_mmap,        mmap),
8646   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)),   // __syscall
8647   MACX_(__NR_lseek,       lseek),
8648   GENX_(__NR_truncate,    sys_truncate64),   // 200
8649   GENX_(__NR_ftruncate,   sys_ftruncate64),
8650   MACXY(__NR___sysctl,    __sysctl),
8651   GENX_(__NR_mlock,       sys_mlock),
8652   GENX_(__NR_munlock,     sys_munlock),
8653// _____(__NR_undelete),
8654// _____(__NR_ATsocket),
8655// _____(__NR_ATgetmsg),
8656// _____(__NR_ATputmsg),
8657// _____(__NR_ATPsndreq),
8658// _____(__NR_ATPsndrsp),
8659// _____(__NR_ATPgetreq),
8660// _____(__NR_ATPgetrsp),
8661   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)),   // Reserved for AppleTalk
8662#if DARWIN_VERS >= DARWIN_10_6
8663   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)),   // old kqueue_from_portset_np
8664   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)),   // old kqueue_portset_np
8665#else
8666// _____(__NR_kqueue_from_portset_np),
8667// _____(__NR_kqueue_portset_np),
8668#endif
8669// _____(__NR_mkcomplex),
8670// _____(__NR_statv),
8671// _____(__NR_lstatv),
8672// _____(__NR_fstatv),
8673   MACXY(__NR_getattrlist, getattrlist),   // 220
8674   MACX_(__NR_setattrlist, setattrlist),
8675   MACXY(__NR_getdirentriesattr, getdirentriesattr),
8676   MACX_(__NR_exchangedata,      exchangedata),
8677   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)),   // checkuseraccess
8678// _____(__NR_searchfs),
8679   GENX_(__NR_delete,      sys_unlink),
8680// _____(__NR_copyfile),
8681#if DARWIN_VERS >= DARWIN_10_6
8682// _____(__NR_fgetattrlist),
8683// _____(__NR_fsetattrlist),
8684#else
8685   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)),   // ??
8686   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)),   // ??
8687#endif
8688   GENXY(__NR_poll,        sys_poll),
8689   MACX_(__NR_watchevent,  watchevent),
8690   MACXY(__NR_waitevent,   waitevent),
8691   MACX_(__NR_modwatch,    modwatch),
8692   MACXY(__NR_getxattr,    getxattr),
8693   MACXY(__NR_fgetxattr,   fgetxattr),
8694   MACX_(__NR_setxattr,    setxattr),
8695   MACX_(__NR_fsetxattr,   fsetxattr),
8696   MACX_(__NR_removexattr, removexattr),
8697   MACX_(__NR_fremovexattr, fremovexattr),
8698   MACXY(__NR_listxattr,   listxattr),    // 240
8699   MACXY(__NR_flistxattr,  flistxattr),
8700   MACXY(__NR_fsctl,       fsctl),
8701   MACX_(__NR_initgroups,  initgroups),
8702   MACXY(__NR_posix_spawn, posix_spawn),
8703#if DARWIN_VERS >= DARWIN_10_6
8704// _____(__NR_ffsctl),
8705#else
8706   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)),   // ???
8707#endif
8708   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)),   // ???
8709// _____(__NR_nfsclnt),
8710// _____(__NR_fhopen),
8711   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)),   // ???
8712// _____(__NR_minherit),
8713// _____(__NR_semsys),
8714// _____(__NR_msgsys),
8715// _____(__NR_shmsys),
8716   MACXY(__NR_semctl,      semctl),
8717   MACX_(__NR_semget,      semget),
8718   MACX_(__NR_semop,       semop),
8719   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)),   // ???
8720// _____(__NR_msgctl),
8721// _____(__NR_msgget),
8722// _____(__NR_msgsnd),   // 260
8723// _____(__NR_msgrcv),
8724   MACXY(__NR_shmat,       shmat),
8725   MACXY(__NR_shmctl,      shmctl),
8726   MACXY(__NR_shmdt,       shmdt),
8727   MACX_(__NR_shmget,      shmget),
8728   MACXY(__NR_shm_open,    shm_open),
8729   MACXY(__NR_shm_unlink,  shm_unlink),
8730   MACX_(__NR_sem_open,    sem_open),
8731   MACX_(__NR_sem_close,   sem_close),
8732   MACX_(__NR_sem_unlink,  sem_unlink),
8733   MACX_(__NR_sem_wait,    sem_wait),
8734   MACX_(__NR_sem_trywait, sem_trywait),
8735   MACX_(__NR_sem_post,    sem_post),
8736// _____(__NR_sem_getvalue),
8737   MACXY(__NR_sem_init,    sem_init),
8738   MACX_(__NR_sem_destroy, sem_destroy),
8739   MACX_(__NR_open_extended,  open_extended),    // 277
8740// _____(__NR_umask_extended),
8741   MACXY(__NR_stat_extended,  stat_extended),
8742   MACXY(__NR_lstat_extended, lstat_extended),   // 280
8743   MACXY(__NR_fstat_extended, fstat_extended),
8744   MACX_(__NR_chmod_extended, chmod_extended),
8745   MACX_(__NR_fchmod_extended,fchmod_extended),
8746   MACXY(__NR_access_extended,access_extended),
8747   MACX_(__NR_settid,         settid),
8748#if DARWIN_VERS >= DARWIN_10_8
8749   MACX_(__NR_gettid, gettid),  // 286
8750#endif
8751// _____(__NR_setsgroups),
8752// _____(__NR_getsgroups),
8753// _____(__NR_setwgroups),
8754// _____(__NR_getwgroups),
8755// _____(__NR_mkfifo_extended),
8756// _____(__NR_mkdir_extended),
8757// _____(__NR_identitysvc),
8758// _____(__NR_shared_region_check_np),
8759// _____(__NR_shared_region_map_np),
8760#if DARWIN_VERS >= DARWIN_10_6
8761// _____(__NR_vm_pressure_monitor),
8762#else
8763   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)),   // old load_shared_file
8764#endif
8765   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)),   // old reset_shared_file
8766   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)),   // old new_system_shared_regions
8767   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)),   // old shared_region_map_file_np
8768   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)),   // old shared_region_make_private_np
8769   MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
8770   MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
8771   MACXY(__NR_psynch_cvbroad,   psynch_cvbroad),   // 303
8772   MACXY(__NR_psynch_cvsignal,  psynch_cvsignal),  // 304
8773   MACXY(__NR_psynch_cvwait,    psynch_cvwait),    // 305
8774   MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
8775   MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
8776   MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
8777   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(309)),   // ???
8778// _____(__NR_getsid),
8779// _____(__NR_settid_with_pid),
8780   MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
8781// _____(__NR_aio_fsync),
8782   MACXY(__NR_aio_return,     aio_return),
8783   MACX_(__NR_aio_suspend,    aio_suspend),
8784// _____(__NR_aio_cancel),
8785   MACX_(__NR_aio_error,      aio_error),
8786   MACXY(__NR_aio_read,       aio_read),
8787   MACX_(__NR_aio_write,      aio_write),
8788// _____(__NR_lio_listio),   // 320
8789   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)),   // ???
8790
8791#if DARWIN_VERS >= DARWIN_10_8
8792   MACXY(__NR_iopolicysys, iopolicysys),
8793   MACXY(__NR_process_policy, process_policy),
8794#else
8795   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)),   // ???
8796   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)),   // ???
8797#endif
8798// _____(__NR_mlockall),
8799// _____(__NR_munlockall),
8800   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)),   // ???
8801   MACX_(__NR_issetugid,               issetugid),
8802   MACX_(__NR___pthread_kill,          __pthread_kill),
8803   MACX_(__NR___pthread_sigmask,       __pthread_sigmask),
8804// _____(__NR___sigwait),
8805   MACX_(__NR___disable_threadsignal,  __disable_threadsignal),
8806   MACX_(__NR___pthread_markcancel,    __pthread_markcancel),
8807   MACX_(__NR___pthread_canceled,      __pthread_canceled),
8808   MACX_(__NR___semwait_signal,        __semwait_signal),
8809   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)),   // old utrace
8810#if DARWIN_VERS >= DARWIN_10_6
8811   MACXY(__NR_proc_info,               proc_info),  // 336
8812#endif
8813   MACXY(__NR_sendfile,    sendfile),
8814   MACXY(__NR_stat64,      stat64),
8815   MACXY(__NR_fstat64,     fstat64),
8816   MACXY(__NR_lstat64,     lstat64),    // 340
8817   MACXY(__NR_stat64_extended,  stat64_extended),
8818   MACXY(__NR_lstat64_extended, lstat64_extended),
8819   MACXY(__NR_fstat64_extended, fstat64_extended),
8820   MACXY(__NR_getdirentries64, getdirentries64),
8821   MACXY(__NR_statfs64,    statfs64),
8822   MACXY(__NR_fstatfs64,   fstatfs64),
8823   MACXY(__NR_getfsstat64, getfsstat64),
8824// _____(__NR___pthread_chdir),
8825// _____(__NR___pthread_fchdir),
8826// _____(__NR_audit),
8827   MACXY(__NR_auditon,     auditon),
8828   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)),   // ???
8829// _____(__NR_getauid),
8830// _____(__NR_setauid),
8831// _____(__NR_getaudit),
8832// _____(__NR_setaudit),
8833#if DARWIN_VERS >= DARWIN_10_7
8834   MACXY(__NR_getaudit_addr, getaudit_addr),
8835#endif
8836// _____(__NR_setaudit_addr),
8837// _____(__NR_auditctl),
8838   MACXY(__NR_bsdthread_create,     bsdthread_create),   // 360
8839   MACX_(__NR_bsdthread_terminate,  bsdthread_terminate),
8840   MACXY(__NR_kqueue,      kqueue),
8841   MACXY(__NR_kevent,      kevent),
8842   GENX_(__NR_lchown,      sys_lchown),
8843// _____(__NR_stack_snapshot),
8844   MACX_(__NR_bsdthread_register, bsdthread_register),
8845   MACX_(__NR_workq_open,  workq_open),
8846   MACXY(__NR_workq_ops,   workq_ops),
8847#if DARWIN_VERS >= DARWIN_10_6
8848   MACXY(__NR_kevent64,      kevent64),
8849#else
8850   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)),   // ???
8851#endif
8852   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)),   // ???
8853   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)),   // ???
8854#if DARWIN_VERS >= DARWIN_10_6
8855   MACX_(__NR___thread_selfid, __thread_selfid),
8856#else
8857   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)),   // ???
8858#endif
8859   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)),   // ???
8860   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)),   // ???
8861   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)),   // ???
8862   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)),   // ???
8863   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)),   // ???
8864   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)),   // ???
8865   _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)),   // ???
8866// _____(__NR___mac_execve),   // 380
8867   MACX_(__NR___mac_syscall, __mac_syscall),
8868// _____(__NR___mac_get_file),
8869// _____(__NR___mac_set_file),
8870// _____(__NR___mac_get_link),
8871// _____(__NR___mac_set_link),
8872// _____(__NR___mac_get_proc),
8873// _____(__NR___mac_set_proc),
8874// _____(__NR___mac_get_fd),
8875// _____(__NR___mac_set_fd),
8876// _____(__NR___mac_get_pid),
8877// _____(__NR___mac_get_lcid),
8878// _____(__NR___mac_get_lctx),
8879// _____(__NR___mac_set_lctx),
8880// _____(__NR_setlcid),
8881// _____(__NR_getlcid),
8882   // GrP fixme need any special nocancel handling?
8883   GENXY(__NR_read_nocancel,     sys_read),
8884   GENX_(__NR_write_nocancel,    sys_write),
8885   GENXY(__NR_open_nocancel,     sys_open),
8886   GENXY(__NR_close_nocancel,    sys_close),
8887   GENXY(__NR_wait4_nocancel,    sys_wait4),   // 400
8888   MACXY(__NR_recvmsg_nocancel,  recvmsg),
8889   MACX_(__NR_sendmsg_nocancel,  sendmsg),
8890   MACXY(__NR_recvfrom_nocancel, recvfrom),
8891   MACXY(__NR_accept_nocancel,   accept),
8892   GENX_(__NR_msync_nocancel,    sys_msync),
8893   MACXY(__NR_fcntl_nocancel,    fcntl),
8894   GENX_(__NR_select_nocancel,   sys_select),
8895   GENX_(__NR_fsync_nocancel,    sys_fsync),
8896   MACX_(__NR_connect_nocancel,  connect),
8897// _____(__NR_sigsuspend_nocancel),
8898   GENXY(__NR_readv_nocancel,    sys_readv),
8899   GENX_(__NR_writev_nocancel,   sys_writev),
8900   MACX_(__NR_sendto_nocancel,   sendto),
8901   GENXY(__NR_pread_nocancel,    sys_pread64),
8902   GENX_(__NR_pwrite_nocancel,   sys_pwrite64),
8903// _____(__NR_waitid_nocancel),
8904   GENXY(__NR_poll_nocancel,     sys_poll),
8905// _____(__NR_msgsnd_nocancel),
8906// _____(__NR_msgrcv_nocancel),
8907   MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
8908// _____(__NR_aio_suspend_nocancel),
8909// _____(__NR___sigwait_nocancel),
8910   MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
8911// _____(__NR___mac_mount),
8912// _____(__NR___mac_get_mount),
8913// _____(__NR___mac_getfsstat),
8914#if DARWIN_VERS >= DARWIN_10_6
8915   MACXY(__NR_fsgetpath, fsgetpath),
8916   MACXY(__NR_audit_session_self, audit_session_self),
8917// _____(__NR_audit_session_join),
8918#endif
8919#if DARWIN_VERS >= DARWIN_10_9
8920    MACX_(__NR_fileport_makeport, fileport_makeport),
8921    MACX_(__NR_guarded_open_np, guarded_open_np),
8922    MACX_(__NR_guarded_close_np, guarded_close_np),
8923    MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
8924    MACX_(__NR_change_fdguard_np, change_fdguard_np),
8925    MACX_(__NR_connectx, connectx),
8926    MACX_(__NR_disconnectx, disconnectx),
8927#endif
8928
8929// _____(__NR_MAXSYSCALL)
8930   MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
8931};
8932
8933
8934// Mach traps use negative syscall numbers.
8935// Use ML_(mach_trap_table)[-mach_trap_number] .
8936// cf xnu sources osfmk/kern/syscall_sw.c
8937
8938const SyscallTableEntry ML_(mach_trap_table)[] = {
8939   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
8940   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
8941   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
8942   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
8943   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
8944   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
8945   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
8946   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
8947   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
8948   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
8949
8950#  if DARWIN_VERS >= DARWIN_10_8
8951   MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
8952#  else
8953   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
8954#  endif
8955
8956   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
8957
8958#  if DARWIN_VERS >= DARWIN_10_8
8959   MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
8960#  else
8961   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
8962#  endif
8963
8964   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
8965
8966#  if DARWIN_VERS >= DARWIN_10_8
8967   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
8968#  endif
8969
8970#  if DARWIN_VERS >= DARWIN_10_9
8971   MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
8972#  endif
8973
8974#  if DARWIN_VERS < DARWIN_10_8
8975   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
8976   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
8977#  endif
8978
8979#  if DARWIN_VERS >= DARWIN_10_8
8980   MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
8981   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
8982   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
8983   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
8984   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
8985   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
8986   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
8987   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
8988#  else
8989   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
8990   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
8991   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
8992   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
8993   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
8994   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
8995   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
8996   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
8997#  endif
8998
8999#  if DARWIN_VERS >= DARWIN_10_9
9000   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
9001   MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
9002#  else
9003   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
9004   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
9005#  endif
9006
9007   MACXY(__NR_mach_reply_port, mach_reply_port),
9008   MACXY(__NR_thread_self_trap, mach_thread_self),
9009   MACXY(__NR_task_self_trap, mach_task_self),
9010   MACXY(__NR_host_self_trap, mach_host_self),
9011   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
9012   MACXY(__NR_mach_msg_trap, mach_msg),
9013// _____(__NR_mach_msg_overwrite_trap),
9014   MACX_(__NR_semaphore_signal_trap, semaphore_signal),
9015   MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
9016   MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
9017   MACX_(__NR_semaphore_wait_trap, semaphore_wait),
9018   MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
9019   MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
9020   MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
9021   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)),    // -40
9022
9023#if defined(VGA_x86)
9024// _____(__NR_init_process),
9025   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
9026// _____(__NR_map_fd),
9027#else
9028#  if DARWIN_VERS >= DARWIN_10_9
9029   MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
9030   MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
9031#  endif
9032   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
9033#endif
9034
9035// _____(__NR_task_name_for_pid),
9036   MACXY(__NR_task_for_pid, task_for_pid),
9037   MACXY(__NR_pid_for_task, pid_for_task),
9038   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
9039#if defined(VGA_x86)
9040// _____(__NR_macx_swapon),
9041// _____(__NR_macx_swapoff),
9042   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
9043// _____(__NR_macx_triggers),
9044// _____(__NR_macx_backing_store_suspend),
9045// _____(__NR_macx_backing_store_recovery),
9046#else
9047   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
9048   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
9049   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
9050   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
9051   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
9052   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
9053#endif
9054   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
9055   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
9056   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
9057   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
9058   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
9059   MACX_(__NR_swtch_pri, swtch_pri),
9060   MACX_(__NR_swtch, swtch),   // -60
9061   MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
9062// _____(__NR_clock_sleep_trap),
9063   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
9064   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
9065   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
9066   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
9067   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
9068   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
9069   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
9070   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
9071   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
9072   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
9073   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
9074   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
9075   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
9076   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
9077   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
9078   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
9079   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
9080   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)),   // -80
9081   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
9082   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
9083   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
9084   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
9085   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
9086   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
9087   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
9088   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
9089   MACXY(__NR_mach_timebase_info, mach_timebase_info),
9090   MACX_(__NR_mach_wait_until, mach_wait_until),
9091   MACXY(__NR_mk_timer_create, mk_timer_create),
9092   MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
9093   MACX_(__NR_mk_timer_arm, mk_timer_arm),
9094   MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
9095   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
9096   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
9097   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
9098   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
9099   _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
9100   MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
9101};
9102
9103
9104// Machine-dependent traps have wacky syscall numbers, and use the Mach trap
9105// calling convention instead of the syscall convention.
9106// Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
9107
9108#if defined(VGA_x86)
9109const SyscallTableEntry ML_(mdep_trap_table)[] = {
9110   MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
9111};
9112#elif defined(VGA_amd64)
9113const SyscallTableEntry ML_(mdep_trap_table)[] = {
9114   MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
9115};
9116#else
9117#error unknown architecture
9118#endif
9119
9120const UInt ML_(syscall_table_size) =
9121            sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
9122
9123const UInt ML_(mach_trap_table_size) =
9124            sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
9125
9126const UInt ML_(mdep_trap_table_size) =
9127            sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
9128
9129#endif // defined(VGO_darwin)
9130
9131/*--------------------------------------------------------------------*/
9132/*--- end                                                          ---*/
9133/*--------------------------------------------------------------------*/
9134