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