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