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