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