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