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