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