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