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