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