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