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