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