Home | History | Annotate | Download | only in m_syswrap
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Darwin-specific syscalls, etc.              syswrap-darwin.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2005-2011 Apple Inc.
     11       Greg Parker  gparker (at) apple.com
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26    02111-1307, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 #if defined(VGO_darwin)
     32 
     33 #include "pub_core_basics.h"
     34 #include "pub_core_vki.h"
     35 #include "pub_core_vkiscnums.h"
     36 #include "pub_core_libcsetjmp.h"   // to keep _threadstate.h happy
     37 #include "pub_core_threadstate.h"
     38 #include "pub_core_aspacemgr.h"
     39 #include "pub_core_xarray.h"
     40 #include "pub_core_clientstate.h"
     41 #include "pub_core_debuglog.h"
     42 #include "pub_core_debuginfo.h"    // VG_(di_notify_*)
     43 #include "pub_core_transtab.h"     // VG_(discard_translations)
     44 #include "pub_tool_gdbserver.h"    // VG_(gdbserver)
     45 #include "pub_core_libcbase.h"
     46 #include "pub_core_libcassert.h"
     47 #include "pub_core_libcfile.h"
     48 #include "pub_core_libcprint.h"
     49 #include "pub_core_libcproc.h"
     50 #include "pub_core_libcsignal.h"
     51 #include "pub_core_machine.h"      // VG_(get_SP)
     52 #include "pub_core_mallocfree.h"
     53 #include "pub_core_options.h"
     54 #include "pub_core_oset.h"
     55 #include "pub_core_scheduler.h"
     56 #include "pub_core_sigframe.h"      // For VG_(sigframe_destroy)()
     57 #include "pub_core_signals.h"
     58 #include "pub_core_syscall.h"
     59 #include "pub_core_syswrap.h"
     60 #include "pub_core_tooliface.h"
     61 
     62 #include "priv_types_n_macros.h"
     63 #include "priv_syswrap-generic.h"   /* for decls of generic wrappers */
     64 #include "priv_syswrap-darwin.h"    /* for decls of darwin-ish wrappers */
     65 #include "priv_syswrap-main.h"
     66 
     67 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
     68 #include <mach/mach.h>
     69 #include <mach/mach_vm.h>
     70 #include <semaphore.h>
     71 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
     72 
     73 #define msgh_request_port      msgh_remote_port
     74 #define msgh_reply_port        msgh_local_port
     75 #define BOOTSTRAP_MAX_NAME_LEN                  128
     76 typedef char name_t[BOOTSTRAP_MAX_NAME_LEN];
     77 
     78 typedef uint64_t mig_addr_t;
     79 
     80 
     81 // Saved ports
     82 static mach_port_t vg_host_port = 0;
     83 static mach_port_t vg_task_port = 0;
     84 static mach_port_t vg_bootstrap_port = 0;
     85 
     86 // Run a thread from beginning to end and return the thread's
     87 // scheduler-return-code.
     88 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
     89 {
     90    VgSchedReturnCode ret;
     91    ThreadId     tid = (ThreadId)tidW;
     92    ThreadState* tst = VG_(get_ThreadState)(tid);
     93 
     94    VG_(debugLog)(1, "syswrap-darwin",
     95                     "thread_wrapper(tid=%lld): entry\n",
     96                     (ULong)tidW);
     97 
     98    vg_assert(tst->status == VgTs_Init);
     99 
    100    /* make sure we get the CPU lock before doing anything significant */
    101    VG_(acquire_BigLock)(tid, "thread_wrapper");
    102 
    103    if (0)
    104       VG_(printf)("thread tid %d started: stack = %p\n",
    105                   tid, &tid);
    106 
    107    /* Make sure error reporting is enabled in the new thread. */
    108    tst->err_disablement_level = 0;
    109 
    110    VG_TRACK(pre_thread_first_insn, tid);
    111 
    112    tst->os_state.lwpid = VG_(gettid)();
    113    tst->os_state.threadgroup = VG_(getpid)();
    114 
    115    /* Thread created with all signals blocked; scheduler will set the
    116       appropriate mask */
    117 
    118    ret = VG_(scheduler)(tid);
    119 
    120    vg_assert(VG_(is_exiting)(tid));
    121 
    122    vg_assert(tst->status == VgTs_Runnable);
    123    vg_assert(VG_(is_running_thread)(tid));
    124 
    125    VG_(debugLog)(1, "syswrap-darwin",
    126                     "thread_wrapper(tid=%lld): done\n",
    127                     (ULong)tidW);
    128 
    129    /* Return to caller, still holding the lock. */
    130    return ret;
    131 }
    132 
    133 
    134 
    135 /* Allocate a stack for this thread, if it doesn't already have one.
    136    Returns the initial stack pointer value to use, or 0 if allocation
    137    failed. */
    138 
    139 Addr allocstack ( ThreadId tid )
    140 {
    141    ThreadState* tst = VG_(get_ThreadState)(tid);
    142    VgStack*     stack;
    143    Addr         initial_SP;
    144 
    145    /* Either the stack_base and stack_init_SP are both zero (in which
    146       case a stack hasn't been allocated) or they are both non-zero,
    147       in which case it has. */
    148 
    149    if (tst->os_state.valgrind_stack_base == 0)
    150       vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
    151 
    152    if (tst->os_state.valgrind_stack_base != 0)
    153       vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
    154 
    155    /* If no stack is present, allocate one. */
    156 
    157    if (tst->os_state.valgrind_stack_base == 0) {
    158       stack = VG_(am_alloc_VgStack)( &initial_SP );
    159       if (stack) {
    160          tst->os_state.valgrind_stack_base    = (Addr)stack;
    161          tst->os_state.valgrind_stack_init_SP = initial_SP;
    162       }
    163    }
    164 
    165    VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
    166                    tid,
    167                    (void*)tst->os_state.valgrind_stack_base,
    168                    (void*)tst->os_state.valgrind_stack_init_SP );
    169 
    170    vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
    171 
    172    return tst->os_state.valgrind_stack_init_SP;
    173 }
    174 
    175 
    176 void find_stack_segment(ThreadId tid, Addr sp)
    177 {
    178    /* We don't really know where the client stack is, because it's
    179       allocated by the client.  The best we can do is look at the
    180       memory mappings and try to derive some useful information.  We
    181       assume that esp starts near its highest possible value, and can
    182       only go down to the start of the mmaped segment. */
    183    ThreadState *tst = VG_(get_ThreadState)(tid);
    184    const NSegment *seg = VG_(am_find_nsegment)(sp);
    185    if (seg && seg->kind != SkResvn) {
    186       tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
    187       tst->client_stack_szB = tst->client_stack_highest_word - seg->start;
    188 
    189       if (1)
    190          VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
    191                      tid, seg->start, VG_PGROUNDUP(sp));
    192    } else {
    193        VG_(printf)("couldn't find user stack\n");
    194       VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n",
    195                    tid, sp);
    196       tst->client_stack_szB  = 0;
    197    }
    198 }
    199 
    200 
    201 /* Run a thread all the way to the end, then do appropriate exit actions
    202    (this is the last-one-out-turn-off-the-lights bit).
    203 */
    204 static void run_a_thread_NORETURN ( Word tidW )
    205 {
    206    Int               c;
    207    VgSchedReturnCode src;
    208    ThreadId          tid = (ThreadId)tidW;
    209    ThreadState*      tst;
    210 
    211    VG_(debugLog)(1, "syswrap-darwin",
    212                     "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
    213                     (ULong)tidW);
    214 
    215    tst = VG_(get_ThreadState)(tid);
    216    vg_assert(tst);
    217 
    218    /* Run the thread all the way through. */
    219    src = thread_wrapper(tid);
    220 
    221    VG_(debugLog)(1, "syswrap-darwin",
    222                     "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
    223                     (ULong)tidW);
    224 
    225    c = VG_(count_living_threads)();
    226    vg_assert(c >= 1); /* stay sane */
    227 
    228    // Tell the tool this thread is exiting
    229    VG_TRACK( pre_thread_ll_exit, tid );
    230 
    231    /* If the thread is exiting with errors disabled, complain loudly;
    232       doing so is bad (does the user know this has happened?)  Also,
    233       in all cases, be paranoid and clear the flag anyway so that the
    234       thread slot is safe in this respect if later reallocated.  This
    235       should be unnecessary since the flag should be cleared when the
    236       slot is reallocated, in thread_wrapper(). */
    237    if (tst->err_disablement_level > 0) {
    238       VG_(umsg)(
    239          "WARNING: exiting thread has error reporting disabled.\n"
    240          "WARNING: possibly as a result of some mistake in the use\n"
    241          "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
    242       );
    243       VG_(debugLog)(
    244          1, "syswrap-linux",
    245             "run_a_thread_NORETURN(tid=%lld): "
    246             "WARNING: exiting thread has err_disablement_level = %u\n",
    247             (ULong)tidW, tst->err_disablement_level
    248       );
    249    }
    250    tst->err_disablement_level = 0;
    251 
    252    if (c == 1) {
    253 
    254       VG_(debugLog)(1, "syswrap-darwin",
    255                        "run_a_thread_NORETURN(tid=%lld): "
    256                           "last one standing\n",
    257                           (ULong)tidW);
    258 
    259       /* We are the last one standing.  Keep hold of the lock and
    260          carry on to show final tool results, then exit the entire system.
    261          Use the continuation pointer set at startup in m_main. */
    262       ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
    263 
    264    } else {
    265 
    266       mach_msg_header_t msg;
    267 
    268       VG_(debugLog)(1, "syswrap-darwin",
    269                        "run_a_thread_NORETURN(tid=%lld): "
    270                           "not last one standing\n",
    271                           (ULong)tidW);
    272 
    273       /* OK, thread is dead, but others still exist.  Just exit. */
    274 
    275       /* This releases the run lock */
    276       VG_(exit_thread)(tid);
    277       vg_assert(tst->status == VgTs_Zombie);
    278 
    279       /* tid is now invalid. */
    280 
    281       // GrP fixme exit race
    282       msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
    283       msg.msgh_request_port = VG_(gettid)();
    284       msg.msgh_reply_port = 0;
    285       msg.msgh_id = 3600;  // thread_terminate
    286 
    287       tst->status = VgTs_Empty;
    288       // GrP fixme race here! new thread may claim this V thread stack
    289       // before we get out here!
    290       // GrP fixme use bsdthread_terminate for safe cleanup?
    291       mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
    292                sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
    293 
    294       // DDD: This is reached sometimes on none/tests/manythreads, maybe
    295       // because of the race above.
    296       VG_(core_panic)("Thread exit failed?\n");
    297    }
    298 
    299    /*NOTREACHED*/
    300    vg_assert(0);
    301 }
    302 
    303 
    304 /* Allocate a stack for the main thread, and run it all the way to the
    305    end.  Although we already have a working VgStack
    306    (VG_(interim_stack)) it's better to allocate a new one, so that
    307    overflow detection works uniformly for all threads.
    308 */
    309 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
    310 {
    311    Addr sp;
    312    VG_(debugLog)(1, "syswrap-darwin",
    313                     "entering VG_(main_thread_wrapper_NORETURN)\n");
    314 
    315    sp = allocstack(tid);
    316 
    317    /* If we can't even allocate the first thread's stack, we're hosed.
    318       Give up. */
    319    vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
    320 
    321    /* shouldn't be any other threads around yet */
    322    vg_assert( VG_(count_living_threads)() == 1 );
    323 
    324    call_on_new_stack_0_1(
    325       (Addr)sp,             /* stack */
    326       0,                     /*bogus return address*/
    327       run_a_thread_NORETURN,  /* fn to call */
    328       (Word)tid              /* arg to give it */
    329    );
    330 
    331    /*NOTREACHED*/
    332    vg_assert(0);
    333 }
    334 
    335 
    336 void start_thread_NORETURN ( Word arg )
    337 {
    338    ThreadState* tst = (ThreadState*)arg;
    339    ThreadId     tid = tst->tid;
    340 
    341    run_a_thread_NORETURN ( (Word)tid );
    342    /*NOTREACHED*/
    343    vg_assert(0);
    344 }
    345 
    346 
    347 void VG_(cleanup_thread) ( ThreadArchState* arch )
    348 {
    349 }
    350 
    351 
    352 /* ---------------------------------------------------------------------
    353    Mach port tracking (based on syswrap-generic's fd tracker)
    354    ------------------------------------------------------------------ */
    355 
    356 /* One of these is allocated for each open port.  */
    357 typedef struct OpenPort
    358 {
    359    mach_port_t port;
    360    mach_port_type_t type;         /* right type(s) */
    361    Int send_count;                /* number of send rights */
    362    Char *name;                    /* bootstrap name or NULL */
    363    ExeContext *where;             /* first allocation only */
    364    struct OpenPort *next, *prev;
    365 } OpenPort;
    366 
    367 // strlen("0x12345678")
    368 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
    369 
    370 /* List of allocated ports. */
    371 static OpenPort *allocated_ports;
    372 
    373 /* Count of open ports. */
    374 static Int allocated_port_count = 0;
    375 
    376 
    377 __attribute__((unused))
    378 static Bool port_exists(mach_port_t port)
    379 {
    380    OpenPort *i;
    381 
    382    /* Check to see if this port is already open. */
    383    i = allocated_ports;
    384    while (i) {
    385       if (i->port == port) {
    386          return True;
    387       }
    388       i = i->next;
    389    }
    390 
    391    return False;
    392 }
    393 
    394 static OpenPort *info_for_port(mach_port_t port)
    395 {
    396    OpenPort *i;
    397    if (!port) return NULL;
    398 
    399    i = allocated_ports;
    400    while (i) {
    401       if (i->port == port) {
    402          return i;
    403       }
    404       i = i->next;
    405    }
    406 
    407    return NULL;
    408 }
    409 
    410 
    411 // Give a port a name, without changing its refcount
    412 // GrP fixme don't override name if it already has a specific one
    413 __private_extern__ void assign_port_name(mach_port_t port, const char *name)
    414 {
    415    OpenPort *i;
    416    if (!port) return;
    417    vg_assert(name);
    418 
    419    i = info_for_port(port);
    420    vg_assert(i);
    421 
    422    if (i->name) VG_(arena_free)(VG_AR_CORE, i->name);
    423    i->name =
    424        VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name",
    425                          VG_(strlen)(name) + PORT_STRLEN + 1);
    426    VG_(sprintf)(i->name, name, port);
    427 }
    428 
    429 
    430 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
    431 static const char *name_for_port(mach_port_t port)
    432 {
    433    static char buf[8 + PORT_STRLEN + 1];
    434    OpenPort *i;
    435 
    436    // hack
    437    if (port == VG_(gettid)()) return "mach_thread_self()";
    438    if (port == 0) return "NULL";
    439 
    440    i = allocated_ports;
    441    while (i) {
    442       if (i->port == port) {
    443          return i->name;
    444       }
    445       i = i->next;
    446    }
    447 
    448    VG_(sprintf)(buf, "NONPORT-%#x", port);
    449    return buf;
    450 }
    451 
    452 /* Note the fact that a port was just deallocated. */
    453 
    454 static
    455 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
    456 {
    457    OpenPort *i = allocated_ports;
    458    if (!port) return;
    459 
    460    while(i) {
    461       if(i->port == port) {
    462          vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
    463          if (right & MACH_PORT_TYPE_SEND) {
    464             // send rights are refcounted
    465             if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
    466             i->send_count += delta;
    467             if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
    468             else i->type &= ~MACH_PORT_TYPE_SEND;
    469          }
    470          right = right & ~MACH_PORT_TYPE_SEND;
    471          if (right) {
    472             // other rights are not refcounted
    473             if (delta > 0) {
    474                i->type |= right;
    475             } else if (delta < 0) {
    476                i->type &= ~right;
    477             }
    478          }
    479 
    480          if (i->type != 0) return;
    481 
    482          // Port has no rights left. Kill it.
    483          // VG_(printf)("deleting port %p %s", i->port, i->name);
    484          if(i->prev)
    485             i->prev->next = i->next;
    486          else
    487             allocated_ports = i->next;
    488          if(i->next)
    489             i->next->prev = i->prev;
    490          if(i->name)
    491             VG_(arena_free) (VG_AR_CORE, i->name);
    492          VG_(arena_free) (VG_AR_CORE, i);
    493          allocated_port_count--;
    494          return;
    495       }
    496       i = i->next;
    497    }
    498 
    499    VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
    500 }
    501 
    502 static
    503 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
    504 {
    505    switch (type) {
    506    case MACH_MSG_TYPE_PORT_NAME:
    507       // this task has no rights for the name
    508       break;
    509    case MACH_MSG_TYPE_PORT_RECEIVE:
    510       // this task gets receive rights
    511       record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
    512       break;
    513    case MACH_MSG_TYPE_PORT_SEND:
    514       // this task gets a send right
    515       record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
    516       break;
    517    case MACH_MSG_TYPE_PORT_SEND_ONCE:
    518       // this task gets send-once rights
    519       record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
    520       break;
    521    default:
    522       vg_assert(0);
    523       break;
    524    }
    525 }
    526 
    527 static
    528 void record_port_dealloc(mach_port_t port)
    529 {
    530    // deletes 1 send or send-once right (port can't have both)
    531    record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
    532 }
    533 
    534 static
    535 void record_port_destroy(mach_port_t port)
    536 {
    537    // deletes all rights to port
    538    record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
    539 }
    540 
    541 
    542 /* Note the fact that a Mach port was just allocated or transferred.
    543    If the port is already known, increment its reference count. */
    544 void record_named_port(ThreadId tid, mach_port_t port,
    545                        mach_port_right_t right, const char *name)
    546 {
    547    OpenPort *i;
    548    if (!port) return;
    549 
    550    /* Check to see if this port is already open. */
    551    i = allocated_ports;
    552    while (i) {
    553       if (i->port == port) {
    554          if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
    555          return;
    556       }
    557       i = i->next;
    558    }
    559 
    560    /* Not already one: allocate an OpenPort */
    561    if (i == NULL) {
    562       i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port",
    563                             sizeof(OpenPort));
    564 
    565       i->prev = NULL;
    566       i->next = allocated_ports;
    567       if(allocated_ports) allocated_ports->prev = i;
    568       allocated_ports = i;
    569       allocated_port_count++;
    570 
    571       i->port = port;
    572       i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
    573       i->name = NULL;
    574       if (right != -1) {
    575          i->type = MACH_PORT_TYPE(right);
    576          i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
    577       } else {
    578          i->type = 0;
    579          i->send_count = 0;
    580       }
    581 
    582       assign_port_name(port, name);
    583    }
    584 }
    585 
    586 
    587 // Record opening of a nameless port.
    588 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
    589 {
    590    record_named_port(tid, port, right, "unnamed-%p");
    591 }
    592 
    593 
    594 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
    595 void VG_(show_open_ports)(void)
    596 {
    597    OpenPort *i;
    598 
    599    VG_(message)(Vg_UserMsg,
    600                 "MACH PORTS: %d open at exit.", allocated_port_count);
    601 
    602    for (i = allocated_ports; i; i = i->next) {
    603       if (i->name) {
    604          VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name);
    605       } else {
    606          VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port);
    607       }
    608 
    609       if (i->where) {
    610          VG_(pp_ExeContext)(i->where);
    611          VG_(message)(Vg_UserMsg, "");
    612       }
    613    }
    614 
    615    VG_(message)(Vg_UserMsg, "");
    616 }
    617 
    618 
    619 /* ---------------------------------------------------------------------
    620    sync_mappings
    621    ------------------------------------------------------------------ */
    622 
    623 void ML_(sync_mappings)(const HChar *when, const HChar *where, Int num)
    624 {
    625    // Usually the number of segments added/removed in a single calls is very
    626    // small e.g. 1.  But it sometimes gets up to at least 100 or so (eg. for
    627    // Quicktime).  So we use a repeat-with-bigger-buffers-until-success model,
    628    // because we can't do dynamic allocation within VG_(get_changed_segments),
    629    // because it's in m_aspacemgr.
    630    ChangedSeg* css = NULL;
    631    Int         css_size;
    632    Int         css_used;
    633    Int         i;
    634    Bool        ok;
    635 
    636    if (VG_(clo_trace_syscalls)) {
    637        VG_(debugLog)(0, "syswrap-darwin",
    638                      "sync_mappings(\"%s\", \"%s\", %d)\n",
    639                      when, where, num);
    640    }
    641 
    642    // 16 is enough for most cases, but small enough that overflow happens
    643    // occasionally and thus the overflow path gets some test coverage.
    644    css_size = 16;
    645    ok = False;
    646    while (!ok) {
    647       VG_(free)(css);   // css is NULL on first iteration;  that's ok.
    648       css = VG_(malloc)("sys_wrap.sync_mappings", css_size*sizeof(ChangedSeg));
    649       ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
    650       css_size *= 2;
    651    }
    652 
    653    // Now add/remove them.
    654    for (i = 0; i < css_used; i++) {
    655       ChangedSeg* cs = &css[i];
    656       Char* action;
    657       if (cs->is_added) {
    658          ML_(notify_core_and_tool_of_mmap)(
    659                cs->start, cs->end - cs->start + 1,
    660                cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
    661          // should this call VG_(di_notify_mmap) also?
    662          action = "added";
    663 
    664       } else {
    665          ML_(notify_core_and_tool_of_munmap)(
    666                cs->start, cs->end - cs->start + 1);
    667          action = "removed";
    668       }
    669       if (VG_(clo_trace_syscalls)) {
    670           VG_(debugLog)(0, "syswrap-darwin",
    671                         "  %s region 0x%010lx..0x%010lx at %s (%s)\n",
    672                         action, cs->start, cs->end + 1, where, when);
    673       }
    674    }
    675 
    676    VG_(free)(css);
    677 }
    678 
    679 /* ---------------------------------------------------------------------
    680    wrappers
    681    ------------------------------------------------------------------ */
    682 
    683 #define PRE(name)       DEFN_PRE_TEMPLATE(darwin, name)
    684 #define POST(name)      DEFN_POST_TEMPLATE(darwin, name)
    685 
    686 #define PRE_FN(name)    vgSysWrap_darwin_##name##_before
    687 #define POST_FN(name)   vgSysWrap_darwin_##name##_after
    688 
    689 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
    690 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
    691 
    692 #if VG_WORDSIZE == 4
    693 // Combine two 32-bit values into a 64-bit value
    694 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
    695 # if defined(VGA_x86)
    696 #  define LOHI64(lo,hi)   ( (lo) | ((ULong)(hi) << 32) )
    697 # else
    698 #  error unknown architecture
    699 # endif
    700 #endif
    701 
    702 // Retrieve the current Mach thread
    703 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
    704 
    705 // Set the POST handler for a mach_msg derivative
    706 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
    707 
    708 // Set or get values saved from Mach messages
    709 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
    710 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
    711 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
    712 
    713 /* ---------------------------------------------------------------------
    714    darwin ioctl wrapper
    715    ------------------------------------------------------------------ */
    716 
    717 PRE(ioctl)
    718 {
    719    *flags |= SfMayBlock;
    720 
    721    /* Handle ioctls that don't take an arg first */
    722    switch (ARG2 /* request */) {
    723    case VKI_TIOCSCTTY:
    724    case VKI_TIOCEXCL:
    725    case VKI_TIOCPTYGRANT:
    726    case VKI_TIOCPTYUNLK:
    727    case VKI_DTRACEHIOC_REMOVE:
    728       PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
    729       PRE_REG_READ2(long, "ioctl",
    730                     unsigned int, fd, unsigned int, request);
    731       return;
    732    default:
    733       PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
    734       PRE_REG_READ3(long, "ioctl",
    735                     unsigned int, fd, unsigned int, request, unsigned long, arg);
    736    }
    737 
    738    switch (ARG2 /* request */) {
    739    case VKI_TIOCGWINSZ:
    740       PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
    741       break;
    742    case VKI_TIOCSWINSZ:
    743       PRE_MEM_READ( "ioctl(TIOCSWINSZ)",  ARG3, sizeof(struct vki_winsize) );
    744       break;
    745    case VKI_TIOCMBIS:
    746       PRE_MEM_READ( "ioctl(TIOCMBIS)",    ARG3, sizeof(unsigned int) );
    747       break;
    748    case VKI_TIOCMBIC:
    749       PRE_MEM_READ( "ioctl(TIOCMBIC)",    ARG3, sizeof(unsigned int) );
    750       break;
    751    case VKI_TIOCMSET:
    752       PRE_MEM_READ( "ioctl(TIOCMSET)",    ARG3, sizeof(unsigned int) );
    753       break;
    754    case VKI_TIOCMGET:
    755       PRE_MEM_WRITE( "ioctl(TIOCMGET)",   ARG3, sizeof(unsigned int) );
    756       break;
    757    case VKI_TIOCGPGRP:
    758       /* Get process group ID for foreground processing group. */
    759       PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
    760       break;
    761    case VKI_TIOCSPGRP:
    762       /* Set a process group ID? */
    763       PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
    764       break;
    765    case VKI_FIONBIO:
    766       PRE_MEM_READ( "ioctl(FIONBIO)",    ARG3, sizeof(int) );
    767       break;
    768    case VKI_FIOASYNC:
    769       PRE_MEM_READ( "ioctl(FIOASYNC)",   ARG3, sizeof(int) );
    770       break;
    771    case VKI_FIONREAD:                /* identical to SIOCINQ */
    772       PRE_MEM_WRITE( "ioctl(FIONREAD)",  ARG3, sizeof(int) );
    773       break;
    774 
    775 
    776       /* These all use struct ifreq AFAIK */
    777       /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
    778    case VKI_SIOCGIFFLAGS:        /* get flags                    */
    779       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
    780                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    781       PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
    782       break;
    783    case VKI_SIOCGIFMTU:          /* get MTU size                 */
    784       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
    785                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    786       PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
    787       break;
    788    case VKI_SIOCGIFADDR:         /* get PA address               */
    789       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
    790                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    791       PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
    792       break;
    793    case VKI_SIOCGIFNETMASK:      /* get network PA mask          */
    794       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
    795                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    796       PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
    797       break;
    798    case VKI_SIOCGIFMETRIC:       /* get metric                   */
    799       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
    800                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    801       PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
    802       break;
    803    case VKI_SIOCGIFDSTADDR:      /* get remote PA address        */
    804       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
    805                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    806       PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
    807       break;
    808    case VKI_SIOCGIFBRDADDR:      /* get broadcast PA address     */
    809       PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
    810                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    811       PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
    812       break;
    813    case VKI_SIOCGIFCONF:         /* get iface list               */
    814       /* WAS:
    815          PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
    816          KERNEL_DO_SYSCALL(tid,RES);
    817          if (!VG_(is_kerror)(RES) && RES == 0)
    818          POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
    819       */
    820       PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
    821                     (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
    822                     sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
    823       PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
    824                     (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
    825                     sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
    826       if ( ARG3 ) {
    827          // TODO len must be readable and writable
    828          // buf pointer only needs to be readable
    829          struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
    830          PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
    831                         (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
    832       }
    833       break;
    834 
    835    case VKI_SIOCSIFFLAGS:        /* set flags                    */
    836       PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
    837                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    838       PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
    839                      (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
    840                      sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
    841       break;
    842    case VKI_SIOCSIFADDR:         /* set PA address               */
    843    case VKI_SIOCSIFDSTADDR:      /* set remote PA address        */
    844    case VKI_SIOCSIFBRDADDR:      /* set broadcast PA address     */
    845    case VKI_SIOCSIFNETMASK:      /* set network PA mask          */
    846       PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
    847                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    848       PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
    849                      (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
    850                      sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
    851       break;
    852    case VKI_SIOCSIFMETRIC:       /* set metric                   */
    853       PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
    854                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    855       PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
    856                      (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
    857                      sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
    858       break;
    859    case VKI_SIOCSIFMTU:          /* set MTU size                 */
    860       PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
    861                      (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
    862       PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
    863                      (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
    864                      sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
    865       break;
    866       /* Routing table calls.  */
    867 #ifdef VKI_SIOCADDRT
    868    case VKI_SIOCADDRT:           /* add routing table entry      */
    869    case VKI_SIOCDELRT:           /* delete routing table entry   */
    870       PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
    871                     sizeof(struct vki_rtentry));
    872       break;
    873 #endif
    874 
    875    case VKI_SIOCGPGRP:
    876       PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
    877       break;
    878    case VKI_SIOCSPGRP:
    879       PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
    880       //tst->sys_flags &= ~SfMayBlock;
    881       break;
    882 
    883    case VKI_FIODTYPE:
    884       PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
    885       break;
    886 
    887    case VKI_DTRACEHIOC_ADDDOF:
    888        break;
    889 
    890        // ttycom.h
    891    case VKI_TIOCGETA:
    892        PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
    893        break;
    894    case VKI_TIOCSETA:
    895        PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
    896        break;
    897    case VKI_TIOCGETD:
    898        PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
    899        break;
    900    case VKI_TIOCSETD:
    901        PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
    902        break;
    903    case VKI_TIOCPTYGNAME:
    904        PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
    905        break;
    906 
    907    default:
    908       ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
    909       break;
    910    }
    911 }
    912 
    913 
    914 POST(ioctl)
    915 {
    916    vg_assert(SUCCESS);
    917    switch (ARG2 /* request */) {
    918    case VKI_TIOCGWINSZ:
    919       POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
    920       break;
    921    case VKI_TIOCSWINSZ:
    922    case VKI_TIOCMBIS:
    923    case VKI_TIOCMBIC:
    924    case VKI_TIOCMSET:
    925       break;
    926    case VKI_TIOCMGET:
    927       POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
    928       break;
    929    case VKI_TIOCGPGRP:
    930       /* Get process group ID for foreground processing group. */
    931       POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
    932       break;
    933    case VKI_TIOCSPGRP:
    934       /* Set a process group ID? */
    935       POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
    936       break;
    937    case VKI_TIOCSCTTY:
    938       break;
    939    case VKI_FIONBIO:
    940       break;
    941    case VKI_FIOASYNC:
    942       break;
    943    case VKI_FIONREAD:                /* identical to SIOCINQ */
    944       POST_MEM_WRITE( ARG3, sizeof(int) );
    945       break;
    946 
    947       /* These all use struct ifreq AFAIK */
    948    case VKI_SIOCGIFFLAGS:        /* get flags                    */
    949       POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
    950                       sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
    951       break;
    952    case VKI_SIOCGIFMTU:          /* get MTU size                 */
    953       POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
    954                       sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
    955       break;
    956    case VKI_SIOCGIFADDR:         /* get PA address               */
    957    case VKI_SIOCGIFDSTADDR:      /* get remote PA address        */
    958    case VKI_SIOCGIFBRDADDR:      /* get broadcast PA address     */
    959    case VKI_SIOCGIFNETMASK:      /* get network PA mask          */
    960       POST_MEM_WRITE(
    961                 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
    962                 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
    963       break;
    964    case VKI_SIOCGIFMETRIC:       /* get metric                   */
    965       POST_MEM_WRITE(
    966                 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
    967                 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
    968       break;
    969    case VKI_SIOCGIFCONF:         /* get iface list               */
    970       /* WAS:
    971          PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
    972          KERNEL_DO_SYSCALL(tid,RES);
    973          if (!VG_(is_kerror)(RES) && RES == 0)
    974          POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
    975       */
    976       if (RES == 0 && ARG3 ) {
    977          struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
    978          if (ifc->vki_ifc_buf != NULL)
    979             POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
    980       }
    981       break;
    982 
    983    case VKI_SIOCSIFFLAGS:        /* set flags                    */
    984    case VKI_SIOCSIFDSTADDR:      /* set remote PA address        */
    985    case VKI_SIOCSIFBRDADDR:      /* set broadcast PA address     */
    986    case VKI_SIOCSIFNETMASK:      /* set network PA mask          */
    987    case VKI_SIOCSIFMETRIC:       /* set metric                   */
    988    case VKI_SIOCSIFADDR:         /* set PA address               */
    989    case VKI_SIOCSIFMTU:          /* set MTU size                 */
    990       break;
    991 
    992 #ifdef VKI_SIOCADDRT
    993       /* Routing table calls.  */
    994    case VKI_SIOCADDRT:           /* add routing table entry      */
    995    case VKI_SIOCDELRT:           /* delete routing table entry   */
    996       break;
    997 #endif
    998 
    999    case VKI_SIOCGPGRP:
   1000       POST_MEM_WRITE(ARG3, sizeof(int));
   1001       break;
   1002    case VKI_SIOCSPGRP:
   1003       break;
   1004 
   1005    case VKI_FIODTYPE:
   1006       POST_MEM_WRITE( ARG3, sizeof(int) );
   1007       break;
   1008 
   1009    case VKI_DTRACEHIOC_REMOVE:
   1010    case VKI_DTRACEHIOC_ADDDOF:
   1011        break;
   1012 
   1013        // ttycom.h
   1014    case VKI_TIOCGETA:
   1015        POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
   1016        break;
   1017    case VKI_TIOCSETA:
   1018        break;
   1019    case VKI_TIOCGETD:
   1020        POST_MEM_WRITE( ARG3, sizeof(int) );
   1021        break;
   1022    case VKI_TIOCSETD:
   1023        break;
   1024    case VKI_TIOCPTYGNAME:
   1025        POST_MEM_WRITE( ARG3, 128);
   1026        break;
   1027    case VKI_TIOCPTYGRANT:
   1028    case VKI_TIOCPTYUNLK:
   1029        break;
   1030 
   1031    default:
   1032       break;
   1033    }
   1034 }
   1035 
   1036 
   1037 /* ---------------------------------------------------------------------
   1038    darwin fcntl wrapper
   1039    ------------------------------------------------------------------ */
   1040 static const char *name_for_fcntl(UWord cmd) {
   1041 #define F(n) case VKI_##n: return #n
   1042    switch (cmd) {
   1043       F(F_CHKCLEAN);
   1044       F(F_RDAHEAD);
   1045       F(F_NOCACHE);
   1046       F(F_FULLFSYNC);
   1047       F(F_FREEZE_FS);
   1048       F(F_THAW_FS);
   1049       F(F_GLOBAL_NOCACHE);
   1050       F(F_PREALLOCATE);
   1051       F(F_SETSIZE);
   1052       F(F_RDADVISE);
   1053       F(F_READBOOTSTRAP);
   1054       F(F_WRITEBOOTSTRAP);
   1055       F(F_LOG2PHYS);
   1056       F(F_GETPATH);
   1057       F(F_PATHPKG_CHECK);
   1058       F(F_ADDSIGS);
   1059    default:
   1060       return "UNKNOWN";
   1061    }
   1062 #undef F
   1063 }
   1064 
   1065 PRE(fcntl)
   1066 {
   1067    switch (ARG2) {
   1068    // These ones ignore ARG3.
   1069    case VKI_F_GETFD:
   1070    case VKI_F_GETFL:
   1071    case VKI_F_GETOWN:
   1072       PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
   1073       PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
   1074       break;
   1075 
   1076    // These ones use ARG3 as "arg".
   1077    case VKI_F_DUPFD:
   1078    case VKI_F_SETFD:
   1079    case VKI_F_SETFL:
   1080    case VKI_F_SETOWN:
   1081       PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
   1082       PRE_REG_READ3(long, "fcntl",
   1083                     unsigned int, fd, unsigned int, cmd, unsigned long, arg);
   1084       break;
   1085 
   1086    // These ones use ARG3 as "lock".
   1087    case VKI_F_GETLK:
   1088    case VKI_F_SETLK:
   1089    case VKI_F_SETLKW:
   1090       PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
   1091       PRE_REG_READ3(long, "fcntl",
   1092                     unsigned int, fd, unsigned int, cmd,
   1093                     struct flock64 *, lock);
   1094       // GrP fixme mem read sizeof(flock64)
   1095       if (ARG2 == VKI_F_SETLKW)
   1096          *flags |= SfMayBlock;
   1097       break;
   1098 
   1099        // none
   1100    case VKI_F_CHKCLEAN:
   1101    case VKI_F_RDAHEAD:
   1102    case VKI_F_NOCACHE:
   1103    case VKI_F_FULLFSYNC:
   1104    case VKI_F_FREEZE_FS:
   1105    case VKI_F_THAW_FS:
   1106    case VKI_F_GLOBAL_NOCACHE:
   1107       PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
   1108       PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
   1109       break;
   1110 
   1111        // struct fstore
   1112    case VKI_F_PREALLOCATE:
   1113       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1114       PRE_REG_READ3(long, "fcntl",
   1115                     unsigned int, fd, unsigned int, cmd,
   1116                     struct fstore *, fstore);
   1117       {
   1118          struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
   1119          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
   1120                          fstore->fst_flags );
   1121          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
   1122                          fstore->fst_posmode );
   1123          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
   1124                          fstore->fst_offset );
   1125          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
   1126                          fstore->fst_length );
   1127          PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
   1128                           fstore->fst_bytesalloc);
   1129       }
   1130       break;
   1131 
   1132        // off_t
   1133    case VKI_F_SETSIZE:
   1134       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1135       PRE_REG_READ3(long, "fcntl",
   1136                     unsigned int, fd, unsigned int, cmd,
   1137                     vki_off_t *, offset);
   1138       break;
   1139 
   1140        // struct radvisory
   1141    case VKI_F_RDADVISE:
   1142       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1143       PRE_REG_READ3(long, "fcntl",
   1144                     unsigned int, fd, unsigned int, cmd,
   1145                     struct vki_radvisory *, radvisory);
   1146       {
   1147          struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
   1148          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
   1149                          radvisory->ra_offset );
   1150          PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
   1151                          radvisory->ra_count );
   1152       }
   1153       break;
   1154 
   1155        // struct fbootstraptransfer
   1156    case VKI_F_READBOOTSTRAP:
   1157    case VKI_F_WRITEBOOTSTRAP:
   1158       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1159       PRE_REG_READ3(long, "fcntl",
   1160                     unsigned int, fd, unsigned int, cmd,
   1161                     struct fbootstraptransfer *, bootstrap);
   1162       PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
   1163                     ARG3, sizeof(struct vki_fbootstraptransfer) );
   1164       break;
   1165 
   1166        // struct log2phys (out)
   1167    case VKI_F_LOG2PHYS:
   1168       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1169       PRE_REG_READ3(long, "fcntl",
   1170                     unsigned int, fd, unsigned int, cmd,
   1171                     struct log2phys *, l2p);
   1172       PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
   1173                      ARG3, sizeof(struct vki_log2phys) );
   1174       break;
   1175 
   1176        // char[maxpathlen] (out)
   1177    case VKI_F_GETPATH:
   1178       PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
   1179       PRE_REG_READ3(long, "fcntl",
   1180                     unsigned int, fd, unsigned int, cmd,
   1181                     char *, pathbuf);
   1182       PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
   1183                      ARG3, VKI_MAXPATHLEN );
   1184       break;
   1185 
   1186        // char[maxpathlen] (in)
   1187    case VKI_F_PATHPKG_CHECK:
   1188       PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
   1189           (char *)ARG3);
   1190       PRE_REG_READ3(long, "fcntl",
   1191                     unsigned int, fd, unsigned int, cmd,
   1192                     char *, pathbuf);
   1193       PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
   1194       break;
   1195 
   1196    case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
   1197       PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
   1198       PRE_REG_READ3(long, "fcntl",
   1199                     unsigned int, fd, unsigned int, cmd,
   1200                     vki_fsignatures_t *, sigs);
   1201 
   1202       {
   1203          vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
   1204          PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
   1205                          fsigs->fs_blob_start);
   1206          PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
   1207                          fsigs->fs_blob_size);
   1208 
   1209          if (fsigs->fs_blob_start)
   1210             PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
   1211                           (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
   1212       }
   1213       break;
   1214 
   1215    default:
   1216       PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
   1217       VG_(printf)("UNKNOWN fcntl %ld!", ARG2);
   1218       break;
   1219    }
   1220 }
   1221 
   1222 POST(fcntl)
   1223 {
   1224    vg_assert(SUCCESS);
   1225    switch (ARG2) {
   1226    case VKI_F_DUPFD:
   1227       if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
   1228          VG_(close)(RES);
   1229          SET_STATUS_Failure( VKI_EMFILE );
   1230       } else {
   1231          if (VG_(clo_track_fds))
   1232             ML_(record_fd_open_named)(tid, RES);
   1233       }
   1234       break;
   1235 
   1236    case VKI_F_GETFD:
   1237    case VKI_F_GETFL:
   1238    case VKI_F_GETOWN:
   1239    case VKI_F_SETFD:
   1240    case VKI_F_SETFL:
   1241    case VKI_F_SETOWN:
   1242    case VKI_F_GETLK:
   1243    case VKI_F_SETLK:
   1244    case VKI_F_SETLKW:
   1245        break;
   1246 
   1247    case VKI_F_PREALLOCATE:
   1248       {
   1249          struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
   1250          POST_FIELD_WRITE( fstore->fst_bytesalloc );
   1251       }
   1252       break;
   1253 
   1254    case VKI_F_LOG2PHYS:
   1255       POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
   1256       break;
   1257 
   1258    case VKI_F_GETPATH:
   1259       POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
   1260       PRINT("\"%s\"", (char*)ARG3);
   1261       break;
   1262 
   1263    default:
   1264       // DDD: ugh, missing lots of cases here, not nice
   1265       break;
   1266    }
   1267 }
   1268 
   1269 /* ---------------------------------------------------------------------
   1270    unix syscalls
   1271    ------------------------------------------------------------------ */
   1272 
   1273 PRE(futimes)
   1274 {
   1275    PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
   1276    PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
   1277    if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
   1278       SET_STATUS_Failure( VKI_EBADF );
   1279    } else if (ARG2 != 0) {
   1280       PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
   1281       PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
   1282    }
   1283 }
   1284 
   1285 PRE(semget)
   1286 {
   1287    PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
   1288    PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
   1289 }
   1290 
   1291 PRE(semop)
   1292 {
   1293    *flags |= SfMayBlock;
   1294    PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
   1295    PRE_REG_READ3(long, "semop",
   1296                  int, semid, struct sembuf *, sops, vki_size_t, nsoops);
   1297    ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
   1298 }
   1299 
   1300 PRE(semctl)
   1301 {
   1302    switch (ARG3) {
   1303    case VKI_IPC_STAT:
   1304    case VKI_IPC_SET:
   1305       PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
   1306       PRE_REG_READ4(long, "semctl",
   1307                     int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
   1308       break;
   1309    case VKI_GETALL:
   1310    case VKI_SETALL:
   1311       PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
   1312       PRE_REG_READ4(long, "semctl",
   1313                     int, semid, int, semnum, int, cmd, unsigned short *, arg);
   1314       break;
   1315    case VKI_SETVAL:
   1316       PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
   1317       PRE_REG_READ4(long, "semctl",
   1318                     int, semid, int, semnum, int, cmd, int, arg);
   1319       break;
   1320    default:
   1321       PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
   1322       PRE_REG_READ3(long, "semctl",
   1323                     int, semid, int, semnum, int, cmd);
   1324       break;
   1325    }
   1326    ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
   1327 }
   1328 POST(semctl)
   1329 {
   1330    ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
   1331 }
   1332 
   1333 PRE(sem_open)
   1334 {
   1335    if (ARG2 & VKI_O_CREAT) {
   1336       // 4-arg version
   1337       PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
   1338             ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
   1339       PRE_REG_READ4(vki_sem_t *, "sem_open",
   1340                     const char *, name, int, oflag, vki_mode_t, mode,
   1341                     unsigned int, value);
   1342    } else {
   1343       // 2-arg version
   1344       PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
   1345       PRE_REG_READ2(vki_sem_t *, "sem_open",
   1346                     const char *, name, int, oflag);
   1347    }
   1348    PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
   1349 
   1350    /* Otherwise handle normally */
   1351    *flags |= SfMayBlock;
   1352 }
   1353 
   1354 PRE(sem_close)
   1355 {
   1356    PRINT("sem_close( %#lx )", ARG1);
   1357    PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
   1358 }
   1359 
   1360 PRE(sem_unlink)
   1361 {
   1362    PRINT("sem_unlink(  %#lx(%s) )", ARG1,(char*)ARG1);
   1363    PRE_REG_READ1(int, "sem_unlink", const char *, name);
   1364    PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
   1365 }
   1366 
   1367 PRE(sem_post)
   1368 {
   1369    PRINT("sem_post( %#lx )", ARG1);
   1370    PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
   1371    *flags |= SfMayBlock;
   1372 }
   1373 
   1374 PRE(sem_destroy)
   1375 {
   1376   PRINT("sem_destroy( %#lx )", ARG1);
   1377   PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
   1378   PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
   1379 }
   1380 
   1381 PRE(sem_init)
   1382 {
   1383   PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
   1384   PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
   1385                 int, pshared, unsigned int, value);
   1386   PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
   1387 }
   1388 
   1389 POST(sem_init)
   1390 {
   1391   POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
   1392 }
   1393 
   1394 PRE(sem_wait)
   1395 {
   1396    PRINT("sem_wait( %#lx )", ARG1);
   1397    PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
   1398    *flags |= SfMayBlock;
   1399 }
   1400 
   1401 PRE(sem_trywait)
   1402 {
   1403    PRINT("sem_trywait( %#lx )", ARG1);
   1404    PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
   1405    *flags |= SfMayBlock;
   1406 }
   1407 
   1408 PRE(kqueue)
   1409 {
   1410     PRINT("kqueue()");
   1411 }
   1412 
   1413 POST(kqueue)
   1414 {
   1415    if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
   1416       VG_(close)(RES);
   1417       SET_STATUS_Failure( VKI_EMFILE );
   1418    } else {
   1419       if (VG_(clo_track_fds)) {
   1420          ML_(record_fd_open_with_given_name)(tid, RES, NULL);
   1421       }
   1422    }
   1423 }
   1424 
   1425 PRE(kevent)
   1426 {
   1427    PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
   1428          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
   1429    PRE_REG_READ6(int,"kevent", int,kq,
   1430                  const struct vki_kevent *,changelist, int,nchanges,
   1431                  struct vki_kevent *,eventlist, int,nevents,
   1432                  const struct vki_timespec *,timeout);
   1433 
   1434    if (ARG3) PRE_MEM_READ ("kevent(changelist)",
   1435                            ARG2, ARG3 * sizeof(struct vki_kevent));
   1436    if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
   1437                            ARG4, ARG5 * sizeof(struct vki_kevent));
   1438    if (ARG6) PRE_MEM_READ ("kevent(timeout)",
   1439                            ARG6, sizeof(struct vki_timespec));
   1440 
   1441    *flags |= SfMayBlock;
   1442 }
   1443 
   1444 POST(kevent)
   1445 {
   1446    PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
   1447    if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
   1448 }
   1449 
   1450 
   1451 Addr pthread_starter = 0;
   1452 Addr wqthread_starter = 0;
   1453 SizeT pthread_structsize = 0;
   1454 
   1455 PRE(bsdthread_register)
   1456 {
   1457    PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
   1458    PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
   1459                  void *,"wqthread", size_t,"pthsize");
   1460 
   1461    pthread_starter = ARG1;
   1462    wqthread_starter = ARG2;
   1463    pthread_structsize = ARG3;
   1464    ARG1 = (Word)&pthread_hijack_asm;
   1465    ARG2 = (Word)&wqthread_hijack_asm;
   1466 }
   1467 
   1468 PRE(workq_open)
   1469 {
   1470    PRINT("workq_open()");
   1471    PRE_REG_READ0(int, "workq_open");
   1472 
   1473    // This creates lots of threads and thread stacks under the covers,
   1474    // but we ignore them all until some work item starts running on it.
   1475 }
   1476 
   1477 static const char *workqop_name(int op)
   1478 {
   1479    switch (op) {
   1480    case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
   1481    case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
   1482    case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
   1483    default: return "?";
   1484    }
   1485 }
   1486 
   1487 
   1488 PRE(workq_ops)
   1489 {
   1490    PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
   1491       ARG3);
   1492    PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
   1493                  int,"priority");
   1494 
   1495    switch (ARG1) {
   1496    case VKI_WQOPS_QUEUE_ADD:
   1497    case VKI_WQOPS_QUEUE_REMOVE:
   1498       // GrP fixme need anything here?
   1499       // GrP fixme may block?
   1500       break;
   1501 
   1502    case VKI_WQOPS_THREAD_RETURN: {
   1503       // The interesting case. The kernel will do one of two things:
   1504       // 1. Return normally. We continue; libc proceeds to stop the thread.
   1505       //    V does nothing special here.
   1506       // 2. Jump to wqthread_hijack. This wipes the stack and runs a
   1507       //    new work item, and never returns from workq_ops.
   1508       //    V handles this by longjmp() from wqthread_hijack back to the
   1509       //    scheduler, which continues at the new client SP/IP/state.
   1510       //    This works something like V's signal handling.
   1511       //    To the tool, this looks like workq_ops() sometimes returns
   1512       //    to a strange address.
   1513       ThreadState *tst = VG_(get_ThreadState)(tid);
   1514       tst->os_state.wq_jmpbuf_valid = True;
   1515       *flags |= SfMayBlock;  // GrP fixme true?
   1516       break;
   1517    }
   1518 
   1519    default:
   1520       VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
   1521       break;
   1522    }
   1523 }
   1524 POST(workq_ops)
   1525 {
   1526    ThreadState *tst = VG_(get_ThreadState)(tid);
   1527    tst->os_state.wq_jmpbuf_valid = False;
   1528 }
   1529 
   1530 
   1531 
   1532 PRE(__mac_syscall)
   1533 {
   1534    PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3);
   1535    PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
   1536                  int,"call", void *,"arg");
   1537 
   1538    // GrP fixme check call's arg?
   1539    // GrP fixme check policy?
   1540 }
   1541 
   1542 
   1543 /* Not like syswrap-generic's sys_exit, which exits only one thread.
   1544    More like syswrap-generic's sys_exit_group. */
   1545 PRE(exit)
   1546 {
   1547    ThreadId     t;
   1548    ThreadState* tst;
   1549 
   1550    PRINT("darwin exit( %ld )", ARG1);
   1551    PRE_REG_READ1(void, "exit", int, status);
   1552 
   1553    tst = VG_(get_ThreadState)(tid);
   1554 
   1555    /* A little complex; find all the threads with the same threadgroup
   1556       as this one (including this one), and mark them to exit */
   1557    for (t = 1; t < VG_N_THREADS; t++) {
   1558       if ( /* not alive */
   1559            VG_(threads)[t].status == VgTs_Empty
   1560            /* GrP fixme zombie? */
   1561          )
   1562          continue;
   1563 
   1564       VG_(threads)[t].exitreason = VgSrc_ExitProcess;
   1565       VG_(threads)[t].os_state.exitcode = ARG1;
   1566 
   1567       if (t != tid)
   1568          VG_(get_thread_out_of_syscall)(t);     /* unblock it, if blocked */
   1569    }
   1570 
   1571    /* We have to claim the syscall already succeeded. */
   1572    SET_STATUS_Success(0);
   1573 }
   1574 
   1575 
   1576 PRE(sigaction)
   1577 {
   1578    PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
   1579    PRE_REG_READ3(long, "sigaction",
   1580                  int, signum, vki_sigaction_toK_t *, act,
   1581                  vki_sigaction_fromK_t *, oldact);
   1582 
   1583    if (ARG2 != 0) {
   1584       vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
   1585       PRE_MEM_READ( "sigaction(act->sa_handler)",
   1586                     (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
   1587       PRE_MEM_READ( "sigaction(act->sa_mask)",
   1588                     (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
   1589       PRE_MEM_READ( "sigaction(act->sa_flags)",
   1590                     (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
   1591    }
   1592    if (ARG3 != 0)
   1593       PRE_MEM_WRITE( "sigaction(oldact)",
   1594                      ARG3, sizeof(vki_sigaction_fromK_t));
   1595 
   1596    SET_STATUS_from_SysRes(
   1597       VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
   1598                                   (vki_sigaction_fromK_t *)ARG3)
   1599    );
   1600 }
   1601 POST(sigaction)
   1602 {
   1603    vg_assert(SUCCESS);
   1604    if (RES == 0 && ARG3 != 0)
   1605       POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
   1606 }
   1607 
   1608 
   1609 PRE(__pthread_kill)
   1610 {
   1611    PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
   1612    PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
   1613 }
   1614 
   1615 
   1616 PRE(__pthread_sigmask)
   1617 {
   1618    // GrP fixme
   1619    // JRS: arguments are identical to sigprocmask
   1620    // (how, sigset_t*, sigset_t*).  Perhaps behave identically?
   1621    static Bool warned;
   1622    if (!warned) {
   1623       VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. "
   1624                   "This warning will not be repeated.\n");
   1625       warned = True;
   1626    }
   1627    SET_STATUS_Success( 0 );
   1628 }
   1629 
   1630 
   1631 PRE(__pthread_canceled)
   1632 {
   1633    *flags |= SfMayBlock; /* might kill this thread??? */
   1634    /* I don't think so -- I think it just changes the cancellation
   1635       state.  But taking no chances. */
   1636    PRINT("__pthread_canceled ( %ld )", ARG1);
   1637    PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
   1638 }
   1639 
   1640 
   1641 PRE(__pthread_markcancel)
   1642 {
   1643    *flags |= SfMayBlock; /* might kill this thread??? */
   1644    PRINT("__pthread_markcancel ( %#lx )", ARG1);
   1645    PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
   1646    /* Just let it go through.  No idea if this is correct. */
   1647 }
   1648 
   1649 
   1650 PRE(__disable_threadsignal)
   1651 {
   1652    vki_sigset_t set;
   1653    PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
   1654    /* I don't think this really looks at its arguments.  So don't
   1655       bother to check them. */
   1656 
   1657    VG_(sigfillset)( &set );
   1658    SET_STATUS_from_SysRes(
   1659       VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
   1660    );
   1661 
   1662    /* We don't expect that blocking all signals for this thread could
   1663       cause any more to be delivered (how could it?), but just in case
   1664       .. */
   1665    if (SUCCESS)
   1666       *flags |= SfPollAfter;
   1667 }
   1668 
   1669 
   1670 PRE(kdebug_trace)
   1671 {
   1672    PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
   1673          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
   1674    /*
   1675      Don't check anything - some clients pass fewer arguments.
   1676    PRE_REG_READ6(long, "kdebug_trace",
   1677                  int,"code", int,"arg1", int,"arg2",
   1678                  int,"arg3", int,"arg4", int,"arg5");
   1679    */
   1680 }
   1681 
   1682 
   1683 PRE(seteuid)
   1684 {
   1685     PRINT("seteuid(%ld)", ARG1);
   1686     PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
   1687 }
   1688 
   1689 
   1690 PRE(setegid)
   1691 {
   1692     PRINT("setegid(%ld)", ARG1);
   1693     PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
   1694 }
   1695 
   1696 PRE(settid)
   1697 {
   1698     PRINT("settid(%ld, %ld)", ARG1, ARG2);
   1699     PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
   1700 }
   1701 
   1702 /* XXX need to check whether we need POST operations for
   1703  * waitevent, watchevent, modwatch -- jpeach
   1704  */
   1705 PRE(watchevent)
   1706 {
   1707     PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
   1708     PRE_REG_READ2(long, "watchevent",
   1709         vki_eventreq *, "event", unsigned int, "eventmask");
   1710 
   1711     PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
   1712     PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
   1713     *flags |= SfMayBlock;
   1714 }
   1715 
   1716 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
   1717 PRE(waitevent)
   1718 {
   1719    PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
   1720    PRE_REG_READ2(long, "waitevent",
   1721       vki_eventreq *, "event", struct timeval *, "timeout");
   1722    PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
   1723 
   1724    if (ARG2  &&  ARG2 != WAITEVENT_FAST_POLL) {
   1725       PRE_timeval_READ("waitevent(timeout)", ARG2);
   1726    }
   1727 
   1728    /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
   1729    *flags |= SfMayBlock;
   1730 }
   1731 
   1732 POST(waitevent)
   1733 {
   1734    POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
   1735 }
   1736 
   1737 PRE(modwatch)
   1738 {
   1739    PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
   1740    PRE_REG_READ2(long, "modwatch",
   1741       vki_eventreq *, "event", unsigned int, "eventmask");
   1742 
   1743    PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
   1744    PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
   1745 }
   1746 
   1747 PRE(getxattr)
   1748 {
   1749    PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
   1750          ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
   1751 
   1752    PRE_REG_READ6(vki_ssize_t, "getxattr",
   1753                 const char *, path, char *, name, void *, value,
   1754                 vki_size_t, size, uint32_t, position, int, options);
   1755    PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
   1756    PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
   1757    PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
   1758 }
   1759 
   1760 POST(getxattr)
   1761 {
   1762    vg_assert((vki_ssize_t)RES >= 0);
   1763    POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
   1764 }
   1765 
   1766 PRE(fgetxattr)
   1767 {
   1768    PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
   1769       ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
   1770 
   1771    PRE_REG_READ6(vki_ssize_t, "fgetxattr",
   1772                  int, fd, char *, name, void *, value,
   1773                  vki_size_t, size, uint32_t, position, int, options);
   1774    PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
   1775    PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
   1776 }
   1777 
   1778 POST(fgetxattr)
   1779 {
   1780    vg_assert((vki_ssize_t)RES >= 0);
   1781    POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
   1782 }
   1783 
   1784 PRE(setxattr)
   1785 {
   1786    PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
   1787          ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
   1788    PRE_REG_READ6(int, "setxattr",
   1789                  const char *,"path", char *,"name", void *,"value",
   1790                  vki_size_t,"size", uint32_t,"position", int,"options" );
   1791 
   1792    PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
   1793    PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
   1794    PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
   1795 }
   1796 
   1797 
   1798 PRE(fsetxattr)
   1799 {
   1800    PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
   1801           ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
   1802    PRE_REG_READ6(int, "fsetxattr",
   1803                  int,"fd", char *,"name", void *,"value",
   1804                  vki_size_t,"size", uint32_t,"position", int,"options" );
   1805 
   1806    PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
   1807    PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
   1808 }
   1809 
   1810 
   1811 PRE(removexattr)
   1812 {
   1813    PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
   1814           ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 );
   1815    PRE_REG_READ3(int, "removexattr",
   1816                  const char*, "path", char*, "attrname", int, "options");
   1817    PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
   1818    PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
   1819 }
   1820 
   1821 
   1822 PRE(fremovexattr)
   1823 {
   1824    PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
   1825           ARG1, ARG2, (HChar*)ARG2, ARG3 );
   1826    PRE_REG_READ3(int, "fremovexattr",
   1827                  int, "fd", char*, "attrname", int, "options");
   1828    PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
   1829 }
   1830 
   1831 
   1832 PRE(listxattr)
   1833 {
   1834    PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
   1835           ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
   1836    PRE_REG_READ4 (long, "listxattr",
   1837                  const char *,"path", char *,"namebuf",
   1838                  vki_size_t,"size", int,"options" );
   1839 
   1840    PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
   1841    PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
   1842    *flags |= SfMayBlock;
   1843 }
   1844 POST(listxattr)
   1845 {
   1846    vg_assert(SUCCESS);
   1847    vg_assert((vki_ssize_t)RES >= 0);
   1848    POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
   1849 }
   1850 
   1851 
   1852 PRE(flistxattr)
   1853 {
   1854    PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
   1855           ARG1, ARG2, ARG3, ARG4 );
   1856    PRE_REG_READ4 (long, "flistxattr",
   1857                   int, "fd", char *,"namebuf",
   1858                  vki_size_t,"size", int,"options" );
   1859    PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
   1860    *flags |= SfMayBlock;
   1861 }
   1862 POST(flistxattr)
   1863 {
   1864    vg_assert(SUCCESS);
   1865    vg_assert((vki_ssize_t)RES >= 0);
   1866    POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
   1867 }
   1868 
   1869 
   1870 PRE(shmat)
   1871 {
   1872    UWord arg2tmp;
   1873    PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   1874    PRE_REG_READ3(long, "shmat",
   1875                  int, shmid, const void *, shmaddr, int, shmflg);
   1876    arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
   1877    if (arg2tmp == 0)
   1878       SET_STATUS_Failure( VKI_EINVAL );
   1879    else
   1880       ARG2 = arg2tmp;  // used in POST
   1881 }
   1882 POST(shmat)
   1883 {
   1884    ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
   1885 }
   1886 
   1887 PRE(shmctl)
   1888 {
   1889    PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
   1890    PRE_REG_READ3(long, "shmctl",
   1891                  int, shmid, int, cmd, struct vki_shmid_ds *, buf);
   1892    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
   1893 }
   1894 POST(shmctl)
   1895 {
   1896    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
   1897 }
   1898 
   1899 PRE(shmdt)
   1900 {
   1901    PRINT("shmdt ( %#lx )",ARG1);
   1902    PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
   1903    if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
   1904       SET_STATUS_Failure( VKI_EINVAL );
   1905 }
   1906 POST(shmdt)
   1907 {
   1908    ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
   1909 }
   1910 
   1911 PRE(shmget)
   1912 {
   1913    PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
   1914    PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
   1915 }
   1916 
   1917 PRE(shm_open)
   1918 {
   1919    PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
   1920    PRE_REG_READ3(long, "shm_open",
   1921                  const char *,"name", int,"flags", vki_mode_t,"mode");
   1922 
   1923    PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
   1924 
   1925    *flags |= SfMayBlock;
   1926 }
   1927 POST(shm_open)
   1928 {
   1929    vg_assert(SUCCESS);
   1930    if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
   1931       VG_(close)(RES);
   1932       SET_STATUS_Failure( VKI_EMFILE );
   1933    } else {
   1934       if (VG_(clo_track_fds))
   1935          ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
   1936    }
   1937 }
   1938 
   1939 
   1940 PRE(stat_extended)
   1941 {
   1942    PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
   1943       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   1944    PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
   1945                  void *, fsacl, vki_size_t *, fsacl_size);
   1946    PRE_MEM_RASCIIZ( "stat_extended(file_name)",  ARG1 );
   1947    PRE_MEM_WRITE(   "stat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
   1948    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1949       PRE_MEM_WRITE("stat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
   1950    PRE_MEM_READ(    "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   1951 }
   1952 POST(stat_extended)
   1953 {
   1954    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
   1955    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1956       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   1957    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   1958 }
   1959 
   1960 
   1961 PRE(lstat_extended)
   1962 {
   1963    PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
   1964       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   1965    PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
   1966                  void *, fsacl, vki_size_t *, fsacl_size);
   1967    PRE_MEM_RASCIIZ( "lstat_extended(file_name)",  ARG1 );
   1968    PRE_MEM_WRITE(   "lstat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
   1969    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1970       PRE_MEM_WRITE("lstat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
   1971    PRE_MEM_READ(    "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   1972 }
   1973 POST(lstat_extended)
   1974 {
   1975    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
   1976    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1977       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   1978    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   1979 }
   1980 
   1981 
   1982 PRE(fstat_extended)
   1983 {
   1984    PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
   1985       ARG1, ARG2, ARG3, ARG4);
   1986    PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
   1987                  void *, fsacl, vki_size_t *, fsacl_size);
   1988    PRE_MEM_WRITE(   "fstat_extended(buf)",        ARG2, sizeof(struct vki_stat) );
   1989    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1990       PRE_MEM_WRITE("fstat_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
   1991    PRE_MEM_READ(    "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   1992 }
   1993 POST(fstat_extended)
   1994 {
   1995    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
   1996    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   1997       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   1998    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   1999 }
   2000 
   2001 
   2002 PRE(stat64_extended)
   2003 {
   2004    PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
   2005       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   2006    PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
   2007                  void *, fsacl, vki_size_t *, fsacl_size);
   2008    PRE_MEM_RASCIIZ( "stat64_extended(file_name)",  ARG1 );
   2009    PRE_MEM_WRITE(   "stat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
   2010    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2011       PRE_MEM_WRITE("stat64_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
   2012    PRE_MEM_READ(    "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   2013 }
   2014 POST(stat64_extended)
   2015 {
   2016    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2017    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2018       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   2019    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   2020 }
   2021 
   2022 
   2023 PRE(lstat64_extended)
   2024 {
   2025    PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
   2026       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   2027    PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
   2028                  void *, fsacl, vki_size_t *, fsacl_size);
   2029    PRE_MEM_RASCIIZ( "lstat64_extended(file_name)",  ARG1 );
   2030    PRE_MEM_WRITE(   "lstat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
   2031    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2032       PRE_MEM_WRITE(   "lstat64_extended(fsacl)",   ARG3, *(vki_size_t *)ARG4 );
   2033    PRE_MEM_READ(    "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   2034 }
   2035 POST(lstat64_extended)
   2036 {
   2037    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2038    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2039       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   2040    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   2041 }
   2042 
   2043 
   2044 PRE(fstat64_extended)
   2045 {
   2046    PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
   2047       ARG1, ARG2, ARG3, ARG4);
   2048    PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
   2049                  void *, fsacl, vki_size_t *, fsacl_size);
   2050    PRE_MEM_WRITE(   "fstat64_extended(buf)",        ARG2, sizeof(struct vki_stat64) );
   2051    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2052       PRE_MEM_WRITE("fstat64_extended(fsacl)",      ARG3, *(vki_size_t *)ARG4 );
   2053    PRE_MEM_READ(    "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
   2054 }
   2055 POST(fstat64_extended)
   2056 {
   2057    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2058    if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
   2059       POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
   2060    POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
   2061 }
   2062 
   2063 
   2064 PRE(fchmod_extended)
   2065 {
   2066    /* DDD: Note: this is not really correct.  Handling of
   2067       chmod_extended is broken in the same way. */
   2068    PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
   2069          ARG1, ARG2, ARG3, ARG4, ARG5);
   2070    PRE_REG_READ5(long, "fchmod_extended",
   2071                  unsigned int, fildes,
   2072                  uid_t, uid,
   2073                  gid_t, gid,
   2074                  vki_mode_t, mode,
   2075                  void* /*really,user_addr_t*/, xsecurity);
   2076    /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
   2077       is just way wrong.  [The trouble is with the size, which depends on a
   2078       non-trival kernel computation] */
   2079    if (ARG5) {
   2080       PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
   2081                     sizeof(struct vki_kauth_filesec) );
   2082    }
   2083 }
   2084 
   2085 PRE(chmod_extended)
   2086 {
   2087    /* DDD: Note: this is not really correct.  Handling of
   2088       fchmod_extended is broken in the same way. */
   2089    PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
   2090          ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
   2091    PRE_REG_READ5(long, "chmod_extended",
   2092                  unsigned int, fildes,
   2093                  uid_t, uid,
   2094                  gid_t, gid,
   2095                  vki_mode_t, mode,
   2096                  void* /*really,user_addr_t*/, xsecurity);
   2097    PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
   2098    /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
   2099       is just way wrong.  [The trouble is with the size, which depends on a
   2100       non-trival kernel computation] */
   2101    if (ARG5) {
   2102       PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
   2103                     sizeof(struct vki_kauth_filesec) );
   2104    }
   2105 }
   2106 
   2107 PRE(open_extended)
   2108 {
   2109    /* DDD: Note: this is not really correct.  Handling of
   2110       {,f}chmod_extended is broken in the same way. */
   2111    PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )",
   2112          ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
   2113 	 ARG2, ARG3, ARG4, ARG5, ARG6);
   2114    PRE_REG_READ6(long, "open_extended",
   2115                  char*, path,
   2116                  int,   flags,
   2117                  uid_t, uid,
   2118                  gid_t, gid,
   2119                  vki_mode_t, mode,
   2120                  void* /*really,user_addr_t*/, xsecurity);
   2121    PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
   2122    /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
   2123       is just way wrong.  [The trouble is with the size, which depends on a
   2124       non-trival kernel computation] */
   2125    if (ARG6)
   2126       PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
   2127                     sizeof(struct vki_kauth_filesec) );
   2128 }
   2129 
   2130 // This is a ridiculous syscall.  Specifically, the 'entries' argument points
   2131 // to a buffer that contains one or more 'accessx_descriptor' structs followed
   2132 // by one or more strings.  Each accessx_descriptor contains a field,
   2133 // 'ad_name_offset', which points to one of the strings (or it can contain
   2134 // zero which means "reuse the string from the previous accessx_descriptor").
   2135 //
   2136 // What's really ridiculous is that we are only given the size of the overall
   2137 // buffer, not the number of accessx_descriptors, nor the number of strings.
   2138 // The kernel determines the number of accessx_descriptors by walking through
   2139 // them one by one, checking that the ad_name_offset points within the buffer,
   2140 // past the current point (or that it's a zero, unless its the first
   2141 // descriptor);  if so, we assume that this really is an accessx_descriptor,
   2142 // if not, we assume we've hit the strings section.  Gah.
   2143 //
   2144 // This affects us here because number of entries in the 'results' buffer is
   2145 // determined by the number of accessx_descriptors.  So we have to know that
   2146 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'.  In
   2147 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
   2148 // computation after the syscall has succeeded, because the kernel will have
   2149 // checked for all the zillion different ways this syscall can fail, and we'll
   2150 // know we have a well-formed 'entries' buffer.  This means we might miss some
   2151 // uses of unaddressable memory but oh well.
   2152 //
   2153 PRE(access_extended)
   2154 {
   2155    PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
   2156       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   2157    // XXX: the accessx_descriptor struct contains padding, so this can cause
   2158    // unnecessary undefined value errors.  But you arguably shouldn't be
   2159    // passing undefined values to the kernel anyway...
   2160    PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
   2161                  vki_errno_t *, results, vki_uid_t *, uid);
   2162    PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
   2163 
   2164    // XXX: as mentioned above, this check is too hard to do before the
   2165    // syscall.
   2166    //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
   2167 }
   2168 POST(access_extended)
   2169 {
   2170    // 'n_descs' is the number of descriptors we think are in the buffer.  We
   2171    // start with the maximum possible value, which occurs if we have the
   2172    // shortest possible string section.  The shortest string section allowed
   2173    // consists of a single one-char string (plus the NUL char).  Hence the
   2174    // '2'.
   2175    struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
   2176    SizeT size = ARG2;
   2177    Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
   2178    Int i;         // Current position in the descriptors section array.
   2179    Int u;         // Upper bound on the length of the descriptors array
   2180                   //   (recomputed each time around the loop)
   2181    vg_assert(n_descs > 0);
   2182 
   2183    // Step through the descriptors, lowering 'n_descs' until we know we've
   2184    // reached the string section.
   2185    for (i = 0; True; i++) {
   2186       // If we're past our estimate, we must be one past the end of the
   2187       // descriptors section (ie. at the start of the string section).  Stop.
   2188       if (i >= n_descs)
   2189          break;
   2190 
   2191       // Get the array index for the string, but pretend momentarily that it
   2192       // is actually another accessx_descriptor.  That gives us an upper bound
   2193       // on the length of the descriptors section.  (Unless the index is zero,
   2194       // in which case we have no new info.)
   2195       u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
   2196       if (u == 0) {
   2197          vg_assert(i != 0);
   2198          continue;
   2199       }
   2200 
   2201       // If the upper bound is below our current estimate, revise that
   2202       // estimate downwards.
   2203       if (u < n_descs)
   2204          n_descs = u;
   2205    }
   2206 
   2207    // Sanity check.
   2208    vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
   2209 
   2210    POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
   2211 }
   2212 
   2213 
   2214 PRE(chflags)
   2215 {
   2216    PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
   2217    PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
   2218    PRE_MEM_RASCIIZ("chflags(path)", ARG1);
   2219 
   2220    // GrP fixme sanity-check flags value?
   2221 }
   2222 
   2223 PRE(fchflags)
   2224 {
   2225    PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
   2226    PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
   2227 
   2228    // GrP fixme sanity-check flags value?
   2229 }
   2230 
   2231 PRE(stat64)
   2232 {
   2233    PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
   2234    PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
   2235    PRE_MEM_RASCIIZ("stat64(path)", ARG1);
   2236    PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
   2237 }
   2238 POST(stat64)
   2239 {
   2240    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2241 }
   2242 
   2243 PRE(lstat64)
   2244 {
   2245    PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
   2246    PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
   2247    PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
   2248    PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
   2249 }
   2250 POST(lstat64)
   2251 {
   2252    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2253 }
   2254 
   2255 PRE(fstat64)
   2256 {
   2257    PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
   2258    PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
   2259    PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
   2260 }
   2261 POST(fstat64)
   2262 {
   2263    POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
   2264 }
   2265 
   2266 PRE(getfsstat)
   2267 {
   2268    PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
   2269    PRE_REG_READ3(int, "getfsstat",
   2270                  struct vki_statfs *, buf, int, bufsize, int, flags);
   2271    if (ARG1) {
   2272       // ARG2 is a BYTE SIZE
   2273       PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
   2274    }
   2275 }
   2276 POST(getfsstat)
   2277 {
   2278    if (ARG1) {
   2279       // RES is a STRUCT COUNT
   2280       POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
   2281    }
   2282 }
   2283 
   2284 PRE(getfsstat64)
   2285 {
   2286    PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
   2287    PRE_REG_READ3(int, "getfsstat64",
   2288                  struct vki_statfs64 *, buf, int, bufsize, int, flags);
   2289    if (ARG1) {
   2290       // ARG2 is a BYTE SIZE
   2291       PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
   2292    }
   2293 }
   2294 POST(getfsstat64)
   2295 {
   2296    if (ARG1) {
   2297       // RES is a STRUCT COUNT
   2298       POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
   2299    }
   2300 }
   2301 
   2302 PRE(mount)
   2303 {
   2304    // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
   2305    // We are conservative and check everything, except the memory pointed to
   2306    // by 'data'.
   2307    *flags |= SfMayBlock;
   2308    PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
   2309          ARG1,(Char*)ARG1, ARG2,(Char*)ARG2, ARG3, ARG4);
   2310    PRE_REG_READ4(long, "mount",
   2311                  const char *, type, const char *, dir,
   2312                  int, flags, void *, data);
   2313    PRE_MEM_RASCIIZ( "mount(type)", ARG1);
   2314    PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
   2315 }
   2316 
   2317 
   2318 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
   2319                           void *attrBuf, SizeT attrBufSize,
   2320                           void (*fn)(ThreadId, void *attrData, SizeT size)
   2321                           )
   2322 {
   2323    typedef struct {
   2324       uint32_t attrBit;
   2325       int32_t attrSize;
   2326    } attrspec;
   2327    static const attrspec commonattr[] = {
   2328       // This order is important.
   2329 #if DARWIN_VERS >= DARWIN_10_6
   2330       { ATTR_CMN_RETURNED_ATTRS,  sizeof(attribute_set_t) },
   2331 #endif
   2332       { ATTR_CMN_NAME,            -1 },
   2333       { ATTR_CMN_DEVID,           sizeof(dev_t) },
   2334       { ATTR_CMN_FSID,            sizeof(fsid_t) },
   2335       { ATTR_CMN_OBJTYPE,         sizeof(fsobj_type_t) },
   2336       { ATTR_CMN_OBJTAG,          sizeof(fsobj_tag_t) },
   2337       { ATTR_CMN_OBJID,           sizeof(fsobj_id_t) },
   2338       { ATTR_CMN_OBJPERMANENTID,  sizeof(fsobj_id_t) },
   2339       { ATTR_CMN_PAROBJID,        sizeof(fsobj_id_t) },
   2340       { ATTR_CMN_SCRIPT,          sizeof(text_encoding_t) },
   2341       { ATTR_CMN_CRTIME,          sizeof(struct timespec) },
   2342       { ATTR_CMN_MODTIME,         sizeof(struct timespec) },
   2343       { ATTR_CMN_CHGTIME,         sizeof(struct timespec) },
   2344       { ATTR_CMN_ACCTIME,         sizeof(struct timespec) },
   2345       { ATTR_CMN_BKUPTIME,        sizeof(struct timespec) },
   2346       { ATTR_CMN_FNDRINFO,        32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
   2347       { ATTR_CMN_OWNERID,         sizeof(uid_t) },
   2348       { ATTR_CMN_GRPID,           sizeof(gid_t) },
   2349       { ATTR_CMN_ACCESSMASK,      sizeof(uint32_t) },
   2350       { ATTR_CMN_NAMEDATTRCOUNT,  sizeof(uint32_t) },
   2351       { ATTR_CMN_NAMEDATTRLIST,   -1 },
   2352       { ATTR_CMN_FLAGS,           sizeof(uint32_t) },
   2353       { ATTR_CMN_USERACCESS,      sizeof(uint32_t) },
   2354       { ATTR_CMN_EXTENDED_SECURITY, -1 },
   2355       { ATTR_CMN_UUID,            sizeof(guid_t) },
   2356       { ATTR_CMN_GRPUUID,         sizeof(guid_t) },
   2357       { ATTR_CMN_FILEID,          sizeof(uint64_t) },
   2358       { ATTR_CMN_PARENTID,        sizeof(uint64_t) },
   2359 #if DARWIN_VERS >= DARWIN_10_6
   2360       { ATTR_CMN_FULLPATH,        -1 },
   2361 #endif
   2362       { 0,                        0 }
   2363    };
   2364    static const attrspec volattr[] = {
   2365       // This order is important.
   2366       { ATTR_VOL_INFO,            0 },
   2367       { ATTR_VOL_FSTYPE,          sizeof(uint32_t) },
   2368       { ATTR_VOL_SIGNATURE,       sizeof(uint32_t) },
   2369       { ATTR_VOL_SIZE,            sizeof(off_t) },
   2370       { ATTR_VOL_SPACEFREE,       sizeof(off_t) },
   2371       { ATTR_VOL_SPACEAVAIL,      sizeof(off_t) },
   2372       { ATTR_VOL_MINALLOCATION,   sizeof(off_t) },
   2373       { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
   2374       { ATTR_VOL_IOBLOCKSIZE,     sizeof(uint32_t) },
   2375       { ATTR_VOL_OBJCOUNT,        sizeof(uint32_t) },
   2376       { ATTR_VOL_FILECOUNT,       sizeof(uint32_t) },
   2377       { ATTR_VOL_DIRCOUNT,        sizeof(uint32_t) },
   2378       { ATTR_VOL_MAXOBJCOUNT,     sizeof(uint32_t) },
   2379       { ATTR_VOL_MOUNTPOINT,      -1 },
   2380       { ATTR_VOL_NAME,            -1 },
   2381       { ATTR_VOL_MOUNTFLAGS,      sizeof(uint32_t) },
   2382       { ATTR_VOL_MOUNTEDDEVICE,   -1 },
   2383       { ATTR_VOL_ENCODINGSUSED,   sizeof(uint64_t) },
   2384       { ATTR_VOL_CAPABILITIES,    sizeof(vol_capabilities_attr_t) },
   2385 #if DARWIN_VERS >= DARWIN_10_6
   2386       { ATTR_VOL_UUID,            sizeof(uuid_t) },
   2387 #endif
   2388       { ATTR_VOL_ATTRIBUTES,      sizeof(vol_attributes_attr_t) },
   2389       { 0,                        0 }
   2390    };
   2391    static const attrspec dirattr[] = {
   2392       // This order is important.
   2393       { ATTR_DIR_LINKCOUNT,       sizeof(uint32_t) },
   2394       { ATTR_DIR_ENTRYCOUNT,      sizeof(uint32_t) },
   2395       { ATTR_DIR_MOUNTSTATUS,     sizeof(uint32_t) },
   2396       { 0,                        0 }
   2397    };
   2398    static const attrspec fileattr[] = {
   2399       // This order is important.
   2400       { ATTR_FILE_LINKCOUNT,      sizeof(uint32_t) },
   2401       { ATTR_FILE_TOTALSIZE,      sizeof(off_t) },
   2402       { ATTR_FILE_ALLOCSIZE,      sizeof(off_t) },
   2403       { ATTR_FILE_IOBLOCKSIZE,    sizeof(uint32_t) },
   2404       { ATTR_FILE_CLUMPSIZE,      sizeof(uint32_t) },
   2405       { ATTR_FILE_DEVTYPE,        sizeof(uint32_t) },
   2406       { ATTR_FILE_FILETYPE,       sizeof(uint32_t) },
   2407       { ATTR_FILE_FORKCOUNT,      sizeof(uint32_t) },
   2408       { ATTR_FILE_FORKLIST,       -1 },
   2409       { ATTR_FILE_DATALENGTH,     sizeof(off_t) },
   2410       { ATTR_FILE_DATAALLOCSIZE,  sizeof(off_t) },
   2411       { ATTR_FILE_DATAEXTENTS,    sizeof(extentrecord) },
   2412       { ATTR_FILE_RSRCLENGTH,     sizeof(off_t) },
   2413       { ATTR_FILE_RSRCALLOCSIZE,  sizeof(off_t) },
   2414       { ATTR_FILE_RSRCEXTENTS,    sizeof(extentrecord) },
   2415       { 0,                        0 }
   2416    };
   2417    static const attrspec forkattr[] = {
   2418       // This order is important.
   2419       { ATTR_FORK_TOTALSIZE,      sizeof(off_t) },
   2420       { ATTR_FORK_ALLOCSIZE,      sizeof(off_t) },
   2421       { 0,                        0 }
   2422    };
   2423 
   2424    static const attrspec *attrdefs[5] = {
   2425       commonattr, volattr, dirattr, fileattr, forkattr
   2426    };
   2427    attrgroup_t a[5];
   2428    uint8_t *d, *dend;
   2429    int g, i;
   2430 
   2431    vg_assert(attrList->bitmapcount == 5);
   2432    VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
   2433    d = attrBuf;
   2434    dend = d + attrBufSize;
   2435 
   2436 #if DARWIN_VERS >= DARWIN_10_6
   2437    // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
   2438    if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
   2439        // fixme range check this?
   2440        a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
   2441        fn(tid, d, sizeof(attribute_set_t));
   2442        VG_(memcpy)(a, d, sizeof(a));
   2443    }
   2444 #endif
   2445 
   2446    for (g = 0; g < 5; g++) {
   2447       for (i = 0; attrdefs[g][i].attrBit; i++) {
   2448          uint32_t bit = attrdefs[g][i].attrBit;
   2449          int32_t size = attrdefs[g][i].attrSize;
   2450 
   2451          if (a[g] & bit) {
   2452              a[g] &= ~bit;  // clear bit for error check later
   2453             if (size == -1) {
   2454                attrreference_t *ref = (attrreference_t *)d;
   2455                size = MIN(sizeof(attrreference_t), dend - d);
   2456                fn(tid, d, size);
   2457                if (size >= sizeof(attrreference_t)  &&
   2458                    d + ref->attr_dataoffset < dend)
   2459                {
   2460                   fn(tid, d + ref->attr_dataoffset,
   2461                      MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
   2462                }
   2463                d += size;
   2464             }
   2465             else {
   2466                size = MIN(size, dend - d);
   2467                fn(tid, d, size);
   2468                d += size;
   2469             }
   2470 
   2471             if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
   2472             if (d > dend) d = dend;
   2473          }
   2474       }
   2475 
   2476       // Known bits are cleared. Die if any bits are left.
   2477       if (a[g] != 0) {
   2478          VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
   2479       }
   2480    }
   2481 }
   2482 
   2483 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
   2484 {
   2485    POST_MEM_WRITE((Addr)attrData, attrDataSize);
   2486 }
   2487 
   2488 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
   2489 {
   2490    PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
   2491 }
   2492 
   2493 PRE(getattrlist)
   2494 {
   2495    PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
   2496          ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
   2497    PRE_REG_READ5(int, "getattrlist",
   2498                  const char *,path, struct vki_attrlist *,attrList,
   2499                  void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
   2500    PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
   2501    PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
   2502    PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
   2503 }
   2504 
   2505 POST(getattrlist)
   2506 {
   2507    if (ARG4 > sizeof(vki_uint32_t)) {
   2508       // attrBuf is uint32_t size followed by attr data
   2509       vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
   2510       POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
   2511       if (ARG5 & FSOPT_REPORT_FULLSIZE) {
   2512          // *sizep is bytes required for return value, including *sizep
   2513       } else {
   2514          // *sizep is actual bytes returned, including *sizep
   2515       }
   2516       scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
   2517    }
   2518 }
   2519 
   2520 
   2521 PRE(setattrlist)
   2522 {
   2523    PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
   2524          ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
   2525    PRE_REG_READ5(int, "setattrlist",
   2526                  const char *,path, struct vki_attrlist *,attrList,
   2527                  void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
   2528    PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
   2529    PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
   2530    scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
   2531 }
   2532 
   2533 
   2534 PRE(getdirentriesattr)
   2535 {
   2536    PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
   2537          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
   2538    PRE_REG_READ8(int, "getdirentriesattr",
   2539                  int,fd, struct vki_attrlist *,attrList,
   2540                  void *,attrBuf, size_t,attrBufSize,
   2541                  unsigned int *,count, unsigned int *,basep,
   2542                  unsigned int *,newState, unsigned int,options);
   2543    PRE_MEM_READ("getdirentriesattr(attrList)",
   2544                 ARG2, sizeof(struct vki_attrlist));
   2545    PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
   2546    PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
   2547    PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
   2548    PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
   2549    PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
   2550 }
   2551 POST(getdirentriesattr)
   2552 {
   2553    char *p, *end;
   2554    unsigned int count;
   2555    unsigned int i;
   2556 
   2557    POST_MEM_WRITE(ARG5, sizeof(unsigned int));
   2558    POST_MEM_WRITE(ARG6, sizeof(unsigned int));
   2559    POST_MEM_WRITE(ARG7, sizeof(unsigned int));
   2560 
   2561    // return buffer is concatenation of variable-size structs
   2562    count = *(unsigned int *)ARG5;
   2563    p = (char *)ARG3;
   2564    end = (char *)ARG3 + ARG4;
   2565    for (i = 0; i < count; i++) {
   2566       vg_assert(p < end);  // failure is kernel bug or Valgrind bug
   2567       p += *(unsigned int *)p;
   2568    }
   2569 
   2570    POST_MEM_WRITE(ARG3, p - (char *)ARG3);
   2571 
   2572    PRINT("got %d records, %ld/%lu bytes\n",
   2573          count, (Addr)p-(Addr)ARG3, ARG4);
   2574 }
   2575 
   2576 
   2577 PRE(fsgetpath)
   2578 {
   2579 #if VG_WORDSIZE == 4
   2580    PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
   2581          ARG1, ARG2, ARG3,
   2582          ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
   2583          LOHI64(ARG4, ARG5));
   2584    PRE_REG_READ5(ssize_t, "fsgetpath",
   2585                  void*,"buf", size_t,"bufsize",
   2586                  fsid_t *,"fsid",
   2587                  vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
   2588 #else
   2589    PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
   2590          ARG1, ARG2, ARG3,
   2591          ((unsigned int *)ARG3)[0],
   2592          ((unsigned int *)ARG3)[1], ARG4);
   2593    PRE_REG_READ4(ssize_t, "fsgetpath",
   2594                  void*,"buf", size_t,"bufsize",
   2595                  fsid_t *,"fsid", uint64_t,"objid");
   2596 #endif
   2597    PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
   2598    PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
   2599 }
   2600 
   2601 POST(fsgetpath)
   2602 {
   2603    POST_MEM_WRITE(ARG1, RES);
   2604 }
   2605 
   2606 PRE(audit_session_self)
   2607 {
   2608   PRINT("audit_session_self()");
   2609 }
   2610 
   2611 POST(audit_session_self)
   2612 {
   2613   record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
   2614   PRINT("audit-session %#lx", RES);
   2615 }
   2616 
   2617 PRE(exchangedata)
   2618 {
   2619    PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
   2620          ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
   2621    PRE_REG_READ3(int, "exchangedata",
   2622                  char *, path1, char *, path2, unsigned long, options);
   2623    PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
   2624    PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
   2625 }
   2626 
   2627 PRE(fsctl)
   2628 {
   2629    PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
   2630       ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
   2631    PRE_REG_READ4( long, "fsctl",
   2632                   char *,"path", unsigned int,"request",
   2633                   void *,"data", unsigned int,"options");
   2634 
   2635    PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
   2636 
   2637    switch (ARG2) {
   2638    case VKI_afpfsByteRangeLock2FSCTL: {
   2639       struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
   2640       PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
   2641                      pb->offset);
   2642       PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
   2643                      pb->length);
   2644       PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
   2645                      pb->unLockFlag);
   2646       PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
   2647                      pb->startEndFlag);
   2648       PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
   2649                      pb->fd);
   2650 
   2651       PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
   2652                       pb->retRangeStart);
   2653 
   2654       // GrP fixme check fd
   2655       break;
   2656    }
   2657    case VKI_FSIOC_SYNC_VOLUME:
   2658        PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
   2659        break;
   2660 
   2661    default:
   2662       // fsctl requests use ioctl encoding
   2663       ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
   2664       break;
   2665    }
   2666 }
   2667 
   2668 POST(fsctl)
   2669 {
   2670    switch (ARG2) {
   2671    case VKI_afpfsByteRangeLock2FSCTL: {
   2672       struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
   2673       POST_FIELD_WRITE(pb->retRangeStart);
   2674       break;
   2675    }
   2676    case VKI_FSIOC_SYNC_VOLUME:
   2677        break;
   2678 
   2679    default:
   2680       // fsctl requests use ioctl encoding
   2681       ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
   2682       break;
   2683    }
   2684 }
   2685 
   2686 PRE(initgroups)
   2687 {
   2688     PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
   2689     PRE_REG_READ3(long, "initgroups",
   2690         int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
   2691     PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
   2692 }
   2693 
   2694 
   2695 //--------- posix_spawn ---------//
   2696 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
   2697    the simpler AIX equivalent (syswrap-aix5.c). */
   2698 // Pre_read a char** argument.
   2699 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
   2700 {
   2701    while (True) {
   2702       Addr a_deref;
   2703       Addr* a_p = (Addr*)a;
   2704       PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
   2705       a_deref = *a_p;
   2706       if (0 == a_deref)
   2707          break;
   2708       PRE_MEM_RASCIIZ( s2, a_deref );
   2709       a += sizeof(char*);
   2710    }
   2711 }
   2712 static SysRes simple_pre_exec_check ( const HChar* exe_name,
   2713                                       Bool trace_this_child )
   2714 {
   2715    Int fd, ret;
   2716    SysRes res;
   2717    Bool setuid_allowed;
   2718 
   2719    // Check it's readable
   2720    res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
   2721    if (sr_isError(res)) {
   2722       return res;
   2723    }
   2724    fd = sr_Res(res);
   2725    VG_(close)(fd);
   2726 
   2727    // Check we have execute permissions.  We allow setuid executables
   2728    // to be run only in the case when we are not simulating them, that
   2729    // is, they to be run natively.
   2730    setuid_allowed = trace_this_child  ? False  : True;
   2731    ret = VG_(check_executable)(NULL/*&is_setuid*/,
   2732                                (HChar*)exe_name, setuid_allowed);
   2733    if (0 != ret) {
   2734       return VG_(mk_SysRes_Error)(ret);
   2735    }
   2736    return VG_(mk_SysRes_Success)(0);
   2737 }
   2738 PRE(posix_spawn)
   2739 {
   2740    Char*        path = NULL;       /* path to executable */
   2741    Char**       envp = NULL;
   2742    Char**       argv = NULL;
   2743    Char**       arg2copy;
   2744    Char*        launcher_basename = NULL;
   2745    Int          i, j, tot_args;
   2746    SysRes       res;
   2747    Bool         trace_this_child;
   2748 
   2749    /* args: pid_t* pid
   2750             char*  path
   2751             posix_spawn_file_actions_t* file_actions
   2752             char** argv
   2753             char** envp
   2754    */
   2755    PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
   2756          ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
   2757 
   2758    /* Standard pre-syscall checks */
   2759 
   2760    PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
   2761                  void*, file_actions, char**, argv, char**, envp );
   2762    PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
   2763    PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
   2764    // DDD: check file_actions
   2765    if (ARG4 != 0)
   2766       pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
   2767                                 "posix_spawn(argv[i])" );
   2768    if (ARG5 != 0)
   2769       pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
   2770                                 "posix_spawn(envp[i])" );
   2771 
   2772    if (0)
   2773    VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
   2774          ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
   2775 
   2776    /* Now follows a bunch of logic copied from PRE(sys_execve) in
   2777       syswrap-generic.c. */
   2778 
   2779    /* Check that the name at least begins in client-accessible storage. */
   2780    if (ARG2 == 0 /* obviously bogus */
   2781        || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
   2782       SET_STATUS_Failure( VKI_EFAULT );
   2783       return;
   2784    }
   2785 
   2786    // Decide whether or not we want to follow along
   2787    { // Make 'child_argv' be a pointer to the child's arg vector
   2788      // (skipping the exe name)
   2789      HChar** child_argv = (HChar**)ARG4;
   2790      if (child_argv && child_argv[0] == NULL)
   2791         child_argv = NULL;
   2792      trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
   2793    }
   2794 
   2795    // Do the important checks:  it is a file, is executable, permissions are
   2796    // ok, etc.  We allow setuid executables to run only in the case when
   2797    // we are not simulating them, that is, they to be run natively.
   2798    res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
   2799    if (sr_isError(res)) {
   2800       SET_STATUS_Failure( sr_Err(res) );
   2801       return;
   2802    }
   2803 
   2804    /* If we're tracing the child, and the launcher name looks bogus
   2805       (possibly because launcher.c couldn't figure it out, see
   2806       comments therein) then we have no option but to fail. */
   2807    if (trace_this_child
   2808        && (VG_(name_of_launcher) == NULL
   2809            || VG_(name_of_launcher)[0] != '/')) {
   2810       SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
   2811       return;
   2812    }
   2813 
   2814    /* Ok.  So let's give it a try. */
   2815    VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2);
   2816 
   2817    // Terminate gdbserver if it is active.
   2818    if (VG_(clo_vgdb)  != Vg_VgdbNo) {
   2819       // If the child will not be traced, we need to terminate gdbserver
   2820       // to cleanup the gdbserver resources (e.g. the FIFO files).
   2821       // If child will be traced, we also terminate gdbserver: the new
   2822       // Valgrind will start a fresh gdbserver after exec.
   2823       VG_(gdbserver) (tid);
   2824    }
   2825 
   2826    // Set up the child's exe path.
   2827    //
   2828    if (trace_this_child) {
   2829 
   2830       // We want to exec the launcher.  Get its pre-remembered path.
   2831       path = VG_(name_of_launcher);
   2832       // VG_(name_of_launcher) should have been acquired by m_main at
   2833       // startup.  The following two assertions should be assured by
   2834       // the "If we're tracking the child .." test just above here.
   2835       vg_assert(path);
   2836       vg_assert(path[0] == '/');
   2837       launcher_basename = path;
   2838 
   2839    } else {
   2840       path = (Char*)ARG2;
   2841    }
   2842 
   2843    // Set up the child's environment.
   2844    //
   2845    // Remove the valgrind-specific stuff from the environment so the
   2846    // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
   2847    // This is done unconditionally, since if we are tracing the child,
   2848    // the child valgrind will set up the appropriate client environment.
   2849    // Nb: we make a copy of the environment before trying to mangle it
   2850    // as it might be in read-only memory (this was bug #101881).
   2851    //
   2852    // Then, if tracing the child, set VALGRIND_LIB for it.
   2853    //
   2854    if (ARG5 == 0) {
   2855       envp = NULL;
   2856    } else {
   2857       envp = VG_(env_clone)( (Char**)ARG5 );
   2858       vg_assert(envp);
   2859       VG_(env_remove_valgrind_env_stuff)( envp );
   2860    }
   2861 
   2862    if (trace_this_child) {
   2863       // Set VALGRIND_LIB in ARG5 (the environment)
   2864       VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
   2865    }
   2866 
   2867    // Set up the child's args.  If not tracing it, they are
   2868    // simply ARG4.  Otherwise, they are
   2869    //
   2870    // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
   2871    //
   2872    // except that the first VG_(args_for_valgrind_noexecpass) args
   2873    // are omitted.
   2874    //
   2875    if (!trace_this_child) {
   2876       argv = (Char**)ARG4;
   2877    } else {
   2878       vg_assert( VG_(args_for_valgrind) );
   2879       vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
   2880       vg_assert( VG_(args_for_valgrind_noexecpass)
   2881                    <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
   2882       /* how many args in total will there be? */
   2883       // launcher basename
   2884       tot_args = 1;
   2885       // V's args
   2886       tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
   2887       tot_args -= VG_(args_for_valgrind_noexecpass);
   2888       // name of client exe
   2889       tot_args++;
   2890       // args for client exe, skipping [0]
   2891       arg2copy = (Char**)ARG4;
   2892       if (arg2copy && arg2copy[0]) {
   2893          for (i = 1; arg2copy[i]; i++)
   2894             tot_args++;
   2895       }
   2896       // allocate
   2897       argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
   2898                           (tot_args+1) * sizeof(HChar*) );
   2899       vg_assert(argv);
   2900       // copy
   2901       j = 0;
   2902       argv[j++] = launcher_basename;
   2903       for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
   2904          if (i < VG_(args_for_valgrind_noexecpass))
   2905             continue;
   2906          argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
   2907       }
   2908       argv[j++] = (Char*)ARG2;
   2909       if (arg2copy && arg2copy[0])
   2910          for (i = 1; arg2copy[i]; i++)
   2911             argv[j++] = arg2copy[i];
   2912       argv[j++] = NULL;
   2913       // check
   2914       vg_assert(j == tot_args+1);
   2915    }
   2916 
   2917    /* DDD: sort out the signal state.  What signal
   2918       state does the child inherit from the parent?  */
   2919 
   2920    if (0) {
   2921       Char **cpp;
   2922       VG_(printf)("posix_spawn: %s\n", path);
   2923       for (cpp = argv; cpp && *cpp; cpp++)
   2924          VG_(printf)("argv: %s\n", *cpp);
   2925       if (1)
   2926          for (cpp = envp; cpp && *cpp; cpp++)
   2927             VG_(printf)("env: %s\n", *cpp);
   2928    }
   2929 
   2930    /* Let the call go through as usual.  However, we have to poke
   2931       the altered arguments back into the argument slots. */
   2932    ARG2 = (UWord)path;
   2933    ARG4 = (UWord)argv;
   2934    ARG5 = (UWord)envp;
   2935 
   2936    /* not to mention .. */
   2937    *flags |= SfMayBlock;
   2938 }
   2939 POST(posix_spawn)
   2940 {
   2941    vg_assert(SUCCESS);
   2942    //POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
   2943 }
   2944 
   2945 
   2946 PRE(socket)
   2947 {
   2948    PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
   2949    PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
   2950 }
   2951 
   2952 POST(socket)
   2953 {
   2954    SysRes r;
   2955    vg_assert(SUCCESS);
   2956    r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
   2957    SET_STATUS_from_SysRes(r);
   2958 }
   2959 
   2960 
   2961 PRE(setsockopt)
   2962 {
   2963    PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
   2964       ARG1,ARG2,ARG3,ARG4,ARG5);
   2965    PRE_REG_READ5(long, "setsockopt",
   2966                  int, s, int, level, int, optname,
   2967                  const void *, optval, vki_socklen_t, optlen);
   2968    ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
   2969 }
   2970 
   2971 
   2972 PRE(getsockopt)
   2973 {
   2974    Addr optval_p = ARG4;
   2975    Addr optlen_p = ARG5;
   2976    PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
   2977       ARG1,ARG2,ARG3,ARG4,ARG5);
   2978    PRE_REG_READ5(long, "getsockopt",
   2979                  int, s, int, level, int, optname,
   2980                  void *, optval, vki_socklen_t *, optlen);
   2981    /* int getsockopt(int socket, int level, int option_name,
   2982                      void *restrict option_value,
   2983                      socklen_t *restrict option_len); */
   2984    /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
   2985    if (optval_p != (Addr)NULL) {
   2986       ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
   2987                                    "socketcall.getsockopt(optval)",
   2988                                    "socketcall.getsockopt(optlen)" );
   2989    }
   2990    // DDD: #warning GrP fixme darwin-specific sockopts
   2991 }
   2992 
   2993 POST(getsockopt)
   2994 {
   2995    Addr optval_p = ARG4;
   2996    Addr optlen_p = ARG5;
   2997    vg_assert(SUCCESS);
   2998    if (optval_p != (Addr)NULL) {
   2999       ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
   3000                                     optval_p, optlen_p,
   3001                                     "socketcall.getsockopt(optlen_out)" );
   3002    // DDD: #warning GrP fixme darwin-specific sockopts
   3003    }
   3004 }
   3005 
   3006 
   3007 PRE(connect)
   3008 {
   3009    *flags |= SfMayBlock;
   3010    PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   3011    PRE_REG_READ3(long, "connect",
   3012                  int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
   3013    ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
   3014 }
   3015 
   3016 
   3017 PRE(accept)
   3018 {
   3019    *flags |= SfMayBlock;
   3020    PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   3021    PRE_REG_READ3(long, "accept",
   3022                  int, s, struct sockaddr *, addr, int, *addrlen);
   3023    ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
   3024 }
   3025 
   3026 POST(accept)
   3027 {
   3028    SysRes r;
   3029    vg_assert(SUCCESS);
   3030    r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
   3031                                          ARG1,ARG2,ARG3);
   3032    SET_STATUS_from_SysRes(r);
   3033 }
   3034 
   3035 
   3036 PRE(sendto)
   3037 {
   3038    *flags |= SfMayBlock;
   3039    PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
   3040       ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
   3041    PRE_REG_READ6(long, "sendto",
   3042                  int, s, const void *, msg, int, len,
   3043                  unsigned int, flags,
   3044                  const struct sockaddr *, to, int, tolen);
   3045    ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
   3046 }
   3047 
   3048 PRE(sendfile)
   3049 {
   3050 #if VG_WORDSIZE == 4
   3051    PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
   3052          ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
   3053 
   3054    PRE_REG_READ7(long, "sendfile",
   3055       int, fromfd, int, tofd,
   3056       vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
   3057       vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
   3058    PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
   3059    if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
   3060 #else
   3061    PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
   3062       ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
   3063 
   3064    PRE_REG_READ6(long, "sendfile",
   3065       int, fromfd, int, tofd,
   3066       vki_uint64_t, offset,
   3067       vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
   3068    PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
   3069    if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
   3070 #endif
   3071 
   3072    *flags |= SfMayBlock;
   3073 }
   3074 POST(sendfile)
   3075 {
   3076 #if VG_WORDSIZE == 4
   3077    POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
   3078    if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
   3079 #else
   3080    POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
   3081    if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
   3082 #endif
   3083 }
   3084 
   3085 PRE(recvfrom)
   3086 {
   3087    *flags |= SfMayBlock;
   3088    PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
   3089       ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
   3090    PRE_REG_READ6(long, "recvfrom",
   3091                  int, s, void *, buf, int, len, unsigned int, flags,
   3092                  struct sockaddr *, from, int *, fromlen);
   3093    ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
   3094 }
   3095 
   3096 POST(recvfrom)
   3097 {
   3098    vg_assert(SUCCESS);
   3099    ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
   3100                                        ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
   3101 }
   3102 
   3103 
   3104 PRE(sendmsg)
   3105 {
   3106    *flags |= SfMayBlock;
   3107    PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   3108    PRE_REG_READ3(long, "sendmsg",
   3109                  int, s, const struct msghdr *, msg, int, flags);
   3110    ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
   3111 }
   3112 
   3113 
   3114 PRE(recvmsg)
   3115 {
   3116    *flags |= SfMayBlock;
   3117    PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   3118    PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
   3119    ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
   3120 }
   3121 
   3122 POST(recvmsg)
   3123 {
   3124    ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
   3125 }
   3126 
   3127 
   3128 PRE(shutdown)
   3129 {
   3130    *flags |= SfMayBlock;
   3131    PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
   3132    PRE_REG_READ2(int, "shutdown", int, s, int, how);
   3133 }
   3134 
   3135 
   3136 PRE(bind)
   3137 {
   3138    PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
   3139    PRE_REG_READ3(long, "bind",
   3140                  int, sockfd, struct sockaddr *, my_addr, int, addrlen);
   3141    ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
   3142 }
   3143 
   3144 
   3145 PRE(listen)
   3146 {
   3147    PRINT("listen ( %ld, %ld )",ARG1,ARG2);
   3148    PRE_REG_READ2(long, "listen", int, s, int, backlog);
   3149 }
   3150 
   3151 
   3152 PRE(getsockname)
   3153 {
   3154    PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
   3155    PRE_REG_READ3(long, "getsockname",
   3156                  int, s, struct sockaddr *, name, int *, namelen);
   3157    ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
   3158 }
   3159 
   3160 POST(getsockname)
   3161 {
   3162    vg_assert(SUCCESS);
   3163    ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
   3164                                           ARG1,ARG2,ARG3);
   3165 }
   3166 
   3167 
   3168 PRE(getpeername)
   3169 {
   3170    PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
   3171    PRE_REG_READ3(long, "getpeername",
   3172                  int, s, struct sockaddr *, name, int *, namelen);
   3173    ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
   3174 }
   3175 
   3176 POST(getpeername)
   3177 {
   3178    vg_assert(SUCCESS);
   3179    ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
   3180                                           ARG1,ARG2,ARG3);
   3181 }
   3182 
   3183 
   3184 PRE(socketpair)
   3185 {
   3186    PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
   3187    PRE_REG_READ4(long, "socketpair",
   3188                  int, d, int, type, int, protocol, int *, sv);
   3189    ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
   3190 }
   3191 
   3192 POST(socketpair)
   3193 {
   3194    vg_assert(SUCCESS);
   3195    ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
   3196                                          ARG1,ARG2,ARG3,ARG4);
   3197 }
   3198 
   3199 
   3200 PRE(gethostuuid)
   3201 {
   3202    PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
   3203    PRE_REG_READ2(int,"gethostuuid",
   3204                  char *,"uuid_buf",
   3205                  const struct vki_timespec *,"timeout");
   3206 
   3207    PRE_MEM_WRITE("uuid_buf", ARG1, 16);
   3208    PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
   3209 
   3210    *flags |= SfMayBlock;
   3211 }
   3212 
   3213 
   3214 POST(gethostuuid)
   3215 {
   3216    POST_MEM_WRITE(ARG1, 16);
   3217 }
   3218 
   3219 /* Darwin pipe() returns the two descriptors in two registers. */
   3220 PRE(pipe)
   3221 {
   3222    PRINT("pipe ( )");
   3223    PRE_REG_READ0(int, "pipe");
   3224 }
   3225 
   3226 POST(pipe)
   3227 {
   3228    Int p0, p1;
   3229    vg_assert(SUCCESS);
   3230    p0 = RES;
   3231    p1 = RESHI;
   3232 
   3233    if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
   3234        !ML_(fd_allowed)(p1, "pipe", tid, True)) {
   3235       VG_(close)(p0);
   3236       VG_(close)(p1);
   3237       SET_STATUS_Failure( VKI_EMFILE );
   3238    } else {
   3239       if (VG_(clo_track_fds)) {
   3240          ML_(record_fd_open_nameless)(tid, p0);
   3241          ML_(record_fd_open_nameless)(tid, p1);
   3242       }
   3243    }
   3244 }
   3245 
   3246 
   3247 PRE(getlogin)
   3248 {
   3249    PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
   3250    PRE_REG_READ2(long, "getlogin",
   3251                  char *,"namebuf", unsigned int,"namelen");
   3252 
   3253    PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
   3254 }
   3255 
   3256 POST(getlogin)
   3257 {
   3258    POST_MEM_WRITE(ARG1, ARG2);
   3259 }
   3260 
   3261 
   3262 PRE(ptrace)
   3263 {
   3264    PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
   3265    PRE_REG_READ4(long, "ptrace",
   3266                  int,"request", vki_pid_t,"pid",
   3267                  vki_caddr_t,"addr", int,"data");
   3268 
   3269    // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
   3270 
   3271    // GrP fixme anything needed?
   3272 }
   3273 
   3274 
   3275 PRE(issetugid)
   3276 {
   3277    PRINT("issetugid ( )");
   3278    PRE_REG_READ0(long, "issetugid");
   3279 }
   3280 
   3281 
   3282 PRE(getdtablesize)
   3283 {
   3284    PRINT("getdtablesize ( )");
   3285    PRE_REG_READ0(long, "getdtablesize");
   3286 }
   3287 
   3288 POST(getdtablesize)
   3289 {
   3290    // Subtract Valgrind's fd range from client's dtable
   3291    if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
   3292 }
   3293 
   3294 PRE(lseek)
   3295 {
   3296    PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
   3297    PRE_REG_READ4(vki_off_t, "lseek",
   3298                  unsigned int,fd, int,offset_hi, int,offset_lo,
   3299                  unsigned int,whence);
   3300 }
   3301 
   3302 
   3303 PRE(pathconf)
   3304 {
   3305    PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
   3306    PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
   3307    PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
   3308 }
   3309 
   3310 
   3311 PRE(fpathconf)
   3312 {
   3313    PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
   3314    PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
   3315 
   3316    if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
   3317       SET_STATUS_Failure( VKI_EBADF );
   3318 }
   3319 
   3320 
   3321 PRE(getdirentries)
   3322 {
   3323    PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
   3324    PRE_REG_READ4(int, "getdirentries",
   3325                  int, fd, char *, buf, int, nbytes, long *, basep);
   3326    PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
   3327    PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
   3328 }
   3329 
   3330 POST(getdirentries)
   3331 {
   3332    POST_MEM_WRITE(ARG4, sizeof(long));
   3333    // GrP fixme be specific about d_name?
   3334    POST_MEM_WRITE(ARG2, RES);
   3335 }
   3336 
   3337 
   3338 PRE(getdirentries64)
   3339 {
   3340    PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
   3341    PRE_REG_READ4(vki_ssize_t, "getdirentries",
   3342                  int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
   3343    PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t));
   3344    PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
   3345 }
   3346 POST(getdirentries64)
   3347 {
   3348    POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
   3349    // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
   3350    POST_MEM_WRITE(ARG2, RES);
   3351 }
   3352 
   3353 
   3354 PRE(statfs64)
   3355 {
   3356    PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
   3357    PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
   3358    PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
   3359    PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
   3360 }
   3361 POST(statfs64)
   3362 {
   3363    POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
   3364 }
   3365 
   3366 
   3367 PRE(fstatfs64)
   3368 {
   3369    PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
   3370    PRE_REG_READ2(long, "fstatfs64",
   3371                  unsigned int, fd, struct statfs *, buf);
   3372    PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
   3373 }
   3374 POST(fstatfs64)
   3375 {
   3376    POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
   3377 }
   3378 
   3379 PRE(csops)
   3380 {
   3381    PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
   3382    PRE_REG_READ4(int, "csops",
   3383                  vki_pid_t, pid, uint32_t, ops,
   3384                  void *, useraddr, vki_size_t, usersize);
   3385 
   3386    PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
   3387 
   3388    // If the pid is ours, don't mark the program as KILL or HARD
   3389    // Maybe we should keep track of this for later calls to STATUS
   3390    if (!ARG1 || VG_(getpid)() == ARG1) {
   3391       switch (ARG2) {
   3392       case VKI_CS_OPS_MARKINVALID:
   3393       case VKI_CS_OPS_MARKHARD:
   3394       case VKI_CS_OPS_MARKKILL:
   3395          SET_STATUS_Success(0);
   3396       }
   3397    }
   3398 }
   3399 POST(csops)
   3400 {
   3401    POST_MEM_WRITE( ARG3, ARG4 );
   3402 }
   3403 
   3404 PRE(auditon)
   3405 {
   3406    PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
   3407    PRE_REG_READ3(int,"auditon",
   3408                  int,"cmd", void*,"data", unsigned int,"length");
   3409 
   3410    switch (ARG1) {
   3411 
   3412    case VKI_A_SETPOLICY:
   3413    case VKI_A_SETKMASK:
   3414    case VKI_A_SETQCTRL:
   3415    case VKI_A_SETCOND:
   3416    case VKI_A_SETCLASS:
   3417    case VKI_A_SETPMASK:
   3418    case VKI_A_SETFSIZE:
   3419 #if DARWIN_VERS >= DARWIN_10_6
   3420    case VKI_A_SENDTRIGGER:
   3421 #endif
   3422       // kernel reads data..data+length
   3423       PRE_MEM_READ("auditon(data)", ARG2, ARG3);
   3424       break;
   3425 
   3426    case VKI_A_GETKMASK:
   3427    case VKI_A_GETPOLICY:
   3428    case VKI_A_GETQCTRL:
   3429    case VKI_A_GETFSIZE:
   3430    case VKI_A_GETCOND:
   3431       // kernel writes data..data+length
   3432       // GrP fixme be precise about what gets written
   3433       PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
   3434       break;
   3435 
   3436 
   3437    case VKI_A_GETCLASS:
   3438    case VKI_A_GETPINFO:
   3439    case VKI_A_GETPINFO_ADDR:
   3440 #if DARWIN_VERS >= DARWIN_10_6
   3441    case VKI_A_GETSINFO_ADDR:
   3442 #endif
   3443       // kernel reads and writes data..data+length
   3444       // GrP fixme be precise about what gets read and written
   3445       PRE_MEM_READ("auditon(data)", ARG2, ARG3);
   3446       PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
   3447       break;
   3448 
   3449    case VKI_A_SETKAUDIT:
   3450    case VKI_A_SETSTAT:
   3451    case VKI_A_SETUMASK:
   3452    case VKI_A_SETSMASK:
   3453    case VKI_A_GETKAUDIT:
   3454    case VKI_A_GETCWD:
   3455    case VKI_A_GETCAR:
   3456    case VKI_A_GETSTAT:
   3457       // unimplemented on darwin
   3458       break;
   3459 
   3460    default:
   3461       VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1);
   3462       break;
   3463    }
   3464 }
   3465 POST(auditon)
   3466 {
   3467    switch (ARG1) {
   3468 
   3469    case VKI_A_SETPOLICY:
   3470    case VKI_A_SETKMASK:
   3471    case VKI_A_SETQCTRL:
   3472    case VKI_A_SETCOND:
   3473    case VKI_A_SETCLASS:
   3474    case VKI_A_SETPMASK:
   3475    case VKI_A_SETFSIZE:
   3476 #if DARWIN_VERS >= DARWIN_10_6
   3477    case VKI_A_SENDTRIGGER:
   3478 #endif
   3479       // kernel reads data..data+length
   3480       break;
   3481 
   3482    case VKI_A_GETKMASK:
   3483    case VKI_A_GETPOLICY:
   3484    case VKI_A_GETQCTRL:
   3485    case VKI_A_GETFSIZE:
   3486    case VKI_A_GETCOND:
   3487       // kernel writes data..data+length
   3488       // GrP fixme be precise about what gets written
   3489       POST_MEM_WRITE(ARG2, ARG3);
   3490       break;
   3491 
   3492 
   3493    case VKI_A_GETCLASS:
   3494    case VKI_A_GETPINFO:
   3495    case VKI_A_GETPINFO_ADDR:
   3496 #if DARWIN_VERS >= DARWIN_10_6
   3497    case VKI_A_GETSINFO_ADDR:
   3498 #endif
   3499       // kernel reads and writes data..data+length
   3500       // GrP fixme be precise about what gets read and written
   3501       POST_MEM_WRITE(ARG2, ARG3);
   3502       break;
   3503 
   3504    case VKI_A_SETKAUDIT:
   3505    case VKI_A_SETSTAT:
   3506    case VKI_A_SETUMASK:
   3507    case VKI_A_SETSMASK:
   3508    case VKI_A_GETKAUDIT:
   3509    case VKI_A_GETCWD:
   3510    case VKI_A_GETCAR:
   3511    case VKI_A_GETSTAT:
   3512       // unimplemented on darwin
   3513       break;
   3514 
   3515    default:
   3516       break;
   3517    }
   3518 }
   3519 
   3520 
   3521 PRE(mmap)
   3522 {
   3523    // SysRes r;
   3524 
   3525 #if VG_WORDSIZE == 4
   3526    PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
   3527          ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
   3528    PRE_REG_READ7(Addr, "mmap",
   3529                  Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
   3530                  unsigned long,offset_hi, unsigned long,offset_lo);
   3531    // GrP fixme V mmap and kernel mach_msg collided once - don't use
   3532    // V's mechanism for now
   3533    // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
   3534    // (Off64T)LOHI64(ARG6, ARG7) );
   3535 #else
   3536    PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
   3537          ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
   3538    PRE_REG_READ6(long, "mmap",
   3539                  Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
   3540                  Off64T,offset);
   3541    // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
   3542 
   3543 #endif
   3544 
   3545    // SET_STATUS_from_SysRes(r);
   3546 }
   3547 
   3548 POST(mmap)
   3549 {
   3550    if (RES != -1) {
   3551       ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
   3552       // Try to load symbols from the region
   3553       VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
   3554                            -1/*don't use_fd*/ );
   3555    }
   3556 }
   3557 
   3558 
   3559 PRE(__sysctl)
   3560 {
   3561    PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
   3562           ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
   3563 
   3564    PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
   3565                  void*, oldp, vki_size_t *, oldlenp,
   3566                  void*, newp, vki_size_t *, newlenp);
   3567 
   3568    PRE_MEM_READ("sysctl(name)", ARG1, ARG2);  // reads name[0..namelen-1]
   3569    if (ARG4) {
   3570       // writes *ARG4
   3571       PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t));
   3572       if (ARG3) {
   3573          // also reads *ARG4, and writes as much as ARG3[0..ARG4-1]
   3574          PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t));
   3575          PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4);
   3576       }
   3577    }
   3578    if (ARG5) {
   3579       PRE_MEM_READ("sysctl(newp)", ARG5, ARG6);
   3580    }
   3581 
   3582    if (VG_(clo_trace_syscalls)) {
   3583       unsigned int i;
   3584       int *name = (int *)ARG1;
   3585       VG_(printf)(" mib: [ ");
   3586       for (i = 0; i < ARG2; i++) {
   3587          VG_(printf)("%d ", name[i]);
   3588       }
   3589       VG_(printf)("]");
   3590    }
   3591 
   3592    // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
   3593    // (executable path and arguments and environment
   3594 
   3595    {
   3596       // Intercept sysctl(kern.usrstack). The kernel's reply would be
   3597       // Valgrind's stack, not the client's stack.
   3598       // GrP fixme kern_usrstack64
   3599       if (ARG1  &&  ARG2 == 2  &&
   3600           ((int *)ARG1)[0] == VKI_CTL_KERN  &&
   3601 #if VG_WORDSIZE == 4
   3602           ((int *)ARG1)[1] == VKI_KERN_USRSTACK32
   3603 #else
   3604           ((int *)ARG1)[1] == VKI_KERN_USRSTACK64
   3605 #endif
   3606           )
   3607       {
   3608          if (ARG5/*newp*/  ||  ARG6/*newlen*/) {
   3609             SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only
   3610          } else {
   3611             Addr *oldp = (Addr *)ARG3;
   3612             size_t *oldlenp = (size_t *)ARG4;
   3613             if (oldlenp) {
   3614                Addr stack_end = VG_(clstk_end)+1;
   3615                size_t oldlen = *oldlenp;
   3616                // always return actual size
   3617                *oldlenp = sizeof(Addr);
   3618                if (oldp  &&  oldlen >= sizeof(Addr)) {
   3619                   // oldp is big enough
   3620                   // copy value and return 0
   3621                   *oldp = stack_end;
   3622                   SET_STATUS_Success(0);
   3623                } else {
   3624                   // oldp isn't big enough
   3625                   // copy as much as possible and return ENOMEM
   3626                   if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen);
   3627                   SET_STATUS_Failure(VKI_ENOMEM);
   3628                }
   3629             }
   3630          }
   3631       }
   3632    }
   3633 
   3634    if (!SUCCESS  &&  !FAILURE) {
   3635       // Don't set SfPostOnFail if we've already handled it locally.
   3636       *flags |= SfPostOnFail;
   3637    }
   3638 }
   3639 
   3640 POST(__sysctl)
   3641 {
   3642    if (SUCCESS  ||  ERR == VKI_ENOMEM) {
   3643       // sysctl can write truncated data and return VKI_ENOMEM
   3644       if (ARG4) {
   3645          POST_MEM_WRITE(ARG4, sizeof(size_t));
   3646       }
   3647       if (ARG3  &&  ARG4) {
   3648          POST_MEM_WRITE(ARG3, *(size_t *)ARG4);
   3649       }
   3650    }
   3651 }
   3652 
   3653 
   3654 PRE(sigpending)
   3655 {
   3656    PRINT( "sigpending ( %#lx )", ARG1 );
   3657    PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
   3658    PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
   3659 }
   3660 POST(sigpending)
   3661 {
   3662    POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
   3663 }
   3664 
   3665 
   3666 PRE(sigprocmask)
   3667 {
   3668    UWord arg1;
   3669    PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
   3670    PRE_REG_READ3(long, "sigprocmask",
   3671                  int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
   3672    if (ARG2 != 0)
   3673       PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
   3674    if (ARG3 != 0)
   3675       PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
   3676 
   3677    /* Massage ARG1 ('how').  If ARG2 (the new mask) is NULL then the
   3678       value of 'how' is irrelevant, and it appears that Darwin's libc
   3679       passes zero, which is not equal to any of
   3680       SIG_{BLOCK,UNBLOCK,SETMASK}.  This causes
   3681       VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
   3682       value independently of the other args.  Solution: in this case,
   3683       simply pass a valid (but irrelevant) value for 'how'. */
   3684    /* Also, in this case the new set is passed to the kernel by
   3685       reference, not value, as in some other sigmask related Darwin
   3686       syscalls. */
   3687    arg1 = ARG1;
   3688    if (ARG2 == 0  /* the new-set is NULL */
   3689        && ARG1 != VKI_SIG_BLOCK
   3690        && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
   3691       arg1 = VKI_SIG_SETMASK;
   3692    }
   3693    SET_STATUS_from_SysRes(
   3694       VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
   3695                                            (vki_sigset_t*)ARG3 )
   3696    );
   3697 
   3698    if (SUCCESS)
   3699       *flags |= SfPollAfter;
   3700 }
   3701 
   3702 POST(sigprocmask)
   3703 {
   3704    vg_assert(SUCCESS);
   3705    if (RES == 0 && ARG3 != 0)
   3706       POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
   3707 }
   3708 
   3709 
   3710 PRE(sigsuspend)
   3711 {
   3712    /* Just hand this off to the kernel.  Is that really correct?  And
   3713       shouldn't we at least set SfPollAfter?  These questions apply to
   3714       all the Linux versions too. */
   3715    /* I think the first arg is the 32-bit signal mask (by value), and
   3716       the other two args are ignored. */
   3717    *flags |= SfMayBlock;
   3718    PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
   3719    PRE_REG_READ1(int, "sigsuspend", int, sigmask);
   3720 }
   3721 
   3722 
   3723 /* Be careful about the 4th arg, since that is a uint64_t.  Hence 64-
   3724    and 32-bit wrappers are different.
   3725 
   3726    ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
   3727    length in the usual way.  I have seen values NULL, 0 passed in some
   3728    cases.  I left the calls to PRE_MEM_WRITE/READ unconditional on the
   3729    basis that they don't do anything if the length is zero, so it's OK
   3730    for the buffer pointer to be NULL in that case (meaning they don't
   3731    complain).
   3732 
   3733    int proc_info(int32_t callnum, int32_t pid,
   3734                  uint32_t flavor, uint64_t arg,
   3735                  user_addr_t buffer, int32_t buffersize)
   3736 */
   3737 #if DARWIN_VERS >= DARWIN_10_6
   3738 PRE(proc_info)
   3739 {
   3740 #if VG_WORDSIZE == 4
   3741    PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
   3742          (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
   3743    PRE_REG_READ7(int, "proc_info",
   3744                  int, callnum, int, pid, unsigned int, flavor,
   3745                  vki_uint32_t, arg_low32,
   3746                  vki_uint32_t, arg_high32,
   3747                  void*, buffer, int, buffersize);
   3748    PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
   3749 #else
   3750    PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
   3751          (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
   3752    PRE_REG_READ6(int, "proc_info",
   3753                  int, callnum, int, pid, unsigned int, flavor,
   3754                  unsigned long long int, arg,
   3755                  void*, buffer, int, buffersize);
   3756    PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
   3757 #endif
   3758 }
   3759 
   3760 POST(proc_info)
   3761 {
   3762 #if VG_WORDSIZE == 4
   3763    vg_assert(SUCCESS);
   3764    POST_MEM_WRITE(ARG6, ARG7);
   3765 #else
   3766    vg_assert(SUCCESS);
   3767    POST_MEM_WRITE(ARG5, ARG6);
   3768 #endif
   3769 }
   3770 
   3771 #endif /* DARWIN_VERS >= DARWIN_10_6 */
   3772 
   3773 /* ---------------------------------------------------------------------
   3774    aio_*
   3775    ------------------------------------------------------------------ */
   3776 
   3777 // We must record the aiocbp for each aio_read() in a table so that when
   3778 // aio_return() is called we can mark the memory written asynchronously by
   3779 // aio_read() as having been written.  We don't have to do this for
   3780 // aio_write().  See bug 197227 for more details.
   3781 static OSet* aiocbp_table = NULL;
   3782 static Bool aio_init_done = False;
   3783 
   3784 static void aio_init(void)
   3785 {
   3786    aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
   3787    aio_init_done = True;
   3788 }
   3789 
   3790 static Bool was_a_successful_aio_read = False;
   3791 
   3792 PRE(aio_return)
   3793 {
   3794    struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
   3795    // This assumes that the kernel looks at the struct pointer, but not the
   3796    // contents of the struct.
   3797    PRINT( "aio_return ( %#lx )", ARG1 );
   3798    PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
   3799 
   3800    if (!aio_init_done) aio_init();
   3801    was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
   3802 }
   3803 POST(aio_return)
   3804 {
   3805    // If we found the aiocbp in our own table it must have been an aio_read(),
   3806    // so mark the buffer as written.  If we didn't find it, it must have been
   3807    // an aio_write() or a bogus aio_return() (eg. a second one on the same
   3808    // aiocbp).  Either way, the buffer won't have been written so we don't
   3809    // have to mark the buffer as written.
   3810    if (was_a_successful_aio_read) {
   3811       struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
   3812       POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
   3813       was_a_successful_aio_read = False;
   3814    }
   3815 }
   3816 
   3817 PRE(aio_suspend)
   3818 {
   3819    // This assumes that the kernel looks at the struct pointers in the list,
   3820    // but not the contents of the structs.
   3821    PRINT( "aio_suspend ( %#lx )", ARG1 );
   3822    PRE_REG_READ3(long, "aio_suspend",
   3823                  const struct vki_aiocb *, aiocbp, int, nent,
   3824                  const struct vki_timespec *, timeout);
   3825    if (ARG2 > 0)
   3826       PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
   3827    if (ARG3)
   3828       PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
   3829 }
   3830 
   3831 PRE(aio_error)
   3832 {
   3833    // This assumes that the kernel looks at the struct pointer, but not the
   3834    // contents of the struct.
   3835    PRINT( "aio_error ( %#lx )", ARG1 );
   3836    PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
   3837 }
   3838 
   3839 PRE(aio_read)
   3840 {
   3841    struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
   3842 
   3843    PRINT( "aio_read ( %#lx )", ARG1 );
   3844    PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
   3845    PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
   3846 
   3847    if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
   3848       if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
   3849          PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
   3850                        (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
   3851       } else {
   3852          SET_STATUS_Failure( VKI_EBADF );
   3853       }
   3854    } else {
   3855       SET_STATUS_Failure( VKI_EINVAL );
   3856    }
   3857 }
   3858 POST(aio_read)
   3859 {
   3860    // We have to record the fact that there is an asynchronous read request
   3861    // pending.  When a successful aio_return() occurs for this aiocb, then we
   3862    // will mark the memory as having been defined.
   3863    struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
   3864    if (!aio_init_done) aio_init();
   3865    // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
   3866    // should have caused the aio_read() to fail and we shouldn't have reached
   3867    // here.
   3868    VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
   3869 }
   3870 
   3871 PRE(aio_write)
   3872 {
   3873    struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
   3874 
   3875    PRINT( "aio_write ( %#lx )", ARG1 );
   3876    PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
   3877    PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
   3878 
   3879    if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
   3880       if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
   3881          PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
   3882                       (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
   3883       } else {
   3884          SET_STATUS_Failure( VKI_EBADF );
   3885       }
   3886    } else {
   3887       SET_STATUS_Failure( VKI_EINVAL );
   3888    }
   3889 }
   3890 
   3891 /* ---------------------------------------------------------------------
   3892    mach_msg: formatted messages
   3893    ------------------------------------------------------------------ */
   3894 
   3895 static size_t desc_size(mach_msg_descriptor_t *desc)
   3896 {
   3897    switch (desc->type.type) {
   3898    case MACH_MSG_PORT_DESCRIPTOR:          return sizeof(desc->port);
   3899    case MACH_MSG_OOL_DESCRIPTOR:           return sizeof(desc->out_of_line);
   3900    case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:  return sizeof(desc->out_of_line);
   3901    case MACH_MSG_OOL_PORTS_DESCRIPTOR:     return sizeof(desc->ool_ports);
   3902    default:
   3903       VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
   3904       return sizeof(desc->type); // guess
   3905    }
   3906 }
   3907 
   3908 
   3909 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
   3910                               const char *name)
   3911 {
   3912    mach_msg_size_t i;
   3913    mach_port_t *ports = (mach_port_t *)desc->address;
   3914    for (i = 0; i < desc->count; i++) {
   3915       assign_port_name(ports[i], name);
   3916    }
   3917 }
   3918 
   3919 
   3920 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
   3921 {
   3922    mach_msg_body_t *body;
   3923    mach_msg_size_t count, i;
   3924    uint8_t *p;
   3925    mach_msg_descriptor_t *desc;
   3926 
   3927    vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
   3928 
   3929    body = (mach_msg_body_t *)(mh+1);
   3930    count = body->msgh_descriptor_count;
   3931    p = (uint8_t *)(body+1);
   3932 
   3933    for (i = 0; i < count; i++) {
   3934       desc = (mach_msg_descriptor_t *)p;
   3935       p += desc_size(desc);
   3936 
   3937       switch (desc->type.type) {
   3938       case MACH_MSG_PORT_DESCRIPTOR:
   3939          // single port
   3940          record_unnamed_port(tid, desc->port.name, -1);
   3941          record_port_insert_rights(desc->port.name, desc->port.disposition);
   3942          PRINT("got port %s;\n", name_for_port(desc->port.name));
   3943          break;
   3944 
   3945       case MACH_MSG_OOL_DESCRIPTOR:
   3946       case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
   3947          // out-of-line memory - map it
   3948          // GrP fixme how is VOLATILE different? do we care?
   3949          // GrP fixme do other flags tell us anything? assume shared for now
   3950          // GrP fixme more SF_ flags marking mach_msg memory might be nice
   3951          // GrP fixme protection
   3952          if (desc->out_of_line.size > 0) {
   3953             Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
   3954             Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
   3955                                     (Addr)desc->out_of_line.size);
   3956             PRINT("got ool mem %p..%#lx;\n", desc->out_of_line.address,
   3957                   (Addr)desc->out_of_line.address+desc->out_of_line.size);
   3958 
   3959             ML_(notify_core_and_tool_of_mmap)(
   3960                start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
   3961                VKI_MAP_PRIVATE, -1, 0);
   3962          }
   3963          // GrP fixme mark only un-rounded part as initialized
   3964          break;
   3965 
   3966       case MACH_MSG_OOL_PORTS_DESCRIPTOR:
   3967          // out-of-line array of ports - map it
   3968          // GrP fixme see fixmes above
   3969          PRINT("got %d ool ports %p..%#lx", desc->ool_ports.count, desc->ool_ports.address, (Addr)desc->ool_ports.address+desc->ool_ports.count*sizeof(mach_port_t));
   3970 
   3971          if (desc->ool_ports.count > 0) {
   3972             Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
   3973             Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
   3974             mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
   3975 
   3976             ML_(notify_core_and_tool_of_mmap)(
   3977                start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
   3978                VKI_MAP_PRIVATE, -1, 0);
   3979 
   3980             PRINT(":");
   3981             for (i = 0; i < desc->ool_ports.count; i++) {
   3982                record_unnamed_port(tid, ports[i], -1);
   3983                record_port_insert_rights(ports[i], desc->port.disposition);
   3984                PRINT(" %s", name_for_port(ports[i]));
   3985             }
   3986          }
   3987          PRINT(";\n");
   3988          break;
   3989 
   3990       default:
   3991          VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
   3992          break;
   3993       }
   3994    }
   3995 }
   3996 
   3997 
   3998 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
   3999 {
   4000 #pragma pack(4)
   4001    struct {
   4002       mach_port_t name;
   4003       mach_msg_size_t pad1;
   4004       uint16_t pad2;
   4005       uint8_t disposition;
   4006       uint8_t type;
   4007    } *desc = (void*)desc2;
   4008 #pragma pack()
   4009 
   4010    PRE_FIELD_READ("msg->desc.port.name",        desc->name);
   4011    PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
   4012    PRE_FIELD_READ("msg->desc.port.type",        desc->type);
   4013 }
   4014 
   4015 
   4016 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
   4017 {
   4018 #pragma pack(4)
   4019    struct {
   4020       Addr address;
   4021 #if VG_WORDSIZE != 8
   4022       mach_msg_size_t size;
   4023 #endif
   4024       uint8_t deallocate;
   4025       uint8_t copy;
   4026       uint8_t pad1;
   4027       uint8_t type;
   4028 #if VG_WORDSIZE == 8
   4029       mach_msg_size_t size;
   4030 #endif
   4031    } *desc = (void*)desc2;
   4032 #pragma pack()
   4033 
   4034    PRE_FIELD_READ("msg->desc.out_of_line.address",    desc->address);
   4035    PRE_FIELD_READ("msg->desc.out_of_line.size",       desc->size);
   4036    PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
   4037    PRE_FIELD_READ("msg->desc.out_of_line.copy",       desc->copy);
   4038    PRE_FIELD_READ("msg->desc.out_of_line.type",       desc->type);
   4039 }
   4040 
   4041 static void pre_oolports_desc_read(ThreadId tid,
   4042                                    mach_msg_ool_ports_descriptor_t *desc2)
   4043 {
   4044 #pragma pack(4)
   4045    struct {
   4046       Addr address;
   4047 #if VG_WORDSIZE != 8
   4048       mach_msg_size_t size;
   4049 #endif
   4050       uint8_t deallocate;
   4051       uint8_t copy;
   4052       uint8_t disposition;
   4053       uint8_t type;
   4054 #if VG_WORDSIZE == 8
   4055       mach_msg_size_t size;
   4056 #endif
   4057    } *desc = (void*)desc2;
   4058 #pragma pack()
   4059 
   4060    PRE_FIELD_READ("msg->desc.ool_ports.address",     desc->address);
   4061    PRE_FIELD_READ("msg->desc.ool_ports.size",        desc->size);
   4062    PRE_FIELD_READ("msg->desc.ool_ports.deallocate",  desc->deallocate);
   4063    PRE_FIELD_READ("msg->desc.ool_ports.copy",        desc->copy);
   4064    PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
   4065    PRE_FIELD_READ("msg->desc.ool_ports.type",        desc->type);
   4066 }
   4067 
   4068 
   4069 // Returns the size of the descriptor area
   4070 // (mach_msg_body_t + any mach_msg_descriptor_t)
   4071 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
   4072 {
   4073    mach_msg_body_t *body;
   4074    mach_msg_size_t count, i;
   4075    uint8_t *p;
   4076    mach_msg_descriptor_t *desc;
   4077 
   4078    vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
   4079 
   4080    body = (mach_msg_body_t *)(mh+1);
   4081    PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
   4082 
   4083    count = body->msgh_descriptor_count;
   4084    p = (uint8_t *)(body+1);
   4085 
   4086    for (i = 0; i < count; i++) {
   4087       desc = (mach_msg_descriptor_t *)p;
   4088       p += desc_size(desc);
   4089 
   4090       switch (desc->type.type) {
   4091       case MACH_MSG_PORT_DESCRIPTOR:
   4092          // single port; no memory map effects
   4093          pre_port_desc_read(tid, &desc->port);
   4094          break;
   4095 
   4096       case MACH_MSG_OOL_DESCRIPTOR:
   4097       case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
   4098          // out-of-line memory - unmap it if it's marked dealloc
   4099          // GrP fixme need to remap if message fails?
   4100          // GrP fixme how is VOLATILE different? do we care?
   4101          // GrP fixme struct is different for lp64
   4102          pre_ool_desc_read(tid, &desc->out_of_line);
   4103 
   4104          if (desc->out_of_line.deallocate  &&  desc->out_of_line.size > 0) {
   4105             vm_size_t size = desc->out_of_line.size;
   4106             Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
   4107             Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
   4108             PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
   4109                   (Addr)desc->out_of_line.address + size);
   4110             ML_(notify_core_and_tool_of_munmap)(start, end - start);
   4111          }
   4112          break;
   4113 
   4114       case MACH_MSG_OOL_PORTS_DESCRIPTOR:
   4115          // out-of-line array of ports - unmap it if it's marked dealloc
   4116          // GrP fixme need to remap if message fails?
   4117          // GrP fixme struct different for lp64
   4118          pre_oolports_desc_read(tid, &desc->ool_ports);
   4119 
   4120          if (desc->ool_ports.deallocate  &&  desc->ool_ports.count > 0) {
   4121             vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
   4122             Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
   4123             Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
   4124             PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
   4125                   (Addr)desc->ool_ports.address + size);
   4126             ML_(notify_core_and_tool_of_munmap)(start, end - start);
   4127          }
   4128          break;
   4129       default:
   4130          VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
   4131          break;
   4132       }
   4133    }
   4134 
   4135    return (size_t)((Addr)p - (Addr)body);
   4136 }
   4137 
   4138 
   4139 /* ---------------------------------------------------------------------
   4140    mach_msg: host-related messages
   4141    ------------------------------------------------------------------ */
   4142 
   4143 
   4144 POST(host_info)
   4145 {
   4146 #pragma pack(4)
   4147    typedef struct {
   4148       mach_msg_header_t Head;
   4149       NDR_record_t NDR;
   4150       kern_return_t RetCode;
   4151       mach_msg_type_number_t host_info_outCnt;
   4152       integer_t host_info_out[14];
   4153    } Reply;
   4154 #pragma pack()
   4155 
   4156    Reply *reply = (Reply *)ARG1;
   4157 
   4158    if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
   4159 }
   4160 
   4161 PRE(host_info)
   4162 {
   4163 #pragma pack(4)
   4164    typedef struct {
   4165       mach_msg_header_t Head;
   4166       NDR_record_t NDR;
   4167       host_flavor_t flavor;
   4168       mach_msg_type_number_t host_info_outCnt;
   4169    } Request;
   4170 #pragma pack()
   4171 
   4172    Request *req = (Request *)ARG1;
   4173 
   4174    PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
   4175 
   4176    AFTER = POST_FN(host_info);
   4177 }
   4178 
   4179 
   4180 POST(host_page_size)
   4181 {
   4182 #pragma pack(4)
   4183    typedef struct {
   4184       mach_msg_header_t Head;
   4185       NDR_record_t NDR;
   4186       kern_return_t RetCode;
   4187       vm_size_t out_page_size;
   4188    } Reply;
   4189 #pragma pack()
   4190 
   4191    Reply *reply = (Reply *)ARG1;
   4192 
   4193    if (!reply->RetCode) {
   4194      PRINT("page size %llu", (ULong)reply->out_page_size);
   4195    } else {
   4196       PRINT("mig return %d", reply->RetCode);
   4197    }
   4198 }
   4199 
   4200 PRE(host_page_size)
   4201 {
   4202    PRINT("host_page_size(mach_host_self(), ...)");
   4203 
   4204    AFTER = POST_FN(host_page_size);
   4205 }
   4206 
   4207 
   4208 POST(host_get_io_master)
   4209 {
   4210 #pragma pack(4)
   4211    typedef struct {
   4212       mach_msg_header_t Head;
   4213       /* start of the kernel processed data */
   4214       mach_msg_body_t msgh_body;
   4215       mach_msg_port_descriptor_t io_master;
   4216       /* end of the kernel processed data */
   4217    } Reply;
   4218 #pragma pack()
   4219 
   4220    Reply *reply = (Reply *)ARG1;
   4221 
   4222    assign_port_name(reply->io_master.name, "io_master-%p");
   4223    PRINT("%s", name_for_port(reply->io_master.name));
   4224 }
   4225 
   4226 PRE(host_get_io_master)
   4227 {
   4228 #pragma pack(4)
   4229    typedef struct {
   4230       mach_msg_header_t Head;
   4231    } Request;
   4232 #pragma pack()
   4233 
   4234    // Request *req = (Request *)ARG1;
   4235 
   4236    PRINT("host_get_io_master(mach_host_self())");
   4237 
   4238    AFTER = POST_FN(host_get_io_master);
   4239 }
   4240 
   4241 
   4242 POST(host_get_clock_service)
   4243 {
   4244 #pragma pack(4)
   4245    typedef struct {
   4246       mach_msg_header_t Head;
   4247       /* start of the kernel processed data */
   4248       mach_msg_body_t msgh_body;
   4249       mach_msg_port_descriptor_t clock_serv;
   4250       /* end of the kernel processed data */
   4251    } Reply;
   4252 #pragma pack()
   4253 
   4254    Reply *reply = (Reply *)ARG1;
   4255 
   4256    assign_port_name(reply->clock_serv.name, "clock-%p");
   4257    PRINT("%s", name_for_port(reply->clock_serv.name));
   4258 }
   4259 
   4260 PRE(host_get_clock_service)
   4261 {
   4262 #pragma pack(4)
   4263    typedef struct {
   4264       mach_msg_header_t Head;
   4265       NDR_record_t NDR;
   4266       clock_id_t clock_id;
   4267    } Request;
   4268 #pragma pack()
   4269 
   4270    Request *req = (Request *)ARG1;
   4271 
   4272    PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
   4273 
   4274    AFTER = POST_FN(host_get_clock_service);
   4275 }
   4276 
   4277 
   4278 PRE(host_request_notification)
   4279 {
   4280 #pragma pack(4)
   4281    typedef struct {
   4282       mach_msg_header_t Head;
   4283       /* start of the kernel processed data */
   4284       mach_msg_body_t msgh_body;
   4285       mach_msg_port_descriptor_t notify_port;
   4286       /* end of the kernel processed data */
   4287       NDR_record_t NDR;
   4288       host_flavor_t notify_type;
   4289    } Request;
   4290 #pragma pack()
   4291 
   4292    Request *req = (Request *)ARG1;
   4293 
   4294    if (MACH_REMOTE == mach_task_self()) {
   4295       if (req->notify_type == 0) {
   4296          PRINT("host_request_notification(mach_host_self(), %s, %s)",
   4297                "HOST_NOTIFY_CALENDAR_CHANGE",
   4298                name_for_port(req->notify_port.name));
   4299       } else {
   4300          PRINT("host_request_notification(mach_host_self(), %d, %s)",
   4301                req->notify_type,
   4302                name_for_port(req->notify_port.name));
   4303       }
   4304    } else {
   4305       PRINT("host_request_notification(%s, %d, %s)",
   4306             name_for_port(MACH_REMOTE),
   4307             req->notify_type,
   4308             name_for_port(req->notify_port.name));
   4309    }
   4310 
   4311     // GrP fixme only do this on success
   4312    assign_port_name(req->notify_port.name, "host_notify-%p");
   4313 }
   4314 
   4315 
   4316 /* ---------------------------------------------------------------------
   4317    mach_msg: messages to a task
   4318    ------------------------------------------------------------------ */
   4319 
   4320 // JRS 2011-Aug-25: just guessing here.  I have no clear idea how
   4321 // these structs are derived.  They obviously relate to the various
   4322 // .def files in the xnu sources, and can also be found in some
   4323 // form in /usr/include/mach/*.h, but not sure how these all
   4324 // relate to each other.
   4325 
   4326 PRE(mach_port_set_context)
   4327 {
   4328 #pragma pack(4)
   4329    typedef struct {
   4330       mach_msg_header_t Head;
   4331       NDR_record_t NDR;
   4332       mach_port_name_t name;
   4333       mach_vm_address_t context;
   4334    } Request;
   4335 #pragma pack()
   4336 
   4337    Request *req = (Request *)ARG1;
   4338 
   4339    PRINT("mach_port_set_context(%s, %s, 0x%llx)",
   4340         name_for_port(MACH_REMOTE),
   4341         name_for_port(req->name), req->context);
   4342 
   4343    AFTER = POST_FN(mach_port_set_context);
   4344 }
   4345 
   4346 POST(mach_port_set_context)
   4347 {
   4348 #pragma pack(4)
   4349    typedef struct {
   4350       mach_msg_header_t Head;
   4351       NDR_record_t NDR;
   4352       kern_return_t RetCode;
   4353    } Reply;
   4354 #pragma pack()
   4355 }
   4356 
   4357 
   4358 // JRS 2011-Aug-25 FIXME completely bogus
   4359 PRE(task_get_exception_ports)
   4360 {
   4361 #pragma pack(4)
   4362    typedef struct {
   4363       mach_msg_header_t Head;
   4364       NDR_record_t NDR;
   4365       exception_mask_t exception_mask;
   4366    } Request;
   4367 #pragma pack()
   4368 
   4369    PRINT("task_get_exception_ports(BOGUS)");
   4370    AFTER = POST_FN(task_get_exception_ports);
   4371 }
   4372 
   4373 POST(task_get_exception_ports)
   4374 {
   4375 #pragma pack(4)
   4376    typedef struct {
   4377       mach_msg_header_t Head;
   4378       /* start of the kernel processed data */
   4379       mach_msg_body_t msgh_body;
   4380       mach_msg_port_descriptor_t old_handlers[32];
   4381       /* end of the kernel processed data */
   4382       NDR_record_t NDR;
   4383       mach_msg_type_number_t masksCnt;
   4384       exception_mask_t masks[32];
   4385       exception_behavior_t old_behaviors[32];
   4386       thread_state_flavor_t old_flavors[32];
   4387    } Reply;
   4388 #pragma pack()
   4389 }
   4390 
   4391 
   4392 ///////////////////////////////////////////////////
   4393 
   4394 PRE(mach_port_type)
   4395 {
   4396 #pragma pack(4)
   4397    typedef struct {
   4398       mach_msg_header_t Head;
   4399       NDR_record_t NDR;
   4400       mach_port_name_t name;
   4401    } Request;
   4402 #pragma pack()
   4403 
   4404    Request *req = (Request *)ARG1;
   4405 
   4406    PRINT("mach_port_type(%s, %s, ...)",
   4407          name_for_port(MACH_REMOTE), name_for_port(req->name));
   4408 
   4409    AFTER = POST_FN(mach_port_type);
   4410 }
   4411 
   4412 POST(mach_port_type)
   4413 {
   4414 }
   4415 
   4416 
   4417 PRE(mach_port_extract_member)
   4418 {
   4419 #pragma pack(4)
   4420    typedef struct {
   4421       mach_msg_header_t Head;
   4422       NDR_record_t NDR;
   4423       mach_port_name_t name;
   4424       mach_port_name_t pset;
   4425    } Request;
   4426 #pragma pack()
   4427 
   4428    Request *req = (Request *)ARG1;
   4429 
   4430    PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
   4431          name_for_port(MACH_REMOTE),
   4432          req->name, req->pset);
   4433 
   4434    AFTER = POST_FN(mach_port_extract_member);
   4435 
   4436    // GrP fixme port tracker?
   4437 }
   4438 
   4439 POST(mach_port_extract_member)
   4440 {
   4441 #pragma pack(4)
   4442    typedef struct {
   4443       mach_msg_header_t Head;
   4444       NDR_record_t NDR;
   4445       kern_return_t RetCode;
   4446    } Reply;
   4447 #pragma pack()
   4448 
   4449    Reply *reply = (Reply *)ARG1;
   4450 
   4451    if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
   4452 }
   4453 
   4454 
   4455 PRE(mach_port_allocate)
   4456 {
   4457 #pragma pack(4)
   4458    typedef struct {
   4459       mach_msg_header_t Head;
   4460       NDR_record_t NDR;
   4461       mach_port_right_t right;
   4462    } Request;
   4463 #pragma pack()
   4464 
   4465    Request *req = (Request *)ARG1;
   4466 
   4467    PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
   4468 
   4469    MACH_ARG(mach_port_allocate.right) = req->right;
   4470 
   4471    AFTER = POST_FN(mach_port_allocate);
   4472 }
   4473 
   4474 POST(mach_port_allocate)
   4475 {
   4476 #pragma pack(4)
   4477    typedef struct {
   4478       mach_msg_header_t Head;
   4479       NDR_record_t NDR;
   4480       kern_return_t RetCode;
   4481       mach_port_name_t name;
   4482    } Reply;
   4483 #pragma pack()
   4484 
   4485    Reply *reply = (Reply *)ARG1;
   4486 
   4487    if (!reply->RetCode) {
   4488       if (MACH_REMOTE == vg_task_port) {
   4489          // GrP fixme port tracking is too imprecise
   4490          // vg_assert(!port_exists(reply->name));
   4491          record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
   4492          PRINT("got port 0x%x", reply->name);
   4493       } else {
   4494          VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
   4495       }
   4496    } else {
   4497       PRINT("mig return %d", reply->RetCode);
   4498    }
   4499 }
   4500 
   4501 
   4502 PRE(mach_port_deallocate)
   4503 {
   4504 #pragma pack(4)
   4505    typedef struct {
   4506       mach_msg_header_t Head;
   4507       NDR_record_t NDR;
   4508       mach_port_name_t name;
   4509    } Request;
   4510 #pragma pack()
   4511 
   4512    Request *req = (Request *)ARG1;
   4513 
   4514    PRINT("mach_port_deallocate(%s, %s)",
   4515          name_for_port(MACH_REMOTE),
   4516          name_for_port(req->name));
   4517 
   4518    MACH_ARG(mach_port.port) = req->name;
   4519 
   4520    AFTER = POST_FN(mach_port_deallocate);
   4521 
   4522    // Must block to prevent race (other thread allocates and
   4523    // notifies after we deallocate but before we notify)
   4524    *flags &= ~SfMayBlock;
   4525 }
   4526 
   4527 POST(mach_port_deallocate)
   4528 {
   4529 #pragma pack(4)
   4530    typedef struct {
   4531       mach_msg_header_t Head;
   4532       NDR_record_t NDR;
   4533       kern_return_t RetCode;
   4534    } Reply;
   4535 #pragma pack()
   4536 
   4537    Reply *reply = (Reply *)ARG1;
   4538 
   4539    if (!reply->RetCode) {
   4540       if (MACH_REMOTE == vg_task_port) {
   4541          // Must have cleared SfMayBlock in PRE to prevent race
   4542          record_port_dealloc(MACH_ARG(mach_port.port));
   4543       } else {
   4544          VG_(printf)("UNKNOWN remote port dealloc\n");
   4545       }
   4546    } else {
   4547       PRINT("mig return %d", reply->RetCode);
   4548    }
   4549 }
   4550 
   4551 
   4552 PRE(mach_port_get_refs)
   4553 {
   4554 #pragma pack(4)
   4555    typedef struct {
   4556       mach_msg_header_t Head;
   4557       NDR_record_t NDR;
   4558       mach_port_name_t name;
   4559       mach_port_right_t right;
   4560    } Request;
   4561 #pragma pack()
   4562 
   4563    Request *req = (Request *)ARG1;
   4564 
   4565    PRINT("mach_port_get_refs(%s, %s, 0x%x)",
   4566          name_for_port(MACH_REMOTE),
   4567          name_for_port(req->name), req->right);
   4568 
   4569    MACH_ARG(mach_port_mod_refs.port) = req->name;
   4570    MACH_ARG(mach_port_mod_refs.right) = req->right;
   4571 
   4572    AFTER = POST_FN(mach_port_get_refs);
   4573 }
   4574 
   4575 POST(mach_port_get_refs)
   4576 {
   4577 #pragma pack(4)
   4578    typedef struct {
   4579       mach_msg_header_t Head;
   4580       NDR_record_t NDR;
   4581       kern_return_t RetCode;
   4582       mach_port_urefs_t refs;
   4583    } Reply;
   4584 #pragma pack()
   4585 
   4586    Reply *reply = (Reply *)ARG1;
   4587 
   4588    if (!reply->RetCode) {
   4589       PRINT("got refs=%d", reply->refs);
   4590    } else {
   4591       PRINT("mig return %d", reply->RetCode);
   4592    }
   4593 }
   4594 
   4595 
   4596 PRE(mach_port_mod_refs)
   4597 {
   4598 #pragma pack(4)
   4599    typedef struct {
   4600       mach_msg_header_t Head;
   4601       NDR_record_t NDR;
   4602       mach_port_name_t name;
   4603       mach_port_right_t right;
   4604       mach_port_delta_t delta;
   4605    } Request;
   4606 #pragma pack()
   4607 
   4608    Request *req = (Request *)ARG1;
   4609 
   4610    PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
   4611          name_for_port(MACH_REMOTE),
   4612          name_for_port(req->name), req->right, req->delta);
   4613 
   4614    MACH_ARG(mach_port_mod_refs.port) = req->name;
   4615    MACH_ARG(mach_port_mod_refs.right) = req->right;
   4616    MACH_ARG(mach_port_mod_refs.delta) = req->delta;
   4617 
   4618    AFTER = POST_FN(mach_port_mod_refs);
   4619 
   4620    // Must block to prevent race (other thread allocates and
   4621    // notifies after we deallocate but before we notify)
   4622    *flags &= ~SfMayBlock;
   4623 }
   4624 
   4625 POST(mach_port_mod_refs)
   4626 {
   4627 #pragma pack(4)
   4628    typedef struct {
   4629       mach_msg_header_t Head;
   4630       NDR_record_t NDR;
   4631       kern_return_t RetCode;
   4632    } Reply;
   4633 #pragma pack()
   4634 
   4635    Reply *reply = (Reply *)ARG1;
   4636 
   4637    if (!reply->RetCode) {
   4638       if (MACH_REMOTE == vg_task_port) {
   4639          // Must have cleared SfMayBlock in PRE to prevent race
   4640          record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
   4641                               MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
   4642                               MACH_ARG(mach_port_mod_refs.delta));
   4643       } else {
   4644          VG_(printf)("UNKNOWN remote port mod refs\n");
   4645       }
   4646    } else {
   4647       PRINT("mig return %d", reply->RetCode);
   4648    }
   4649 }
   4650 
   4651 
   4652 PRE(mach_port_get_set_status)
   4653 {
   4654 #pragma pack(4)
   4655    typedef struct {
   4656       mach_msg_header_t Head;
   4657       NDR_record_t NDR;
   4658       mach_port_name_t name;
   4659    } Request;
   4660 #pragma pack()
   4661 
   4662    Request *req = (Request *)ARG1;
   4663 
   4664    PRINT("mach_port_get_set_status(%s, %s)",
   4665          name_for_port(MACH_REMOTE),
   4666          name_for_port(req->name));
   4667 
   4668    AFTER = POST_FN(mach_port_get_set_status);
   4669 }
   4670 
   4671 POST(mach_port_get_set_status)
   4672 {
   4673 #pragma pack(4)
   4674    typedef struct {
   4675       mach_msg_header_t Head;
   4676       /* start of the kernel processed data */
   4677       mach_msg_body_t msgh_body;
   4678       mach_msg_ool_descriptor_t members;
   4679       /* end of the kernel processed data */
   4680       NDR_record_t NDR;
   4681       mach_msg_type_number_t membersCnt;
   4682       mach_msg_trailer_t trailer;
   4683    } Reply;
   4684 #pragma pack()
   4685 
   4686    // Reply *reply = (Reply *)ARG1;
   4687 
   4688    // GrP fixme nothing to do?
   4689 }
   4690 
   4691 
   4692 PRE(mach_port_move_member)
   4693 {
   4694 #pragma pack(4)
   4695     typedef struct {
   4696         mach_msg_header_t Head;
   4697         NDR_record_t NDR;
   4698         mach_port_name_t member;
   4699         mach_port_name_t after;
   4700     } Request;
   4701 #pragma pack()
   4702 
   4703     Request *req = (Request *)ARG1;
   4704 
   4705     PRINT("mach_port_move_member(%s, %s, %s)",
   4706           name_for_port(MACH_REMOTE),
   4707           name_for_port(req->member),
   4708           name_for_port(req->after));
   4709     /*
   4710     MACH_ARG(mach_port_move_member.member) = req->member;
   4711     MACH_ARG(mach_port_move_member.after) = req->after;
   4712     */
   4713     AFTER = POST_FN(mach_port_move_member);
   4714 }
   4715 
   4716 POST(mach_port_move_member)
   4717 {
   4718 #pragma pack(4)
   4719    typedef struct {
   4720       mach_msg_header_t Head;
   4721       NDR_record_t NDR;
   4722       kern_return_t RetCode;
   4723       mach_msg_trailer_t trailer;
   4724    } Reply;
   4725 #pragma pack()
   4726 
   4727    Reply *reply = (Reply *)ARG1;
   4728 
   4729    if (!reply->RetCode) {
   4730       // fixme port set tracker?
   4731    } else {
   4732       PRINT("mig return %d", reply->RetCode);
   4733    }
   4734 }
   4735 
   4736 
   4737 PRE(mach_port_destroy)
   4738 {
   4739 #pragma pack(4)
   4740    typedef struct {
   4741       mach_msg_header_t Head;
   4742       NDR_record_t NDR;
   4743       mach_port_name_t name;
   4744    } Request;
   4745 #pragma pack()
   4746 
   4747    Request *req = (Request *)ARG1;
   4748 
   4749    PRINT("mach_port_destroy(%s, %s)",
   4750          name_for_port(MACH_REMOTE),
   4751          name_for_port(req->name));
   4752 
   4753    MACH_ARG(mach_port.port) = req->name;
   4754 
   4755    AFTER = POST_FN(mach_port_destroy);
   4756 
   4757    // Must block to prevent race (other thread allocates and
   4758    // notifies after we deallocate but before we notify)
   4759    *flags &= ~SfMayBlock;
   4760 }
   4761 
   4762 POST(mach_port_destroy)
   4763 {
   4764 #pragma pack(4)
   4765    typedef struct {
   4766       mach_msg_header_t Head;
   4767       NDR_record_t NDR;
   4768       kern_return_t RetCode;
   4769    } Reply;
   4770 #pragma pack()
   4771 
   4772    Reply *reply = (Reply *)ARG1;
   4773 
   4774    if (!reply->RetCode) {
   4775       if (MACH_REMOTE == vg_task_port) {
   4776          // Must have cleared SfMayBlock in PRE to prevent race
   4777          record_port_destroy(MACH_ARG(mach_port.port));
   4778       } else {
   4779          VG_(printf)("UNKNOWN remote port destroy\n");
   4780       }
   4781    } else {
   4782       PRINT("mig return %d", reply->RetCode);
   4783    }
   4784 }
   4785 
   4786 
   4787 PRE(mach_port_request_notification)
   4788 {
   4789 #pragma pack(4)
   4790    typedef struct {
   4791       mach_msg_header_t Head;
   4792       /* start of the kernel processed data */
   4793       mach_msg_body_t msgh_body;
   4794       mach_msg_port_descriptor_t notify;
   4795       /* end of the kernel processed data */
   4796       NDR_record_t NDR;
   4797       mach_port_name_t name;
   4798       mach_msg_id_t msgid;
   4799       mach_port_mscount_t sync;
   4800    } Request;
   4801 #pragma pack()
   4802 
   4803    Request *req = (Request *)ARG1;
   4804 
   4805    PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
   4806          name_for_port(MACH_REMOTE),
   4807          name_for_port(req->name), req->msgid, req->sync,
   4808          req->notify.name, req->notify.disposition);
   4809 
   4810    AFTER = POST_FN(mach_port_request_notification);
   4811 }
   4812 
   4813 POST(mach_port_request_notification)
   4814 {
   4815    // GrP fixme port tracker? not sure
   4816 }
   4817 
   4818 
   4819 PRE(mach_port_insert_right)
   4820 {
   4821 #pragma pack(4)
   4822    typedef struct {
   4823       mach_msg_header_t Head;
   4824       /* start of the kernel processed data */
   4825       mach_msg_body_t msgh_body;
   4826       mach_msg_port_descriptor_t poly;
   4827       /* end of the kernel processed data */
   4828       NDR_record_t NDR;
   4829       mach_port_name_t name;
   4830    } Request;
   4831 #pragma pack()
   4832 
   4833    Request *req = (Request *)ARG1;
   4834 
   4835    PRINT("mach_port_insert_right(%s, %s, %d, %d)",
   4836          name_for_port(MACH_REMOTE),
   4837          name_for_port(req->name), req->poly.name, req->poly.disposition);
   4838 
   4839    AFTER = POST_FN(mach_port_insert_right);
   4840 
   4841    if (MACH_REMOTE == mach_task_self()) {
   4842       // GrP fixme import_complex_message handles everything?
   4843       // what about export_complex_message for MOVE variants?
   4844    } else {
   4845       VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
   4846       // GrP fixme also may remove rights from this task?
   4847    }
   4848 
   4849    // GrP fixme port tracker?
   4850 }
   4851 
   4852 POST(mach_port_insert_right)
   4853 {
   4854 }
   4855 
   4856 
   4857 PRE(mach_port_extract_right)
   4858 {
   4859 #pragma pack(4)
   4860    typedef struct {
   4861       mach_msg_header_t Head;
   4862       NDR_record_t NDR;
   4863       mach_port_name_t name;
   4864       mach_msg_type_name_t msgt_name;
   4865    } Request;
   4866 #pragma pack()
   4867 
   4868    Request *req = (Request *)ARG1;
   4869 
   4870    PRINT("mach_port_extract_right(%s, %s, %d)",
   4871          name_for_port(MACH_REMOTE),
   4872          name_for_port(req->name), req->msgt_name);
   4873 
   4874    AFTER = POST_FN(mach_port_extract_right);
   4875 
   4876    // fixme port tracker?
   4877 }
   4878 
   4879 POST(mach_port_extract_right)
   4880 {
   4881    // fixme import_complex_message handles the returned result, right?
   4882 }
   4883 
   4884 
   4885 PRE(mach_port_get_attributes)
   4886 {
   4887 #pragma pack(4)
   4888    typedef struct {
   4889       mach_msg_header_t Head;
   4890       NDR_record_t NDR;
   4891       mach_port_name_t name;
   4892       mach_port_flavor_t flavor;
   4893       mach_msg_type_number_t port_info_outCnt;
   4894    } Request;
   4895 #pragma pack()
   4896 
   4897    Request *req = (Request *)ARG1;
   4898 
   4899    PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
   4900          name_for_port(MACH_REMOTE),
   4901          name_for_port(req->name), req->flavor, req->port_info_outCnt);
   4902 
   4903    AFTER = POST_FN(mach_port_get_attributes);
   4904 }
   4905 
   4906 POST(mach_port_get_attributes)
   4907 {
   4908 }
   4909 
   4910 
   4911 PRE(mach_port_set_attributes)
   4912 {
   4913 #pragma pack(4)
   4914    typedef struct {
   4915       mach_msg_header_t Head;
   4916       NDR_record_t NDR;
   4917       mach_port_name_t name;
   4918       mach_port_flavor_t flavor;
   4919       mach_msg_type_number_t port_infoCnt;
   4920       integer_t port_info[10];
   4921    } Request;
   4922 #pragma pack()
   4923 
   4924    Request *req = (Request *)ARG1;
   4925 
   4926    PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
   4927         name_for_port(MACH_REMOTE),
   4928         name_for_port(req->name), req->flavor, req->port_infoCnt);
   4929 
   4930    AFTER = POST_FN(mach_port_set_attributes);
   4931 }
   4932 
   4933 POST(mach_port_set_attributes)
   4934 {
   4935 }
   4936 
   4937 
   4938 PRE(mach_port_insert_member)
   4939 {
   4940 #pragma pack(4)
   4941    typedef struct {
   4942       mach_msg_header_t Head;
   4943       NDR_record_t NDR;
   4944       mach_port_name_t name;
   4945       mach_port_name_t pset;
   4946    } Request;
   4947 #pragma pack()
   4948 
   4949    Request *req = (Request *)ARG1;
   4950 
   4951    PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
   4952          name_for_port(MACH_REMOTE), req->name, req->pset);
   4953 
   4954    AFTER = POST_FN(mach_port_insert_member);
   4955 
   4956    // GrP fixme port tracker?
   4957 }
   4958 
   4959 POST(mach_port_insert_member)
   4960 {
   4961 }
   4962 
   4963 
   4964 PRE(task_get_special_port)
   4965 {
   4966 #pragma pack(4)
   4967    typedef struct {
   4968       mach_msg_header_t Head;
   4969       NDR_record_t NDR;
   4970       int which_port;
   4971    } Request;
   4972 #pragma pack()
   4973 
   4974    Request *req = (Request *)ARG1;
   4975 
   4976    switch (req->which_port) {
   4977    case TASK_KERNEL_PORT:
   4978       PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
   4979             name_for_port(MACH_REMOTE));
   4980       break;
   4981    case TASK_HOST_PORT:
   4982       PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
   4983             name_for_port(MACH_REMOTE));
   4984       break;
   4985    case TASK_BOOTSTRAP_PORT:
   4986       PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
   4987             name_for_port(MACH_REMOTE));
   4988       break;
   4989    case TASK_WIRED_LEDGER_PORT:
   4990       PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
   4991             name_for_port(MACH_REMOTE));
   4992       break;
   4993    case TASK_PAGED_LEDGER_PORT:
   4994       PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
   4995             name_for_port(MACH_REMOTE));
   4996       break;
   4997    default:
   4998       PRINT("task_get_special_port(%s, %d)",
   4999             name_for_port(MACH_REMOTE), req->which_port);
   5000       break;
   5001    }
   5002 
   5003    MACH_ARG(task_get_special_port.which_port) = req->which_port;
   5004 
   5005    AFTER = POST_FN(task_get_special_port);
   5006 }
   5007 
   5008 POST(task_get_special_port)
   5009 {
   5010 #pragma pack(4)
   5011    typedef struct {
   5012       mach_msg_header_t Head;
   5013       /* start of the kernel processed data */
   5014       mach_msg_body_t msgh_body;
   5015       mach_msg_port_descriptor_t special_port;
   5016       /* end of the kernel processed data */
   5017    } Reply;
   5018 #pragma pack()
   5019 
   5020    Reply *reply = (Reply *)ARG1;
   5021 
   5022    PRINT("got port %#x ", reply->special_port.name);
   5023 
   5024    switch (MACH_ARG(task_get_special_port.which_port)) {
   5025    case TASK_BOOTSTRAP_PORT:
   5026       vg_bootstrap_port = reply->special_port.name;
   5027       assign_port_name(reply->special_port.name, "bootstrap");
   5028       break;
   5029    case TASK_KERNEL_PORT:
   5030       assign_port_name(reply->special_port.name, "kernel");
   5031       break;
   5032    case TASK_HOST_PORT:
   5033       assign_port_name(reply->special_port.name, "host");
   5034       break;
   5035    case TASK_WIRED_LEDGER_PORT:
   5036       assign_port_name(reply->special_port.name, "wired-ledger");
   5037       break;
   5038    case TASK_PAGED_LEDGER_PORT:
   5039       assign_port_name(reply->special_port.name, "paged-ledger");
   5040       break;
   5041    default:
   5042       assign_port_name(reply->special_port.name, "special-%p");
   5043       break;
   5044    }
   5045 
   5046    PRINT("%s", name_for_port(reply->special_port.name));
   5047 }
   5048 
   5049 
   5050 PRE(semaphore_create)
   5051 {
   5052 #pragma pack(4)
   5053    typedef struct {
   5054       mach_msg_header_t Head;
   5055       NDR_record_t NDR;
   5056       int policy;
   5057       int value;
   5058    } Request;
   5059 #pragma pack()
   5060 
   5061    Request *req = (Request *)ARG1;
   5062 
   5063    PRINT("semaphore_create(%s, ..., %d, %d)",
   5064          name_for_port(MACH_REMOTE), req->policy, req->value);
   5065 
   5066    AFTER = POST_FN(semaphore_create);
   5067 }
   5068 
   5069 POST(semaphore_create)
   5070 {
   5071 #pragma pack(4)
   5072    typedef struct {
   5073       mach_msg_header_t Head;
   5074       /* start of the kernel processed data */
   5075       mach_msg_body_t msgh_body;
   5076       mach_msg_port_descriptor_t semaphore;
   5077       /* end of the kernel processed data */
   5078       mach_msg_trailer_t trailer;
   5079    } Reply;
   5080 #pragma pack()
   5081 
   5082    Reply *reply = (Reply *)ARG1;
   5083 
   5084    assign_port_name(reply->semaphore.name, "semaphore-%p");
   5085    PRINT("%s", name_for_port(reply->semaphore.name));
   5086 }
   5087 
   5088 
   5089 PRE(semaphore_destroy)
   5090 {
   5091 #pragma pack(4)
   5092    typedef struct {
   5093       mach_msg_header_t Head;
   5094       /* start of the kernel processed data */
   5095       mach_msg_body_t msgh_body;
   5096       mach_msg_port_descriptor_t semaphore;
   5097       /* end of the kernel processed data */
   5098       mach_msg_trailer_t trailer;
   5099    } Request;
   5100 #pragma pack()
   5101 
   5102    Request *req = (Request *)ARG1;
   5103 
   5104    PRINT("semaphore_destroy(%s, %s)",
   5105          name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
   5106 
   5107    record_port_destroy(req->semaphore.name);
   5108 
   5109    AFTER = POST_FN(semaphore_destroy);
   5110 }
   5111 
   5112 POST(semaphore_destroy)
   5113 {
   5114 #pragma pack(4)
   5115    typedef struct {
   5116       mach_msg_header_t Head;
   5117       NDR_record_t NDR;
   5118       kern_return_t RetCode;
   5119       mach_msg_trailer_t trailer;
   5120    } Reply;
   5121 #pragma pack()
   5122 
   5123    Reply *reply = (Reply *)ARG1;
   5124    if (!reply->RetCode) {
   5125    } else {
   5126       PRINT("mig return %d", reply->RetCode);
   5127    }
   5128 }
   5129 
   5130 
   5131 PRE(mach_ports_lookup)
   5132 {
   5133 #pragma pack(4)
   5134    typedef struct {
   5135        mach_msg_header_t Head;
   5136    } Request;
   5137 #pragma pack()
   5138 
   5139    // Request *req = (Request *)ARG1;
   5140 
   5141    PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
   5142 
   5143    AFTER = POST_FN(mach_ports_lookup);
   5144 }
   5145 
   5146 POST(mach_ports_lookup)
   5147 {
   5148 #pragma pack(4)
   5149    typedef struct {
   5150       mach_msg_header_t Head;
   5151       /* start of the kernel processed data */
   5152       mach_msg_body_t msgh_body;
   5153       mach_msg_ool_ports_descriptor_t init_port_set;
   5154       /* end of the kernel processed data */
   5155       NDR_record_t NDR;
   5156       mach_msg_type_number_t init_port_setCnt;
   5157    } Reply;
   5158 #pragma pack()
   5159 
   5160     // Reply *reply = (Reply *)ARG1;
   5161 }
   5162 
   5163 
   5164 PRE(task_threads)
   5165 {
   5166 #pragma pack(4)
   5167    typedef struct {
   5168       mach_msg_header_t Head;
   5169    } Request;
   5170 #pragma pack()
   5171 
   5172    // Request *req = (Request *)ARG1;
   5173 
   5174    PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
   5175 
   5176    AFTER = POST_FN(task_threads);
   5177 }
   5178 
   5179 POST(task_threads)
   5180 {
   5181 #pragma pack(4)
   5182    typedef struct {
   5183       mach_msg_header_t Head;
   5184       /* start of the kernel processed data */
   5185       mach_msg_body_t msgh_body;
   5186       mach_msg_ool_ports_descriptor_t act_list;
   5187       /* end of the kernel processed data */
   5188       NDR_record_t NDR;
   5189       mach_msg_type_number_t act_listCnt;
   5190       mach_msg_trailer_t trailer;
   5191    } Reply;
   5192 #pragma pack()
   5193 
   5194    Reply *reply = (Reply *)ARG1;
   5195 
   5196    if (MACH_REMOTE == vg_task_port) {
   5197       assign_port_names(&reply->act_list, "thread-%p");
   5198    } else {
   5199       assign_port_names(&reply->act_list, "remote-thread-%p");
   5200    }
   5201 }
   5202 
   5203 
   5204 PRE(task_suspend)
   5205 {
   5206    PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
   5207 
   5208    if (MACH_REMOTE == vg_task_port) {
   5209       // GrP fixme self-suspend
   5210       vg_assert(0);
   5211    } else {
   5212       // suspend other - no problem
   5213    }
   5214 
   5215    AFTER = POST_FN(task_suspend);
   5216 }
   5217 
   5218 POST(task_suspend)
   5219 {
   5220 }
   5221 
   5222 
   5223 PRE(task_resume)
   5224 {
   5225    PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
   5226 
   5227    if (MACH_REMOTE == vg_task_port) {
   5228       // GrP fixme self-resume
   5229       vg_assert(0);
   5230    } else {
   5231       // resume other - no problem
   5232    }
   5233 
   5234    AFTER = POST_FN(task_resume);
   5235 }
   5236 
   5237 POST(task_resume)
   5238 {
   5239 }
   5240 
   5241 
   5242 PRE(vm_allocate)
   5243 {
   5244 #pragma pack(4)
   5245    typedef struct {
   5246       mach_msg_header_t Head;
   5247       NDR_record_t NDR;
   5248       vm_address_t address;
   5249       vm_size_t size;
   5250       int flags;
   5251    } Request;
   5252 #pragma pack()
   5253 
   5254    Request *req = (Request *)ARG1;
   5255 
   5256    PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
   5257          name_for_port(MACH_REMOTE),
   5258          (ULong)req->address, (ULong)req->size, req->flags);
   5259 
   5260    MACH_ARG(vm_allocate.size) = req->size;
   5261    MACH_ARG(vm_allocate.flags) = req->flags;
   5262 
   5263    AFTER = POST_FN(vm_allocate);
   5264 }
   5265 
   5266 POST(vm_allocate)
   5267 {
   5268 #pragma pack(4)
   5269    typedef struct {
   5270       mach_msg_header_t Head;
   5271       NDR_record_t NDR;
   5272       kern_return_t RetCode;
   5273       vm_address_t address;
   5274       mach_msg_trailer_t trailer;
   5275    } Reply;
   5276 #pragma pack()
   5277 
   5278    Reply *reply = (Reply *)ARG1;
   5279 
   5280    if (!reply->RetCode) {
   5281       if (MACH_REMOTE == vg_task_port) {
   5282         PRINT("allocated at %#llx", (ULong)reply->address);
   5283          // requesting 0 bytes returns address 0 with no error
   5284          if (MACH_ARG(vm_allocate.size)) {
   5285             ML_(notify_core_and_tool_of_mmap)(
   5286                   reply->address, MACH_ARG(vm_allocate.size),
   5287                   VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
   5288          }
   5289       } else {
   5290          PRINT("allocated at %#llx in remote task %s",
   5291                (ULong)reply->address,
   5292                name_for_port(MACH_REMOTE));
   5293       }
   5294    } else {
   5295       PRINT("mig return %d", reply->RetCode);
   5296    }
   5297 }
   5298 
   5299 
   5300 PRE(vm_deallocate)
   5301 {
   5302 #pragma pack(4)
   5303    typedef struct {
   5304       mach_msg_header_t Head;
   5305       NDR_record_t NDR;
   5306       vm_address_t address;
   5307       vm_size_t size;
   5308    } Request;
   5309 #pragma pack()
   5310 
   5311    Request *req = (Request *)ARG1;
   5312 
   5313    PRINT("vm_deallocate(%s, at %#llx, size %lld)",
   5314          name_for_port(MACH_REMOTE),
   5315          (ULong)req->address, (ULong)req->size);
   5316 
   5317    MACH_ARG(vm_deallocate.address) = req->address;
   5318    MACH_ARG(vm_deallocate.size) = req->size;
   5319 
   5320    AFTER = POST_FN(vm_deallocate);
   5321 
   5322    // Must block to prevent race (other thread allocates and
   5323    // notifies after we deallocate but before we notify)
   5324    *flags &= ~SfMayBlock;
   5325 }
   5326 
   5327 POST(vm_deallocate)
   5328 {
   5329 #pragma pack(4)
   5330    typedef struct {
   5331       mach_msg_header_t Head;
   5332       NDR_record_t NDR;
   5333       kern_return_t RetCode;
   5334       mach_msg_trailer_t trailer;
   5335    } Reply;
   5336 #pragma pack()
   5337 
   5338    Reply *reply = (Reply *)ARG1;
   5339 
   5340    if (!reply->RetCode) {
   5341       if (MACH_REMOTE == vg_task_port) {
   5342          if (MACH_ARG(vm_deallocate.size)) {
   5343             Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
   5344             Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
   5345                                     MACH_ARG(vm_deallocate.size));
   5346             // Must have cleared SfMayBlock in PRE to prevent race
   5347             ML_(notify_core_and_tool_of_munmap)(start, end - start);
   5348          }
   5349       }
   5350    } else {
   5351       PRINT("mig return %d", reply->RetCode);
   5352    }
   5353 }
   5354 
   5355 
   5356 PRE(vm_protect)
   5357 {
   5358 #pragma pack(4)
   5359    typedef struct {
   5360       mach_msg_header_t Head;
   5361       NDR_record_t NDR;
   5362       vm_address_t address;
   5363       vm_size_t size;
   5364       boolean_t set_maximum;
   5365       vm_prot_t new_protection;
   5366    } Request;
   5367 #pragma pack()
   5368 
   5369    Request *req = (Request *)ARG1;
   5370 
   5371    PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
   5372          name_for_port(MACH_REMOTE),
   5373          (ULong)req->address, (ULong)req->size,
   5374          req->set_maximum, req->new_protection);
   5375 
   5376    MACH_ARG(vm_protect.address) = req->address;
   5377    MACH_ARG(vm_protect.size) = req->size;
   5378    MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
   5379    MACH_ARG(vm_protect.new_protection) = req->new_protection;
   5380 
   5381    AFTER = POST_FN(vm_protect);
   5382 }
   5383 
   5384 POST(vm_protect)
   5385 {
   5386 #pragma pack(4)
   5387    typedef struct {
   5388       mach_msg_header_t Head;
   5389       NDR_record_t NDR;
   5390       kern_return_t RetCode;
   5391       mach_msg_trailer_t trailer;
   5392    } Reply;
   5393 #pragma pack()
   5394 
   5395    Reply *reply = (Reply *)ARG1;
   5396 
   5397    if (!reply->RetCode) {
   5398       if (MACH_REMOTE == vg_task_port) {
   5399          Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
   5400          Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
   5401                                  MACH_ARG(vm_protect.size));
   5402          UInt prot = MACH_ARG(vm_protect.new_protection);
   5403          if (MACH_ARG(vm_protect.set_maximum)) {
   5404              // GrP fixme mprotect max
   5405              VG_(printf)("UNKNOWN vm_protect set maximum");
   5406             //VG_(mprotect_max_range)(start, end-start, prot);
   5407          } else {
   5408             ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
   5409             VG_(di_notify_vm_protect)(start, end-start, prot);
   5410          }
   5411       }
   5412    } else {
   5413       PRINT("mig return %d", reply->RetCode);
   5414    }
   5415 }
   5416 
   5417 
   5418 PRE(vm_inherit)
   5419 {
   5420 #pragma pack(4)
   5421    typedef struct {
   5422       mach_msg_header_t Head;
   5423       NDR_record_t NDR;
   5424       vm_address_t address;
   5425       vm_size_t size;
   5426       vm_inherit_t new_inheritance;
   5427    } Request;
   5428 #pragma pack()
   5429 
   5430    Request *req = (Request *)ARG1;
   5431 
   5432    PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
   5433          name_for_port(MACH_REMOTE),
   5434          (ULong)req->address, (ULong)req->size,
   5435          req->new_inheritance);
   5436 
   5437    AFTER = POST_FN(vm_inherit);
   5438 }
   5439 
   5440 POST(vm_inherit)
   5441 {
   5442 #pragma pack(4)
   5443    typedef struct {
   5444       mach_msg_header_t Head;
   5445       NDR_record_t NDR;
   5446       kern_return_t RetCode;
   5447       mach_msg_trailer_t trailer;
   5448    } Reply;
   5449 #pragma pack()
   5450 
   5451    Reply *reply = (Reply *)ARG1;
   5452 
   5453    if (!reply->RetCode) {
   5454       if (MACH_REMOTE == vg_task_port) {
   5455          // GrP fixme do something?
   5456       }
   5457    } else {
   5458       PRINT("mig return %d", reply->RetCode);
   5459    }
   5460 }
   5461 
   5462 
   5463 PRE(vm_read)
   5464 {
   5465 #pragma pack(4)
   5466    typedef struct {
   5467       mach_msg_header_t Head;
   5468       NDR_record_t NDR;
   5469       vm_address_t address;
   5470       vm_size_t size;
   5471    } Request;
   5472 #pragma pack()
   5473 
   5474    Request *req = (Request *)ARG1;
   5475 
   5476    PRINT("vm_read(from %s at %#llx size %llu)",
   5477          name_for_port(MACH_REMOTE),
   5478          (ULong)req->address, (ULong)req->size);
   5479 
   5480    MACH_ARG(vm_read.addr) = req->address;
   5481    MACH_ARG(vm_read.size) = req->size;
   5482 
   5483    AFTER = POST_FN(vm_read);
   5484 }
   5485 
   5486 POST(vm_read)
   5487 {
   5488 #pragma pack(4)
   5489    typedef struct {
   5490       mach_msg_header_t Head;
   5491       /* start of the kernel processed data */
   5492       mach_msg_body_t msgh_body;
   5493       mach_msg_ool_descriptor_t data;
   5494       /* end of the kernel processed data */
   5495       NDR_record_t NDR;
   5496       mach_msg_type_number_t dataCnt;
   5497    } Reply;
   5498 #pragma pack()
   5499 
   5500    // Reply *reply = (Reply *)ARG1;
   5501 
   5502    if (MACH_REMOTE == vg_task_port) {
   5503       // vm_read from self
   5504       // GrP fixme copy initialized state
   5505    }
   5506 }
   5507 
   5508 
   5509 
   5510 PRE(mach_vm_read)
   5511 {
   5512 #pragma pack(4)
   5513    typedef struct {
   5514       mach_msg_header_t Head;
   5515       NDR_record_t NDR;
   5516       mach_vm_address_t address;
   5517       mach_vm_size_t size;
   5518    } Request;
   5519 #pragma pack()
   5520 
   5521    Request *req = (Request *)ARG1;
   5522 
   5523    PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
   5524          name_for_port(MACH_REMOTE), req->address, req->size);
   5525 
   5526    MACH_ARG(mach_vm_read.addr) = req->address;
   5527    MACH_ARG(mach_vm_read.size) = req->size;
   5528 
   5529    AFTER = POST_FN(mach_vm_read);
   5530 }
   5531 
   5532 POST(mach_vm_read)
   5533 {
   5534 #pragma pack(4)
   5535    typedef struct {
   5536       mach_msg_header_t Head;
   5537       /* start of the kernel processed data */
   5538       mach_msg_body_t msgh_body;
   5539       mach_msg_ool_descriptor_t data;
   5540       /* end of the kernel processed data */
   5541       NDR_record_t NDR;
   5542       mach_msg_type_number_t dataCnt;
   5543    } Reply;
   5544 #pragma pack()
   5545 
   5546    // Reply *reply = (Reply *)ARG1;
   5547 
   5548    if (MACH_REMOTE == vg_task_port) {
   5549       // vm_read from self
   5550       // GrP fixme copy initialized state
   5551    }
   5552 }
   5553 
   5554 
   5555 PRE(vm_read_overwrite)
   5556 {
   5557 #pragma pack(4)
   5558    typedef struct {
   5559       mach_msg_header_t Head;
   5560       NDR_record_t NDR;
   5561       vm_address_t address;
   5562       vm_size_t size;
   5563       vm_address_t data;
   5564    } Request;
   5565 #pragma pack()
   5566 </