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