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