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