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