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