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