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