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