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