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