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