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