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