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