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