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