Support new faccessat2 linux syscall (439)
[valgrind.git] / coregrind / m_syswrap / syswrap-darwin.c
blob5861b3985e4048dccaf664499c7d459ce16f2c0f
2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2005-2017 Apple Inc.
11 Greg Parker gparker@apple.com
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.
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.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGO_darwin)
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_vkiscnums.h"
34 #include "pub_core_threadstate.h"
35 #include "pub_core_aspacemgr.h"
36 #include "pub_core_xarray.h"
37 #include "pub_core_clientstate.h"
38 #include "pub_core_debuglog.h"
39 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
40 #include "pub_core_transtab.h" // VG_(discard_translations)
41 #include "pub_core_libcbase.h"
42 #include "pub_core_libcassert.h"
43 #include "pub_core_libcfile.h"
44 #include "pub_core_libcprint.h"
45 #include "pub_core_libcproc.h"
46 #include "pub_core_libcsignal.h"
47 #include "pub_core_machine.h" // VG_(get_SP)
48 #include "pub_core_mallocfree.h"
49 #include "pub_core_options.h"
50 #include "pub_core_oset.h"
51 #include "pub_core_scheduler.h"
52 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
53 #include "pub_core_signals.h"
54 #include "pub_core_stacks.h"
55 #include "pub_core_syscall.h"
56 #include "pub_core_syswrap.h"
57 #include "pub_core_tooliface.h"
58 #include "pub_core_wordfm.h"
60 #include "priv_types_n_macros.h"
61 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
62 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
63 #include "priv_syswrap-main.h"
65 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
66 #include <mach/mach.h>
67 #include <mach/mach_vm.h>
68 #include <semaphore.h>
69 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
71 #define msgh_request_port msgh_remote_port
72 #define msgh_reply_port msgh_local_port
73 #define BOOTSTRAP_MAX_NAME_LEN 128
74 typedef HChar name_t[BOOTSTRAP_MAX_NAME_LEN];
76 typedef uint64_t mig_addr_t;
79 // Saved ports
80 static mach_port_t vg_host_port = 0;
81 static mach_port_t vg_task_port = 0;
82 static mach_port_t vg_bootstrap_port = 0;
84 // Run a thread from beginning to end and return the thread's
85 // scheduler-return-code.
86 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
88 VgSchedReturnCode ret;
89 ThreadId tid = (ThreadId)tidW;
90 ThreadState* tst = VG_(get_ThreadState)(tid);
92 VG_(debugLog)(1, "syswrap-darwin",
93 "thread_wrapper(tid=%u): entry\n",
94 tid);
96 vg_assert(tst->status == VgTs_Init);
98 /* make sure we get the CPU lock before doing anything significant */
99 VG_(acquire_BigLock)(tid, "thread_wrapper");
101 if (0)
102 VG_(printf)("thread tid %u started: stack = %p\n",
103 tid, (void *)&tid);
105 /* Make sure error reporting is enabled in the new thread. */
106 tst->err_disablement_level = 0;
108 VG_TRACK(pre_thread_first_insn, tid);
110 tst->os_state.lwpid = VG_(gettid)();
111 tst->os_state.threadgroup = VG_(getpid)();
113 /* Thread created with all signals blocked; scheduler will set the
114 appropriate mask */
116 ret = VG_(scheduler)(tid);
118 vg_assert(VG_(is_exiting)(tid));
120 vg_assert(tst->status == VgTs_Runnable);
121 vg_assert(VG_(is_running_thread)(tid));
123 VG_(debugLog)(1, "syswrap-darwin",
124 "thread_wrapper(tid=%u): done\n",
125 tid);
127 /* Return to caller, still holding the lock. */
128 return ret;
133 /* Allocate a stack for this thread, if it doesn't already have one.
134 Returns the initial stack pointer value to use, or 0 if allocation
135 failed. */
137 Addr allocstack ( ThreadId tid )
139 ThreadState* tst = VG_(get_ThreadState)(tid);
140 VgStack* stack;
141 Addr initial_SP;
143 /* Either the stack_base and stack_init_SP are both zero (in which
144 case a stack hasn't been allocated) or they are both non-zero,
145 in which case it has. */
147 if (tst->os_state.valgrind_stack_base == 0)
148 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
150 if (tst->os_state.valgrind_stack_base != 0)
151 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
153 /* If no stack is present, allocate one. */
155 if (tst->os_state.valgrind_stack_base == 0) {
156 stack = VG_(am_alloc_VgStack)( &initial_SP );
157 if (stack) {
158 tst->os_state.valgrind_stack_base = (Addr)stack;
159 tst->os_state.valgrind_stack_init_SP = initial_SP;
163 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %u at %p; init_SP=%p\n",
164 tid,
165 (void*)tst->os_state.valgrind_stack_base,
166 (void*)tst->os_state.valgrind_stack_init_SP );
168 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
170 return tst->os_state.valgrind_stack_init_SP;
174 void find_stack_segment(ThreadId tid, Addr sp)
176 ML_(guess_and_register_stack) (sp, VG_(get_ThreadState)(tid));
180 /* Run a thread all the way to the end, then do appropriate exit actions
181 (this is the last-one-out-turn-off-the-lights bit).
183 static void run_a_thread_NORETURN ( Word tidW )
185 Int c;
186 VgSchedReturnCode src;
187 ThreadId tid = (ThreadId)tidW;
188 ThreadState* tst;
190 VG_(debugLog)(1, "syswrap-darwin",
191 "run_a_thread_NORETURN(tid=%u): pre-thread_wrapper\n",
192 tid);
194 tst = VG_(get_ThreadState)(tid);
195 vg_assert(tst);
197 /* Run the thread all the way through. */
198 src = thread_wrapper(tid);
200 VG_(debugLog)(1, "syswrap-darwin",
201 "run_a_thread_NORETURN(tid=%u): post-thread_wrapper\n",
202 tid);
204 c = VG_(count_living_threads)();
205 vg_assert(c >= 1); /* stay sane */
207 /* Deregister thread's stack. */
208 if (tst->os_state.stk_id != NULL_STK_ID)
209 VG_(deregister_stack)(tst->os_state.stk_id);
211 // Tell the tool this thread is exiting
212 VG_TRACK( pre_thread_ll_exit, tid );
214 /* If the thread is exiting with errors disabled, complain loudly;
215 doing so is bad (does the user know this has happened?) Also,
216 in all cases, be paranoid and clear the flag anyway so that the
217 thread slot is safe in this respect if later reallocated. This
218 should be unnecessary since the flag should be cleared when the
219 slot is reallocated, in thread_wrapper(). */
220 if (tst->err_disablement_level > 0) {
221 VG_(umsg)(
222 "WARNING: exiting thread has error reporting disabled.\n"
223 "WARNING: possibly as a result of some mistake in the use\n"
224 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
226 VG_(debugLog)(
227 1, "syswrap-darwin",
228 "run_a_thread_NORETURN(tid=%u): "
229 "WARNING: exiting thread has err_disablement_level = %u\n",
230 tid, tst->err_disablement_level
233 tst->err_disablement_level = 0;
235 if (c == 1) {
237 VG_(debugLog)(1, "syswrap-darwin",
238 "run_a_thread_NORETURN(tid=%u): "
239 "last one standing\n",
240 tid);
242 /* We are the last one standing. Keep hold of the lock and
243 carry on to show final tool results, then exit the entire system.
244 Use the continuation pointer set at startup in m_main. */
245 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
247 } else {
249 mach_msg_header_t msg;
251 VG_(debugLog)(1, "syswrap-darwin",
252 "run_a_thread_NORETURN(tid=%u): "
253 "not last one standing\n",
254 tid);
256 /* OK, thread is dead, but others still exist. Just exit. */
258 /* This releases the run lock */
259 VG_(exit_thread)(tid);
260 vg_assert(tst->status == VgTs_Zombie);
262 /* tid is now invalid. */
264 // GrP fixme exit race
265 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
266 msg.msgh_request_port = VG_(gettid)();
267 msg.msgh_reply_port = 0;
268 msg.msgh_id = 3600; // thread_terminate
270 tst->status = VgTs_Empty;
271 // GrP fixme race here! new thread may claim this V thread stack
272 // before we get out here!
273 // GrP fixme use bsdthread_terminate for safe cleanup?
274 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
275 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
277 // DDD: This is reached sometimes on none/tests/manythreads, maybe
278 // because of the race above.
279 VG_(core_panic)("Thread exit failed?\n");
282 /*NOTREACHED*/
283 vg_assert(0);
287 /* Allocate a stack for the main thread, and run it all the way to the
288 end. Although we already have a working VgStack
289 (VG_(interim_stack)) it's better to allocate a new one, so that
290 overflow detection works uniformly for all threads.
292 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
294 Addr sp;
295 VG_(debugLog)(1, "syswrap-darwin",
296 "entering VG_(main_thread_wrapper_NORETURN)\n");
298 sp = allocstack(tid);
300 /* If we can't even allocate the first thread's stack, we're hosed.
301 Give up. */
302 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
304 /* shouldn't be any other threads around yet */
305 vg_assert( VG_(count_living_threads)() == 1 );
307 call_on_new_stack_0_1(
308 (Addr)sp, /* stack */
309 0, /*bogus return address*/
310 run_a_thread_NORETURN, /* fn to call */
311 (Word)tid /* arg to give it */
314 /*NOTREACHED*/
315 vg_assert(0);
319 void start_thread_NORETURN ( Word arg )
321 ThreadState* tst = (ThreadState*)arg;
322 ThreadId tid = tst->tid;
324 run_a_thread_NORETURN ( (Word)tid );
325 /*NOTREACHED*/
326 vg_assert(0);
330 void VG_(cleanup_thread) ( ThreadArchState* arch )
335 /* ---------------------------------------------------------------------
336 Message reporting, with duplicate removal
337 ------------------------------------------------------------------ */
339 static WordFM* decaying_string_table = NULL; /* HChar* -> UWord */
341 static Word decaying_string_table_cmp ( UWord s1, UWord s2 ) {
342 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
345 static void log_decaying ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
346 static void log_decaying ( const HChar* format, ... )
348 // get the message into a stack-allocated string.
349 HChar buf[256];
350 VG_(memset)(buf, 0, sizeof(buf));
351 va_list vargs;
352 va_start(vargs,format);
353 (void) VG_(vsnprintf)(buf, sizeof(buf), format, vargs);
354 va_end(vargs);
355 buf[sizeof(buf)-1] = 0;
357 // Now see if it already exists in the table of strings that we have.
358 if (!decaying_string_table) {
359 decaying_string_table
360 = VG_(newFM)( VG_(malloc), "syswrap-darwin.pd.1",
361 VG_(free), decaying_string_table_cmp );
364 const HChar* key = NULL;
365 UWord val = 0;
366 if (!VG_(lookupFM)(decaying_string_table,
367 (UWord*)&key, &val, (UWord)&buf[0])) {
368 // We haven't seen this string before, so strdup it and add
369 // it to the table.
370 vg_assert(key == NULL && val == 0);
371 key = VG_(strdup)("syswrap-darwin.pd.2", buf);
372 VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)0);
375 vg_assert(key != NULL && key != &buf[0]);
377 // So, finally, |key| is in the tree, and |val| is what it is
378 // currently associated with. Increment that counter.
379 val++;
380 Bool b = VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)val);
381 vg_assert(b);
383 if (-1 != VG_(log2)( (UInt)val )) {
384 if (val == 1)
385 VG_(dmsg)("%s\n", key);
386 else
387 VG_(dmsg)("%s (repeated %lu times)\n", key, val);
392 /* ---------------------------------------------------------------------
393 Mach port tracking (based on syswrap-generic's fd tracker)
394 ------------------------------------------------------------------ */
396 /* One of these is allocated for each open port. */
397 typedef struct OpenPort
399 mach_port_t port;
400 mach_port_type_t type; /* right type(s) */
401 Int send_count; /* number of send rights */
402 HChar *name; /* bootstrap name or NULL */
403 ExeContext *where; /* first allocation only */
404 struct OpenPort *next, *prev;
405 } OpenPort;
407 // strlen("0x12345678")
408 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
410 /* List of allocated ports. */
411 static OpenPort *allocated_ports;
413 /* Count of open ports. */
414 static Int allocated_port_count = 0;
416 /* Create an entry for |port|, with no other info. Assumes it doesn't
417 already exist. */
418 static void port_create_vanilla(mach_port_t port)
420 OpenPort* op
421 = VG_(calloc)("syswrap-darwin.port_create_vanilla", sizeof(OpenPort), 1);
422 op->port = port;
423 /* Add it to the list. */
424 op->next = allocated_ports;
425 if (allocated_ports) allocated_ports->prev = op;
426 allocated_ports = op;
427 allocated_port_count++;
430 __attribute__((unused))
431 static Bool port_exists(mach_port_t port)
433 OpenPort *i;
435 /* Check to see if this port is already open. */
436 i = allocated_ports;
437 while (i) {
438 if (i->port == port) {
439 return True;
441 i = i->next;
444 return False;
447 static OpenPort *info_for_port(mach_port_t port)
449 OpenPort *i;
450 if (!port) return NULL;
452 i = allocated_ports;
453 while (i) {
454 if (i->port == port) {
455 return i;
457 i = i->next;
460 return NULL;
464 // Give a port a name, without changing its refcount
465 // GrP fixme don't override name if it already has a specific one
466 __private_extern__ void assign_port_name(mach_port_t port, const HChar *name)
468 OpenPort *i;
469 if (!port) return;
470 vg_assert(name);
472 i = info_for_port(port);
473 vg_assert(i);
475 if (i->name) VG_(free)(i->name);
476 i->name =
477 VG_(malloc)("syswrap-darwin.mach-port-name",
478 VG_(strlen)(name) + PORT_STRLEN + 1);
479 VG_(sprintf)(i->name, name, port);
483 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
484 static const HChar *name_for_port(mach_port_t port)
486 static HChar buf[8 + PORT_STRLEN + 1];
487 OpenPort *i;
489 // hack
490 if (port == VG_(gettid)()) return "mach_thread_self()";
491 if (port == 0) return "NULL";
493 i = allocated_ports;
494 while (i) {
495 if (i->port == port) {
496 return i->name;
498 i = i->next;
501 VG_(sprintf)(buf, "NONPORT-%#x", port);
502 return buf;
505 /* Note the fact that a port was just deallocated. */
507 static
508 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
510 OpenPort *i = allocated_ports;
511 if (!port) return;
513 while(i) {
514 if(i->port == port) {
515 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
516 if (right & MACH_PORT_TYPE_SEND) {
517 // send rights are refcounted
518 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
519 i->send_count += delta;
520 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
521 else i->type &= ~MACH_PORT_TYPE_SEND;
523 right = right & ~MACH_PORT_TYPE_SEND;
524 if (right) {
525 // other rights are not refcounted
526 if (delta > 0) {
527 i->type |= right;
528 } else if (delta < 0) {
529 i->type &= ~right;
533 if (i->type != 0) return;
535 // Port has no rights left. Kill it.
536 // VG_(printf)("deleting port %p %s", i->port, i->name);
537 if(i->prev)
538 i->prev->next = i->next;
539 else
540 allocated_ports = i->next;
541 if(i->next)
542 i->next->prev = i->prev;
543 if(i->name)
544 VG_(free) (i->name);
545 VG_(free) (i);
546 allocated_port_count--;
547 return;
549 i = i->next;
552 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
555 static
556 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
558 switch (type) {
559 case MACH_MSG_TYPE_PORT_NAME:
560 // this task has no rights for the name
561 break;
562 case MACH_MSG_TYPE_PORT_RECEIVE:
563 // this task gets receive rights
564 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
565 break;
566 case MACH_MSG_TYPE_PORT_SEND:
567 // this task gets a send right
568 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
569 break;
570 case MACH_MSG_TYPE_PORT_SEND_ONCE:
571 // this task gets send-once rights
572 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
573 break;
574 default:
575 vg_assert(0);
576 break;
580 static
581 void record_port_dealloc(mach_port_t port)
583 // deletes 1 send or send-once right (port can't have both)
584 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
587 static
588 void record_port_destroy(mach_port_t port)
590 // deletes all rights to port
591 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
595 /* Note the fact that a Mach port was just allocated or transferred.
596 If the port is already known, increment its reference count. */
597 void record_named_port(ThreadId tid, mach_port_t port,
598 mach_port_right_t right, const HChar *name)
600 OpenPort *i;
601 if (!port) return;
603 /* Check to see if this port is already open. */
604 i = allocated_ports;
605 while (i) {
606 if (i->port == port) {
607 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
608 return;
610 i = i->next;
613 /* Not already one: allocate an OpenPort */
614 if (i == NULL) {
615 i = VG_(malloc)("syswrap-darwin.mach-port", sizeof(OpenPort));
617 i->prev = NULL;
618 i->next = allocated_ports;
619 if(allocated_ports) allocated_ports->prev = i;
620 allocated_ports = i;
621 allocated_port_count++;
623 i->port = port;
624 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
625 i->name = NULL;
626 if (right != -1) {
627 i->type = MACH_PORT_TYPE(right);
628 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
629 } else {
630 i->type = 0;
631 i->send_count = 0;
634 assign_port_name(port, name);
639 // Record opening of a nameless port.
640 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
642 record_named_port(tid, port, right, "unnamed-%p");
646 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
647 void VG_(show_open_ports)(void)
649 OpenPort *i;
651 VG_(message)(Vg_UserMsg,
652 "MACH PORTS: %d open at exit.\n", allocated_port_count);
654 for (i = allocated_ports; i; i = i->next) {
655 if (i->name) {
656 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s\n", i->port,
657 i->name);
658 } else {
659 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x\n", i->port);
662 if (i->where) {
663 VG_(pp_ExeContext)(i->where);
664 VG_(message)(Vg_UserMsg, "\n");
668 VG_(message)(Vg_UserMsg, "\n");
672 /* ---------------------------------------------------------------------
673 sync_mappings
674 ------------------------------------------------------------------ */
676 typedef
677 enum { CheckAlways=1, CheckEvery20, CheckNever }
678 CheckHowOften;
680 static const HChar* show_CheckHowOften ( CheckHowOften cho ) {
681 switch (cho) {
682 case CheckAlways: return "Always ";
683 case CheckEvery20: return "Every20";
684 case CheckNever: return "Never ";
685 default: vg_assert(0);
689 /* Statistics for one particular resync-call set of arguments,
690 as specified by key1, key2 and key3. */
691 typedef
692 struct {
693 CheckHowOften cho;
694 const HChar* key1;
695 const HChar* key2;
696 UWord key3;
697 ULong n_checks;
698 ULong n_mappings_added;
699 ULong n_mappings_removed;
701 SyncStats;
703 static Bool cmp_eqkeys_SyncStats ( SyncStats* ss1, SyncStats* ss2 ) {
704 return ss1->key3 == ss2->key3
705 && 0 == VG_(strcmp)(ss1->key1, ss2->key1)
706 && 0 == VG_(strcmp)(ss1->key2, ss2->key2);
709 /* The filter data. */
710 #define N_SYNCSTATS 1000
711 static Int syncstats_used = 0;
712 static SyncStats syncstats[N_SYNCSTATS];
714 /* Statistics overall, for the filter. */
715 static ULong n_syncsRequested = 0; // Total number requested
716 static ULong n_syncsPerformed = 0; // Number carried out (the rest skipped)
719 static
720 void update_syncstats ( CheckHowOften cho,
721 const HChar* key1, const HChar* key2,
722 UWord key3,
723 UInt n_mappings_added, UInt n_mappings_removed )
725 SyncStats dummy = { CheckAlways, key1, key2, key3, 0, 0, 0 };
726 Int i;
727 for (i = 0; i < syncstats_used; i++) {
728 if (cmp_eqkeys_SyncStats(&syncstats[i], &dummy))
729 break;
731 vg_assert(i >= 0 && i <= syncstats_used);
732 if (i == syncstats_used) {
733 // alloc new
734 vg_assert(syncstats_used < N_SYNCSTATS);
735 syncstats_used++;
736 syncstats[i] = dummy;
737 syncstats[i].cho = cho;
739 vg_assert(cmp_eqkeys_SyncStats(&syncstats[i], &dummy));
740 syncstats[i].n_checks++;
741 syncstats[i].n_mappings_added += (ULong)n_mappings_added;
742 syncstats[i].n_mappings_removed += (ULong)n_mappings_removed;
743 // reorder
744 static UInt reorder_ctr = 0;
745 if (i > 0 && 0 == (1 & reorder_ctr++)) {
746 SyncStats tmp = syncstats[i-1];
747 syncstats[i-1] = syncstats[i];
748 syncstats[i] = tmp;
753 static void maybe_show_syncstats ( void )
755 Int i;
757 // display
758 if (0 == (n_syncsRequested & 0xFF)) {
759 VG_(printf)("Resync filter: %'llu requested, %'llu performed (%llu%%)\n",
760 n_syncsRequested, n_syncsPerformed,
761 (100 * n_syncsPerformed) /
762 (n_syncsRequested == 0 ? 1 : n_syncsRequested));
763 for (i = 0; i < syncstats_used; i++) {
764 if (i >= 40) break; // just show the top 40
765 VG_(printf)(" [%3d] (%s) upd %6llu diff %4llu+,%3llu-"
766 " %s %s 0x%08llx\n",
767 i, show_CheckHowOften(syncstats[i].cho),
768 syncstats[i].n_checks,
769 syncstats[i].n_mappings_added,
770 syncstats[i].n_mappings_removed,
771 syncstats[i].key1, syncstats[i].key2,
772 (ULong)syncstats[i].key3);
774 if (i < syncstats_used) {
775 VG_(printf)(" and %d more entries not shown.\n", syncstats_used - i);
777 VG_(printf)("\n");
782 Bool ML_(sync_mappings)(const HChar* when, const HChar* where, UWord num)
784 // If VG(clo_resync_filter) == 0, the filter is disabled, and
785 // we must always honour the resync request.
787 // If VG(clo_resync_filter) == 1, the filter is enabled,
788 // so we try to avoid doing the sync if possible, but keep
789 // quiet.
791 // If VG(clo_resync_filter) == 2, the filter is enabled,
792 // so we try to avoid doing the sync if possible, and also
793 // periodically show stats, so that the filter can be updated.
794 // (by hand).
796 if (VG_(clo_resync_filter) >= 2)
797 maybe_show_syncstats();
799 n_syncsRequested++;
801 // Usually the number of segments added/removed in a single call is very
802 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
803 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
804 // because we can't do dynamic allocation within VG_(get_changed_segments),
805 // because it's in m_aspacemgr.
806 ChangedSeg* css = NULL;
807 Int css_size;
808 Int css_used;
809 Int i;
810 Bool ok;
812 // -------------- BEGIN resync-filter-kludge --------------
814 // Some kludges to try and avoid the worst case cost hit of doing
815 // zillions of resyncs (huge). The idea is that many of the most
816 // common resyncs never appear to cause a delta, so we just ignore
817 // them (CheckNever). Then, a bunch of them also happen a lot, but
818 // only very occasionally cause a delta. We resync after 20 of those
819 // (CheckEvery20). Finally, the rest form a long tail, so we always
820 // resync after those (CheckAlways).
822 // Assume this is kernel-version and word-size specific, so develop
823 // filters accordingly. This might be overly conservative --
824 // I don't know.
826 # define STREQ(_s1, _s2) (0 == VG_(strcmp)((_s1),(_s2)))
827 Bool when_in = STREQ(when, "in");
828 Bool when_after = STREQ(when, "after");
829 Bool where_mmr = STREQ(where, "mach_msg_receive");
830 Bool where_mmrU = STREQ(where, "mach_msg_receive-UNHANDLED");
831 Bool where_iuct = STREQ(where, "iokit_user_client_trap");
832 Bool where_MwcN = STREQ(where, "ML_(wqthread_continue_NORETURN)");
833 Bool where_woQR = STREQ(where, "workq_ops(QUEUE_REQTHREADS)");
834 Bool where_woQ2 = STREQ(where, "workq_ops(QUEUE_REQTHREADS2)");
835 Bool where_woTR = STREQ(where, "workq_ops(THREAD_RETURN)");
836 Bool where_ke64 = STREQ(where, "kevent64");
837 # undef STREQ
839 vg_assert(
840 1 >= ( (where_mmr ? 1 : 0) + (where_mmrU ? 1 : 0)
841 + (where_iuct ? 1 : 0) + (where_MwcN ? 1 : 0)
842 + (where_woQR ? 1 : 0) + (where_woQ2 ? 1 : 0)
843 + (where_woTR ? 1 : 0) + (where_ke64 ? 1 : 0)
845 // merely to stop gcc complaining of non-use in the case where
846 // there's no filter:
847 vg_assert(when_in == True || when_in == False);
848 vg_assert(when_after == True || when_after == False);
850 CheckHowOften check = CheckAlways;
852 # if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
853 /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
854 if (when_after && where_mmr) {
855 // "after mach_msg_receive <number>"
856 switch (num) {
857 case 0x00000000: // upd 12414 diff 36+,0-
858 check = CheckEvery20;
859 break;
860 default:
861 break;
864 else
865 if (when_after && where_mmrU) {
866 // "after mach_msg_receive-UNHANDLED <number>"
867 switch (num) {
868 case 0x00000000: // upd 16687 diff 73+,0-
869 case 0x00000001: // upd 5106 diff 89+,0-
870 case 0x00000002: // upd 1609 diff 1+,0-
871 case 0x00000003: // upd 1987 diff 6+,0-
872 // case 0x00000b95: // upd 2894 diff 57+,1- <==dangerous
873 case 0x000072d9: // upd 2616 diff 11+,0-
874 case 0x000072cb: // upd 2616 diff 9+,0-
875 case 0x000074d5: // upd 172 diff 0+,0-
876 check = CheckEvery20;
877 break;
878 default:
879 break;
882 else
883 if (when_in && where_MwcN && num == 0x00000000) {
884 // in ML_(wqthread_continue_NORETURN) 0x00000000
885 // upd 4346 diff 0+,0-
886 check = CheckEvery20;
888 else
889 if (when_after && where_woQR && num == 0x00000000) {
890 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
891 // upd 14434 diff 102+,0-
892 check = CheckEvery20;
894 /* if (when_after && where_woQ2 && num == 0x00000000) {
895 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
896 // upd XXXX diff XX+,0-
897 check = CheckEvery20;
898 } */
899 else
900 if (when_after && where_woTR && num == 0x00000000) {
901 // after workq_ops(THREAD_RETURN) 0x00000000
902 // upd 14434 diff 102+,0-
903 check = CheckEvery20;
905 else
906 if (when_after && where_ke64 && num == 0x00000000) {
907 // after kevent64 0x00000000
908 // upd 1736 diff 78+,0-
909 check = CheckEvery20;
911 /* ----------- END filter for 64-bit 10.9.x ----------- */
912 # endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
914 # if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
915 /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
916 if (when_after && where_mmr) {
917 // "after mach_msg_receive <number>"
918 switch (num) {
919 case 0x00000000: // upd 2380 diff 23+,0-
920 check = CheckEvery20;
921 break;
922 default:
923 break;
926 else
927 if (when_after && where_mmrU) {
928 // "after mach_msg_receive-UNHANDLED <number>"
929 switch (num) {
930 case 0x00000000: // upd 2370 diff 93+,1- <==dangerous
931 case 0x0000004f: // upd 212 diff 2+,0-
932 case 0x00000b95: // upd 9826 diff 163+,1- diff scale, dangerous
933 case 0x00000ba5: // upd 304 diff 0+,0-
934 case 0x0000157f: // upd 201 diff 2+,0-
935 case 0x0000157d: // upd 197 diff 1+,0-
936 case 0x0000333d: // upd 112 diff 0+,0-
937 case 0x0000333f: // upd 223 diff 10+,0-
938 case 0x000072cd: // upd 8286 diff 98+,0- diff scale
939 case 0x000072ae: // upd 193 diff 10+,0-
940 case 0x000072ec: // upd 319 diff 7+,0-
941 case 0x77303074: // upd 113 diff 3+,0-
942 case 0x10000000: // upd 314 diff 6+,0-
943 check = CheckEvery20;
944 break;
945 default:
946 break;
949 else
950 if (when_in && where_MwcN && num == 0x00000000) {
951 // in ML_(wqthread_continue_NORETURN) 0x00000000
952 // upd 1110 diff 37+,0-
953 check = CheckEvery20;
955 else
956 if (when_after && where_woQR && num == 0x00000000) {
957 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
958 // upd 1099 diff 37+,0-
959 check = CheckEvery20;
961 /* if (when_after && where_woQ2 && num == 0x00000000) {
962 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
963 // upd XXXX diff XX+,0-
964 check = CheckEvery20;
965 } */
966 else
967 if (when_after && where_woTR && num == 0x00000000) {
968 // after workq_ops(THREAD_RETURN) 0x00000000
969 // 1239 diff 53+,0-
970 check = CheckEvery20;
972 else
973 if (when_after && where_ke64 && num == 0x00000000) {
974 // after kevent64 0x00000000
975 // upd 1463 diff 15+,0-
976 check = CheckEvery20;
978 /* ----------- END filter for 64-bit 10.10.x ----------- */
979 # endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
981 /* Regardless of what the filter says, force a sync every 1 time in
982 1000, to stop things getting too far out of sync. */
984 static UInt ctr1k = 0;
985 ctr1k++;
986 if ((ctr1k % 1000) == 0)
987 check = CheckAlways;
990 /* If the filter is disabled, we must always check. */
991 if (VG_(clo_resync_filter) == 0)
992 check = CheckAlways;
994 switch (check) {
995 case CheckAlways:
996 break;
997 case CheckEvery20: {
998 // only resync once every 20th time
999 static UInt ctr10 = 0;
1000 ctr10++;
1001 if ((ctr10 % 20) != 0) return False;
1002 break;
1004 case CheckNever:
1005 return False;
1006 default:
1007 vg_assert(0);
1010 // --------------- END resync-filter-kludge ---------------
1012 if (0 || VG_(clo_trace_syscalls)) {
1013 VG_(debugLog)(0, "syswrap-darwin",
1014 "sync_mappings (%s) (\"%s\", \"%s\", 0x%lx)\n",
1015 show_CheckHowOften(check), when, where, num);
1018 // 16 is enough for most cases, but small enough that overflow happens
1019 // occasionally and thus the overflow path gets some test coverage.
1020 css_size = 16;
1021 ok = False;
1022 while (!ok) {
1023 VG_(free)(css); // css is NULL on first iteration; that's ok.
1024 css = VG_(calloc)("sys_wrap.sync_mappings",
1025 css_size, sizeof(ChangedSeg));
1026 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
1027 css_size *= 2;
1030 UInt css_added = 0, css_removed = 0;
1032 // Now add/remove them.
1033 for (i = 0; i < css_used; i++) {
1034 ChangedSeg* cs = &css[i];
1035 if (cs->is_added) {
1036 css_added++;
1037 ML_(notify_core_and_tool_of_mmap)(
1038 cs->start, cs->end - cs->start + 1,
1039 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
1040 // should this call VG_(di_notify_mmap) also?
1041 } else {
1042 css_removed++;
1043 ML_(notify_core_and_tool_of_munmap)(
1044 cs->start, cs->end - cs->start + 1);
1046 if (VG_(clo_trace_syscalls)) {
1047 if (cs->is_added) {
1048 VG_(debugLog)(0, "syswrap-darwin",
1049 " added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
1050 cs->start, cs->end + 1, (UInt)cs->prot, where, when);
1051 } else {
1052 VG_(debugLog)(0, "syswrap-darwin",
1053 " removed region 0x%010lx..0x%010lx at %s (%s)\n",
1054 cs->start, cs->end + 1, where, when);
1059 VG_(free)(css);
1061 if (0)
1062 VG_(debugLog)(0, "syswrap-darwin", "SYNC: %d %s %s\n",
1063 css_used, when, where);
1065 // Update the stats, so we can derive the filter above.
1066 n_syncsPerformed++;
1067 update_syncstats(check, when, where, num, css_added, css_removed);
1069 return css_used > 0;
1072 /* ---------------------------------------------------------------------
1073 wrappers
1074 ------------------------------------------------------------------ */
1076 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
1077 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
1079 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
1080 #define POST_FN(name) vgSysWrap_darwin_##name##_after
1082 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
1083 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
1085 #if VG_WORDSIZE == 4
1086 // Combine two 32-bit values into a 64-bit value
1087 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
1088 # if defined(VGA_x86)
1089 # define LOHI64(lo,hi) ( ((ULong)(UInt)(lo)) | (((ULong)(UInt)(hi)) << 32) )
1090 # else
1091 # error unknown architecture
1092 # endif
1093 #endif
1095 // Retrieve the current Mach thread
1096 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1098 // Set the POST handler for a mach_msg derivative
1099 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1101 // Set or get values saved from Mach messages
1102 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
1103 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
1104 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
1106 /* ---------------------------------------------------------------------
1107 darwin ioctl wrapper
1108 ------------------------------------------------------------------ */
1110 PRE(ioctl)
1112 *flags |= SfMayBlock;
1114 /* Handle ioctls that don't take an arg first */
1115 switch (ARG2 /* request */) {
1116 case VKI_TIOCSCTTY:
1117 case VKI_TIOCEXCL:
1118 case VKI_TIOCSBRK:
1119 case VKI_TIOCCBRK:
1120 case VKI_TIOCPTYGRANT:
1121 case VKI_TIOCPTYUNLK:
1122 case VKI_DTRACEHIOC_REMOVE:
1123 case VKI_BIOCFLUSH:
1124 case VKI_BIOCPROMISC:
1125 PRINT("ioctl ( %lu, 0x%lx )", ARG1, ARG2);
1126 PRE_REG_READ2(long, "ioctl",
1127 unsigned int, fd, unsigned int, request);
1128 return;
1129 default:
1130 PRINT("ioctl ( %lu, 0x%lx, %#lx )", ARG1, ARG2, ARG3);
1131 PRE_REG_READ3(long, "ioctl",
1132 unsigned int, fd, unsigned int, request, unsigned long, arg);
1135 switch (ARG2 /* request */) {
1136 case VKI_TIOCGWINSZ:
1137 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
1138 break;
1139 case VKI_TIOCSWINSZ:
1140 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
1141 break;
1142 case VKI_TIOCMBIS:
1143 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
1144 break;
1145 case VKI_TIOCMBIC:
1146 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
1147 break;
1148 case VKI_TIOCMSET:
1149 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
1150 break;
1151 case VKI_TIOCMGET:
1152 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
1153 break;
1154 case VKI_TIOCGPGRP:
1155 /* Get process group ID for foreground processing group. */
1156 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1157 break;
1158 case VKI_TIOCSPGRP:
1159 /* Set a process group ID? */
1160 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1161 break;
1162 case VKI_FIONBIO:
1163 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
1164 break;
1165 case VKI_FIOASYNC:
1166 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
1167 break;
1168 case VKI_FIONREAD: /* identical to SIOCINQ */
1169 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1170 break;
1173 /* These all use struct ifreq AFAIK */
1174 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1175 case VKI_SIOCGIFFLAGS: /* get flags */
1176 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1177 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1178 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
1179 break;
1180 case VKI_SIOCGIFMTU: /* get MTU size */
1181 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1182 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1183 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
1184 break;
1185 case VKI_SIOCGIFADDR: /* get PA address */
1186 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1187 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1188 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
1189 break;
1190 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1191 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1192 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1193 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
1194 break;
1195 case VKI_SIOCGIFMETRIC: /* get metric */
1196 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1197 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1198 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
1199 break;
1200 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1201 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1202 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1203 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
1204 break;
1205 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1206 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1207 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1208 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
1209 break;
1210 case VKI_SIOCGIFCONF: /* get iface list */
1211 /* WAS:
1212 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1213 KERNEL_DO_SYSCALL(tid,RES);
1214 if (!VG_(is_kerror)(RES) && RES == 0)
1215 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1217 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1218 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
1219 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
1220 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1221 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
1222 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
1223 if ( ARG3 ) {
1224 // TODO len must be readable and writable
1225 // buf pointer only needs to be readable
1226 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1227 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1228 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1230 break;
1232 case VKI_SIOCSIFFLAGS: /* set flags */
1233 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1234 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1235 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1236 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1237 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1238 break;
1239 case VKI_SIOCSIFADDR: /* set PA address */
1240 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1241 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1242 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1243 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1244 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1245 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1246 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1247 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1248 break;
1249 case VKI_SIOCSIFMETRIC: /* set metric */
1250 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1251 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1252 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1253 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1254 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1255 break;
1256 case VKI_SIOCSIFMTU: /* set MTU size */
1257 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1258 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1259 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1260 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1261 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1262 break;
1263 /* Routing table calls. */
1264 #ifdef VKI_SIOCADDRT
1265 case VKI_SIOCADDRT: /* add routing table entry */
1266 case VKI_SIOCDELRT: /* delete routing table entry */
1267 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
1268 sizeof(struct vki_rtentry));
1269 break;
1270 #endif
1272 case VKI_SIOCGPGRP:
1273 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
1274 break;
1275 case VKI_SIOCSPGRP:
1276 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
1277 //tst->sys_flags &= ~SfMayBlock;
1278 break;
1280 case VKI_FIODTYPE:
1281 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1282 break;
1284 case VKI_DTRACEHIOC_ADDDOF:
1285 break;
1287 // ttycom.h
1288 case VKI_TIOCGETA:
1289 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
1290 break;
1291 case VKI_TIOCSETA:
1292 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
1293 break;
1294 case VKI_TIOCGETD:
1295 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
1296 break;
1297 case VKI_TIOCSETD:
1298 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
1299 break;
1300 case VKI_TIOCPTYGNAME:
1301 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
1302 break;
1304 // filio.h
1305 case VKI_FIOCLEX:
1306 break;
1307 case VKI_FIONCLEX:
1308 break;
1310 // net/bpf.h
1311 case VKI_BIOCSETF: /* set BPF filter */
1313 * struct bpf_program has a 32-bit count of instructions,
1314 * followed by a pointer to an array of those instructions.
1315 * In 64-bit mode, there's padding between those two elements.
1317 * So that we don't bogusly complain about the padding bytes,
1318 * we just report that we read bf_len and and bf_insns.
1320 * We then make sure that what bf_insns points to is valid.
1322 PRE_MEM_READ( "ioctl(BIOCSETF)",
1323 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_len,
1324 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_len) );
1325 PRE_MEM_READ( "ioctl(BIOCSETF)",
1326 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_insns,
1327 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_insns) );
1328 if ( ARG3 ) {
1329 /* bf_len * sizeof (*bf_insns) */
1330 struct vki_bpf_program *bp = (struct vki_bpf_program *)ARG3;
1331 if ( bp->bf_insns != NULL )
1332 PRE_MEM_READ( "ioctl(BIOCSETF) points to a struct bpf_program whose bf_insns member",
1333 (Addr)(bp->vki_bf_insns),
1334 bp->vki_bf_len * sizeof(*bp->vki_bf_insns) );
1336 break;
1337 case VKI_BIOCSETIF: /* set BPF interface */
1338 PRE_MEM_RASCIIZ( "ioctl(BIOCSETIF)",
1339 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1340 break;
1341 case VKI_BIOCSRTIMEOUT: /* set BPF timeout */
1343 * 64-bit struct timeval starts with a 64-bit "seconds since the
1344 * Epoch" value, followed by a 32-bit microseconds value. The
1345 * resulting structure is padded to a multiple of 8 bytes, so
1346 * there are 4 padding bytes at the end.
1348 * So that we don't bogusly complain about the padding bytes,
1349 * we just report that we read tv_sec and tv_usec.
1351 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1352 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_sec,
1353 sizeof(((struct vki_timeval *)ARG3)->vki_tv_sec) );
1354 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1355 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_usec,
1356 sizeof(((struct vki_timeval *)ARG3)->vki_tv_usec) );
1357 break;
1358 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1359 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1360 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list,
1361 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list) );
1362 if ( ARG3 ) {
1363 /* bfl_len * sizeof (*bfl_list) */
1364 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1365 if ( bdl->bfl_list != NULL )
1366 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1367 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len,
1368 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len) );
1369 PRE_MEM_WRITE( "ioctl(BIOCGDLTLIST) points to a struct bpf_dltlist whose bfl_list member",
1370 (Addr)(bdl->vki_bfl_list),
1371 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1373 break;
1375 default:
1376 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
1377 break;
1382 POST(ioctl)
1384 vg_assert(SUCCESS);
1385 switch (ARG2 /* request */) {
1386 case VKI_TIOCGWINSZ:
1387 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
1388 break;
1389 case VKI_TIOCSWINSZ:
1390 case VKI_TIOCMBIS:
1391 case VKI_TIOCMBIC:
1392 case VKI_TIOCMSET:
1393 break;
1394 case VKI_TIOCMGET:
1395 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
1396 break;
1397 case VKI_TIOCGPGRP:
1398 /* Get process group ID for foreground processing group. */
1399 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1400 break;
1401 case VKI_TIOCSPGRP:
1402 /* Set a process group ID? */
1403 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1404 break;
1405 case VKI_TIOCSCTTY:
1406 break;
1407 case VKI_FIONBIO:
1408 break;
1409 case VKI_FIOASYNC:
1410 break;
1411 case VKI_FIONREAD: /* identical to SIOCINQ */
1412 POST_MEM_WRITE( ARG3, sizeof(int) );
1413 break;
1415 /* These all use struct ifreq AFAIK */
1416 case VKI_SIOCGIFFLAGS: /* get flags */
1417 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1418 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1419 break;
1420 case VKI_SIOCGIFMTU: /* get MTU size */
1421 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1422 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1423 break;
1424 case VKI_SIOCGIFADDR: /* get PA address */
1425 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1426 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1427 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1428 POST_MEM_WRITE(
1429 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1430 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1431 break;
1432 case VKI_SIOCGIFMETRIC: /* get metric */
1433 POST_MEM_WRITE(
1434 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1435 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1436 break;
1437 case VKI_SIOCGIFCONF: /* get iface list */
1438 /* WAS:
1439 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1440 KERNEL_DO_SYSCALL(tid,RES);
1441 if (!VG_(is_kerror)(RES) && RES == 0)
1442 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1444 if (RES == 0 && ARG3 ) {
1445 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1446 if (ifc->vki_ifc_buf != NULL)
1447 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1449 break;
1451 case VKI_SIOCSIFFLAGS: /* set flags */
1452 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1453 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1454 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1455 case VKI_SIOCSIFMETRIC: /* set metric */
1456 case VKI_SIOCSIFADDR: /* set PA address */
1457 case VKI_SIOCSIFMTU: /* set MTU size */
1458 break;
1460 #ifdef VKI_SIOCADDRT
1461 /* Routing table calls. */
1462 case VKI_SIOCADDRT: /* add routing table entry */
1463 case VKI_SIOCDELRT: /* delete routing table entry */
1464 break;
1465 #endif
1467 case VKI_SIOCGPGRP:
1468 POST_MEM_WRITE(ARG3, sizeof(int));
1469 break;
1470 case VKI_SIOCSPGRP:
1471 break;
1473 case VKI_FIODTYPE:
1474 POST_MEM_WRITE( ARG3, sizeof(int) );
1475 break;
1477 case VKI_DTRACEHIOC_REMOVE:
1478 case VKI_DTRACEHIOC_ADDDOF:
1479 break;
1481 // ttycom.h
1482 case VKI_TIOCGETA:
1483 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1484 break;
1485 case VKI_TIOCSETA:
1486 break;
1487 case VKI_TIOCGETD:
1488 POST_MEM_WRITE( ARG3, sizeof(int) );
1489 break;
1490 case VKI_TIOCSETD:
1491 break;
1492 case VKI_TIOCPTYGNAME:
1493 POST_MEM_WRITE( ARG3, 128);
1494 break;
1495 case VKI_TIOCSBRK: /* set break bit */
1496 case VKI_TIOCCBRK: /* clear break bit */
1497 case VKI_TIOCPTYGRANT:
1498 case VKI_TIOCPTYUNLK:
1499 break;
1501 // bpf.h
1502 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1503 if (RES == 0 && ARG3 ) {
1504 /* bfl_len * sizeof (*bfl_list) */
1505 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1506 if ( bdl->vki_bfl_list != NULL )
1507 POST_MEM_WRITE( (Addr)(bdl->vki_bfl_list),
1508 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1510 break;
1512 default:
1513 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
1514 break;
1519 /* ---------------------------------------------------------------------
1520 darwin fcntl wrapper
1521 ------------------------------------------------------------------ */
1522 static const HChar *name_for_fcntl(UWord cmd) {
1523 #define F(n) case VKI_##n: return #n
1524 switch (cmd) {
1525 F(F_CHKCLEAN);
1526 F(F_RDAHEAD);
1527 F(F_NOCACHE);
1528 F(F_FULLFSYNC);
1529 F(F_FREEZE_FS);
1530 F(F_THAW_FS);
1531 F(F_GLOBAL_NOCACHE);
1532 F(F_PREALLOCATE);
1533 F(F_SETSIZE);
1534 F(F_RDADVISE);
1535 # if DARWIN_VERS < DARWIN_10_9
1536 F(F_READBOOTSTRAP);
1537 F(F_WRITEBOOTSTRAP);
1538 # endif
1539 F(F_LOG2PHYS);
1540 F(F_GETPATH);
1541 F(F_PATHPKG_CHECK);
1542 F(F_ADDSIGS);
1543 # if DARWIN_VERS >= DARWIN_10_9
1544 F(F_ADDFILESIGS);
1545 # endif
1546 # if DARWIN_VERS >= DARWIN_10_11
1547 F(F_ADDFILESIGS_FOR_DYLD_SIM);
1548 F(F_BARRIERFSYNC);
1549 F(F_ADDFILESIGS_RETURN);
1550 # endif
1551 default:
1552 return "UNKNOWN";
1554 #undef F
1557 PRE(fcntl)
1559 switch (ARG2) {
1560 // These ones ignore ARG3.
1561 case VKI_F_GETFD:
1562 case VKI_F_GETFL:
1563 case VKI_F_GETOWN:
1564 PRINT("fcntl ( %lu, %lu )", ARG1,ARG2);
1565 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1566 break;
1568 // These ones use ARG3 as "arg".
1569 case VKI_F_DUPFD:
1570 case VKI_F_SETFD:
1571 case VKI_F_SETFL:
1572 case VKI_F_SETOWN:
1573 PRINT("fcntl[ARG3=='arg'] ( %lu, %lu, %lu )", ARG1,ARG2,ARG3);
1574 PRE_REG_READ3(long, "fcntl",
1575 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1576 break;
1578 // These ones use ARG3 as "lock".
1579 case VKI_F_GETLK:
1580 case VKI_F_SETLK:
1581 case VKI_F_SETLKW:
1582 PRINT("fcntl[ARG3=='lock'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1583 PRE_REG_READ3(long, "fcntl",
1584 unsigned int, fd, unsigned int, cmd,
1585 struct flock64 *, lock);
1586 // GrP fixme mem read sizeof(flock64)
1587 if (ARG2 == VKI_F_SETLKW)
1588 *flags |= SfMayBlock;
1589 break;
1590 # if DARWIN_VERS >= DARWIN_10_10
1591 case VKI_F_SETLKWTIMEOUT:
1592 PRINT("fcntl[ARG3=='locktimeout'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1593 PRE_REG_READ3(long, "fcntl",
1594 unsigned int, fd, unsigned int, cmd,
1595 struct flocktimeout *, lock);
1596 *flags |= SfMayBlock;
1597 break;
1598 # endif
1600 // none
1601 case VKI_F_CHKCLEAN:
1602 case VKI_F_RDAHEAD:
1603 case VKI_F_NOCACHE:
1604 case VKI_F_FULLFSYNC:
1605 case VKI_F_FREEZE_FS:
1606 case VKI_F_THAW_FS:
1607 case VKI_F_GLOBAL_NOCACHE:
1608 PRINT("fcntl ( %lu, %s, %lu )", ARG1, name_for_fcntl(ARG1), ARG2);
1609 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1610 break;
1612 // struct fstore
1613 case VKI_F_PREALLOCATE:
1614 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1615 PRE_REG_READ3(long, "fcntl",
1616 unsigned int, fd, unsigned int, cmd,
1617 struct fstore *, fstore);
1619 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1620 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1621 fstore->fst_flags );
1622 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1623 fstore->fst_posmode );
1624 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1625 fstore->fst_offset );
1626 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1627 fstore->fst_length );
1628 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1629 fstore->fst_bytesalloc);
1631 break;
1633 // off_t
1634 case VKI_F_SETSIZE:
1635 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1636 PRE_REG_READ3(long, "fcntl",
1637 unsigned int, fd, unsigned int, cmd,
1638 vki_off_t *, offset);
1639 break;
1641 // struct radvisory
1642 case VKI_F_RDADVISE:
1643 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1644 PRE_REG_READ3(long, "fcntl",
1645 unsigned int, fd, unsigned int, cmd,
1646 struct vki_radvisory *, radvisory);
1648 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1649 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1650 radvisory->ra_offset );
1651 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1652 radvisory->ra_count );
1654 break;
1656 # if DARWIN_VERS < DARWIN_10_9
1657 // struct fbootstraptransfer
1658 case VKI_F_READBOOTSTRAP:
1659 case VKI_F_WRITEBOOTSTRAP:
1660 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1661 PRE_REG_READ3(long, "fcntl",
1662 unsigned int, fd, unsigned int, cmd,
1663 struct fbootstraptransfer *, bootstrap);
1664 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1665 ARG3, sizeof(struct vki_fbootstraptransfer) );
1666 break;
1667 # endif
1669 // struct log2phys (out)
1670 case VKI_F_LOG2PHYS:
1671 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1672 PRE_REG_READ3(long, "fcntl",
1673 unsigned int, fd, unsigned int, cmd,
1674 struct log2phys *, l2p);
1675 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1676 ARG3, sizeof(struct vki_log2phys) );
1677 break;
1679 // char[maxpathlen] (out)
1680 case VKI_F_GETPATH:
1681 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1682 PRE_REG_READ3(long, "fcntl",
1683 unsigned int, fd, unsigned int, cmd,
1684 char *, pathbuf);
1685 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1686 ARG3, VKI_MAXPATHLEN );
1687 break;
1689 // char[maxpathlen] (in)
1690 case VKI_F_PATHPKG_CHECK:
1691 PRINT("fcntl ( %lu, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1692 (HChar *)ARG3);
1693 PRE_REG_READ3(long, "fcntl",
1694 unsigned int, fd, unsigned int, cmd,
1695 char *, pathbuf);
1696 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1697 break;
1699 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1700 PRINT("fcntl ( %lu, %s )", ARG1, name_for_fcntl(ARG2));
1701 PRE_REG_READ3(long, "fcntl",
1702 unsigned int, fd, unsigned int, cmd,
1703 vki_fsignatures_t *, sigs);
1706 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1707 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1708 fsigs->fs_blob_start);
1709 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1710 fsigs->fs_blob_size);
1712 if (fsigs->fs_blob_start)
1713 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1714 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1716 break;
1718 case VKI_F_ADDFILESIGS: /* Add signature from same file (used by dyld for shared libs) */
1719 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1720 PRE_REG_READ3(long, "fcntl",
1721 unsigned int, fd, unsigned int, cmd,
1722 vki_fsignatures_t *, sigs);
1725 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1726 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1727 fsigs->fs_blob_start);
1728 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1729 fsigs->fs_blob_size);
1731 break;
1733 # if DARWIN_VERS >= DARWIN_10_11
1734 case VKI_F_ADDFILESIGS_FOR_DYLD_SIM: /* Add signature from same file, only if it is signed
1735 by Apple used by dyld for simulator */
1736 // FIXME: RK
1737 break;
1739 case VKI_F_BARRIERFSYNC: /* fsync + issue barrier to drive */
1740 // FIXME: RK
1741 break;
1743 case VKI_F_ADDFILESIGS_RETURN: /* Add signature from same file, return end offset in
1744 structure on success */
1745 // FIXME: RK
1746 break;
1747 # endif
1749 default:
1750 PRINT("fcntl ( %lu, %lu [??] )", ARG1, ARG2);
1751 log_decaying("UNKNOWN fcntl %lu!", ARG2);
1752 break;
1756 POST(fcntl)
1758 vg_assert(SUCCESS);
1759 switch (ARG2) {
1760 case VKI_F_DUPFD:
1761 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1762 VG_(close)(RES);
1763 SET_STATUS_Failure( VKI_EMFILE );
1764 } else {
1765 if (VG_(clo_track_fds))
1766 ML_(record_fd_open_named)(tid, RES);
1768 break;
1770 case VKI_F_GETFD:
1771 case VKI_F_GETFL:
1772 case VKI_F_GETOWN:
1773 case VKI_F_SETFD:
1774 case VKI_F_SETFL:
1775 case VKI_F_SETOWN:
1776 case VKI_F_GETLK:
1777 case VKI_F_SETLK:
1778 case VKI_F_SETLKW:
1779 # if DARWIN_VERS >= DARWIN_10_10
1780 case VKI_F_SETLKWTIMEOUT:
1781 break;
1782 # endif
1784 case VKI_F_PREALLOCATE:
1786 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1787 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1789 break;
1791 case VKI_F_LOG2PHYS:
1792 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1793 break;
1795 case VKI_F_GETPATH:
1796 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1797 PRINT("\"%s\"", (char*)ARG3);
1798 break;
1800 default:
1801 // DDD: ugh, missing lots of cases here, not nice
1802 break;
1806 /* ---------------------------------------------------------------------
1807 unix syscalls
1808 ------------------------------------------------------------------ */
1810 PRE(futimes)
1812 PRINT("futimes ( %ld, %#lx )", SARG1, ARG2);
1813 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1814 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1815 SET_STATUS_Failure( VKI_EBADF );
1816 } else if (ARG2 != 0) {
1817 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1818 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1822 PRE(semget)
1824 PRINT("semget ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1825 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1828 PRE(semop)
1830 *flags |= SfMayBlock;
1831 PRINT("semop ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
1832 PRE_REG_READ3(long, "semop",
1833 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1834 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1837 PRE(semctl)
1839 switch (ARG3) {
1840 case VKI_IPC_STAT:
1841 case VKI_IPC_SET:
1842 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1843 PRE_REG_READ4(long, "semctl",
1844 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1845 break;
1846 case VKI_GETALL:
1847 case VKI_SETALL:
1848 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1849 PRE_REG_READ4(long, "semctl",
1850 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1851 break;
1852 case VKI_SETVAL:
1853 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1854 PRE_REG_READ4(long, "semctl",
1855 int, semid, int, semnum, int, cmd, int, arg);
1856 break;
1857 default:
1858 PRINT("semctl ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1859 PRE_REG_READ3(long, "semctl",
1860 int, semid, int, semnum, int, cmd);
1861 break;
1863 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1865 POST(semctl)
1867 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1870 PRE(sem_open)
1872 if (ARG2 & VKI_O_CREAT) {
1873 // 4-arg version
1874 PRINT("sem_open ( %#lx(%s), %ld, %lu, %lu )",
1875 ARG1, (HChar*)ARG1, SARG2, ARG3, ARG4);
1876 PRE_REG_READ4(vki_sem_t *, "sem_open",
1877 const char *, name, int, oflag, vki_mode_t, mode,
1878 unsigned int, value);
1879 } else {
1880 // 2-arg version
1881 PRINT("sem_open ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
1882 PRE_REG_READ2(vki_sem_t *, "sem_open",
1883 const char *, name, int, oflag);
1885 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1887 /* Otherwise handle normally */
1888 *flags |= SfMayBlock;
1891 PRE(sem_close)
1893 PRINT("sem_close( %#lx )", ARG1);
1894 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1897 PRE(sem_unlink)
1899 PRINT("sem_unlink( %#lx(%s) )", ARG1, (HChar*)ARG1);
1900 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1901 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1904 PRE(sem_post)
1906 PRINT("sem_post( %#lx )", ARG1);
1907 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1908 *flags |= SfMayBlock;
1911 PRE(sem_destroy)
1913 PRINT("sem_destroy( %#lx )", ARG1);
1914 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1915 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1918 PRE(sem_init)
1920 PRINT("sem_init( %#lx, %ld, %lu )", ARG1, SARG2, ARG3);
1921 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1922 int, pshared, unsigned int, value);
1923 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1926 POST(sem_init)
1928 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1931 PRE(sem_wait)
1933 PRINT("sem_wait( %#lx )", ARG1);
1934 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1935 *flags |= SfMayBlock;
1938 PRE(sem_trywait)
1940 PRINT("sem_trywait( %#lx )", ARG1);
1941 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1942 *flags |= SfMayBlock;
1945 PRE(kqueue)
1947 PRINT("kqueue()");
1950 POST(kqueue)
1952 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1953 VG_(close)(RES);
1954 SET_STATUS_Failure( VKI_EMFILE );
1955 } else {
1956 if (VG_(clo_track_fds)) {
1957 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1962 PRE(fileport_makeport)
1964 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1965 ARG1, ARG2);
1968 PRE(guarded_open_np)
1970 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1971 ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1974 PRE(guarded_kqueue_np)
1976 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1977 ARG1, ARG2);
1980 POST(guarded_kqueue_np)
1982 if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1983 VG_(close)(RES);
1984 SET_STATUS_Failure( VKI_EMFILE );
1985 } else {
1986 if (VG_(clo_track_fds)) {
1987 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1992 PRE(guarded_close_np)
1994 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1995 ARG1, ARG2);
1998 PRE(change_fdguard_np)
2000 PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
2001 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2004 PRE(connectx)
2006 PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
2007 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2010 PRE(disconnectx)
2012 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
2013 ARG1, ARG2, ARG3);
2017 PRE(kevent)
2019 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2020 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2021 PRE_REG_READ6(int,"kevent", int,kq,
2022 const struct vki_kevent *,changelist, int,nchanges,
2023 struct vki_kevent *,eventlist, int,nevents,
2024 const struct vki_timespec *,timeout);
2026 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
2027 ARG2, ARG3 * sizeof(struct vki_kevent));
2028 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
2029 ARG4, ARG5 * sizeof(struct vki_kevent));
2030 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
2031 ARG6, sizeof(struct vki_timespec));
2033 *flags |= SfMayBlock;
2036 POST(kevent)
2038 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
2039 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
2043 PRE(kevent64)
2045 PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2046 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6);
2047 PRE_REG_READ6(int,"kevent64", int,kq,
2048 const struct vki_kevent64 *,changelist, int,nchanges,
2049 struct vki_kevent64 *,eventlist, int,nevents,
2050 const struct vki_timespec *,timeout);
2052 if (ARG3) PRE_MEM_READ ("kevent64(changelist)",
2053 ARG2, ARG3 * sizeof(struct vki_kevent64));
2054 if (ARG5) PRE_MEM_WRITE("kevent64(eventlist)",
2055 ARG4, ARG5 * sizeof(struct vki_kevent64));
2056 if (ARG6) PRE_MEM_READ ("kevent64(timeout)",
2057 ARG6, sizeof(struct vki_timespec));
2059 *flags |= SfMayBlock;
2062 POST(kevent64)
2064 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
2065 if (RES > 0) {
2066 ML_(sync_mappings)("after", "kevent64", 0);
2067 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
2072 Addr pthread_starter = 0;
2073 Addr wqthread_starter = 0;
2074 SizeT pthread_structsize = 0;
2076 PRE(bsdthread_register)
2078 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
2079 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
2080 void *,"wqthread", size_t,"pthsize");
2082 pthread_starter = ARG1;
2083 wqthread_starter = ARG2;
2084 pthread_structsize = ARG3;
2085 ARG1 = (Word)&pthread_hijack_asm;
2086 ARG2 = (Word)&wqthread_hijack_asm;
2089 PRE(workq_open)
2091 PRINT("workq_open()");
2092 PRE_REG_READ0(int, "workq_open");
2094 // This creates lots of threads and thread stacks under the covers,
2095 // but we ignore them all until some work item starts running on it.
2098 static const HChar *workqop_name(int op)
2100 switch (op) {
2101 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
2102 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
2103 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
2104 case VKI_WQOPS_THREAD_SETCONC: return "THREAD_SETCONC";
2105 case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
2106 case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
2107 case VKI_WQOPS_QUEUE_REQTHREADS2: return "QUEUE_REQTHREADS2";
2108 case VKI_WQOPS_THREAD_KEVENT_RETURN: return "THREAD_KEVENT_RETURN";
2109 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY: return "SET_EVENT_MANAGER_PRIORITY";
2110 case VKI_WQOPS_THREAD_WORKLOOP_RETURN: return "THREAD_WORKLOOP_RETURN";
2111 case VKI_WQOPS_SHOULD_NARROW: return "SHOULD_NARROW";
2112 default: return "?";
2117 PRE(workq_ops)
2119 PRINT("workq_ops( %ld(%s), %#lx, %ld )", SARG1, workqop_name(ARG1), ARG2,
2120 SARG3);
2121 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2122 int,"priority");
2124 switch (ARG1) {
2125 case VKI_WQOPS_QUEUE_ADD:
2126 case VKI_WQOPS_QUEUE_REMOVE:
2127 // GrP fixme need anything here?
2128 // GrP fixme may block?
2129 break;
2130 case VKI_WQOPS_THREAD_RETURN: {
2131 // The interesting case. The kernel will do one of two things:
2132 // 1. Return normally. We continue; libc proceeds to stop the thread.
2133 // V does nothing special here.
2134 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2135 // new work item, and never returns from workq_ops.
2136 // V handles this by longjmp() from wqthread_hijack back to the
2137 // scheduler, which continues at the new client SP/IP/state.
2138 // This works something like V's signal handling.
2139 // To the tool, this looks like workq_ops() sometimes returns
2140 // to a strange address.
2141 ThreadState *tst = VG_(get_ThreadState)(tid);
2142 tst->os_state.wq_jmpbuf_valid = True;
2143 *flags |= SfMayBlock; // GrP fixme true?
2144 break;
2146 case VKI_WQOPS_THREAD_SETCONC:
2147 // RK fixme need anything here?
2148 // RK fixme may block?
2149 break;
2150 case VKI_WQOPS_QUEUE_NEWSPISUPP:
2151 // JRS don't think we need to do anything here -- this just checks
2152 // whether some newer functionality is supported
2153 break;
2154 case VKI_WQOPS_QUEUE_REQTHREADS:
2155 case VKI_WQOPS_QUEUE_REQTHREADS2:
2156 // JRS uh, looks like it queues up a bunch of threads, or some such?
2157 *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
2158 break;
2159 case VKI_WQOPS_THREAD_KEVENT_RETURN:
2160 // RK fixme need anything here?
2161 // perhaps similar to VKI_WQOPS_THREAD_RETURN above?
2162 break;
2163 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY:
2164 // RK fixme this just sets scheduling priorities - don't think we need
2165 // to do anything here
2166 break;
2167 case VKI_WQOPS_THREAD_WORKLOOP_RETURN:
2168 case VKI_WQOPS_SHOULD_NARROW:
2169 // RK fixme need anything here?
2170 // RK fixme may block?
2171 break;
2172 default:
2173 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
2174 break;
2177 POST(workq_ops)
2179 ThreadState *tst = VG_(get_ThreadState)(tid);
2180 tst->os_state.wq_jmpbuf_valid = False;
2181 switch (ARG1) {
2182 case VKI_WQOPS_THREAD_RETURN:
2183 ML_(sync_mappings)("after", "workq_ops(THREAD_RETURN)", 0);
2184 break;
2185 case VKI_WQOPS_QUEUE_REQTHREADS:
2186 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2187 break;
2188 case VKI_WQOPS_QUEUE_REQTHREADS2:
2189 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS2)", 0);
2190 break;
2191 default:
2192 break;
2198 PRE(__mac_syscall)
2200 PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
2201 ARG1, (HChar*)ARG1, SARG2, ARG3);
2202 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
2203 int,"call", void *,"arg");
2205 // GrP fixme check call's arg?
2206 // GrP fixme check policy?
2210 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2211 More like syswrap-generic's sys_exit_group. */
2212 PRE(exit)
2214 ThreadId t;
2215 ThreadState* tst;
2217 PRINT("darwin exit( %ld )", SARG1);
2218 PRE_REG_READ1(void, "exit", int, status);
2220 tst = VG_(get_ThreadState)(tid);
2222 /* A little complex; find all the threads with the same threadgroup
2223 as this one (including this one), and mark them to exit */
2224 for (t = 1; t < VG_N_THREADS; t++) {
2225 if ( /* not alive */
2226 VG_(threads)[t].status == VgTs_Empty
2227 /* GrP fixme zombie? */
2229 continue;
2231 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
2232 VG_(threads)[t].os_state.exitcode = ARG1;
2234 if (t != tid)
2235 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
2238 /* We have to claim the syscall already succeeded. */
2239 SET_STATUS_Success(0);
2243 PRE(sigaction)
2245 PRINT("sigaction ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2246 PRE_REG_READ3(long, "sigaction",
2247 int, signum, vki_sigaction_toK_t *, act,
2248 vki_sigaction_fromK_t *, oldact);
2250 if (ARG2 != 0) {
2251 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
2252 PRE_MEM_READ( "sigaction(act->sa_handler)",
2253 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2254 PRE_MEM_READ( "sigaction(act->sa_mask)",
2255 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2256 PRE_MEM_READ( "sigaction(act->sa_flags)",
2257 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2259 if (ARG3 != 0)
2260 PRE_MEM_WRITE( "sigaction(oldact)",
2261 ARG3, sizeof(vki_sigaction_fromK_t));
2263 SET_STATUS_from_SysRes(
2264 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
2265 (vki_sigaction_fromK_t *)ARG3)
2268 POST(sigaction)
2270 vg_assert(SUCCESS);
2271 if (RES == 0 && ARG3 != 0)
2272 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
2276 PRE(__pthread_kill)
2278 PRINT("__pthread_kill ( %#lx, %ld )", ARG1, SARG2);
2279 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
2283 PRE(__pthread_sigmask)
2285 // arguments are identical to sigprocmask (how, sigset_t*, sigset_t*).
2286 UWord arg1;
2287 PRINT("__pthread_sigmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2288 PRE_REG_READ3(long, "__pthread_sigmask",
2289 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
2290 if (ARG2 != 0)
2291 PRE_MEM_READ( "__pthread_sigmask(set)", ARG2, sizeof(vki_sigset_t));
2292 if (ARG3 != 0)
2293 PRE_MEM_WRITE( "__pthread_sigmask(oldset)", ARG3, sizeof(vki_sigset_t));
2295 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
2296 value of 'how' is irrelevant, and it appears that Darwin's libc
2297 passes zero, which is not equal to any of
2298 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
2299 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
2300 value independently of the other args. Solution: in this case,
2301 simply pass a valid (but irrelevant) value for 'how'. */
2302 /* Also, in this case the new set is passed to the kernel by
2303 reference, not value, as in some other sigmask related Darwin
2304 syscalls. */
2305 arg1 = ARG1;
2306 if (ARG2 == 0 /* the new-set is NULL */
2307 && ARG1 != VKI_SIG_BLOCK
2308 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
2309 arg1 = VKI_SIG_SETMASK;
2311 SET_STATUS_from_SysRes(
2312 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
2313 (vki_sigset_t*)ARG3 )
2316 if (SUCCESS)
2317 *flags |= SfPollAfter;
2319 POST(__pthread_sigmask)
2321 vg_assert(SUCCESS);
2322 if (RES == 0 && ARG3 != 0)
2323 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2327 PRE(__pthread_canceled)
2329 *flags |= SfMayBlock; /* might kill this thread??? */
2330 /* I don't think so -- I think it just changes the cancellation
2331 state. But taking no chances. */
2332 PRINT("__pthread_canceled ( %#lx )", ARG1);
2333 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
2337 PRE(__pthread_markcancel)
2339 *flags |= SfMayBlock; /* might kill this thread??? */
2340 PRINT("__pthread_markcancel ( %#lx )", ARG1);
2341 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
2342 /* Just let it go through. No idea if this is correct. */
2346 PRE(__disable_threadsignal)
2348 vki_sigset_t set;
2349 PRINT("__disable_threadsignal(%ld, %ld, %ld)", SARG1, SARG2, SARG3);
2350 /* I don't think this really looks at its arguments. So don't
2351 bother to check them. */
2353 VG_(sigfillset)( &set );
2354 SET_STATUS_from_SysRes(
2355 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
2358 /* We don't expect that blocking all signals for this thread could
2359 cause any more to be delivered (how could it?), but just in case
2360 .. */
2361 if (SUCCESS)
2362 *flags |= SfPollAfter;
2366 PRE(__pthread_chdir)
2368 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2369 PRE_REG_READ1(long, "__pthread_chdir", const char *, path);
2370 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1 );
2375 PRE(__pthread_fchdir)
2377 PRINT("__pthread_fchdir ( %lu )", ARG1);
2378 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd);
2382 PRE(kdebug_trace)
2384 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2385 SARG1, SARG2, SARG3, SARG4, SARG5, SARG6);
2387 Don't check anything - some clients pass fewer arguments.
2388 PRE_REG_READ6(long, "kdebug_trace",
2389 int,"code", int,"arg1", int,"arg2",
2390 int,"arg3", int,"arg4", int,"arg5");
2395 PRE(seteuid)
2397 PRINT("seteuid(%lu)", ARG1);
2398 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
2402 PRE(setegid)
2404 PRINT("setegid(%lu)", ARG1);
2405 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
2408 PRE(settid)
2410 PRINT("settid(%lu, %lu)", ARG1, ARG2);
2411 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
2414 PRE(gettid)
2416 PRINT("gettid()");
2417 PRE_REG_READ0(long, gettid);
2420 /* XXX need to check whether we need POST operations for
2421 * waitevent, watchevent, modwatch -- jpeach
2423 PRE(watchevent)
2425 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
2426 PRE_REG_READ2(long, "watchevent",
2427 vki_eventreq *, "event", unsigned int, "eventmask");
2429 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
2430 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
2431 *flags |= SfMayBlock;
2434 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
2435 PRE(waitevent)
2437 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
2438 PRE_REG_READ2(long, "waitevent",
2439 vki_eventreq *, "event", struct timeval *, "timeout");
2440 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
2442 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
2443 PRE_timeval_READ("waitevent(timeout)", ARG2);
2446 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2447 *flags |= SfMayBlock;
2450 POST(waitevent)
2452 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
2455 PRE(modwatch)
2457 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
2458 PRE_REG_READ2(long, "modwatch",
2459 vki_eventreq *, "event", unsigned int, "eventmask");
2461 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
2462 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
2465 PRE(getxattr)
2467 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2468 ARG1, (HChar *)ARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2470 PRE_REG_READ6(vki_ssize_t, "getxattr",
2471 const char *, path, char *, name, void *, value,
2472 vki_size_t, size, uint32_t, position, int, options);
2473 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
2474 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2475 if (ARG3)
2476 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2479 POST(getxattr)
2481 vg_assert((vki_ssize_t)RES >= 0);
2482 if (ARG3)
2483 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2486 PRE(fgetxattr)
2488 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2489 SARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2491 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
2492 int, fd, char *, name, void *, value,
2493 vki_size_t, size, uint32_t, position, int, options);
2494 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2495 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2498 POST(fgetxattr)
2500 vg_assert((vki_ssize_t)RES >= 0);
2501 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2504 PRE(setxattr)
2506 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2507 ARG1, (HChar *)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2508 PRE_REG_READ6(int, "setxattr",
2509 const char *,"path", char *,"name", void *,"value",
2510 vki_size_t,"size", uint32_t,"position", int,"options" );
2512 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
2513 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
2514 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
2518 PRE(fsetxattr)
2520 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2521 SARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2522 PRE_REG_READ6(int, "fsetxattr",
2523 int,"fd", char *,"name", void *,"value",
2524 vki_size_t,"size", uint32_t,"position", int,"options" );
2526 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
2527 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
2531 PRE(removexattr)
2533 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2534 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, SARG3 );
2535 PRE_REG_READ3(int, "removexattr",
2536 const char*, "path", char*, "attrname", int, "options");
2537 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
2538 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2542 PRE(fremovexattr)
2544 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2545 SARG1, ARG2, (HChar*)ARG2, SARG3 );
2546 PRE_REG_READ3(int, "fremovexattr",
2547 int, "fd", char*, "attrname", int, "options");
2548 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2552 PRE(listxattr)
2554 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2555 ARG1, (HChar *)ARG1, ARG2, ARG3, SARG4 );
2556 PRE_REG_READ4 (long, "listxattr",
2557 const char *,"path", char *,"namebuf",
2558 vki_size_t,"size", int,"options" );
2560 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
2561 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
2562 *flags |= SfMayBlock;
2564 POST(listxattr)
2566 vg_assert(SUCCESS);
2567 vg_assert((vki_ssize_t)RES >= 0);
2568 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2572 PRE(flistxattr)
2574 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2575 SARG1, ARG2, ARG3, SARG4 );
2576 PRE_REG_READ4 (long, "flistxattr",
2577 int, "fd", char *,"namebuf",
2578 vki_size_t,"size", int,"options" );
2579 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2580 *flags |= SfMayBlock;
2582 POST(flistxattr)
2584 vg_assert(SUCCESS);
2585 vg_assert((vki_ssize_t)RES >= 0);
2586 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2590 PRE(shmat)
2592 UWord arg2tmp;
2593 PRINT("shmat ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
2594 PRE_REG_READ3(long, "shmat",
2595 int, shmid, const void *, shmaddr, int, shmflg);
2596 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2597 if (arg2tmp == 0)
2598 SET_STATUS_Failure( VKI_EINVAL );
2599 else
2600 ARG2 = arg2tmp; // used in POST
2602 POST(shmat)
2604 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2607 PRE(shmctl)
2609 PRINT("shmctl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
2610 PRE_REG_READ3(long, "shmctl",
2611 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2612 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2614 POST(shmctl)
2616 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2619 PRE(shmdt)
2621 PRINT("shmdt ( %#lx )",ARG1);
2622 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2623 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2624 SET_STATUS_Failure( VKI_EINVAL );
2626 POST(shmdt)
2628 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2631 PRE(shmget)
2633 PRINT("shmget ( %ld, %lu, %ld )", SARG1, ARG2, SARG3);
2634 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2637 PRE(shm_open)
2639 PRINT("shm_open(%#lx(%s), %ld, %lu)", ARG1, (HChar *)ARG1, SARG2, ARG3);
2640 PRE_REG_READ3(long, "shm_open",
2641 const char *,"name", int,"flags", vki_mode_t,"mode");
2643 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2645 *flags |= SfMayBlock;
2647 POST(shm_open)
2649 vg_assert(SUCCESS);
2650 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2651 VG_(close)(RES);
2652 SET_STATUS_Failure( VKI_EMFILE );
2653 } else {
2654 if (VG_(clo_track_fds))
2655 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
2659 PRE(shm_unlink)
2661 *flags |= SfMayBlock;
2662 PRINT("shm_unlink ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2663 PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2664 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2666 POST(shm_unlink)
2668 /* My reading of the man page suggests that a call may cause memory
2669 mappings to change: "if no references exist at the time of the
2670 call to shm_unlink(), the resources are reclaimed immediately".
2671 So we need to resync here, sigh. */
2672 ML_(sync_mappings)("after", "shm_unlink", 0);
2675 PRE(stat_extended)
2677 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2678 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2679 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2680 void *, fsacl, vki_size_t *, fsacl_size);
2681 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
2682 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2683 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2684 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2685 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2687 POST(stat_extended)
2689 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2690 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2691 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2692 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2696 PRE(lstat_extended)
2698 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2699 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2700 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2701 void *, fsacl, vki_size_t *, fsacl_size);
2702 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
2703 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2704 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2705 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2706 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2708 POST(lstat_extended)
2710 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2711 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2712 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2713 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2717 PRE(fstat_extended)
2719 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2720 SARG1, ARG2, ARG3, ARG4);
2721 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2722 void *, fsacl, vki_size_t *, fsacl_size);
2723 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2724 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2725 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2726 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2728 POST(fstat_extended)
2730 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2731 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2732 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2733 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2737 PRE(stat64_extended)
2739 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2740 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2741 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2742 void *, fsacl, vki_size_t *, fsacl_size);
2743 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
2744 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2745 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2746 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2747 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2749 POST(stat64_extended)
2751 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2752 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2753 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2754 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2758 PRE(lstat64_extended)
2760 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2761 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2762 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2763 void *, fsacl, vki_size_t *, fsacl_size);
2764 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2765 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2766 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2767 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2768 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2770 POST(lstat64_extended)
2772 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2773 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2774 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2775 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2779 PRE(fstat64_extended)
2781 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2782 SARG1, ARG2, ARG3, ARG4);
2783 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2784 void *, fsacl, vki_size_t *, fsacl_size);
2785 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2786 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2787 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2788 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2790 POST(fstat64_extended)
2792 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2793 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2794 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2795 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2799 PRE(fchmod_extended)
2801 /* DDD: Note: this is not really correct. Handling of
2802 chmod_extended is broken in the same way. */
2803 PRINT("fchmod_extended ( %lu, %lu, %lu, %lu, %#lx )",
2804 ARG1, ARG2, ARG3, ARG4, ARG5);
2805 PRE_REG_READ5(long, "fchmod_extended",
2806 unsigned int, fildes,
2807 uid_t, uid,
2808 gid_t, gid,
2809 vki_mode_t, mode,
2810 void* /*really,user_addr_t*/, xsecurity);
2811 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2812 is just way wrong. [The trouble is with the size, which depends on a
2813 non-trival kernel computation] */
2814 if (ARG5) {
2815 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2816 sizeof(struct vki_kauth_filesec) );
2820 PRE(chmod_extended)
2822 /* DDD: Note: this is not really correct. Handling of
2823 fchmod_extended is broken in the same way. */
2824 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2825 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2826 PRE_REG_READ5(long, "chmod_extended",
2827 unsigned int, fildes,
2828 uid_t, uid,
2829 gid_t, gid,
2830 vki_mode_t, mode,
2831 void* /*really,user_addr_t*/, xsecurity);
2832 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2833 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2834 is just way wrong. [The trouble is with the size, which depends on a
2835 non-trival kernel computation] */
2836 if (ARG5) {
2837 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2838 sizeof(struct vki_kauth_filesec) );
2842 PRE(open_extended)
2844 /* DDD: Note: this is not really correct. Handling of
2845 {,f}chmod_extended is broken in the same way. */
2846 PRINT("open_extended ( %#lx(%s), %ld, %lu, %lu, %lu, %#lx )",
2847 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2848 SARG2, ARG3, ARG4, ARG5, ARG6);
2849 PRE_REG_READ6(long, "open_extended",
2850 char*, path,
2851 int, flags,
2852 uid_t, uid,
2853 gid_t, gid,
2854 vki_mode_t, mode,
2855 void* /*really,user_addr_t*/, xsecurity);
2856 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2857 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2858 is just way wrong. [The trouble is with the size, which depends on a
2859 non-trival kernel computation] */
2860 if (ARG6)
2861 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2862 sizeof(struct vki_kauth_filesec) );
2865 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2866 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2867 // by one or more strings. Each accessx_descriptor contains a field,
2868 // 'ad_name_offset', which points to one of the strings (or it can contain
2869 // zero which means "reuse the string from the previous accessx_descriptor").
2871 // What's really ridiculous is that we are only given the size of the overall
2872 // buffer, not the number of accessx_descriptors, nor the number of strings.
2873 // The kernel determines the number of accessx_descriptors by walking through
2874 // them one by one, checking that the ad_name_offset points within the buffer,
2875 // past the current point (or that it's a zero, unless its the first
2876 // descriptor); if so, we assume that this really is an accessx_descriptor,
2877 // if not, we assume we've hit the strings section. Gah.
2879 // This affects us here because number of entries in the 'results' buffer is
2880 // determined by the number of accessx_descriptors. So we have to know that
2881 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2882 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2883 // computation after the syscall has succeeded, because the kernel will have
2884 // checked for all the zillion different ways this syscall can fail, and we'll
2885 // know we have a well-formed 'entries' buffer. This means we might miss some
2886 // uses of unaddressable memory but oh well.
2888 PRE(access_extended)
2890 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2891 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2892 // XXX: the accessx_descriptor struct contains padding, so this can cause
2893 // unnecessary undefined value errors. But you arguably shouldn't be
2894 // passing undefined values to the kernel anyway...
2895 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2896 vki_errno_t *, results, vki_uid_t *, uid);
2897 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2899 // XXX: as mentioned above, this check is too hard to do before the
2900 // syscall.
2901 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2903 POST(access_extended)
2905 // 'n_descs' is the number of descriptors we think are in the buffer. We
2906 // start with the maximum possible value, which occurs if we have the
2907 // shortest possible string section. The shortest string section allowed
2908 // consists of a single one-char string (plus the NUL char). Hence the
2909 // '2'.
2910 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2911 SizeT size = ARG2;
2912 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2913 Int i; // Current position in the descriptors section array.
2914 Int u; // Upper bound on the length of the descriptors array
2915 // (recomputed each time around the loop)
2916 vg_assert(n_descs > 0);
2918 // Step through the descriptors, lowering 'n_descs' until we know we've
2919 // reached the string section.
2920 for (i = 0; True; i++) {
2921 // If we're past our estimate, we must be one past the end of the
2922 // descriptors section (ie. at the start of the string section). Stop.
2923 if (i >= n_descs)
2924 break;
2926 // Get the array index for the string, but pretend momentarily that it
2927 // is actually another accessx_descriptor. That gives us an upper bound
2928 // on the length of the descriptors section. (Unless the index is zero,
2929 // in which case we have no new info.)
2930 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2931 if (u == 0) {
2932 vg_assert(i != 0);
2933 continue;
2936 // If the upper bound is below our current estimate, revise that
2937 // estimate downwards.
2938 if (u < n_descs)
2939 n_descs = u;
2942 // Sanity check.
2943 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2945 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2949 PRE(chflags)
2951 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (HChar *)ARG1, ARG2);
2952 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2953 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2955 // GrP fixme sanity-check flags value?
2958 PRE(fchflags)
2960 PRINT("fchflags ( %ld, %lu )", SARG1, ARG2);
2961 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2963 // GrP fixme sanity-check flags value?
2966 PRE(stat64)
2968 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
2969 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2970 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2971 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2973 POST(stat64)
2975 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2978 PRE(lstat64)
2980 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
2981 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2982 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2983 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2985 POST(lstat64)
2987 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2990 PRE(fstat64)
2992 PRINT("fstat64 ( %lu, %#lx )", ARG1,ARG2);
2993 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2994 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2996 POST(fstat64)
2998 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
3001 PRE(getfsstat)
3003 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3004 PRE_REG_READ3(int, "getfsstat",
3005 struct vki_statfs *, buf, int, bufsize, int, flags);
3006 if (ARG1) {
3007 // ARG2 is a BYTE SIZE
3008 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
3011 POST(getfsstat)
3013 if (ARG1) {
3014 // RES is a STRUCT COUNT
3015 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
3019 PRE(getfsstat64)
3021 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3022 PRE_REG_READ3(int, "getfsstat64",
3023 struct vki_statfs64 *, buf, int, bufsize, int, flags);
3024 if (ARG1) {
3025 // ARG2 is a BYTE SIZE
3026 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
3029 POST(getfsstat64)
3031 if (ARG1) {
3032 // RES is a STRUCT COUNT
3033 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
3037 PRE(mount)
3039 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
3040 // We are conservative and check everything, except the memory pointed to
3041 // by 'data'.
3042 *flags |= SfMayBlock;
3043 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
3044 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
3045 PRE_REG_READ4(long, "mount",
3046 const char *, type, const char *, dir,
3047 int, flags, void *, data);
3048 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
3049 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
3053 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
3054 void *attrBuf, SizeT attrBufSize,
3055 void (*fn)(ThreadId, void *attrData, SizeT size)
3058 typedef struct {
3059 uint32_t attrBit;
3060 int32_t attrSize;
3061 } attrspec;
3062 static const attrspec commonattr[] = {
3063 // This order is important.
3064 #if DARWIN_VERS >= DARWIN_10_6
3065 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
3066 #endif
3067 { ATTR_CMN_NAME, -1 },
3068 { ATTR_CMN_DEVID, sizeof(dev_t) },
3069 { ATTR_CMN_FSID, sizeof(fsid_t) },
3070 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
3071 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
3072 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
3073 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
3074 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
3075 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
3076 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
3077 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
3078 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
3079 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
3080 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
3081 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
3082 { ATTR_CMN_OWNERID, sizeof(uid_t) },
3083 { ATTR_CMN_GRPID, sizeof(gid_t) },
3084 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
3085 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
3086 { ATTR_CMN_NAMEDATTRLIST, -1 },
3087 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
3088 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
3089 { ATTR_CMN_EXTENDED_SECURITY, -1 },
3090 { ATTR_CMN_UUID, sizeof(guid_t) },
3091 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
3092 { ATTR_CMN_FILEID, sizeof(uint64_t) },
3093 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
3094 #if DARWIN_VERS >= DARWIN_10_6
3095 { ATTR_CMN_FULLPATH, -1 },
3096 #endif
3097 #if DARWIN_VERS >= DARWIN_10_8
3098 { ATTR_CMN_ADDEDTIME, -1 },
3099 #endif
3100 { 0, 0 }
3102 static const attrspec volattr[] = {
3103 // This order is important.
3104 { ATTR_VOL_INFO, 0 },
3105 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
3106 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
3107 { ATTR_VOL_SIZE, sizeof(off_t) },
3108 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
3109 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
3110 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
3111 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
3112 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
3113 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
3114 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
3115 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
3116 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
3117 { ATTR_VOL_MOUNTPOINT, -1 },
3118 { ATTR_VOL_NAME, -1 },
3119 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
3120 { ATTR_VOL_MOUNTEDDEVICE, -1 },
3121 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
3122 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
3123 #if DARWIN_VERS >= DARWIN_10_6
3124 { ATTR_VOL_UUID, sizeof(uuid_t) },
3125 #endif
3126 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
3127 { 0, 0 }
3129 static const attrspec dirattr[] = {
3130 // This order is important.
3131 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
3132 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
3133 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
3134 { 0, 0 }
3136 static const attrspec fileattr[] = {
3137 // This order is important.
3138 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
3139 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
3140 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
3141 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
3142 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
3143 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
3144 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
3145 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
3146 { ATTR_FILE_FORKLIST, -1 },
3147 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
3148 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
3149 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
3150 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
3151 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
3152 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
3153 { 0, 0 }
3155 static const attrspec forkattr[] = {
3156 // This order is important.
3157 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
3158 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
3159 { 0, 0 }
3162 static const attrspec *attrdefs[5] = {
3163 commonattr, volattr, dirattr, fileattr, forkattr
3165 attrgroup_t a[5];
3166 uint8_t *d, *dend;
3167 int g, i;
3169 vg_assert(attrList->bitmapcount == 5);
3170 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
3171 d = attrBuf;
3172 dend = d + attrBufSize;
3174 #if DARWIN_VERS >= DARWIN_10_6
3175 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3176 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
3177 // fixme range check this?
3178 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
3179 fn(tid, d, sizeof(attribute_set_t));
3180 VG_(memcpy)(a, d, sizeof(a));
3182 #endif
3184 for (g = 0; g < 5; g++) {
3185 for (i = 0; attrdefs[g][i].attrBit; i++) {
3186 uint32_t bit = attrdefs[g][i].attrBit;
3187 int32_t size = attrdefs[g][i].attrSize;
3189 if (a[g] & bit) {
3190 a[g] &= ~bit; // clear bit for error check later
3191 if (size == -1) {
3192 attrreference_t *ref = (attrreference_t *)d;
3193 size = MIN(sizeof(attrreference_t), dend - d);
3194 fn(tid, d, size);
3195 if (size >= sizeof(attrreference_t) &&
3196 d + ref->attr_dataoffset < dend)
3198 fn(tid, d + ref->attr_dataoffset,
3199 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
3201 d += size;
3203 else {
3204 size = MIN(size, dend - d);
3205 fn(tid, d, size);
3206 d += size;
3209 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
3210 if (d > dend) d = dend;
3214 // Known bits are cleared. Die if any bits are left.
3215 if (a[g] != 0) {
3216 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
3221 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3223 POST_MEM_WRITE((Addr)attrData, attrDataSize);
3226 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3228 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
3231 PRE(getattrlist)
3233 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3234 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3235 PRE_REG_READ5(int, "getattrlist",
3236 const char *,path, struct vki_attrlist *,attrList,
3237 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3238 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
3239 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3240 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
3243 POST(getattrlist)
3245 if (ARG4 > sizeof(vki_uint32_t)) {
3246 // attrBuf is uint32_t size followed by attr data
3247 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
3248 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
3249 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
3250 // *sizep is bytes required for return value, including *sizep
3251 } else {
3252 // *sizep is actual bytes returned, including *sizep
3254 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
3259 PRE(setattrlist)
3261 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3262 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3263 PRE_REG_READ5(int, "setattrlist",
3264 const char *,path, struct vki_attrlist *,attrList,
3265 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3266 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
3267 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3268 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
3272 PRE(getdirentriesattr)
3274 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %lu, %#lx, %#lx, %#lx, %lu)",
3275 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
3276 PRE_REG_READ8(int, "getdirentriesattr",
3277 int,fd, struct vki_attrlist *,attrList,
3278 void *,attrBuf, size_t,attrBufSize,
3279 unsigned int *,count, unsigned int *,basep,
3280 unsigned int *,newState, unsigned int,options);
3281 PRE_MEM_READ("getdirentriesattr(attrList)",
3282 ARG2, sizeof(struct vki_attrlist));
3283 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
3284 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3285 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3286 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
3287 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
3289 POST(getdirentriesattr)
3291 char *p, *end;
3292 unsigned int count;
3293 unsigned int i;
3295 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
3296 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
3297 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
3299 // return buffer is concatenation of variable-size structs
3300 count = *(unsigned int *)ARG5;
3301 p = (char *)ARG3;
3302 end = (char *)ARG3 + ARG4;
3303 for (i = 0; i < count; i++) {
3304 vg_assert(p < end); // failure is kernel bug or Valgrind bug
3305 p += *(unsigned int *)p;
3308 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
3310 PRINT("got %d records, %ld/%lu bytes\n",
3311 count, (Addr)p-(Addr)ARG3, ARG4);
3314 PRE(exchangedata)
3316 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3317 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3);
3318 PRE_REG_READ3(int, "exchangedata",
3319 char *, path1, char *, path2, unsigned long, options);
3320 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
3321 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
3324 PRE(fsctl)
3326 PRINT("fsctl ( %#lx(%s), %lu, %#lx, %lu )",
3327 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
3328 PRE_REG_READ4( long, "fsctl",
3329 char *,"path", unsigned int,"request",
3330 void *,"data", unsigned int,"options");
3332 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
3334 switch (ARG2) {
3335 case VKI_afpfsByteRangeLock2FSCTL: {
3336 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3337 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3338 pb->offset);
3339 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3340 pb->length);
3341 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3342 pb->unLockFlag);
3343 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3344 pb->startEndFlag);
3345 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3346 pb->fd);
3348 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3349 pb->retRangeStart);
3351 // GrP fixme check fd
3352 break;
3354 case VKI_FSIOC_SYNC_VOLUME:
3355 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
3356 break;
3358 default:
3359 // fsctl requests use ioctl encoding
3360 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3361 break;
3365 POST(fsctl)
3367 switch (ARG2) {
3368 case VKI_afpfsByteRangeLock2FSCTL: {
3369 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3370 POST_FIELD_WRITE(pb->retRangeStart);
3371 break;
3373 case VKI_FSIOC_SYNC_VOLUME:
3374 break;
3376 default:
3377 // fsctl requests use ioctl encoding
3378 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
3379 break;
3383 PRE(initgroups)
3385 PRINT("initgroups(%s, %#lx, %lu)", (HChar *)ARG1, ARG2, ARG3);
3386 PRE_REG_READ3(long, "initgroups",
3387 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
3388 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
3392 //--------- posix_spawn ---------//
3393 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3394 the simpler AIX equivalent (syswrap-aix5.c). */
3395 // Pre_read a char** argument.
3396 static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
3398 while (True) {
3399 Addr a_deref;
3400 Addr* a_p = (Addr*)a;
3401 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
3402 a_deref = *a_p;
3403 if (0 == a_deref)
3404 break;
3405 PRE_MEM_RASCIIZ( s2, a_deref );
3406 a += sizeof(char*);
3409 static SysRes simple_pre_exec_check ( const HChar* exe_name,
3410 Bool trace_this_child )
3412 Int fd, ret;
3413 SysRes res;
3414 Bool setuid_allowed;
3416 // Check it's readable
3417 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
3418 if (sr_isError(res)) {
3419 return res;
3421 fd = sr_Res(res);
3422 VG_(close)(fd);
3424 // Check we have execute permissions. We allow setuid executables
3425 // to be run only in the case when we are not simulating them, that
3426 // is, they to be run natively.
3427 setuid_allowed = trace_this_child ? False : True;
3428 ret = VG_(check_executable)(NULL/*&is_setuid*/,
3429 exe_name, setuid_allowed);
3430 if (0 != ret) {
3431 return VG_(mk_SysRes_Error)(ret);
3433 return VG_(mk_SysRes_Success)(0);
3435 PRE(posix_spawn)
3437 HChar* path = NULL; /* path to executable */
3438 HChar** envp = NULL;
3439 HChar** argv = NULL;
3440 HChar** arg2copy;
3441 HChar* launcher_basename = NULL;
3442 Int i, j, tot_args;
3443 SysRes res;
3444 Bool trace_this_child;
3446 /* args: pid_t* pid
3447 char* path
3448 posix_spawn_file_actions_t* file_actions
3449 char** argv
3450 char** envp
3452 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3453 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3455 /* Standard pre-syscall checks */
3457 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
3458 void*, file_actions, char**, argv, char**, envp );
3459 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
3460 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
3461 // DDD: check file_actions
3462 if (ARG4 != 0)
3463 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
3464 "posix_spawn(argv[i])" );
3465 if (ARG5 != 0)
3466 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
3467 "posix_spawn(envp[i])" );
3469 if (0)
3470 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3471 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3473 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3474 syswrap-generic.c. */
3476 /* Check that the name at least begins in client-accessible storage. */
3477 if (ARG2 == 0 /* obviously bogus */
3478 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
3479 SET_STATUS_Failure( VKI_EFAULT );
3480 return;
3483 // Decide whether or not we want to follow along
3484 { // Make 'child_argv' be a pointer to the child's arg vector
3485 // (skipping the exe name)
3486 const HChar** child_argv = (const HChar**)ARG4;
3487 if (child_argv && child_argv[0] == NULL)
3488 child_argv = NULL;
3489 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
3492 // Do the important checks: it is a file, is executable, permissions are
3493 // ok, etc. We allow setuid executables to run only in the case when
3494 // we are not simulating them, that is, they to be run natively.
3495 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
3496 if (sr_isError(res)) {
3497 SET_STATUS_Failure( sr_Err(res) );
3498 return;
3501 /* If we're tracing the child, and the launcher name looks bogus
3502 (possibly because launcher.c couldn't figure it out, see
3503 comments therein) then we have no option but to fail. */
3504 if (trace_this_child
3505 && (VG_(name_of_launcher) == NULL
3506 || VG_(name_of_launcher)[0] != '/')) {
3507 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
3508 return;
3511 /* Ok. So let's give it a try. */
3512 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
3514 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3515 So, we should not terminate gdbserver : this is still the parent
3516 running, which will terminate its gdbserver when exiting.
3517 If the child process is traced, it will start a fresh gdbserver
3518 after posix_spawn. */
3520 // Set up the child's exe path.
3522 if (trace_this_child) {
3524 // We want to exec the launcher. Get its pre-remembered path.
3525 path = VG_(name_of_launcher);
3526 // VG_(name_of_launcher) should have been acquired by m_main at
3527 // startup. The following two assertions should be assured by
3528 // the "If we're tracking the child .." test just above here.
3529 vg_assert(path);
3530 vg_assert(path[0] == '/');
3531 launcher_basename = path;
3533 } else {
3534 path = (HChar*)ARG2;
3537 // Set up the child's environment.
3539 // Remove the valgrind-specific stuff from the environment so the
3540 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3541 // This is done unconditionally, since if we are tracing the child,
3542 // the child valgrind will set up the appropriate client environment.
3543 // Nb: we make a copy of the environment before trying to mangle it
3544 // as it might be in read-only memory (this was bug #101881).
3546 // Then, if tracing the child, set VALGRIND_LIB for it.
3548 if (ARG5 == 0) {
3549 envp = NULL;
3550 } else {
3551 envp = VG_(env_clone)( (HChar**)ARG5 );
3552 vg_assert(envp);
3553 VG_(env_remove_valgrind_env_stuff)( envp, /* ro_strings */ False, NULL);
3556 if (trace_this_child) {
3557 // Set VALGRIND_LIB in ARG5 (the environment)
3558 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3561 // Set up the child's args. If not tracing it, they are
3562 // simply ARG4. Otherwise, they are
3564 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3566 // except that the first VG_(args_for_valgrind_noexecpass) args
3567 // are omitted.
3569 if (!trace_this_child) {
3570 argv = (HChar**)ARG4;
3571 } else {
3572 vg_assert( VG_(args_for_valgrind) );
3573 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3574 vg_assert( VG_(args_for_valgrind_noexecpass)
3575 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3576 /* how many args in total will there be? */
3577 // launcher basename
3578 tot_args = 1;
3579 // V's args
3580 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3581 tot_args -= VG_(args_for_valgrind_noexecpass);
3582 // name of client exe
3583 tot_args++;
3584 // args for client exe, skipping [0]
3585 arg2copy = (HChar**)ARG4;
3586 if (arg2copy && arg2copy[0]) {
3587 for (i = 1; arg2copy[i]; i++)
3588 tot_args++;
3590 // allocate
3591 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3592 (tot_args+1) * sizeof(HChar*) );
3593 // copy
3594 j = 0;
3595 argv[j++] = launcher_basename;
3596 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3597 if (i < VG_(args_for_valgrind_noexecpass))
3598 continue;
3599 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3601 argv[j++] = (HChar*)ARG2;
3602 if (arg2copy && arg2copy[0])
3603 for (i = 1; arg2copy[i]; i++)
3604 argv[j++] = arg2copy[i];
3605 argv[j++] = NULL;
3606 // check
3607 vg_assert(j == tot_args+1);
3610 /* DDD: sort out the signal state. What signal
3611 state does the child inherit from the parent? */
3613 if (0) {
3614 HChar **cpp;
3615 VG_(printf)("posix_spawn: %s\n", path);
3616 for (cpp = argv; cpp && *cpp; cpp++)
3617 VG_(printf)("argv: %s\n", *cpp);
3618 if (1)
3619 for (cpp = envp; cpp && *cpp; cpp++)
3620 VG_(printf)("env: %s\n", *cpp);
3623 /* Let the call go through as usual. However, we have to poke
3624 the altered arguments back into the argument slots. */
3625 ARG2 = (UWord)path;
3626 ARG4 = (UWord)argv;
3627 ARG5 = (UWord)envp;
3629 /* not to mention .. */
3630 *flags |= SfMayBlock;
3632 POST(posix_spawn)
3634 vg_assert(SUCCESS);
3635 if (ARG1 != 0) {
3636 POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3641 PRE(socket)
3643 PRINT("socket ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
3644 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3647 POST(socket)
3649 SysRes r;
3650 vg_assert(SUCCESS);
3651 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3652 SET_STATUS_from_SysRes(r);
3656 PRE(setsockopt)
3658 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3659 SARG1, SARG2, SARG3, ARG4, SARG5);
3660 PRE_REG_READ5(long, "setsockopt",
3661 int, s, int, level, int, optname,
3662 const void *, optval, vki_socklen_t, optlen);
3663 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3667 PRE(getsockopt)
3669 Addr optval_p = ARG4;
3670 Addr optlen_p = ARG5;
3671 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3672 SARG1, SARG2, SARG3, ARG4, ARG5);
3673 PRE_REG_READ5(long, "getsockopt",
3674 int, s, int, level, int, optname,
3675 void *, optval, vki_socklen_t *, optlen);
3676 /* int getsockopt(int socket, int level, int option_name,
3677 void *restrict option_value,
3678 socklen_t *restrict option_len); */
3679 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3680 if (optval_p != (Addr)NULL) {
3681 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3682 "socketcall.getsockopt(optval)",
3683 "socketcall.getsockopt(optlen)" );
3685 // DDD: #warning GrP fixme darwin-specific sockopts
3688 POST(getsockopt)
3690 Addr optval_p = ARG4;
3691 Addr optlen_p = ARG5;
3692 vg_assert(SUCCESS);
3693 if (optval_p != (Addr)NULL) {
3694 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3695 optval_p, optlen_p,
3696 "socketcall.getsockopt(optlen_out)" );
3697 // DDD: #warning GrP fixme darwin-specific sockopts
3702 PRE(connect)
3704 *flags |= SfMayBlock;
3705 PRINT("connect ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3706 PRE_REG_READ3(long, "connect",
3707 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3708 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3712 PRE(accept)
3714 *flags |= SfMayBlock;
3715 PRINT("accept ( %ld, %#lx, %#lx )", SARG1, ARG2, SARG3);
3716 PRE_REG_READ3(long, "accept",
3717 int, s, struct sockaddr *, addr, int *, addrlen);
3718 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3721 POST(accept)
3723 SysRes r;
3724 vg_assert(SUCCESS);
3725 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3726 ARG1,ARG2,ARG3);
3727 SET_STATUS_from_SysRes(r);
3730 PRE(mkfifo)
3732 *flags |= SfMayBlock;
3733 PRINT("mkfifo ( %#lx(%s), %lx )", ARG1, (HChar *)ARG1, ARG2);
3734 PRE_REG_READ2(long, "mkfifo", const char *, path, vki_mode_t, mode);
3735 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1 );
3738 POST(mkfifo)
3740 vg_assert(SUCCESS);
3741 if (!ML_(fd_allowed)(RES, "mkfifo", tid, True)) {
3742 VG_(close)(RES);
3743 SET_STATUS_Failure( VKI_EMFILE );
3744 } else {
3745 if (VG_(clo_track_fds))
3746 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3750 PRE(sendto)
3752 *flags |= SfMayBlock;
3753 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3754 SARG1, (HChar *)ARG2, SARG3, ARG4, ARG5, SARG6);
3755 PRE_REG_READ6(long, "sendto",
3756 int, s, const void *, msg, int, len,
3757 unsigned int, flags,
3758 const struct sockaddr *, to, int, tolen);
3759 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3762 PRE(sendfile)
3764 #if VG_WORDSIZE == 4
3765 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3766 SARG1, SARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, SARG7);
3768 PRE_REG_READ7(long, "sendfile",
3769 int, fromfd, int, tofd,
3770 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3771 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3772 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3773 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3774 #else
3775 PRINT("sendfile(%ld, %ld, %lu, %#lx, %#lx, %ld)",
3776 SARG1, SARG2, ARG3, ARG4, ARG5, SARG6);
3778 PRE_REG_READ6(long, "sendfile",
3779 int, fromfd, int, tofd,
3780 vki_uint64_t, offset,
3781 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3782 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3783 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3784 #endif
3786 *flags |= SfMayBlock;
3788 POST(sendfile)
3790 #if VG_WORDSIZE == 4
3791 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3792 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3793 #else
3794 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3795 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3796 #endif
3799 PRE(recvfrom)
3801 *flags |= SfMayBlock;
3802 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3803 SARG1, ARG2, SARG3, ARG4, ARG5, ARG6);
3804 PRE_REG_READ6(long, "recvfrom",
3805 int, s, void *, buf, int, len, unsigned int, flags,
3806 struct sockaddr *, from, int *, fromlen);
3807 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3810 POST(recvfrom)
3812 vg_assert(SUCCESS);
3813 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3814 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3818 PRE(sendmsg)
3820 *flags |= SfMayBlock;
3821 PRINT("sendmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3822 PRE_REG_READ3(long, "sendmsg",
3823 int, s, const struct msghdr *, msg, int, flags);
3824 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3828 PRE(recvmsg)
3830 *flags |= SfMayBlock;
3831 PRINT("recvmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3832 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3833 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3836 POST(recvmsg)
3838 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3842 PRE(shutdown)
3844 *flags |= SfMayBlock;
3845 PRINT("shutdown ( %ld, %ld )", SARG1, SARG2);
3846 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3850 PRE(bind)
3852 PRINT("bind ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3853 PRE_REG_READ3(long, "bind",
3854 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3855 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3859 PRE(listen)
3861 PRINT("listen ( %ld, %ld )", SARG1, SARG2);
3862 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3866 PRE(getsockname)
3868 PRINT("getsockname ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3869 PRE_REG_READ3(long, "getsockname",
3870 int, s, struct sockaddr *, name, int *, namelen);
3871 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3874 POST(getsockname)
3876 vg_assert(SUCCESS);
3877 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3878 ARG1,ARG2,ARG3);
3882 PRE(getpeername)
3884 PRINT("getpeername ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3885 PRE_REG_READ3(long, "getpeername",
3886 int, s, struct sockaddr *, name, int *, namelen);
3887 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3890 POST(getpeername)
3892 vg_assert(SUCCESS);
3893 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3894 ARG1,ARG2,ARG3);
3898 PRE(socketpair)
3900 PRINT("socketpair ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
3901 PRE_REG_READ4(long, "socketpair",
3902 int, d, int, type, int, protocol, int *, sv);
3903 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3906 POST(socketpair)
3908 vg_assert(SUCCESS);
3909 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3910 ARG1,ARG2,ARG3,ARG4);
3914 PRE(gethostuuid)
3916 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3917 PRE_REG_READ2(int,"gethostuuid",
3918 char *,"uuid_buf",
3919 const struct vki_timespec *,"timeout");
3921 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3922 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3924 *flags |= SfMayBlock;
3928 POST(gethostuuid)
3930 POST_MEM_WRITE(ARG1, 16);
3933 /* Darwin pipe() returns the two descriptors in two registers. */
3934 PRE(pipe)
3936 PRINT("pipe ( )");
3937 PRE_REG_READ0(int, "pipe");
3940 POST(pipe)
3942 Int p0, p1;
3943 vg_assert(SUCCESS);
3944 p0 = RES;
3945 p1 = RESHI;
3947 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3948 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3949 VG_(close)(p0);
3950 VG_(close)(p1);
3951 SET_STATUS_Failure( VKI_EMFILE );
3952 } else {
3953 if (VG_(clo_track_fds)) {
3954 ML_(record_fd_open_nameless)(tid, p0);
3955 ML_(record_fd_open_nameless)(tid, p1);
3961 PRE(getlogin)
3963 PRINT("getlogin ( %#lx, %lu )", ARG1, ARG2);
3964 PRE_REG_READ2(long, "getlogin",
3965 char *,"namebuf", unsigned int,"namelen");
3967 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3970 POST(getlogin)
3972 POST_MEM_WRITE(ARG1, ARG2);
3976 PRE(ptrace)
3978 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
3979 PRE_REG_READ4(long, "ptrace",
3980 int,"request", vki_pid_t,"pid",
3981 vki_caddr_t,"addr", int,"data");
3983 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3985 // GrP fixme anything needed?
3989 PRE(issetugid)
3991 PRINT("issetugid ( )");
3992 PRE_REG_READ0(long, "issetugid");
3996 PRE(getdtablesize)
3998 PRINT("getdtablesize ( )");
3999 PRE_REG_READ0(long, "getdtablesize");
4002 POST(getdtablesize)
4004 // Subtract Valgrind's fd range from client's dtable
4005 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
4008 PRE(lseek)
4010 PRINT("lseek ( %lu, %ld, %ld )", ARG1, SARG2, SARG3);
4011 PRE_REG_READ4(vki_off_t, "lseek",
4012 unsigned int,fd, int,offset_hi, int,offset_lo,
4013 unsigned int,whence);
4017 PRE(pathconf)
4019 PRINT("pathconf(%#lx(%s), %ld)", ARG1, (HChar *)ARG1, SARG2);
4020 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
4021 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
4025 PRE(fpathconf)
4027 PRINT("fpathconf(%ld, %ld)", SARG1, SARG2);
4028 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
4030 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
4031 SET_STATUS_Failure( VKI_EBADF );
4035 PRE(getdirentries)
4037 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", SARG1, ARG2, SARG3, ARG4);
4038 PRE_REG_READ4(int, "getdirentries",
4039 int, fd, char *, buf, int, nbytes, long *, basep);
4040 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
4041 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
4044 POST(getdirentries)
4046 POST_MEM_WRITE(ARG4, sizeof(long));
4047 // GrP fixme be specific about d_name?
4048 POST_MEM_WRITE(ARG2, RES);
4052 PRE(getdirentries64)
4054 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", SARG1, ARG2, ARG3, ARG4);
4055 PRE_REG_READ4(vki_ssize_t, "getdirentries",
4056 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
4057 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
4058 to valid memory and the kernel doesn't modify it. I can't
4059 determine the conditions under which that happens. But it
4060 causes Memcheck to complain, confusingly. So disable this check
4061 for the time being.
4063 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
4065 PRE_MEM_WRITE("getdirentries64(buf)", ARG2, ARG3);
4067 POST(getdirentries64)
4069 /* Disabled; see comments in the PRE wrapper.
4070 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
4072 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
4073 POST_MEM_WRITE(ARG2, RES);
4077 PRE(statfs64)
4079 PRINT("statfs64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
4080 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
4081 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4082 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4084 POST(statfs64)
4086 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4090 PRE(fstatfs64)
4092 PRINT("fstatfs64 ( %lu, %#lx )", ARG1, ARG2);
4093 PRE_REG_READ2(long, "fstatfs64",
4094 unsigned int, fd, struct statfs *, buf);
4095 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4097 POST(fstatfs64)
4099 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4102 PRE(csops)
4104 PRINT("csops ( %ld, %#lx, %#lx, %lu )", SARG1, ARG2, ARG3, ARG4);
4105 PRE_REG_READ4(int, "csops",
4106 vki_pid_t, pid, uint32_t, ops,
4107 void *, useraddr, vki_size_t, usersize);
4109 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
4111 // If the pid is ours, don't mark the program as KILL or HARD
4112 // Maybe we should keep track of this for later calls to STATUS
4113 if (!ARG1 || VG_(getpid)() == ARG1) {
4114 switch (ARG2) {
4115 case VKI_CS_OPS_MARKINVALID:
4116 case VKI_CS_OPS_MARKHARD:
4117 case VKI_CS_OPS_MARKKILL:
4118 SET_STATUS_Success(0);
4122 POST(csops)
4124 POST_MEM_WRITE( ARG3, ARG4 );
4127 PRE(auditon)
4129 PRINT("auditon ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
4130 PRE_REG_READ3(int,"auditon",
4131 int,"cmd", void*,"data", unsigned int,"length");
4133 switch (ARG1) {
4135 case VKI_A_SETPOLICY:
4136 case VKI_A_SETKMASK:
4137 case VKI_A_SETQCTRL:
4138 case VKI_A_SETCOND:
4139 case VKI_A_SETCLASS:
4140 case VKI_A_SETPMASK:
4141 case VKI_A_SETFSIZE:
4142 #if DARWIN_VERS >= DARWIN_10_6
4143 case VKI_A_SENDTRIGGER:
4144 #endif
4145 // kernel reads data..data+length
4146 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4147 break;
4149 case VKI_A_GETKMASK:
4150 case VKI_A_GETPOLICY:
4151 case VKI_A_GETQCTRL:
4152 case VKI_A_GETFSIZE:
4153 case VKI_A_GETCOND:
4154 // kernel writes data..data+length
4155 // GrP fixme be precise about what gets written
4156 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4157 break;
4160 case VKI_A_GETCLASS:
4161 case VKI_A_GETPINFO:
4162 case VKI_A_GETPINFO_ADDR:
4163 #if DARWIN_VERS >= DARWIN_10_6
4164 case VKI_A_GETSINFO_ADDR:
4165 #endif
4166 // kernel reads and writes data..data+length
4167 // GrP fixme be precise about what gets read and written
4168 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4169 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4170 break;
4172 case VKI_A_SETKAUDIT:
4173 case VKI_A_SETSTAT:
4174 case VKI_A_SETUMASK:
4175 case VKI_A_SETSMASK:
4176 case VKI_A_GETKAUDIT:
4177 case VKI_A_GETCWD:
4178 case VKI_A_GETCAR:
4179 case VKI_A_GETSTAT:
4180 // unimplemented on darwin
4181 break;
4183 default:
4184 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld\n", ARG1);
4185 break;
4188 POST(auditon)
4190 switch (ARG1) {
4192 case VKI_A_SETPOLICY:
4193 case VKI_A_SETKMASK:
4194 case VKI_A_SETQCTRL:
4195 case VKI_A_SETCOND:
4196 case VKI_A_SETCLASS:
4197 case VKI_A_SETPMASK:
4198 case VKI_A_SETFSIZE:
4199 #if DARWIN_VERS >= DARWIN_10_6
4200 case VKI_A_SENDTRIGGER:
4201 #endif
4202 // kernel reads data..data+length
4203 break;
4205 case VKI_A_GETKMASK:
4206 case VKI_A_GETPOLICY:
4207 case VKI_A_GETQCTRL:
4208 case VKI_A_GETFSIZE:
4209 case VKI_A_GETCOND:
4210 // kernel writes data..data+length
4211 // GrP fixme be precise about what gets written
4212 POST_MEM_WRITE(ARG2, ARG3);
4213 break;
4216 case VKI_A_GETCLASS:
4217 case VKI_A_GETPINFO:
4218 case VKI_A_GETPINFO_ADDR:
4219 #if DARWIN_VERS >= DARWIN_10_6
4220 case VKI_A_GETSINFO_ADDR:
4221 #endif
4222 // kernel reads and writes data..data+length
4223 // GrP fixme be precise about what gets read and written
4224 POST_MEM_WRITE(ARG2, ARG3);
4225 break;
4227 case VKI_A_SETKAUDIT:
4228 case VKI_A_SETSTAT:
4229 case VKI_A_SETUMASK:
4230 case VKI_A_SETSMASK:
4231 case VKI_A_GETKAUDIT:
4232 case VKI_A_GETCWD:
4233 case VKI_A_GETCAR:
4234 case VKI_A_GETSTAT:
4235 // unimplemented on darwin
4236 break;
4238 default:
4239 break;
4243 PRE(getaudit_addr)
4245 PRINT("getaudit_addr(%#lx, %ld)", ARG1, SARG2);
4246 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
4247 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
4249 POST(getaudit_addr)
4251 POST_MEM_WRITE(ARG1, ARG2);
4255 PRE(mmap)
4257 // SysRes r;
4258 if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
4260 #if VG_WORDSIZE == 4
4261 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %llu )",
4262 ARG1, ARG2, SARG3, SARG4, SARG5, LOHI64(ARG6, ARG7) );
4263 PRE_REG_READ7(Addr, "mmap",
4264 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4265 unsigned long,offset_hi, unsigned long,offset_lo);
4266 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4267 // V's mechanism for now
4268 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4269 // (Off64T)LOHI64(ARG6, ARG7) );
4270 #else
4271 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4272 ARG1, ARG2, SARG3, SARG4, SARG5, SARG6 );
4273 PRE_REG_READ6(long, "mmap",
4274 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4275 Off64T,offset);
4276 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4278 #endif
4280 // SET_STATUS_from_SysRes(r);
4283 POST(mmap)
4285 if (RES != -1) {
4286 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
4287 // Try to load symbols from the region
4288 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
4289 -1/*don't use_fd*/ );
4290 ML_(sync_mappings)("after", "mmap", 0);
4295 /* This function holds common elements of PRE(__sysctl) and
4296 PRE(sysctlbyname). */
4297 static void common_PRE_sysctl (
4298 /*IMPLICIT ARGS*/
4299 ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
4300 /*!IMPLICIT ARGS*/
4301 Bool is_kern_dot_userstack,
4302 UWord oldp, UWord oldlenp,
4303 UWord newp, UWord newlen )
4305 if (oldlenp) {
4306 // writes *oldlenp
4307 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4308 if (oldp) {
4309 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4310 PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4311 PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
4314 if (newp) {
4315 PRE_MEM_READ("sysctl(newp)", newp, newlen);
4318 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4319 // (executable path and arguments and environment
4321 if (is_kern_dot_userstack) {
4322 // Intercept sysctl(kern.usrstack). The kernel's reply
4323 // would be Valgrind's stack, not the client's stack.
4324 // GrP fixme kern_usrstack64 */
4325 if (newp || newlen) {
4326 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
4327 } else {
4328 Addr* t_oldp = (Addr*)oldp;
4329 size_t* t_oldlenp = (size_t*)oldlenp;
4330 if (t_oldlenp) {
4331 // According to some searches on the net, it looks like
4332 // USRSTACK gives the address of the byte following the
4333 // highest byte of the stack. As VG_(clstk_end) is the
4334 // address of the highest addressable byte, we add 1.
4335 Addr stack_end = VG_(clstk_end)+1;
4336 size_t oldlen = *t_oldlenp;
4337 // always return actual size
4338 *t_oldlenp = sizeof(Addr);
4339 if (t_oldp && oldlen >= sizeof(Addr)) {
4340 // oldp is big enough. copy value and return 0
4341 *t_oldp = stack_end;
4342 SET_STATUS_Success(0);
4343 } else {
4344 // oldp isn't big enough. copy as much as possible
4345 // and return ENOMEM
4346 if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
4347 SET_STATUS_Failure(VKI_ENOMEM);
4353 if (!SUCCESS && !FAILURE) {
4354 // Don't set SfPostOnFail if we've already handled it locally.
4355 *flags |= SfPostOnFail;
4360 PRE(__sysctl)
4362 UWord name = ARG1;
4363 UWord namelen = ARG2;
4364 UWord oldp = ARG3;
4365 UWord oldlenp = ARG4;
4366 UWord newp = ARG5;
4367 UWord newlen = ARG6;
4369 PRINT( "__sysctl ( %#lx, %lu, %#lx, %#lx, %#lx, %#lx )",
4370 name, namelen, oldp, oldlenp, newp, newlen );
4372 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
4373 void*, oldp, vki_size_t *, oldlenp,
4374 void*, newp, vki_size_t *, newlenp);
4376 PRE_MEM_READ("sysctl(name)", name, namelen); // reads name[0..namelen-1]
4378 if (VG_(clo_trace_syscalls)) {
4379 UInt i;
4380 Int* t_name = (Int*)name;
4381 VG_(printf)(" mib: [ ");
4382 for (i = 0; i < namelen; i++) {
4383 VG_(printf)("%d ", t_name[i]);
4385 VG_(printf)("]");
4388 Int vKI_KERN_USRSTACKXX
4389 = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64;
4390 Bool is_kern_dot_userstack
4391 = name && namelen == 2
4392 && ((Int*)name)[0] == VKI_CTL_KERN
4393 && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
4395 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
4396 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
4399 POST(__sysctl)
4401 UWord oldp = ARG3;
4402 UWord oldlenp = ARG4;
4404 if (SUCCESS || ERR == VKI_ENOMEM) {
4405 // sysctl can write truncated data and return VKI_ENOMEM
4406 if (oldlenp) {
4407 POST_MEM_WRITE(oldlenp, sizeof(size_t));
4409 if (oldp && oldlenp) {
4410 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
4416 PRE(sigpending)
4418 PRINT( "sigpending ( %#lx )", ARG1 );
4419 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
4420 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
4422 POST(sigpending)
4424 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
4428 PRE(sigprocmask)
4430 UWord arg1;
4431 PRINT("sigprocmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
4432 PRE_REG_READ3(long, "sigprocmask",
4433 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
4434 if (ARG2 != 0)
4435 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4436 if (ARG3 != 0)
4437 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
4439 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4440 value of 'how' is irrelevant, and it appears that Darwin's libc
4441 passes zero, which is not equal to any of
4442 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4443 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4444 value independently of the other args. Solution: in this case,
4445 simply pass a valid (but irrelevant) value for 'how'. */
4446 /* Also, in this case the new set is passed to the kernel by
4447 reference, not value, as in some other sigmask related Darwin
4448 syscalls. */
4449 arg1 = ARG1;
4450 if (ARG2 == 0 /* the new-set is NULL */
4451 && ARG1 != VKI_SIG_BLOCK
4452 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
4453 arg1 = VKI_SIG_SETMASK;
4455 SET_STATUS_from_SysRes(
4456 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
4457 (vki_sigset_t*)ARG3 )
4460 if (SUCCESS)
4461 *flags |= SfPollAfter;
4464 POST(sigprocmask)
4466 vg_assert(SUCCESS);
4467 if (RES == 0 && ARG3 != 0)
4468 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
4472 PRE(sigsuspend)
4474 /* Just hand this off to the kernel. Is that really correct? And
4475 shouldn't we at least set SfPollAfter? These questions apply to
4476 all the Linux versions too. */
4477 /* I think the first arg is the 32-bit signal mask (by value), and
4478 the other two args are ignored. */
4479 *flags |= SfMayBlock;
4480 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
4481 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
4485 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4486 and 32-bit wrappers are different.
4488 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4489 length in the usual way. I have seen values NULL, 0 passed in some
4490 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4491 basis that they don't do anything if the length is zero, so it's OK
4492 for the buffer pointer to be NULL in that case (meaning they don't
4493 complain).
4495 int proc_info(int32_t callnum, int32_t pid,
4496 uint32_t flavor, uint64_t arg,
4497 user_addr_t buffer, int32_t buffersize)
4499 PRE(proc_info)
4501 #if VG_WORDSIZE == 4
4502 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4503 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
4504 PRE_REG_READ7(int, "proc_info",
4505 int, callnum, int, pid, unsigned int, flavor,
4506 vki_uint32_t, arg_low32,
4507 vki_uint32_t, arg_high32,
4508 void*, buffer, int, buffersize);
4509 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
4510 #else
4511 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4512 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
4513 PRE_REG_READ6(int, "proc_info",
4514 int, callnum, int, pid, unsigned int, flavor,
4515 unsigned long long int, arg,
4516 void*, buffer, int, buffersize);
4517 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
4518 #endif
4521 POST(proc_info)
4523 #if VG_WORDSIZE == 4
4524 vg_assert(SUCCESS);
4526 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4527 if (ARG1 == 5 && ARG3 == 2 && LOHI64(ARG4,ARG5) == 0 )
4529 const HChar* new_name = (const HChar*) ARG6;
4530 if (new_name) { // Paranoia
4531 ThreadState* tst = VG_(get_ThreadState)(tid);
4532 SizeT new_len = VG_(strlen)(new_name);
4534 /* Don't bother reusing the memory. This is a rare event. */
4535 tst->thread_name =
4536 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4537 VG_(strcpy)(tst->thread_name, new_name);
4541 POST_MEM_WRITE(ARG6, ARG7);
4542 #else
4543 vg_assert(SUCCESS);
4545 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4546 if (ARG1 == 5 && ARG3 == 2 && ARG4 == 0 )
4548 const HChar* new_name = (const HChar*) ARG5;
4549 if (new_name) { // Paranoia
4550 ThreadState* tst = VG_(get_ThreadState)(tid);
4551 SizeT new_len = VG_(strlen)(new_name);
4553 /* Don't bother reusing the memory. This is a rare event. */
4554 tst->thread_name =
4555 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4556 VG_(strcpy)(tst->thread_name, new_name);
4560 POST_MEM_WRITE(ARG5, ARG6);
4561 #endif
4565 /* ---------------------------------------------------------------------
4566 aio_*
4567 ------------------------------------------------------------------ */
4569 // We must record the aiocbp for each aio_read() in a table so that when
4570 // aio_return() is called we can mark the memory written asynchronously by
4571 // aio_read() as having been written. We don't have to do this for
4572 // aio_write(). See bug 197227 for more details.
4573 static OSet* aiocbp_table = NULL;
4574 static Bool aio_init_done = False;
4576 static void aio_init(void)
4578 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
4579 aio_init_done = True;
4582 static Bool was_a_successful_aio_read = False;
4584 PRE(aio_return)
4586 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4587 // This assumes that the kernel looks at the struct pointer, but not the
4588 // contents of the struct.
4589 PRINT( "aio_return ( %#lx )", ARG1 );
4590 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
4592 if (!aio_init_done) aio_init();
4593 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
4595 POST(aio_return)
4597 // If we found the aiocbp in our own table it must have been an aio_read(),
4598 // so mark the buffer as written. If we didn't find it, it must have been
4599 // an aio_write() or a bogus aio_return() (eg. a second one on the same
4600 // aiocbp). Either way, the buffer won't have been written so we don't
4601 // have to mark the buffer as written.
4602 if (was_a_successful_aio_read) {
4603 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4604 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4605 was_a_successful_aio_read = False;
4609 PRE(aio_suspend)
4611 // This assumes that the kernel looks at the struct pointers in the list,
4612 // but not the contents of the structs.
4613 PRINT( "aio_suspend ( %#lx )", ARG1 );
4614 PRE_REG_READ3(long, "aio_suspend",
4615 const struct vki_aiocb *, aiocbp, int, nent,
4616 const struct vki_timespec *, timeout);
4617 if (ARG2 > 0)
4618 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
4619 if (ARG3)
4620 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
4623 PRE(aio_error)
4625 // This assumes that the kernel looks at the struct pointer, but not the
4626 // contents of the struct.
4627 PRINT( "aio_error ( %#lx )", ARG1 );
4628 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
4631 PRE(aio_read)
4633 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4635 PRINT( "aio_read ( %#lx )", ARG1 );
4636 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4637 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4639 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4640 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4641 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4642 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4643 } else {
4644 SET_STATUS_Failure( VKI_EBADF );
4646 } else {
4647 SET_STATUS_Failure( VKI_EINVAL );
4650 POST(aio_read)
4652 // We have to record the fact that there is an asynchronous read request
4653 // pending. When a successful aio_return() occurs for this aiocb, then we
4654 // will mark the memory as having been defined.
4655 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4656 if (!aio_init_done) aio_init();
4657 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4658 // should have caused the aio_read() to fail and we shouldn't have reached
4659 // here.
4660 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4663 PRE(aio_write)
4665 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4667 PRINT( "aio_write ( %#lx )", ARG1 );
4668 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4669 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4671 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4672 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4673 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4674 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4675 } else {
4676 SET_STATUS_Failure( VKI_EBADF );
4678 } else {
4679 SET_STATUS_Failure( VKI_EINVAL );
4683 /* ---------------------------------------------------------------------
4684 mach_msg: formatted messages
4685 ------------------------------------------------------------------ */
4687 static size_t desc_size(mach_msg_descriptor_t *desc)
4689 switch (desc->type.type) {
4690 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
4691 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
4692 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
4693 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
4694 default:
4695 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4696 return sizeof(desc->type); // guess
4701 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4702 const char *name)
4704 mach_msg_size_t i;
4705 mach_port_t *ports = (mach_port_t *)desc->address;
4706 for (i = 0; i < desc->count; i++) {
4707 assign_port_name(ports[i], name);
4712 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4714 mach_msg_body_t *body;
4715 mach_msg_size_t count, i;
4716 uint8_t *p;
4717 mach_msg_descriptor_t *desc;
4719 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4721 body = (mach_msg_body_t *)(mh+1);
4722 count = body->msgh_descriptor_count;
4723 p = (uint8_t *)(body+1);
4725 for (i = 0; i < count; i++) {
4726 desc = (mach_msg_descriptor_t *)p;
4727 p += desc_size(desc);
4729 switch (desc->type.type) {
4730 case MACH_MSG_PORT_DESCRIPTOR:
4731 // single port
4732 record_unnamed_port(tid, desc->port.name, -1);
4733 record_port_insert_rights(desc->port.name, desc->port.disposition);
4734 PRINT("got port %s;\n", name_for_port(desc->port.name));
4735 break;
4737 case MACH_MSG_OOL_DESCRIPTOR:
4738 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4739 // out-of-line memory - map it
4740 // GrP fixme how is VOLATILE different? do we care?
4741 // GrP fixme do other flags tell us anything? assume shared for now
4742 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4743 // GrP fixme protection
4744 if (desc->out_of_line.size > 0) {
4745 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4746 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4747 (Addr)desc->out_of_line.size);
4748 PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4749 (char*)desc->out_of_line.address+desc->out_of_line.size);
4751 ML_(notify_core_and_tool_of_mmap)(
4752 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4753 VKI_MAP_PRIVATE, -1, 0);
4755 // GrP fixme mark only un-rounded part as initialized
4756 break;
4758 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4759 // out-of-line array of ports - map it
4760 // GrP fixme see fixmes above
4761 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));
4763 if (desc->ool_ports.count > 0) {
4764 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4765 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4766 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4768 ML_(notify_core_and_tool_of_mmap)(
4769 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4770 VKI_MAP_PRIVATE, -1, 0);
4772 PRINT(":");
4773 for (i = 0; i < desc->ool_ports.count; i++) {
4774 record_unnamed_port(tid, ports[i], -1);
4775 record_port_insert_rights(ports[i], desc->port.disposition);
4776 PRINT(" %s", name_for_port(ports[i]));
4779 PRINT(";\n");
4780 break;
4782 default:
4783 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4784 break;
4790 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4792 #pragma pack(4)
4793 struct {
4794 mach_port_t name;
4795 mach_msg_size_t pad1;
4796 uint16_t pad2;
4797 uint8_t disposition;
4798 uint8_t type;
4799 } *desc = (void*)desc2;
4800 #pragma pack()
4802 PRE_FIELD_READ("msg->desc.port.name", desc->name);
4803 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4804 PRE_FIELD_READ("msg->desc.port.type", desc->type);
4808 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4810 #pragma pack(4)
4811 struct {
4812 Addr address;
4813 #if VG_WORDSIZE != 8
4814 mach_msg_size_t size;
4815 #endif
4816 uint8_t deallocate;
4817 uint8_t copy;
4818 uint8_t pad1;
4819 uint8_t type;
4820 #if VG_WORDSIZE == 8
4821 mach_msg_size_t size;
4822 #endif
4823 } *desc = (void*)desc2;
4824 #pragma pack()
4826 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4827 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4828 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4829 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4830 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4833 static void pre_oolports_desc_read(ThreadId tid,
4834 mach_msg_ool_ports_descriptor_t *desc2)
4836 #pragma pack(4)
4837 struct {
4838 Addr address;
4839 #if VG_WORDSIZE != 8
4840 mach_msg_size_t size;
4841 #endif
4842 uint8_t deallocate;
4843 uint8_t copy;
4844 uint8_t disposition;
4845 uint8_t type;
4846 #if VG_WORDSIZE == 8
4847 mach_msg_size_t size;
4848 #endif
4849 } *desc = (void*)desc2;
4850 #pragma pack()
4852 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4853 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4854 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4855 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4856 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4857 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4861 // Returns the size of the descriptor area
4862 // (mach_msg_body_t + any mach_msg_descriptor_t)
4863 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4865 mach_msg_body_t *body;
4866 mach_msg_size_t count, i;
4867 uint8_t *p;
4868 mach_msg_descriptor_t *desc;
4870 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4872 body = (mach_msg_body_t *)(mh+1);
4873 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4875 count = body->msgh_descriptor_count;
4876 p = (uint8_t *)(body+1);
4878 for (i = 0; i < count; i++) {
4879 desc = (mach_msg_descriptor_t *)p;
4880 p += desc_size(desc);
4882 switch (desc->type.type) {
4883 case MACH_MSG_PORT_DESCRIPTOR:
4884 // single port; no memory map effects
4885 pre_port_desc_read(tid, &desc->port);
4886 break;
4888 case MACH_MSG_OOL_DESCRIPTOR:
4889 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4890 // out-of-line memory - unmap it if it's marked dealloc
4891 // GrP fixme need to remap if message fails?
4892 // GrP fixme how is VOLATILE different? do we care?
4893 // GrP fixme struct is different for lp64
4894 pre_ool_desc_read(tid, &desc->out_of_line);
4896 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4897 vm_size_t size = desc->out_of_line.size;
4898 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4899 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4900 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4901 (Addr)desc->out_of_line.address + size);
4902 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4904 break;
4906 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4907 // out-of-line array of ports - unmap it if it's marked dealloc
4908 // GrP fixme need to remap if message fails?
4909 // GrP fixme struct different for lp64
4910 pre_oolports_desc_read(tid, &desc->ool_ports);
4912 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4913 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4914 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4915 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4916 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4917 (Addr)desc->ool_ports.address + size);
4918 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4920 break;
4921 default:
4922 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4923 break;
4927 return (size_t)((Addr)p - (Addr)body);
4931 /* ---------------------------------------------------------------------
4932 mach_msg: host-related messages
4933 ------------------------------------------------------------------ */
4936 POST(host_info)
4938 #pragma pack(4)
4939 typedef struct {
4940 mach_msg_header_t Head;
4941 NDR_record_t NDR;
4942 kern_return_t RetCode;
4943 mach_msg_type_number_t host_info_outCnt;
4944 integer_t host_info_out[14];
4945 } Reply;
4946 #pragma pack()
4948 Reply *reply = (Reply *)ARG1;
4950 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4953 PRE(host_info)
4955 #pragma pack(4)
4956 typedef struct {
4957 mach_msg_header_t Head;
4958 NDR_record_t NDR;
4959 host_flavor_t flavor;
4960 mach_msg_type_number_t host_info_outCnt;
4961 } Request;
4962 #pragma pack()
4964 Request *req = (Request *)ARG1;
4966 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4968 AFTER = POST_FN(host_info);
4972 POST(host_page_size)
4974 #pragma pack(4)
4975 typedef struct {
4976 mach_msg_header_t Head;
4977 NDR_record_t NDR;
4978 kern_return_t RetCode;
4979 vm_size_t out_page_size;
4980 } Reply;
4981 #pragma pack()
4983 Reply *reply = (Reply *)ARG1;
4985 if (!reply->RetCode) {
4986 PRINT("page size %llu", (ULong)reply->out_page_size);
4987 } else {
4988 PRINT("mig return %d", reply->RetCode);
4992 PRE(host_page_size)
4994 PRINT("host_page_size(mach_host_self(), ...)");
4996 AFTER = POST_FN(host_page_size);
5000 POST(host_get_io_master)
5002 #pragma pack(4)
5003 typedef struct {
5004 mach_msg_header_t Head;
5005 /* start of the kernel processed data */
5006 mach_msg_body_t msgh_body;
5007 mach_msg_port_descriptor_t io_master;
5008 /* end of the kernel processed data */
5009 } Reply;
5010 #pragma pack()
5012 Reply *reply = (Reply *)ARG1;
5014 assign_port_name(reply->io_master.name, "io_master-%p");
5015 PRINT("%s", name_for_port(reply->io_master.name));
5018 PRE(host_get_io_master)
5020 #pragma pack(4)
5021 typedef struct {
5022 mach_msg_header_t Head;
5023 } Request;
5024 #pragma pack()
5026 // Request *req = (Request *)ARG1;
5028 PRINT("host_get_io_master(mach_host_self())");
5030 AFTER = POST_FN(host_get_io_master);
5034 POST(host_get_clock_service)
5036 #pragma pack(4)
5037 typedef struct {
5038 mach_msg_header_t Head;
5039 /* start of the kernel processed data */
5040 mach_msg_body_t msgh_body;
5041 mach_msg_port_descriptor_t clock_serv;
5042 /* end of the kernel processed data */
5043 } Reply;
5044 #pragma pack()
5046 Reply *reply = (Reply *)ARG1;
5048 assign_port_name(reply->clock_serv.name, "clock-%p");
5049 PRINT("%s", name_for_port(reply->clock_serv.name));
5052 PRE(host_get_clock_service)
5054 #pragma pack(4)
5055 typedef struct {
5056 mach_msg_header_t Head;
5057 NDR_record_t NDR;
5058 clock_id_t clock_id;
5059 } Request;
5060 #pragma pack()
5062 Request *req = (Request *)ARG1;
5064 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
5066 AFTER = POST_FN(host_get_clock_service);
5070 PRE(host_request_notification)
5072 #pragma pack(4)
5073 typedef struct {
5074 mach_msg_header_t Head;
5075 /* start of the kernel processed data */
5076 mach_msg_body_t msgh_body;
5077 mach_msg_port_descriptor_t notify_port;
5078 /* end of the kernel processed data */
5079 NDR_record_t NDR;
5080 host_flavor_t notify_type;
5081 } Request;
5082 #pragma pack()
5084 Request *req = (Request *)ARG1;
5086 if (MACH_REMOTE == mach_task_self()) {
5087 if (req->notify_type == 0) {
5088 PRINT("host_request_notification(mach_host_self(), %s, %s)",
5089 "HOST_NOTIFY_CALENDAR_CHANGE",
5090 name_for_port(req->notify_port.name));
5091 } else {
5092 PRINT("host_request_notification(mach_host_self(), %d, %s)",
5093 req->notify_type,
5094 name_for_port(req->notify_port.name));
5096 } else {
5097 PRINT("host_request_notification(%s, %d, %s)",
5098 name_for_port(MACH_REMOTE),
5099 req->notify_type,
5100 name_for_port(req->notify_port.name));
5103 // GrP fixme only do this on success
5104 assign_port_name(req->notify_port.name, "host_notify-%p");
5108 PRE(host_create_mach_voucher)
5110 #pragma pack(4)
5111 typedef struct {
5112 mach_msg_header_t Head;
5113 NDR_record_t NDR;
5114 mach_msg_type_number_t recipesCnt;
5115 uint8_t recipes[5120];
5116 } Request;
5117 #pragma pack()
5119 Request *req = (Request *)ARG1;
5121 PRINT("host_create_mach_voucher(count %u)",
5122 req->recipesCnt);
5124 AFTER = POST_FN(host_create_mach_voucher);
5128 POST(host_create_mach_voucher)
5130 #pragma pack(4)
5131 typedef struct {
5132 mach_msg_header_t Head;
5133 /* start of the kernel processed data */
5134 mach_msg_body_t msgh_body;
5135 mach_msg_port_descriptor_t voucher;
5136 /* end of the kernel processed data */
5137 } Reply;
5138 #pragma pack()
5140 Reply *reply = (Reply *)ARG1;
5142 // RK fixme properly parse this return type
5143 PRINT("got voucher %#x ", reply->voucher.name);
5147 PRE(host_get_special_port)
5149 #pragma pack(4)
5150 typedef struct {
5151 mach_msg_header_t Head;
5152 NDR_record_t NDR;
5153 int node;
5154 int which;
5155 } Request;
5156 #pragma pack()
5158 Request *req = (Request *)ARG1;
5160 PRINT("host_get_special_port(node %d)", req->node);
5162 switch (req->which) {
5163 case HOST_PORT:
5164 PRINT("host_get_special_port(%s, HOST_PORT)",
5165 name_for_port(MACH_REMOTE));
5166 break;
5167 case HOST_PRIV_PORT:
5168 PRINT("host_get_special_port(%s, HOST_PRIV_PORT)",
5169 name_for_port(MACH_REMOTE));
5170 break;
5171 case HOST_IO_MASTER_PORT:
5172 PRINT("host_get_special_port(%s, HOST_IO_MASTER_PORT)",
5173 name_for_port(MACH_REMOTE));
5174 break;
5175 // Not provided by kernel
5176 case HOST_DYNAMIC_PAGER_PORT:
5177 PRINT("host_get_special_port(%s, HOST_DYNAMIC_PAGER_PORT)",
5178 name_for_port(MACH_REMOTE));
5179 break;
5180 case HOST_AUDIT_CONTROL_PORT:
5181 PRINT("host_get_special_port(%s, HOST_AUDIT_CONTROL_PORT)",
5182 name_for_port(MACH_REMOTE));
5183 break;
5184 case HOST_USER_NOTIFICATION_PORT:
5185 PRINT("host_get_special_port(%s, HOST_USER_NOTIFICATION_PORT)",
5186 name_for_port(MACH_REMOTE));
5187 break;
5188 // ...
5190 default:
5191 PRINT("host_get_special_port(%s, %d)",
5192 name_for_port(MACH_REMOTE), req->which);
5193 break;
5196 MACH_ARG(host_get_special_port.which) = req->which;
5198 AFTER = POST_FN(host_get_special_port);
5202 POST(host_get_special_port)
5204 #pragma pack(4)
5205 typedef struct {
5206 mach_msg_header_t Head;
5207 /* start of the kernel processed data */
5208 mach_msg_body_t msgh_body;
5209 mach_msg_port_descriptor_t port;
5210 /* end of the kernel processed data */
5211 } Reply;
5212 #pragma pack()
5214 Reply *reply = (Reply *)ARG1;
5216 PRINT("got port %#x ", reply->port.name);
5218 /* The required entry in the allocated_ports list (mapping) might
5219 not exist, due perhaps to broken syscall wrappers (mach__N etc).
5220 Create a minimal entry so that assign_port_name below doesn't
5221 cause an assertion. */
5222 if (!port_exists(reply->port.name)) {
5223 port_create_vanilla(reply->port.name);
5226 switch (MACH_ARG(host_get_special_port.which)) {
5227 case HOST_PORT:
5228 assign_port_name(reply->port.name, "port-%p");
5229 break;
5230 case HOST_PRIV_PORT:
5231 assign_port_name(reply->port.name, "priv-%p");
5232 break;
5233 case HOST_IO_MASTER_PORT:
5234 assign_port_name(reply->port.name, "io-master-%p");
5235 break;
5236 // Not provided by kernel
5237 case HOST_DYNAMIC_PAGER_PORT:
5238 assign_port_name(reply->port.name, "dynamic-pager-%p");
5239 break;
5240 case HOST_AUDIT_CONTROL_PORT:
5241 assign_port_name(reply->port.name, "audit-control-%p");
5242 break;
5243 case HOST_USER_NOTIFICATION_PORT:
5244 assign_port_name(reply->port.name, "user-notification-%p");
5245 break;
5246 // ...
5248 default:
5249 assign_port_name(reply->port.name, "special-%p");
5250 break;
5253 PRINT("%s", name_for_port(reply->port.name));
5256 /* ---------------------------------------------------------------------
5257 mach_msg: messages to a task
5258 ------------------------------------------------------------------ */
5260 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
5261 // these structs are derived. They obviously relate to the various
5262 // .def files in the xnu sources, and can also be found in some
5263 // form in /usr/include/mach/*.h, but not sure how these all
5264 // relate to each other.
5266 PRE(mach_port_set_context)
5268 #pragma pack(4)
5269 typedef struct {
5270 mach_msg_header_t Head;
5271 NDR_record_t NDR;
5272 mach_port_name_t name;
5273 mach_vm_address_t context;
5274 } Request;
5275 #pragma pack()
5277 Request *req = (Request *)ARG1;
5279 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
5280 name_for_port(MACH_REMOTE),
5281 name_for_port(req->name), req->context);
5283 AFTER = POST_FN(mach_port_set_context);
5286 POST(mach_port_set_context)
5288 #pragma pack(4)
5289 typedef struct {
5290 mach_msg_header_t Head;
5291 NDR_record_t NDR;
5292 kern_return_t RetCode;
5293 } Reply;
5294 #pragma pack()
5298 // JRS 2011-Aug-25 FIXME completely bogus
5299 PRE(task_get_exception_ports)
5301 #pragma pack(4)
5302 typedef struct {
5303 mach_msg_header_t Head;
5304 NDR_record_t NDR;
5305 exception_mask_t exception_mask;
5306 } Request;
5307 #pragma pack()
5309 PRINT("task_get_exception_ports(BOGUS)");
5310 AFTER = POST_FN(task_get_exception_ports);
5313 POST(task_get_exception_ports)
5315 #pragma pack(4)
5316 typedef struct {
5317 mach_msg_header_t Head;
5318 /* start of the kernel processed data */
5319 mach_msg_body_t msgh_body;
5320 mach_msg_port_descriptor_t old_handlers[32];
5321 /* end of the kernel processed data */
5322 NDR_record_t NDR;
5323 mach_msg_type_number_t masksCnt;
5324 exception_mask_t masks[32];
5325 exception_behavior_t old_behaviors[32];
5326 thread_state_flavor_t old_flavors[32];
5327 } Reply;
5328 #pragma pack()
5332 ///////////////////////////////////////////////////
5334 PRE(mach_port_type)
5336 #pragma pack(4)
5337 typedef struct {
5338 mach_msg_header_t Head;
5339 NDR_record_t NDR;
5340 mach_port_name_t name;
5341 } Request;
5342 #pragma pack()
5344 Request *req = (Request *)ARG1;
5346 PRINT("mach_port_type(%s, %s, ...)",
5347 name_for_port(MACH_REMOTE), name_for_port(req->name));
5349 AFTER = POST_FN(mach_port_type);
5352 POST(mach_port_type)
5357 PRE(mach_port_extract_member)
5359 #pragma pack(4)
5360 typedef struct {
5361 mach_msg_header_t Head;
5362 NDR_record_t NDR;
5363 mach_port_name_t name;
5364 mach_port_name_t pset;
5365 } Request;
5366 #pragma pack()
5368 Request *req = (Request *)ARG1;
5370 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5371 name_for_port(MACH_REMOTE),
5372 req->name, req->pset);
5374 AFTER = POST_FN(mach_port_extract_member);
5376 // GrP fixme port tracker?
5379 POST(mach_port_extract_member)
5381 #pragma pack(4)
5382 typedef struct {
5383 mach_msg_header_t Head;
5384 NDR_record_t NDR;
5385 kern_return_t RetCode;
5386 } Reply;
5387 #pragma pack()
5389 Reply *reply = (Reply *)ARG1;
5391 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
5395 PRE(mach_port_allocate)
5397 #pragma pack(4)
5398 typedef struct {
5399 mach_msg_header_t Head;
5400 NDR_record_t NDR;
5401 mach_port_right_t right;
5402 } Request;
5403 #pragma pack()
5405 Request *req = (Request *)ARG1;
5407 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
5409 MACH_ARG(mach_port_allocate.right) = req->right;
5411 AFTER = POST_FN(mach_port_allocate);
5414 POST(mach_port_allocate)
5416 #pragma pack(4)
5417 typedef struct {
5418 mach_msg_header_t Head;
5419 NDR_record_t NDR;
5420 kern_return_t RetCode;
5421 mach_port_name_t name;
5422 } Reply;
5423 #pragma pack()
5425 Reply *reply = (Reply *)ARG1;
5427 if (!reply->RetCode) {
5428 if (MACH_REMOTE == vg_task_port) {
5429 // GrP fixme port tracking is too imprecise
5430 // vg_assert(!port_exists(reply->name));
5431 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
5432 PRINT("got port 0x%x", reply->name);
5433 } else {
5434 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
5436 } else {
5437 PRINT("mig return %d", reply->RetCode);
5442 PRE(mach_port_deallocate)
5444 #pragma pack(4)
5445 typedef struct {
5446 mach_msg_header_t Head;
5447 NDR_record_t NDR;
5448 mach_port_name_t name;
5449 } Request;
5450 #pragma pack()
5452 Request *req = (Request *)ARG1;
5454 PRINT("mach_port_deallocate(%s, %s)",
5455 name_for_port(MACH_REMOTE),
5456 name_for_port(req->name));
5458 MACH_ARG(mach_port.port) = req->name;
5460 AFTER = POST_FN(mach_port_deallocate);
5462 // Must block to prevent race (other thread allocates and
5463 // notifies after we deallocate but before we notify)
5464 *flags &= ~SfMayBlock;
5467 POST(mach_port_deallocate)
5469 #pragma pack(4)
5470 typedef struct {
5471 mach_msg_header_t Head;
5472 NDR_record_t NDR;
5473 kern_return_t RetCode;
5474 } Reply;
5475 #pragma pack()
5477 Reply *reply = (Reply *)ARG1;
5479 if (!reply->RetCode) {
5480 if (MACH_REMOTE == vg_task_port) {
5481 // Must have cleared SfMayBlock in PRE to prevent race
5482 record_port_dealloc(MACH_ARG(mach_port.port));
5483 } else {
5484 VG_(printf)("UNKNOWN remote port dealloc\n");
5486 } else {
5487 PRINT("mig return %d", reply->RetCode);
5492 PRE(mach_port_get_refs)
5494 #pragma pack(4)
5495 typedef struct {
5496 mach_msg_header_t Head;
5497 NDR_record_t NDR;
5498 mach_port_name_t name;
5499 mach_port_right_t right;
5500 } Request;
5501 #pragma pack()
5503 Request *req = (Request *)ARG1;
5505 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5506 name_for_port(MACH_REMOTE),
5507 name_for_port(req->name), req->right);
5509 MACH_ARG(mach_port_mod_refs.port) = req->name;
5510 MACH_ARG(mach_port_mod_refs.right) = req->right;
5512 AFTER = POST_FN(mach_port_get_refs);
5515 POST(mach_port_get_refs)
5517 #pragma pack(4)
5518 typedef struct {
5519 mach_msg_header_t Head;
5520 NDR_record_t NDR;
5521 kern_return_t RetCode;
5522 mach_port_urefs_t refs;
5523 } Reply;
5524 #pragma pack()
5526 Reply *reply = (Reply *)ARG1;
5528 if (!reply->RetCode) {
5529 PRINT("got refs=%d", reply->refs);
5530 } else {
5531 PRINT("mig return %d", reply->RetCode);
5536 PRE(mach_port_mod_refs)
5538 #pragma pack(4)
5539 typedef struct {
5540 mach_msg_header_t Head;
5541 NDR_record_t NDR;
5542 mach_port_name_t name;
5543 mach_port_right_t right;
5544 mach_port_delta_t delta;
5545 } Request;
5546 #pragma pack()
5548 Request *req = (Request *)ARG1;
5550 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5551 name_for_port(MACH_REMOTE),
5552 name_for_port(req->name), req->right, req->delta);
5554 MACH_ARG(mach_port_mod_refs.port) = req->name;
5555 MACH_ARG(mach_port_mod_refs.right) = req->right;
5556 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
5558 AFTER = POST_FN(mach_port_mod_refs);
5560 // Must block to prevent race (other thread allocates and
5561 // notifies after we deallocate but before we notify)
5562 *flags &= ~SfMayBlock;
5565 POST(mach_port_mod_refs)
5567 #pragma pack(4)
5568 typedef struct {
5569 mach_msg_header_t Head;
5570 NDR_record_t NDR;
5571 kern_return_t RetCode;
5572 } Reply;
5573 #pragma pack()
5575 Reply *reply = (Reply *)ARG1;
5577 if (!reply->RetCode) {
5578 if (MACH_REMOTE == vg_task_port) {
5579 // Must have cleared SfMayBlock in PRE to prevent race
5580 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
5581 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
5582 MACH_ARG(mach_port_mod_refs.delta));
5583 } else {
5584 VG_(printf)("UNKNOWN remote port mod refs\n");
5586 } else {
5587 PRINT("mig return %d", reply->RetCode);
5592 PRE(mach_port_get_set_status)
5594 #pragma pack(4)
5595 typedef struct {
5596 mach_msg_header_t Head;
5597 NDR_record_t NDR;
5598 mach_port_name_t name;
5599 } Request;
5600 #pragma pack()
5602 Request *req = (Request *)ARG1;
5604 PRINT("mach_port_get_set_status(%s, %s)",
5605 name_for_port(MACH_REMOTE),
5606 name_for_port(req->name));
5608 AFTER = POST_FN(mach_port_get_set_status);
5611 POST(mach_port_get_set_status)
5613 #pragma pack(4)
5614 typedef struct {
5615 mach_msg_header_t Head;
5616 /* start of the kernel processed data */
5617 mach_msg_body_t msgh_body;
5618 mach_msg_ool_descriptor_t members;
5619 /* end of the kernel processed data */
5620 NDR_record_t NDR;
5621 mach_msg_type_number_t membersCnt;
5622 mach_msg_trailer_t trailer;
5623 } Reply;
5624 #pragma pack()
5626 // Reply *reply = (Reply *)ARG1;
5628 // GrP fixme nothing to do?
5632 PRE(mach_port_move_member)
5634 #pragma pack(4)
5635 typedef struct {
5636 mach_msg_header_t Head;
5637 NDR_record_t NDR;
5638 mach_port_name_t member;
5639 mach_port_name_t after;
5640 } Request;
5641 #pragma pack()
5643 Request *req = (Request *)ARG1;
5645 PRINT("mach_port_move_member(%s, %s, %s)",
5646 name_for_port(MACH_REMOTE),
5647 name_for_port(req->member),
5648 name_for_port(req->after));
5650 MACH_ARG(mach_port_move_member.member) = req->member;
5651 MACH_ARG(mach_port_move_member.after) = req->after;
5653 AFTER = POST_FN(mach_port_move_member);
5656 POST(mach_port_move_member)
5658 #pragma pack(4)
5659 typedef struct {
5660 mach_msg_header_t Head;
5661 NDR_record_t NDR;
5662 kern_return_t RetCode;
5663 mach_msg_trailer_t trailer;
5664 } Reply;
5665 #pragma pack()
5667 Reply *reply = (Reply *)ARG1;
5669 if (!reply->RetCode) {
5670 // fixme port set tracker?
5671 } else {
5672 PRINT("mig return %d", reply->RetCode);
5677 PRE(mach_port_destroy)
5679 #pragma pack(4)
5680 typedef struct {
5681 mach_msg_header_t Head;
5682 NDR_record_t NDR;
5683 mach_port_name_t name;
5684 } Request;
5685 #pragma pack()
5687 Request *req = (Request *)ARG1;
5689 PRINT("mach_port_destroy(%s, %s)",
5690 name_for_port(MACH_REMOTE),
5691 name_for_port(req->name));
5693 MACH_ARG(mach_port.port) = req->name;
5695 AFTER = POST_FN(mach_port_destroy);
5697 // Must block to prevent race (other thread allocates and
5698 // notifies after we deallocate but before we notify)
5699 *flags &= ~SfMayBlock;
5702 POST(mach_port_destroy)
5704 #pragma pack(4)
5705 typedef struct {
5706 mach_msg_header_t Head;
5707 NDR_record_t NDR;
5708 kern_return_t RetCode;
5709 } Reply;
5710 #pragma pack()
5712 Reply *reply = (Reply *)ARG1;
5714 if (!reply->RetCode) {
5715 if (MACH_REMOTE == vg_task_port) {
5716 // Must have cleared SfMayBlock in PRE to prevent race
5717 record_port_destroy(MACH_ARG(mach_port.port));
5718 } else {
5719 VG_(printf)("UNKNOWN remote port destroy\n");
5721 } else {
5722 PRINT("mig return %d", reply->RetCode);
5727 PRE(mach_port_request_notification)
5729 #pragma pack(4)
5730 typedef struct {
5731 mach_msg_header_t Head;
5732 /* start of the kernel processed data */
5733 mach_msg_body_t msgh_body;
5734 mach_msg_port_descriptor_t notify;
5735 /* end of the kernel processed data */
5736 NDR_record_t NDR;
5737 mach_port_name_t name;
5738 mach_msg_id_t msgid;
5739 mach_port_mscount_t sync;
5740 } Request;
5741 #pragma pack()
5743 Request *req = (Request *)ARG1;
5745 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5746 name_for_port(MACH_REMOTE),
5747 name_for_port(req->name), req->msgid, req->sync,
5748 req->notify.name, req->notify.disposition);
5750 AFTER = POST_FN(mach_port_request_notification);
5753 POST(mach_port_request_notification)
5755 // GrP fixme port tracker? not sure
5759 PRE(mach_port_insert_right)
5761 #pragma pack(4)
5762 typedef struct {
5763 mach_msg_header_t Head;
5764 /* start of the kernel processed data */
5765 mach_msg_body_t msgh_body;
5766 mach_msg_port_descriptor_t poly;
5767 /* end of the kernel processed data */
5768 NDR_record_t NDR;
5769 mach_port_name_t name;
5770 } Request;
5771 #pragma pack()
5773 Request *req = (Request *)ARG1;
5775 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5776 name_for_port(MACH_REMOTE),
5777 name_for_port(req->name), req->poly.name, req->poly.disposition);
5779 AFTER = POST_FN(mach_port_insert_right);
5781 if (MACH_REMOTE == mach_task_self()) {
5782 // GrP fixme import_complex_message handles everything?
5783 // what about export_complex_message for MOVE variants?
5784 } else {
5785 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5786 // GrP fixme also may remove rights from this task?
5789 // GrP fixme port tracker?
5792 POST(mach_port_insert_right)
5797 PRE(mach_port_extract_right)
5799 #pragma pack(4)
5800 typedef struct {
5801 mach_msg_header_t Head;
5802 NDR_record_t NDR;
5803 mach_port_name_t name;
5804 mach_msg_type_name_t msgt_name;
5805 } Request;
5806 #pragma pack()
5808 Request *req = (Request *)ARG1;
5810 PRINT("mach_port_extract_right(%s, %s, %d)",
5811 name_for_port(MACH_REMOTE),
5812 name_for_port(req->name), req->msgt_name);
5814 AFTER = POST_FN(mach_port_extract_right);
5816 // fixme port tracker?
5819 POST(mach_port_extract_right)
5821 // fixme import_complex_message handles the returned result, right?
5825 PRE(mach_port_get_attributes)
5827 #pragma pack(4)
5828 typedef struct {
5829 mach_msg_header_t Head;
5830 NDR_record_t NDR;
5831 mach_port_name_t name;
5832 mach_port_flavor_t flavor;
5833 mach_msg_type_number_t port_info_outCnt;
5834 } Request;
5835 #pragma pack()
5837 Request *req = (Request *)ARG1;
5839 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5840 name_for_port(MACH_REMOTE),
5841 name_for_port(req->name), req->flavor, req->port_info_outCnt);
5843 AFTER = POST_FN(mach_port_get_attributes);
5846 POST(mach_port_get_attributes)
5851 PRE(mach_port_set_attributes)
5853 #pragma pack(4)
5854 typedef struct {
5855 mach_msg_header_t Head;
5856 NDR_record_t NDR;
5857 mach_port_name_t name;
5858 mach_port_flavor_t flavor;
5859 mach_msg_type_number_t port_infoCnt;
5860 integer_t port_info[10];
5861 } Request;
5862 #pragma pack()
5864 Request *req = (Request *)ARG1;
5866 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5867 name_for_port(MACH_REMOTE),
5868 name_for_port(req->name), req->flavor, req->port_infoCnt);
5870 AFTER = POST_FN(mach_port_set_attributes);
5873 POST(mach_port_set_attributes)
5878 PRE(mach_port_insert_member)
5880 #pragma pack(4)
5881 typedef struct {
5882 mach_msg_header_t Head;
5883 NDR_record_t NDR;
5884 mach_port_name_t name;
5885 mach_port_name_t pset;
5886 } Request;
5887 #pragma pack()
5889 Request *req = (Request *)ARG1;
5891 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5892 name_for_port(MACH_REMOTE), req->name, req->pset);
5894 AFTER = POST_FN(mach_port_insert_member);
5896 // GrP fixme port tracker?
5899 POST(mach_port_insert_member)
5904 PRE(task_get_special_port)
5906 #pragma pack(4)
5907 typedef struct {
5908 mach_msg_header_t Head;
5909 NDR_record_t NDR;
5910 int which_port;
5911 } Request;
5912 #pragma pack()
5914 Request *req = (Request *)ARG1;
5916 switch (req->which_port) {
5917 case TASK_KERNEL_PORT:
5918 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5919 name_for_port(MACH_REMOTE));
5920 break;
5921 case TASK_HOST_PORT:
5922 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5923 name_for_port(MACH_REMOTE));
5924 break;
5925 case TASK_BOOTSTRAP_PORT:
5926 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5927 name_for_port(MACH_REMOTE));
5928 break;
5929 #if DARWIN_VERS < DARWIN_10_8
5930 /* These disappeared in 10.8 */
5931 case TASK_WIRED_LEDGER_PORT:
5932 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5933 name_for_port(MACH_REMOTE));
5934 break;
5935 case TASK_PAGED_LEDGER_PORT:
5936 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5937 name_for_port(MACH_REMOTE));
5938 break;
5939 #endif
5940 default:
5941 PRINT("task_get_special_port(%s, %d)",
5942 name_for_port(MACH_REMOTE), req->which_port);
5943 break;
5946 MACH_ARG(task_get_special_port.which_port) = req->which_port;
5948 AFTER = POST_FN(task_get_special_port);
5951 POST(task_get_special_port)
5953 #pragma pack(4)
5954 typedef struct {
5955 mach_msg_header_t Head;
5956 /* start of the kernel processed data */
5957 mach_msg_body_t msgh_body;
5958 mach_msg_port_descriptor_t special_port;
5959 /* end of the kernel processed data */
5960 } Reply;
5961 #pragma pack()
5963 Reply *reply = (Reply *)ARG1;
5965 PRINT("got port %#x ", reply->special_port.name);
5967 switch (MACH_ARG(task_get_special_port.which_port)) {
5968 case TASK_BOOTSTRAP_PORT:
5969 vg_bootstrap_port = reply->special_port.name;
5970 assign_port_name(reply->special_port.name, "bootstrap");
5971 break;
5972 case TASK_KERNEL_PORT:
5973 assign_port_name(reply->special_port.name, "kernel");
5974 break;
5975 case TASK_HOST_PORT:
5976 assign_port_name(reply->special_port.name, "host");
5977 break;
5978 #if DARWIN_VERS < DARWIN_10_8
5979 /* These disappeared in 10.8 */
5980 case TASK_WIRED_LEDGER_PORT:
5981 assign_port_name(reply->special_port.name, "wired-ledger");
5982 break;
5983 case TASK_PAGED_LEDGER_PORT:
5984 assign_port_name(reply->special_port.name, "paged-ledger");
5985 break;
5986 #endif
5987 default:
5988 assign_port_name(reply->special_port.name, "special-%p");
5989 break;
5992 PRINT("%s", name_for_port(reply->special_port.name));
5996 PRE(task_set_special_port)
5998 #pragma pack(4)
5999 typedef struct {
6000 mach_msg_header_t Head;
6001 /* start of the kernel processed data */
6002 mach_msg_body_t msgh_body;
6003 mach_msg_port_descriptor_t special_port;
6004 /* end of the kernel processed data */
6005 NDR_record_t NDR;
6006 int which_port;
6007 } Request;
6008 #pragma pack()
6010 Request *req = (Request *)ARG1;
6012 PRINT("got port %#x ", req->special_port.name);
6014 // MACH_ARG(task_set_special_port.which_port) = req->which_port;
6015 PRINT("%s", name_for_port(req->special_port.name));
6017 AFTER = POST_FN(task_set_special_port);
6020 POST(task_set_special_port)
6022 #pragma pack(4)
6023 typedef struct {
6024 mach_msg_header_t Head;
6025 NDR_record_t NDR;
6026 kern_return_t RetCode;
6027 } Reply;
6028 #pragma pack()
6030 Reply *reply = (Reply *)ARG1;
6031 if (!reply->RetCode) {
6032 } else {
6033 PRINT("mig return %d", reply->RetCode);
6038 PRE(semaphore_create)
6040 #pragma pack(4)
6041 typedef struct {
6042 mach_msg_header_t Head;
6043 NDR_record_t NDR;
6044 int policy;
6045 int value;
6046 } Request;
6047 #pragma pack()
6049 Request *req = (Request *)ARG1;
6051 PRINT("semaphore_create(%s, ..., %d, %d)",
6052 name_for_port(MACH_REMOTE), req->policy, req->value);
6054 AFTER = POST_FN(semaphore_create);
6057 POST(semaphore_create)
6059 #pragma pack(4)
6060 typedef struct {
6061 mach_msg_header_t Head;
6062 /* start of the kernel processed data */
6063 mach_msg_body_t msgh_body;
6064 mach_msg_port_descriptor_t semaphore;
6065 /* end of the kernel processed data */
6066 mach_msg_trailer_t trailer;
6067 } Reply;
6068 #pragma pack()
6070 Reply *reply = (Reply *)ARG1;
6072 assign_port_name(reply->semaphore.name, "semaphore-%p");
6073 PRINT("%s", name_for_port(reply->semaphore.name));
6077 PRE(semaphore_destroy)
6079 #pragma pack(4)
6080 typedef struct {
6081 mach_msg_header_t Head;
6082 /* start of the kernel processed data */
6083 mach_msg_body_t msgh_body;
6084 mach_msg_port_descriptor_t semaphore;
6085 /* end of the kernel processed data */
6086 mach_msg_trailer_t trailer;
6087 } Request;
6088 #pragma pack()
6090 Request *req = (Request *)ARG1;
6092 PRINT("semaphore_destroy(%s, %s)",
6093 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
6095 record_port_destroy(req->semaphore.name);
6097 AFTER = POST_FN(semaphore_destroy);
6100 POST(semaphore_destroy)
6102 #pragma pack(4)
6103 typedef struct {
6104 mach_msg_header_t Head;
6105 NDR_record_t NDR;
6106 kern_return_t RetCode;
6107 mach_msg_trailer_t trailer;
6108 } Reply;
6109 #pragma pack()
6111 Reply *reply = (Reply *)ARG1;
6112 if (!reply->RetCode) {
6113 } else {
6114 PRINT("mig return %d", reply->RetCode);
6118 PRE(task_policy_set)
6120 #pragma pack(4)
6121 typedef struct {
6122 mach_msg_header_t Head;
6123 NDR_record_t NDR;
6124 task_policy_flavor_t flavor;
6125 mach_msg_type_number_t policy_infoCnt;
6126 integer_t policy_info[16];
6127 } Request;
6128 #pragma pack()
6130 Request *req = (Request *)ARG1;
6132 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6134 AFTER = POST_FN(task_policy_set);
6137 POST(task_policy_set)
6139 #pragma pack(4)
6140 typedef struct {
6141 mach_msg_header_t Head;
6142 NDR_record_t NDR;
6143 kern_return_t RetCode;
6144 } Reply;
6145 #pragma pack()
6147 Reply *reply = (Reply *)ARG1;
6148 if (!reply->RetCode) {
6149 } else {
6150 PRINT("mig return %d", reply->RetCode);
6155 PRE(mach_ports_register)
6157 #pragma pack(4)
6158 typedef struct {
6159 mach_msg_header_t Head;
6160 /* start of the kernel processed data */
6161 mach_msg_body_t msgh_body;
6162 mach_msg_ool_ports_descriptor_t init_port_set;
6163 /* end of the kernel processed data */
6164 NDR_record_t NDR;
6165 mach_msg_type_number_t init_port_setCnt;
6166 } Request;
6167 #pragma pack()
6169 // Request *req = (Request *)ARG1;
6171 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE));
6173 AFTER = POST_FN(mach_ports_register);
6176 POST(mach_ports_register)
6178 #pragma pack(4)
6179 typedef struct {
6180 mach_msg_header_t Head;
6181 NDR_record_t NDR;
6182 kern_return_t RetCode;
6183 } Reply;
6184 #pragma pack()
6186 Reply *reply = (Reply *)ARG1;
6187 if (!reply->RetCode) {
6188 } else {
6189 PRINT("mig return %d", reply->RetCode);
6194 PRE(mach_ports_lookup)
6196 #pragma pack(4)
6197 typedef struct {
6198 mach_msg_header_t Head;
6199 } Request;
6200 #pragma pack()
6202 // Request *req = (Request *)ARG1;
6204 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
6206 AFTER = POST_FN(mach_ports_lookup);
6209 POST(mach_ports_lookup)
6211 #pragma pack(4)
6212 typedef struct {
6213 mach_msg_header_t Head;
6214 /* start of the kernel processed data */
6215 mach_msg_body_t msgh_body;
6216 mach_msg_ool_ports_descriptor_t init_port_set;
6217 /* end of the kernel processed data */
6218 NDR_record_t NDR;
6219 mach_msg_type_number_t init_port_setCnt;
6220 } Reply;
6221 #pragma pack()
6223 // Reply *reply = (Reply *)ARG1;
6227 PRE(task_info)
6229 #pragma pack(4)
6230 typedef struct {
6231 mach_msg_header_t Head;
6232 NDR_record_t NDR;
6233 task_flavor_t flavor;
6234 mach_msg_type_number_t task_info_outCnt;
6235 } Request;
6236 #pragma pack()
6238 Request *req = (Request *)ARG1;
6240 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6242 AFTER = POST_FN(task_info);
6245 POST(task_info)
6247 #pragma pack(4)
6248 typedef struct {
6249 mach_msg_header_t Head;
6250 NDR_record_t NDR;
6251 kern_return_t RetCode;
6252 mach_msg_type_number_t task_info_outCnt;
6253 integer_t task_info_out[52];
6254 } Reply;
6255 #pragma pack()
6257 Reply *reply = (Reply *)ARG1;
6258 if (!reply->RetCode) {
6259 } else {
6260 PRINT("mig return %d", reply->RetCode);
6265 PRE(task_set_info)
6267 #pragma pack(4)
6268 typedef struct {
6269 mach_msg_header_t Head;
6270 NDR_record_t NDR;
6271 task_flavor_t flavor;
6272 mach_msg_type_number_t task_info_inCnt;
6273 integer_t task_info_in[52];
6274 } Request;
6275 #pragma pack()
6277 Request *req = (Request *)ARG1;
6279 PRINT("task_set_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6281 AFTER = POST_FN(task_set_info);
6284 POST(task_set_info)
6286 #pragma pack(4)
6287 typedef struct {
6288 mach_msg_header_t Head;
6289 NDR_record_t NDR;
6290 kern_return_t RetCode;
6291 } Reply;
6292 #pragma pack()
6294 Reply *reply = (Reply *)ARG1;
6295 if (!reply->RetCode) {
6296 } else {
6297 PRINT("mig return %d", reply->RetCode);
6301 PRE(task_threads)
6303 #pragma pack(4)
6304 typedef struct {
6305 mach_msg_header_t Head;
6306 } Request;
6307 #pragma pack()
6309 // Request *req = (Request *)ARG1;
6311 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
6313 AFTER = POST_FN(task_threads);
6316 POST(task_threads)
6318 #pragma pack(4)
6319 typedef struct {
6320 mach_msg_header_t Head;
6321 /* start of the kernel processed data */
6322 mach_msg_body_t msgh_body;
6323 mach_msg_ool_ports_descriptor_t act_list;
6324 /* end of the kernel processed data */
6325 NDR_record_t NDR;
6326 mach_msg_type_number_t act_listCnt;
6327 mach_msg_trailer_t trailer;
6328 } Reply;
6329 #pragma pack()
6331 Reply *reply = (Reply *)ARG1;
6333 if (MACH_REMOTE == vg_task_port) {
6334 assign_port_names(&reply->act_list, "thread-%p");
6335 } else {
6336 assign_port_names(&reply->act_list, "remote-thread-%p");
6341 PRE(task_suspend)
6343 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
6345 if (MACH_REMOTE == vg_task_port) {
6346 // GrP fixme self-suspend
6347 vg_assert(0);
6348 } else {
6349 // suspend other - no problem
6352 AFTER = POST_FN(task_suspend);
6355 POST(task_suspend)
6360 PRE(task_resume)
6362 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
6364 if (MACH_REMOTE == vg_task_port) {
6365 // GrP fixme self-resume
6366 vg_assert(0);
6367 } else {
6368 // resume other - no problem
6371 AFTER = POST_FN(task_resume);
6374 POST(task_resume)
6379 PRE(vm_allocate)
6381 #pragma pack(4)
6382 typedef struct {
6383 mach_msg_header_t Head;
6384 NDR_record_t NDR;
6385 vm_address_t address;
6386 vm_size_t size;
6387 int flags;
6388 } Request;
6389 #pragma pack()
6391 Request *req = (Request *)ARG1;
6393 PRINT("vm_allocate (%s, at %#llx, size %llu, flags %#x)",
6394 name_for_port(MACH_REMOTE),
6395 (ULong)req->address, (ULong)req->size, req->flags);
6397 MACH_ARG(vm_allocate.size) = req->size;
6398 MACH_ARG(vm_allocate.flags) = req->flags;
6400 AFTER = POST_FN(vm_allocate);
6403 POST(vm_allocate)
6405 #pragma pack(4)
6406 typedef struct {
6407 mach_msg_header_t Head;
6408 NDR_record_t NDR;
6409 kern_return_t RetCode;
6410 vm_address_t address;
6411 mach_msg_trailer_t trailer;
6412 } Reply;
6413 #pragma pack()
6415 Reply *reply = (Reply *)ARG1;
6417 if (!reply->RetCode) {
6418 if (MACH_REMOTE == vg_task_port) {
6419 PRINT("allocated at %#llx", (ULong)reply->address);
6420 // requesting 0 bytes returns address 0 with no error
6421 if (MACH_ARG(vm_allocate.size)) {
6422 ML_(notify_core_and_tool_of_mmap)(
6423 reply->address, MACH_ARG(vm_allocate.size),
6424 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6426 } else {
6427 PRINT("allocated at %#llx in remote task %s",
6428 (ULong)reply->address,
6429 name_for_port(MACH_REMOTE));
6431 } else {
6432 PRINT("mig return %d", reply->RetCode);
6437 PRE(vm_deallocate)
6439 #pragma pack(4)
6440 typedef struct {
6441 mach_msg_header_t Head;
6442 NDR_record_t NDR;
6443 vm_address_t address;
6444 vm_size_t size;
6445 } Request;
6446 #pragma pack()
6448 Request *req = (Request *)ARG1;
6450 PRINT("vm_deallocate(%s, at %#llx, size %llu)",
6451 name_for_port(MACH_REMOTE),
6452 (ULong)req->address, (ULong)req->size);
6454 MACH_ARG(vm_deallocate.address) = req->address;
6455 MACH_ARG(vm_deallocate.size) = req->size;
6457 AFTER = POST_FN(vm_deallocate);
6459 // Must block to prevent race (other thread allocates and
6460 // notifies after we deallocate but before we notify)
6461 *flags &= ~SfMayBlock;
6464 POST(vm_deallocate)
6466 #pragma pack(4)
6467 typedef struct {
6468 mach_msg_header_t Head;
6469 NDR_record_t NDR;
6470 kern_return_t RetCode;
6471 mach_msg_trailer_t trailer;
6472 } Reply;
6473 #pragma pack()
6475 Reply *reply = (Reply *)ARG1;
6477 if (!reply->RetCode) {
6478 if (MACH_REMOTE == vg_task_port) {
6479 if (MACH_ARG(vm_deallocate.size)) {
6480 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
6481 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
6482 MACH_ARG(vm_deallocate.size));
6483 // Must have cleared SfMayBlock in PRE to prevent race
6484 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6487 } else {
6488 PRINT("mig return %d", reply->RetCode);
6493 PRE(vm_protect)
6495 #pragma pack(4)
6496 typedef struct {
6497 mach_msg_header_t Head;
6498 NDR_record_t NDR;
6499 vm_address_t address;
6500 vm_size_t size;
6501 boolean_t set_maximum;
6502 vm_prot_t new_protection;
6503 } Request;
6504 #pragma pack()
6506 Request *req = (Request *)ARG1;
6508 PRINT("vm_protect(%s, at %#llx, size %llu, set_max %d, prot %d)",
6509 name_for_port(MACH_REMOTE),
6510 (ULong)req->address, (ULong)req->size,
6511 req->set_maximum, req->new_protection);
6513 MACH_ARG(vm_protect.address) = req->address;
6514 MACH_ARG(vm_protect.size) = req->size;
6515 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
6516 MACH_ARG(vm_protect.new_protection) = req->new_protection;
6518 AFTER = POST_FN(vm_protect);
6521 POST(vm_protect)
6523 #pragma pack(4)
6524 typedef struct {
6525 mach_msg_header_t Head;
6526 NDR_record_t NDR;
6527 kern_return_t RetCode;
6528 mach_msg_trailer_t trailer;
6529 } Reply;
6530 #pragma pack()
6532 Reply *reply = (Reply *)ARG1;
6534 if (!reply->RetCode) {
6535 if (MACH_REMOTE == vg_task_port) {
6536 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
6537 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
6538 MACH_ARG(vm_protect.size));
6539 UInt prot = MACH_ARG(vm_protect.new_protection);
6540 if (MACH_ARG(vm_protect.set_maximum)) {
6541 // GrP fixme mprotect max
6542 VG_(printf)("UNKNOWN vm_protect set maximum");
6543 //VG_(mprotect_max_range)(start, end-start, prot);
6544 } else {
6545 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6546 VG_(di_notify_vm_protect)(start, end-start, prot);
6549 } else {
6550 PRINT("mig return %d", reply->RetCode);
6555 PRE(vm_inherit)
6557 #pragma pack(4)
6558 typedef struct {
6559 mach_msg_header_t Head;
6560 NDR_record_t NDR;
6561 vm_address_t address;
6562 vm_size_t size;
6563 vm_inherit_t new_inheritance;
6564 } Request;
6565 #pragma pack()
6567 Request *req = (Request *)ARG1;
6569 PRINT("vm_inherit(%s, at %#llx, size %llu, value %d)",
6570 name_for_port(MACH_REMOTE),
6571 (ULong)req->address, (ULong)req->size,
6572 req->new_inheritance);
6574 AFTER = POST_FN(vm_inherit);
6577 POST(vm_inherit)
6579 #pragma pack(4)
6580 typedef struct {
6581 mach_msg_header_t Head;
6582 NDR_record_t NDR;
6583 kern_return_t RetCode;
6584 mach_msg_trailer_t trailer;
6585 } Reply;
6586 #pragma pack()
6588 Reply *reply = (Reply *)ARG1;
6590 if (!reply->RetCode) {
6591 if (MACH_REMOTE == vg_task_port) {
6592 // GrP fixme do something?
6594 } else {
6595 PRINT("mig return %d", reply->RetCode);
6600 PRE(vm_read)
6602 #pragma pack(4)
6603 typedef struct {
6604 mach_msg_header_t Head;
6605 NDR_record_t NDR;
6606 vm_address_t address;
6607 vm_size_t size;
6608 } Request;
6609 #pragma pack()
6611 Request *req = (Request *)ARG1;
6613 PRINT("vm_read(from %s at %#llx size %llu)",
6614 name_for_port(MACH_REMOTE),
6615 (ULong)req->address, (ULong)req->size);
6617 MACH_ARG(vm_read.addr) = req->address;
6618 MACH_ARG(vm_read.size) = req->size;
6620 AFTER = POST_FN(vm_read);
6623 POST(vm_read)
6625 #pragma pack(4)
6626 typedef struct {
6627 mach_msg_header_t Head;
6628 /* start of the kernel processed data */
6629 mach_msg_body_t msgh_body;
6630 mach_msg_ool_descriptor_t data;
6631 /* end of the kernel processed data */
6632 NDR_record_t NDR;
6633 mach_msg_type_number_t dataCnt;
6634 } Reply;
6635 #pragma pack()
6637 // Reply *reply = (Reply *)ARG1;
6639 if (MACH_REMOTE == vg_task_port) {
6640 // vm_read from self
6641 // GrP fixme copy initialized state
6647 PRE(mach_vm_read)
6649 #pragma pack(4)
6650 typedef struct {
6651 mach_msg_header_t Head;
6652 NDR_record_t NDR;
6653 mach_vm_address_t address;
6654 mach_vm_size_t size;
6655 } Request;
6656 #pragma pack()
6658 Request *req = (Request *)ARG1;
6660 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6661 name_for_port(MACH_REMOTE), req->address, req->size);
6663 MACH_ARG(mach_vm_read.addr) = req->address;
6664 MACH_ARG(mach_vm_read.size) = req->size;
6666 AFTER = POST_FN(mach_vm_read);
6669 POST(mach_vm_read)
6671 #pragma pack(4)
6672 typedef struct {
6673 mach_msg_header_t Head;
6674 /* start of the kernel processed data */
6675 mach_msg_body_t msgh_body;
6676 mach_msg_ool_descriptor_t data;
6677 /* end of the kernel processed data */
6678 NDR_record_t NDR;
6679 mach_msg_type_number_t dataCnt;
6680 } Reply;
6681 #pragma pack()
6683 // Reply *reply = (Reply *)ARG1;
6685 if (MACH_REMOTE == vg_task_port) {
6686 // vm_read from self
6687 // GrP fixme copy initialized state
6692 PRE(vm_read_overwrite)
6694 #pragma pack(4)
6695 typedef struct {
6696 mach_msg_header_t Head;
6697 NDR_record_t NDR;
6698 vm_address_t address;
6699 vm_size_t size;
6700 vm_address_t data;
6701 } Request;
6702 #pragma pack()
6704 Request *req = (Request *)ARG1;
6706 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6707 name_for_port(MACH_REMOTE),
6708 (ULong)req->address, (ULong)req->size, (ULong)req->data);
6710 MACH_ARG(vm_read_overwrite.addr) = req->address;
6711 MACH_ARG(vm_read_overwrite.size) = req->size;
6712 MACH_ARG(vm_read_overwrite.data) = req->data;
6714 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
6716 AFTER = POST_FN(vm_read_overwrite);
6719 POST(vm_read_overwrite)
6721 #pragma pack(4)
6722 typedef struct {
6723 mach_msg_header_t Head;
6724 NDR_record_t NDR;
6725 kern_return_t RetCode;
6726 vm_size_t outsize;
6727 } Reply;
6728 #pragma pack()
6730 Reply *reply = (Reply *)ARG1;
6732 if (reply->RetCode) {
6733 PRINT("mig return %d", reply->RetCode);
6734 } else {
6735 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
6736 if (MACH_REMOTE == vg_task_port) {
6737 // vm_read_overwrite from self
6738 // GrP fixme copy initialized state
6739 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6740 } else {
6741 // vm_read_overwrite from remote
6742 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6748 PRE(vm_copy)
6750 #pragma pack(4)
6751 typedef struct {
6752 mach_msg_header_t Head;
6753 NDR_record_t NDR;
6754 vm_address_t source_address;
6755 vm_size_t size;
6756 vm_address_t dest_address;
6757 } Request;
6758 #pragma pack()
6760 Request *req = (Request *)ARG1;
6762 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6763 name_for_port(MACH_REMOTE),
6764 (ULong)req->source_address,
6765 (ULong)req->size, (ULong)req->dest_address);
6767 MACH_ARG(vm_copy.src) = req->source_address;
6768 MACH_ARG(vm_copy.dst) = req->dest_address;
6769 MACH_ARG(vm_copy.size) = req->size;
6771 AFTER = POST_FN(vm_copy);
6774 POST(vm_copy)
6776 #pragma pack(4)
6777 typedef struct {
6778 mach_msg_header_t Head;
6779 NDR_record_t NDR;
6780 kern_return_t RetCode;
6781 mach_msg_trailer_t trailer;
6782 } Reply;
6783 #pragma pack()
6785 Reply *reply = (Reply *)ARG1;
6787 if (!reply->RetCode) {
6788 if (MACH_REMOTE == vg_task_port) {
6789 // GrP fixme set dst's initialization equal to src's
6790 // and wipe any symbols or translations in dst
6792 } else {
6793 PRINT("mig return %d", reply->RetCode);
6798 PRE(vm_map)
6800 #pragma pack(4)
6801 typedef struct {
6802 mach_msg_header_t Head;
6803 /* start of the kernel processed data */
6804 mach_msg_body_t msgh_body;
6805 mach_msg_port_descriptor_t object;
6806 /* end of the kernel processed data */
6807 NDR_record_t NDR;
6808 vm_address_t address;
6809 vm_size_t size;
6810 vm_address_t mask;
6811 int flags;
6812 vm_offset_t offset;
6813 boolean_t copy;
6814 vm_prot_t cur_protection;
6815 vm_prot_t max_protection;
6816 vm_inherit_t inheritance;
6817 } Request;
6818 #pragma pack()
6820 Request *req = (Request *)ARG1;
6822 // GrP fixme check these
6823 PRINT("vm_map(in %s, at %#llx, size %llu, from %s ...)",
6824 name_for_port(MACH_REMOTE),
6825 (ULong)req->address, (ULong)req->size,
6826 name_for_port(req->object.name));
6828 MACH_ARG(vm_map.size) = req->size;
6829 MACH_ARG(vm_map.copy) = req->copy;
6830 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
6832 AFTER = POST_FN(vm_map);
6835 POST(vm_map)
6837 #pragma pack(4)
6838 typedef struct {
6839 mach_msg_header_t Head;
6840 NDR_record_t NDR;
6841 kern_return_t RetCode;
6842 vm_address_t address;
6843 mach_msg_trailer_t trailer;
6844 } Reply;
6845 #pragma pack()
6847 Reply *reply = (Reply *)ARG1;
6849 if (!reply->RetCode) {
6850 // GrP fixme check src and dest tasks
6851 PRINT("mapped at %#llx", (ULong)reply->address);
6852 // GrP fixme max prot
6853 ML_(notify_core_and_tool_of_mmap)(
6854 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
6855 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
6856 // GrP fixme VKI_MAP_PRIVATE if !copy?
6857 } else {
6858 PRINT("mig return %d", reply->RetCode);
6863 PRE(vm_remap)
6865 #pragma pack(4)
6866 typedef struct {
6867 mach_msg_header_t Head;
6868 /* start of the kernel processed data */
6869 mach_msg_body_t msgh_body;
6870 mach_msg_port_descriptor_t src_task;
6871 /* end of the kernel processed data */
6872 NDR_record_t NDR;
6873 vm_address_t target_address;
6874 vm_size_t size;
6875 vm_address_t mask;
6876 boolean_t anywhere;
6877 vm_address_t src_address;
6878 boolean_t copy;
6879 vm_inherit_t inheritance;
6880 } Request;
6881 #pragma pack()
6883 Request *req = (Request *)ARG1;
6885 // GrP fixme check src and dest tasks
6887 if (VG_(clo_trace_syscalls)) {
6888 mach_port_name_t source_task = req->src_task.name;
6889 if (source_task == mach_task_self()) {
6890 PRINT("vm_remap(mach_task_self(), "
6891 "to %#llx size %llu, from mach_task_self() at %#llx, ...)",
6892 (ULong)req->target_address,
6893 (ULong)req->size, (ULong)req->src_address);
6894 } else {
6895 PRINT("vm_remap(mach_task_self(), "
6896 "to %#llx size %llu, from task %u at %#llx, ...)",
6897 (ULong)req->target_address, (ULong)req->size,
6898 source_task, (ULong)req->src_address);
6902 // arg1 is task
6903 // vt->syscall_arg2 = req->target_address;
6904 MACH_ARG(vm_remap.size) = req->size;
6905 // vt->syscall_arg4 = req->copy;
6907 AFTER = POST_FN(vm_remap);
6910 POST(vm_remap)
6912 #pragma pack(4)
6913 typedef struct {
6914 mach_msg_header_t Head;
6915 NDR_record_t NDR;
6916 kern_return_t RetCode;
6917 vm_address_t target_address;
6918 vm_prot_t cur_protection;
6919 vm_prot_t max_protection;
6920 mach_msg_trailer_t trailer;
6921 } Reply;
6922 #pragma pack()
6924 Reply *reply = (Reply *)ARG1;
6926 if (!reply->RetCode) {
6927 // GrP fixme check src and dest tasks
6928 UInt prot = reply->cur_protection & reply->max_protection;
6929 // GrP fixme max prot
6930 PRINT("mapped at %#llx", (ULong)reply->target_address);
6931 ML_(notify_core_and_tool_of_mmap)(
6932 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
6933 prot, VKI_MAP_SHARED, -1, 0);
6934 // GrP fixme VKI_MAP_FIXED if !copy?
6935 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6936 } else {
6937 PRINT("mig return %d", reply->RetCode);
6942 PRE(mach_make_memory_entry_64)
6944 #pragma pack(4)
6945 typedef struct {
6946 mach_msg_header_t Head;
6947 /* start of the kernel processed data */
6948 mach_msg_body_t msgh_body;
6949 mach_msg_port_descriptor_t parent_entry;
6950 /* end of the kernel processed data */
6951 NDR_record_t NDR;
6952 memory_object_size_t size;
6953 memory_object_offset_t offset;
6954 vm_prot_t permission;
6955 } Request;
6956 #pragma pack()
6958 Request *req = (Request *)ARG1;
6960 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6961 name_for_port(MACH_REMOTE),
6962 req->size, req->offset, req->permission, req->parent_entry.type);
6964 AFTER = POST_FN(mach_make_memory_entry_64);
6967 POST(mach_make_memory_entry_64)
6969 #pragma pack(4)
6970 typedef struct {
6971 mach_msg_header_t Head;
6972 mach_msg_body_t msgh_body;
6973 mach_msg_port_descriptor_t object;
6974 NDR_record_t NDR;
6975 memory_object_size_t size;
6976 } Reply;
6977 #pragma pack()
6979 Reply *reply = (Reply *)ARG1;
6981 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6982 assign_port_name(reply->object.name, "memory-%p");
6983 PRINT("%s", name_for_port(reply->object.name));
6988 PRE(vm_purgable_control)
6990 #pragma pack(4)
6991 typedef struct {
6992 mach_msg_header_t Head;
6993 NDR_record_t NDR;
6994 vm_address_t address;
6995 vm_purgable_t control;
6996 int state;
6997 } Request;
6998 #pragma pack()
7000 Request *req = (Request *)ARG1;
7002 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
7003 name_for_port(MACH_REMOTE),
7004 (ULong)req->address, req->control, req->state);
7006 // GrP fixme verify address?
7008 AFTER = POST_FN(vm_purgable_control);
7011 POST(vm_purgable_control)
7013 #pragma pack(4)
7014 typedef struct {
7015 mach_msg_header_t Head;
7016 NDR_record_t NDR;
7017 kern_return_t RetCode;
7018 int state;
7019 } Reply;
7020 #pragma pack()
7022 Reply *reply = (Reply *)ARG1;
7024 if (!reply->RetCode) {
7025 } else {
7026 PRINT("mig return %d", reply->RetCode);
7031 PRE(mach_vm_purgable_control)
7033 #pragma pack(4)
7034 typedef struct {
7035 mach_msg_header_t Head;
7036 NDR_record_t NDR;
7037 mach_vm_address_t address;
7038 vm_purgable_t control;
7039 int state;
7040 } Request;
7041 #pragma pack()
7043 Request *req = (Request *)ARG1;
7045 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
7046 name_for_port(MACH_REMOTE),
7047 (ULong)req->address, req->control, req->state);
7049 // GrP fixme verify address?
7051 AFTER = POST_FN(mach_vm_purgable_control);
7054 POST(mach_vm_purgable_control)
7056 #pragma pack(4)
7057 typedef struct {
7058 mach_msg_header_t Head;
7059 NDR_record_t NDR;
7060 kern_return_t RetCode;
7061 int state;
7062 } Reply;
7063 #pragma pack()
7065 Reply *reply = (Reply *)ARG1;
7067 if (!reply->RetCode) {
7068 } else {
7069 PRINT("mig return %d", reply->RetCode);
7074 PRE(mach_vm_allocate)
7076 #pragma pack(4)
7077 typedef struct {
7078 mach_msg_header_t Head;
7079 NDR_record_t NDR;
7080 mach_vm_address_t address;
7081 mach_vm_size_t size;
7082 int flags;
7083 } Request;
7084 #pragma pack()
7086 Request *req = (Request *)ARG1;
7088 PRINT("mach_vm_allocate (%s, at 0x%llx, size %llu, flags 0x%x)",
7089 name_for_port(MACH_REMOTE),
7090 req->address, req->size, req->flags);
7092 MACH_ARG(mach_vm_allocate.size) = req->size;
7093 MACH_ARG(mach_vm_allocate.flags) = req->flags;
7095 AFTER = POST_FN(mach_vm_allocate);
7098 POST(mach_vm_allocate)
7100 #pragma pack(4)
7101 typedef struct {
7102 mach_msg_header_t Head;
7103 NDR_record_t NDR;
7104 kern_return_t RetCode;
7105 mach_vm_address_t address;
7106 mach_msg_trailer_t trailer;
7107 } Reply;
7108 #pragma pack()
7110 Reply *reply = (Reply *)ARG1;
7112 if (!reply->RetCode) {
7113 if (MACH_REMOTE == vg_task_port) {
7114 PRINT("allocated at 0x%llx", reply->address);
7115 // requesting 0 bytes returns address 0 with no error
7116 if (MACH_ARG(mach_vm_allocate.size)) {
7117 ML_(notify_core_and_tool_of_mmap)(
7118 reply->address, MACH_ARG(mach_vm_allocate.size),
7119 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
7121 } else {
7122 PRINT("allocated at 0x%llx in remote task %s", reply->address,
7123 name_for_port(MACH_REMOTE));
7125 } else {
7126 PRINT("mig return %d", reply->RetCode);
7131 PRE(mach_vm_deallocate)
7133 #pragma pack(4)
7134 typedef struct {
7135 mach_msg_header_t Head;
7136 NDR_record_t NDR;
7137 mach_vm_address_t address;
7138 mach_vm_size_t size;
7139 } Request;
7140 #pragma pack()
7142 Request *req = (Request *)ARG1;
7144 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %llu)",
7145 name_for_port(MACH_REMOTE),
7146 req->address, req->size);
7148 MACH_ARG(mach_vm_deallocate.address) = req->address;
7149 MACH_ARG(mach_vm_deallocate.size) = req->size;
7151 AFTER = POST_FN(mach_vm_deallocate);
7153 // Must block to prevent race (other thread allocates and
7154 // notifies after we deallocate but before we notify)
7155 *flags &= ~SfMayBlock;
7158 POST(mach_vm_deallocate)
7160 #pragma pack(4)
7161 typedef struct {
7162 mach_msg_header_t Head;
7163 NDR_record_t NDR;
7164 kern_return_t RetCode;
7165 mach_msg_trailer_t trailer;
7166 } Reply;
7167 #pragma pack()
7169 Reply *reply = (Reply *)ARG1;
7171 if (!reply->RetCode) {
7172 if (MACH_REMOTE == vg_task_port) {
7173 if (MACH_ARG(mach_vm_deallocate.size)) {
7174 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
7175 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
7176 MACH_ARG(mach_vm_deallocate.size));
7177 // Must have cleared SfMayBlock in PRE to prevent race
7178 ML_(notify_core_and_tool_of_munmap)(start, end - start);
7181 } else {
7182 PRINT("mig return %d", reply->RetCode);
7187 PRE(mach_vm_protect)
7189 #pragma pack(4)
7190 typedef struct {
7191 mach_msg_header_t Head;
7192 NDR_record_t NDR;
7193 mach_vm_address_t address;
7194 mach_vm_size_t size;
7195 boolean_t set_maximum;
7196 vm_prot_t new_protection;
7197 } Request;
7198 #pragma pack()
7200 Request *req = (Request *)ARG1;
7202 PRINT("mach_vm_protect(%s, at 0x%llx, size %llu, set_max %d, prot %d)",
7203 name_for_port(MACH_REMOTE), req->address, req->size,
7204 req->set_maximum, req->new_protection);
7206 MACH_ARG(mach_vm_protect.address) = req->address;
7207 MACH_ARG(mach_vm_protect.size) = req->size;
7208 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
7209 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
7211 AFTER = POST_FN(mach_vm_protect);
7214 POST(mach_vm_protect)
7216 #pragma pack(4)
7217 typedef struct {
7218 mach_msg_header_t Head;
7219 NDR_record_t NDR;
7220 kern_return_t RetCode;
7221 mach_msg_trailer_t trailer;
7222 } Reply;
7223 #pragma pack()
7225 Reply *reply = (Reply *)ARG1;
7227 if (!reply->RetCode) {
7228 if (MACH_REMOTE == vg_task_port) {
7229 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
7230 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
7231 MACH_ARG(mach_vm_protect.size));
7232 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
7233 if (MACH_ARG(mach_vm_protect.set_maximum)) {
7234 // DDD: #warning GrP fixme mprotect max
7235 //VG_(mprotect_max_range)(start, end-start, prot);
7236 } else {
7237 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
7240 } else {
7241 PRINT("mig return %d", reply->RetCode);
7246 PRE(mach_vm_inherit)
7248 #pragma pack(4)
7249 typedef struct {
7250 mach_msg_header_t Head;
7251 NDR_record_t NDR;
7252 mach_vm_address_t address;
7253 mach_vm_size_t size;
7254 vm_inherit_t new_inheritance;
7255 } Request;
7256 #pragma pack()
7258 Request *req = (Request *)ARG1;
7260 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
7261 name_for_port(MACH_REMOTE),
7262 req->address, req->size, req->new_inheritance);
7264 AFTER = POST_FN(mach_vm_inherit);
7267 POST(mach_vm_inherit)
7269 #pragma pack(4)
7270 typedef struct {
7271 mach_msg_header_t Head;
7272 NDR_record_t NDR;
7273 kern_return_t RetCode;
7274 mach_msg_trailer_t trailer;
7275 } Reply;
7276 #pragma pack()
7278 Reply *reply = (Reply *)ARG1;
7280 if (!reply->RetCode) {
7281 // no V-visible side effects
7282 // GrP fixme except maybe fork/exec
7283 } else {
7284 PRINT("mig return %d", reply->RetCode);
7289 PRE(mach_vm_copy)
7291 #pragma pack(4)
7292 typedef struct {
7293 mach_msg_header_t Head;
7294 NDR_record_t NDR;
7295 mach_vm_address_t source_address;
7296 mach_vm_size_t size;
7297 mach_vm_address_t dest_address;
7298 } Request;
7299 #pragma pack()
7301 Request *req = (Request *)ARG1;
7303 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
7304 name_for_port(MACH_REMOTE),
7305 req->source_address, req->size, req->dest_address);
7307 // arg1 is task
7308 // vt->syscall_arg2 = req->source_address;
7309 // vt->syscall_arg3 = req->size;
7310 // vt->syscall_arg4 = req->dest_address;
7312 AFTER = POST_FN(mach_vm_copy);
7315 POST(mach_vm_copy)
7317 #pragma pack(4)
7318 typedef struct {
7319 mach_msg_header_t Head;
7320 NDR_record_t NDR;
7321 kern_return_t RetCode;
7322 mach_msg_trailer_t trailer;
7323 } Reply;
7324 #pragma pack()
7326 Reply *reply = (Reply *)ARG1;
7328 if (!reply->RetCode) {
7329 if (MACH_REMOTE == vg_task_port) {
7330 // GrP fixme set dest's initialization equal to src's
7331 // BUT vm_copy allocates no memory
7333 } else {
7334 PRINT("mig return %d", reply->RetCode);
7338 PRE(mach_vm_read_overwrite)
7340 #pragma pack(4)
7341 typedef struct {
7342 mach_msg_header_t Head;
7343 NDR_record_t NDR;
7344 mach_vm_address_t address;
7345 mach_vm_size_t size;
7346 mach_vm_address_t data;
7347 } Request;
7348 #pragma pack()
7350 Request *req = (Request *)ARG1;
7352 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
7353 name_for_port(MACH_REMOTE),
7354 req->address, req->size, req->data);
7356 AFTER = POST_FN(mach_vm_read_overwrite);
7359 POST(mach_vm_read_overwrite)
7361 #pragma pack(4)
7362 typedef struct {
7363 mach_msg_header_t Head;
7364 NDR_record_t NDR;
7365 kern_return_t RetCode;
7366 mach_vm_size_t outsize;
7367 } Reply;
7368 #pragma pack()
7370 Reply *reply = (Reply *)ARG1;
7372 if (!reply->RetCode) {
7373 if (MACH_REMOTE == vg_task_port) {
7374 // GrP fixme set dest's initialization equal to src's
7375 // BUT vm_copy allocates no memory
7377 } else {
7378 PRINT("mig return %d", reply->RetCode);
7382 PRE(mach_vm_map)
7384 #pragma pack(4)
7385 typedef struct {
7386 mach_msg_header_t Head;
7387 /* start of the kernel processed data */
7388 mach_msg_body_t msgh_body;
7389 mach_msg_port_descriptor_t object;
7390 /* end of the kernel processed data */
7391 NDR_record_t NDR;
7392 mach_vm_address_t address;
7393 mach_vm_size_t size;
7394 mach_vm_address_t mask;
7395 int flags;
7396 memory_object_offset_t offset;
7397 boolean_t copy;
7398 vm_prot_t cur_protection;
7399 vm_prot_t max_protection;
7400 vm_inherit_t inheritance;
7401 } Request;
7402 #pragma pack()
7404 Request *req = (Request *)ARG1;
7406 // GrP fixme check these
7407 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7408 name_for_port(req->Head.msgh_remote_port),
7409 name_for_port(req->object.name),
7410 req->address, req->size,
7411 req->cur_protection,
7412 req->max_protection);
7414 MACH_ARG(mach_vm_map.size) = req->size;
7415 MACH_ARG(mach_vm_map.copy) = req->copy;
7416 MACH_ARG(mach_vm_map.protection) =
7417 (req->cur_protection & req->max_protection);
7419 AFTER = POST_FN(mach_vm_map);
7422 POST(mach_vm_map)
7424 #pragma pack(4)
7425 typedef struct {
7426 mach_msg_header_t Head;
7427 NDR_record_t NDR;
7428 kern_return_t RetCode;
7429 mach_vm_address_t address;
7430 mach_msg_trailer_t trailer;
7431 } Reply;
7432 #pragma pack()
7434 Reply *reply = (Reply *)ARG1;
7436 if (!reply->RetCode) {
7437 // GrP fixme check src and dest tasks
7438 PRINT("mapped at 0x%llx", reply->address);
7439 # if 0
7440 // GrP fixme max prot
7441 ML_(notify_core_and_tool_of_mmap)(
7442 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
7443 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
7444 // GrP fixme VKI_MAP_PRIVATE if !copy?
7445 # else
7446 ML_(sync_mappings)("after", "mach_vm_map", 0);
7447 # endif
7448 } else {
7449 PRINT("mig return %d", reply->RetCode);
7454 PRE(mach_vm_remap)
7456 #pragma pack(4)
7457 typedef struct {
7458 mach_msg_header_t Head;
7459 /* start of the kernel processed data */
7460 mach_msg_body_t msgh_body;
7461 mach_msg_port_descriptor_t src_task;
7462 /* end of the kernel processed data */
7463 NDR_record_t NDR;
7464 mach_vm_address_t target_address;
7465 mach_vm_size_t size;
7466 mach_vm_offset_t mask;
7467 int flags;
7468 mach_vm_address_t src_address;
7469 boolean_t copy;
7470 vm_inherit_t inheritance;
7471 } Request;
7472 #pragma pack()
7474 Request *req = (Request *)ARG1;
7476 // GrP fixme check these
7477 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7478 name_for_port(MACH_REMOTE),
7479 req->target_address, req->size,
7480 name_for_port(req->src_task.name));
7482 MACH_ARG(mach_vm_remap.size) = req->size;
7483 MACH_ARG(mach_vm_remap.copy) = req->copy;
7485 AFTER = POST_FN(mach_vm_remap);
7488 POST(mach_vm_remap)
7490 #pragma pack(4)
7491 typedef struct {
7492 mach_msg_header_t Head;
7493 NDR_record_t NDR;
7494 kern_return_t RetCode;
7495 mach_vm_address_t target_address;
7496 vm_prot_t cur_protection;
7497 vm_prot_t max_protection;
7498 } Reply;
7499 #pragma pack()
7501 Reply *reply = (Reply *)ARG1;
7503 if (!reply->RetCode) {
7504 // GrP fixme check src and dest tasks
7505 PRINT("mapped at 0x%llx", reply->target_address);
7506 // GrP fixme max prot
7507 ML_(notify_core_and_tool_of_mmap)(
7508 reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
7509 reply->cur_protection, VKI_MAP_SHARED, -1, 0);
7510 // GrP fixme VKI_MAP_PRIVATE if !copy?
7511 } else {
7512 PRINT("mig return %d", reply->RetCode);
7517 PRE(mach_vm_region_recurse)
7519 #pragma pack(4)
7520 typedef struct {
7521 mach_msg_header_t Head;
7522 NDR_record_t NDR;
7523 mach_vm_address_t address;
7524 natural_t nesting_depth;
7525 mach_msg_type_number_t infoCnt;
7526 } Request;
7527 #pragma pack()
7529 Request *req = (Request *)ARG1;
7531 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7532 name_for_port(MACH_REMOTE),
7533 req->address, req->nesting_depth, req->infoCnt);
7535 AFTER = POST_FN(mach_vm_region_recurse);
7538 POST(mach_vm_region_recurse)
7540 #pragma pack(4)
7541 typedef struct {
7542 mach_msg_header_t Head;
7543 NDR_record_t NDR;
7544 kern_return_t RetCode;
7545 mach_vm_address_t address;
7546 mach_vm_size_t size;
7547 natural_t nesting_depth;
7548 mach_msg_type_number_t infoCnt;
7549 int info[19];
7550 } Reply;
7551 #pragma pack()
7553 Reply *reply = (Reply *)ARG1;
7555 if (!reply->RetCode) {
7556 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7557 reply->address, reply->size,
7558 reply->nesting_depth, reply->infoCnt);
7559 // GrP fixme mark info contents beyond infoCnt as bogus
7560 } else {
7561 PRINT("mig return %d", reply->RetCode);
7566 /* ---------------------------------------------------------------------
7567 mach_msg: messages to thread
7568 ------------------------------------------------------------------ */
7572 POST(thread_terminate)
7577 PRE(thread_terminate)
7579 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7580 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
7582 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
7584 AFTER = POST_FN(thread_terminate);
7586 if (self_terminate) {
7587 // Terminating this thread.
7588 // Copied from sys_exit.
7589 ThreadState *tst = VG_(get_ThreadState)(tid);
7590 tst->exitreason = VgSrc_ExitThread;
7591 tst->os_state.exitcode = 0; // GrP fixme anything better?
7592 // What we would like to do is:
7593 // SET_STATUS_Success(0);
7594 // but that doesn't work, because this is a MACH-class syscall,
7595 // and SET_STATUS_Success creates a UNIX-class syscall result.
7596 // Hence we have to laboriously construct the full SysRes "by hand"
7597 // and use that to set the syscall return status.
7598 #if defined(VGA_x86)
7599 SET_STATUS_from_SysRes(
7600 VG_(mk_SysRes_x86_darwin)(
7601 VG_DARWIN_SYSCALL_CLASS_MACH,
7602 False/*success*/, 0, 0
7605 #elif defined(VGA_amd64)
7606 SET_STATUS_from_SysRes(
7607 VG_(mk_SysRes_amd64_darwin)(
7608 VG_DARWIN_SYSCALL_CLASS_MACH,
7609 False/*success*/, 0, 0
7612 #else
7613 #error unknown architecture
7614 #endif
7615 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
7616 } else {
7617 // Terminating some other thread.
7618 // Do keep the scheduler lock while terminating any other thread.
7619 // Otherwise we might halt the other thread while it holds the lock,
7620 // which would deadlock the process.
7621 // GrP fixme good enough?
7622 // GrP fixme need to clean up other thread's valgrind data?
7627 POST(thread_create)
7632 PRE(thread_create)
7634 PRINT("thread_create(mach_task_self(), ...)");
7636 AFTER = POST_FN(thread_create);
7638 // GrP fixme
7639 VG_(core_panic)("thread_create() unimplemented");
7643 PRE(thread_create_running)
7645 #pragma pack(4)
7646 typedef struct {
7647 mach_msg_header_t Head;
7648 NDR_record_t NDR;
7649 thread_state_flavor_t flavor;
7650 mach_msg_type_number_t new_stateCnt;
7651 natural_t new_state[144];
7652 } Request;
7653 #pragma pack()
7655 Request *req;
7656 thread_state_t regs;
7657 ThreadState *new_thread;
7659 PRINT("thread_create_running(mach_task_self(), ...)");
7661 // The new thread will immediately begin execution,
7662 // so we need to hijack the register state here.
7664 req = (Request *)ARG1;
7665 regs = (thread_state_t)req->new_state;
7667 // Build virtual thread.
7668 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
7670 // Edit the thread state to send to the real kernel.
7671 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
7673 AFTER = POST_FN(thread_create_running);
7677 POST(thread_create_running)
7679 #pragma pack(4)
7680 typedef struct {
7681 mach_msg_header_t Head;
7682 /* start of the kernel processed data */
7683 mach_msg_body_t msgh_body;
7684 mach_msg_port_descriptor_t child_act;
7685 /* end of the kernel processed data */
7686 } Reply;
7687 #pragma pack()
7689 Reply *reply = (Reply *)ARG1;
7691 assign_port_name(reply->child_act.name, "thread-%p");
7692 PRINT("%s", name_for_port(reply->child_act.name));
7696 PRE(bsdthread_create)
7698 ThreadState *tst;
7700 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7701 ARG1, ARG2, ARG3, ARG4, ARG5);
7702 PRE_REG_READ5(pthread_t,"bsdthread_create",
7703 void *,"func", void *,"func_arg", void *,"stack",
7704 pthread_t,"thread", unsigned int,"flags");
7706 // The kernel will call V's pthread_hijack() to launch the thread.
7707 // Here we allocate the thread state and pass it to pthread_hijack()
7708 // via the func_arg parameter.
7710 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
7711 allocstack(tst->tid);
7713 tst->os_state.func_arg = (Addr)ARG2;
7714 ARG2 = (Word)tst;
7716 // Create a semaphore that pthread_hijack will signal once it starts
7717 // POST(bsdthread_create) needs to wait for the new memory map to appear
7718 semaphore_create(mach_task_self(), &tst->os_state.child_go,
7719 SYNC_POLICY_FIFO, 0);
7720 semaphore_create(mach_task_self(), &tst->os_state.child_done,
7721 SYNC_POLICY_FIFO, 0);
7724 POST(bsdthread_create)
7726 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7727 // We hold V's lock on the child's behalf.
7728 // If we return before letting pthread_hijack do its thing, V thinks
7729 // the new pthread struct is still unmapped when we return to libc,
7730 // causing false errors.
7732 ThreadState *tst = (ThreadState *)ARG2;
7733 semaphore_signal(tst->os_state.child_go);
7734 semaphore_wait(tst->os_state.child_done);
7735 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
7736 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
7738 // GrP fixme semaphore destroy needed when thread creation fails
7739 // GrP fixme probably other cleanup too
7740 // GrP fixme spinlocks might be good enough?
7742 // DDD: I'm not at all sure this is the right spot for this. It probably
7743 // should be in pthread_hijack instead, just before the call to
7744 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7745 // parent tid value there...
7746 vg_assert(VG_(owns_BigLock_LL)(tid));
7747 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
7751 PRE(bsdthread_terminate)
7753 ThreadState *tst;
7755 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7756 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
7757 PRE_REG_READ4(int,"bsdthread_terminate",
7758 void *,"freeaddr", size_t,"freesize",
7759 mach_port_t,"kport", mach_port_t,"joinsem");
7761 // Free memory and signal semaphore.
7762 // GrP fixme errors?
7763 if (ARG4) semaphore_signal((semaphore_t)ARG4);
7764 if (ARG1 && ARG2) {
7765 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
7766 # if DARWIN_VERS >= DARWIN_10_8
7767 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7768 the mig output. Work around it for the time being. */
7769 VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
7770 # else
7771 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
7772 # endif
7775 // Tell V to terminate the thread.
7776 // Copied from sys_exit.
7777 tst = VG_(get_ThreadState)(tid);
7778 tst->exitreason = VgSrc_ExitThread;
7779 tst->os_state.exitcode = 0; // GrP fixme anything better?
7780 SET_STATUS_Success(0);
7784 POST(thread_suspend)
7788 PRE(thread_suspend)
7790 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7791 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
7793 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
7795 AFTER = POST_FN(thread_suspend);
7797 if (self_suspend) {
7798 // Don't keep the scheduler lock while self-suspending.
7799 // Otherwise we might halt while still holding the lock,
7800 // which would deadlock the process.
7801 *flags |= SfMayBlock;
7802 } else {
7803 // Do keep the scheduler lock while suspending any other thread.
7804 // Otherwise we might halt the other thread while it holds the lock,
7805 // which would deadlock the process.
7806 *flags &= ~SfMayBlock;
7811 POST(thread_resume)
7815 PRE(thread_resume)
7817 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7818 Bool self_resume = (mh->msgh_request_port == MACH_THREAD);
7820 PRINT("thread_resume(%s)", name_for_port(mh->msgh_request_port));
7822 AFTER = POST_FN(thread_resume);
7824 if (self_resume) {
7825 // This doesn't make much sense. If we are resuming ourself, we can't
7826 // already be running. So I don't see how we can ever get here.
7827 vg_assert(0);
7828 } else {
7829 // Resuming some other thread. It might not yet come back to life
7830 // (if the suspend count is still above zero) so make sure we keep
7831 // holding the lock.
7832 *flags &= ~SfMayBlock;
7837 POST(thread_get_state)
7839 #pragma pack(4)
7840 typedef struct {
7841 mach_msg_header_t Head;
7842 NDR_record_t NDR;
7843 kern_return_t RetCode;
7844 mach_msg_type_number_t old_stateCnt;
7845 natural_t old_state[144];
7846 mach_msg_trailer_t trailer;
7847 } Reply;
7848 #pragma pack()
7850 Reply *reply = (Reply *)ARG1;
7851 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7852 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
7854 if (!reply->RetCode) {
7855 thread_state_from_vex((thread_state_t)reply->old_state,
7856 flavor, reply->old_stateCnt,
7857 &VG_(get_ThreadState)(tid)->arch.vex);
7858 } else {
7859 PRINT("mig return %d", reply->RetCode);
7863 PRE(thread_get_state)
7865 #pragma pack(4)
7866 typedef struct {
7867 mach_msg_header_t Head;
7868 NDR_record_t NDR;
7869 thread_state_flavor_t flavor;
7870 mach_msg_type_number_t old_stateCnt;
7871 } Request;
7872 #pragma pack()
7874 Request *req = (Request *)ARG1;
7875 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7877 // GrP fixme if (self) {
7878 PRINT("thread_get_state(%s, %d)",
7879 name_for_port(req->Head.msgh_request_port), req->flavor);
7880 /*} else {
7881 PRINT("thread_get_state(0x%x, %d)",
7882 req->Head.msgh_request_port, req->flavor);
7885 // Hack the thread state after making the real call.
7886 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
7887 MACH_ARG(thread_get_state.flavor) = req->flavor;
7889 AFTER = POST_FN(thread_get_state);
7893 PRE(thread_policy)
7895 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7896 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7898 // GrP fixme if (self) {
7899 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
7900 /*} else {
7901 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7904 AFTER = POST_FN(thread_policy);
7907 POST(thread_policy)
7912 PRE(thread_policy_set)
7914 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7916 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
7918 AFTER = POST_FN(thread_policy_set);
7921 POST(thread_policy_set)
7926 PRE(thread_info)
7928 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7930 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
7931 // GrP fixme does any thread info need to be hijacked?
7933 AFTER = POST_FN(thread_info);
7936 POST(thread_info)
7938 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7943 /* ---------------------------------------------------------------------
7944 mach_msg: messages to bootstrap port
7945 ------------------------------------------------------------------ */
7948 POST(bootstrap_register)
7950 #pragma pack(4)
7951 typedef struct {
7952 mach_msg_header_t Head;
7953 NDR_record_t NDR;
7954 kern_return_t RetCode;
7955 mach_msg_trailer_t trailer;
7956 } Reply;
7957 #pragma pack()
7959 Reply *reply = (Reply *)ARG1;
7961 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
7964 PRE(bootstrap_register)
7966 #pragma pack(4)
7967 typedef struct {
7968 mach_msg_header_t Head;
7969 /* start of the kernel processed data */
7970 mach_msg_body_t msgh_body;
7971 mach_msg_port_descriptor_t service_port;
7972 /* end of the kernel processed data */
7973 NDR_record_t NDR;
7974 name_t service_name;
7975 } Request;
7976 #pragma pack()
7978 Request *req = (Request *)ARG1;
7980 PRINT("bootstrap_register(port 0x%x, \"%s\")",
7981 req->service_port.name, req->service_name);
7983 /* The required entry in the allocated_ports list (mapping) might
7984 not exist, due perhaps to broken syscall wrappers (mach__N etc).
7985 Create a minimal entry so that assign_port_name below doesn't
7986 cause an assertion. */
7987 if (!port_exists(req->service_port.name)) {
7988 port_create_vanilla(req->service_port.name);
7991 assign_port_name(req->service_port.name, req->service_name);
7993 AFTER = POST_FN(bootstrap_register);
7997 POST(bootstrap_look_up)
7999 #pragma pack(4)
8000 typedef struct {
8001 mach_msg_header_t Head;
8002 /* start of the kernel processed data */
8003 mach_msg_body_t msgh_body;
8004 mach_msg_port_descriptor_t service_port;
8005 /* end of the kernel processed data */
8006 mach_msg_trailer_t trailer;
8007 } Reply;
8008 #pragma pack()
8010 Reply *reply = (Reply *)ARG1;
8012 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
8013 reply->service_port.name)
8015 assign_port_name(reply->service_port.name,
8016 MACH_ARG(bootstrap_look_up.service_name));
8017 PRINT("%s", name_for_port(reply->service_port.name));
8018 } else {
8019 PRINT("not found");
8021 VG_(free)(MACH_ARG(bootstrap_look_up.service_name));
8024 PRE(bootstrap_look_up)
8026 #pragma pack(4)
8027 typedef struct {
8028 mach_msg_header_t Head;
8029 NDR_record_t NDR;
8030 name_t service_name;
8031 } Request;
8032 #pragma pack()
8034 Request *req = (Request *)ARG1;
8036 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
8038 MACH_ARG(bootstrap_look_up.service_name) =
8039 VG_(strdup)("syswrap-darwin.bootstrap-name", req->service_name);
8041 AFTER = POST_FN(bootstrap_look_up);
8045 /* ---------------------------------------------------------------------
8046 mach_msg: receiver-specific handlers
8047 ------------------------------------------------------------------ */
8050 POST(mach_msg_receive)
8052 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8054 // GrP fixme don't know of anything interesting here currently
8055 // import_complex_message handles everything
8056 // PRINT("UNHANDLED reply %d", mh->msgh_id);
8058 // Assume the call may have mapped or unmapped memory
8059 ML_(sync_mappings)("after", "mach_msg_receive", mh->msgh_id);
8062 PRE(mach_msg_receive)
8064 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8066 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
8068 AFTER = POST_FN(mach_msg_receive);
8070 // no message sent, only listening for a reply
8071 // assume message may block
8072 *flags |= SfMayBlock;
8076 PRE(mach_msg_bootstrap)
8078 // message to bootstrap port
8080 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8082 switch (mh->msgh_id) {
8083 case 403:
8084 CALL_PRE(bootstrap_register);
8085 return;
8086 case 404:
8087 CALL_PRE(bootstrap_look_up);
8088 return;
8090 default:
8091 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
8092 mh->msgh_id, name_for_port(mh->msgh_request_port),
8093 mh->msgh_reply_port);
8094 return;
8099 PRE(mach_msg_host)
8101 // message to host self - check for host-level kernel calls
8103 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8105 switch (mh->msgh_id) {
8106 case 200:
8107 CALL_PRE(host_info);
8108 return;
8109 case 202:
8110 CALL_PRE(host_page_size);
8111 return;
8112 case 205:
8113 CALL_PRE(host_get_io_master);
8114 return;
8115 case 206:
8116 CALL_PRE(host_get_clock_service);
8117 return;
8118 case 217:
8119 CALL_PRE(host_request_notification);
8120 return;
8121 case 222:
8122 CALL_PRE(host_create_mach_voucher);
8123 return;
8125 case 412:
8126 CALL_PRE(host_get_special_port);
8127 return;
8129 default:
8130 // unknown message to host self
8131 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
8132 mh->msgh_id, name_for_port(mh->msgh_request_port),
8133 mh->msgh_reply_port);
8134 return;
8138 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
8139 // /usr/include/mach/mach_port.h et al (grep in /usr/include
8140 // for them)
8141 PRE(mach_msg_task)
8143 // message to a task port
8145 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8147 switch (mh->msgh_id) {
8148 case 3201:
8149 CALL_PRE(mach_port_type);
8150 return;
8151 case 3204:
8152 CALL_PRE(mach_port_allocate);
8153 return;
8154 case 3205:
8155 CALL_PRE(mach_port_destroy);
8156 return;
8157 case 3206:
8158 CALL_PRE(mach_port_deallocate);
8159 return;
8160 case 3207:
8161 CALL_PRE(mach_port_get_refs);
8162 return;
8163 case 3208:
8164 CALL_PRE(mach_port_mod_refs);
8165 return;
8166 case 3211:
8167 CALL_PRE(mach_port_get_set_status);
8168 return;
8169 case 3212:
8170 CALL_PRE(mach_port_move_member);
8171 return;
8172 case 3213:
8173 CALL_PRE(mach_port_request_notification);
8174 return;
8175 case 3214:
8176 CALL_PRE(mach_port_insert_right);
8177 return;
8178 case 3215:
8179 CALL_PRE(mach_port_extract_right);
8180 return;
8181 case 3217:
8182 CALL_PRE(mach_port_get_attributes);
8183 return;
8184 case 3218:
8185 CALL_PRE(mach_port_set_attributes);
8186 return;
8187 case 3226:
8188 CALL_PRE(mach_port_insert_member);
8189 return;
8190 case 3227:
8191 CALL_PRE(mach_port_extract_member);
8192 return;
8194 case 3229:
8195 CALL_PRE(mach_port_set_context);
8196 return;
8198 case 3402:
8199 CALL_PRE(task_threads);
8200 return;
8201 case 3403:
8202 CALL_PRE(mach_ports_register);
8203 return;
8204 case 3404:
8205 CALL_PRE(mach_ports_lookup);
8206 return;
8207 case 3405:
8208 CALL_PRE(task_info);
8209 return;
8210 case 3406:
8211 CALL_PRE(task_set_info);
8212 return;
8213 case 3407:
8214 CALL_PRE(task_suspend);
8215 return;
8216 case 3408:
8217 CALL_PRE(task_resume);
8218 return;
8219 case 3409:
8220 CALL_PRE(task_get_special_port);
8221 return;
8222 case 3410:
8223 CALL_PRE(task_set_special_port);
8224 return;
8225 case 3411:
8226 CALL_PRE(thread_create);
8227 return;
8228 case 3412:
8229 CALL_PRE(thread_create_running);
8230 return;
8232 case 3414:
8233 CALL_PRE(task_get_exception_ports);
8234 return;
8236 case 3418:
8237 CALL_PRE(semaphore_create);
8238 return;
8239 case 3419:
8240 CALL_PRE(semaphore_destroy);
8241 return;
8242 case 3420:
8243 CALL_PRE(task_policy_set);
8244 return;
8246 #if DARWIN_VERS >= DARWIN_10_12
8247 case 3444:
8248 CALL_PRE(task_register_dyld_image_infos);
8249 return;
8251 case 3447:
8252 CALL_PRE(task_register_dyld_shared_cache_image_info);
8253 return;
8254 #endif /* DARWIN_VERS >= DARWIN_10_12 */
8256 case 3801:
8257 CALL_PRE(vm_allocate);
8258 return;
8259 case 3802:
8260 CALL_PRE(vm_deallocate);
8261 return;
8262 case 3803:
8263 CALL_PRE(vm_protect);
8264 return;
8265 case 3804:
8266 CALL_PRE(vm_inherit);
8267 return;
8268 case 3805:
8269 CALL_PRE(vm_read);
8270 return;
8271 case 3808:
8272 CALL_PRE(vm_copy);
8273 return;
8274 case 3809:
8275 CALL_PRE(vm_read_overwrite);
8276 return;
8277 case 3812:
8278 CALL_PRE(vm_map);
8279 return;
8280 case 3814:
8281 CALL_PRE(vm_remap);
8282 return;
8283 case 3825:
8284 CALL_PRE(mach_make_memory_entry_64);
8285 return;
8286 case 3830:
8287 CALL_PRE(vm_purgable_control);
8288 return;
8290 case 4800:
8291 CALL_PRE(mach_vm_allocate);
8292 return;
8293 case 4801:
8294 CALL_PRE(mach_vm_deallocate);
8295 return;
8296 case 4802:
8297 CALL_PRE(mach_vm_protect);
8298 return;
8299 case 4803:
8300 CALL_PRE(mach_vm_inherit);
8301 return;
8302 case 4804:
8303 CALL_PRE(mach_vm_read);
8304 return;
8305 case 4807:
8306 CALL_PRE(mach_vm_copy);
8307 return;
8308 case 4808:
8309 CALL_PRE(mach_vm_read_overwrite);
8310 return;
8311 case 4811:
8312 CALL_PRE(mach_vm_map);
8313 return;
8314 case 4813:
8315 CALL_PRE(mach_vm_remap);
8316 return;
8317 case 4815:
8318 CALL_PRE(mach_vm_region_recurse);
8319 return;
8320 case 4817:
8321 CALL_PRE(mach_make_memory_entry_64);
8322 return;
8323 case 4818:
8324 CALL_PRE(mach_vm_purgable_control);
8325 return;
8327 default:
8328 // unknown message to task self
8329 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
8330 mh->msgh_id, name_for_port(mh->msgh_remote_port),
8331 mh->msgh_reply_port);
8332 return;
8337 PRE(mach_msg_thread)
8339 // message to local thread - check for thread-level kernel calls
8341 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8343 switch (mh->msgh_id) {
8344 case 3600:
8345 CALL_PRE(thread_terminate);
8346 return;
8347 case 3603:
8348 CALL_PRE(thread_get_state);
8349 return;
8350 case 3605:
8351 CALL_PRE(thread_suspend);
8352 return;
8353 case 3606:
8354 CALL_PRE(thread_resume);
8355 return;
8356 case 3612:
8357 CALL_PRE(thread_info);
8358 return;
8359 case 3616:
8360 CALL_PRE(thread_policy);
8361 return;
8362 case 3617:
8363 CALL_PRE(thread_policy_set);
8364 return;
8365 default:
8366 // unknown message to a thread
8367 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
8368 mh->msgh_id, name_for_port(mh->msgh_request_port),
8369 mh->msgh_reply_port);
8370 return;
8375 static int is_thread_port(mach_port_t port)
8377 if (port == 0) return False;
8379 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
8383 static int is_task_port(mach_port_t port)
8385 if (port == 0) return False;
8387 if (port == vg_task_port) return True;
8389 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
8393 /* ---------------------------------------------------------------------
8394 mach_msg: base handlers
8395 ------------------------------------------------------------------ */
8397 PRE(mach_msg)
8399 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8400 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8401 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8402 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
8403 // mach_port_t rcv_name = (mach_port_t)ARG5;
8404 size_t complex_header_size = 0;
8406 PRE_REG_READ7(long, "mach_msg",
8407 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
8408 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
8409 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
8410 mach_port_t,"notify");
8412 // Assume default POST handler until specified otherwise
8413 AFTER = NULL;
8415 // Assume call may block unless specified otherwise
8416 *flags |= SfMayBlock;
8418 if (option & MACH_SEND_MSG) {
8419 // Validate outgoing message header
8420 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8421 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
8422 // msgh_size not required, use parameter instead
8423 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8424 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
8425 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8426 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
8427 // msgh_reserved not required
8428 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8429 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
8431 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8432 // Validate typed message data and handle memory map changes.
8433 complex_header_size = export_complex_message(tid, mh);
8436 // GrP fixme handle sender-specified message trailer
8437 // (but is this only for too-secure processes?)
8438 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8439 # if DARWIN_VERS >= DARWIN_10_10
8440 if (mh->msgh_bits & MACH_SEND_TRAILER) {
8441 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8443 # else
8444 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
8445 # endif
8447 MACH_REMOTE = mh->msgh_remote_port;
8448 MACH_MSGH_ID = mh->msgh_id;
8451 if (option & MACH_RCV_MSG) {
8452 // Pre-validate receive buffer
8453 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
8456 // Call a PRE handler. The PRE handler may set an AFTER handler.
8458 if (!(option & MACH_SEND_MSG)) {
8459 // no message sent, receive only
8460 CALL_PRE(mach_msg_receive);
8461 return;
8463 else if (mh->msgh_request_port == vg_host_port) {
8464 // message sent to mach_host_self()
8465 CALL_PRE(mach_msg_host);
8466 return;
8468 else if (is_task_port(mh->msgh_request_port)) {
8469 // message sent to a task
8470 CALL_PRE(mach_msg_task);
8471 return;
8473 else if (mh->msgh_request_port == vg_bootstrap_port) {
8474 // message sent to bootstrap port
8475 CALL_PRE(mach_msg_bootstrap);
8476 return;
8478 else if (is_thread_port(mh->msgh_request_port)) {
8479 // message sent to one of this process's threads
8480 CALL_PRE(mach_msg_thread);
8481 return;
8483 else {
8484 // this is an attempt to optimize mapping sync
8485 // but there are always some cases hard to find
8486 #if 0
8487 Bool do_mapping_update = False;
8488 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8489 // which is obviously not true...
8490 switch (mh->msgh_id) {
8491 // com.apple.windowserver.active
8492 case 29008: // this one opens a port type 'a'
8494 // com.apple.windowserver.active 'a' port
8495 case 29000:
8496 case 29822:
8497 case 29820: // adds a vm mapping
8498 case 29809: // contains a ool mem
8499 case 29800: // opens a port type 'b'
8500 case 29873:
8501 case 29876: // adds a vm mapping
8503 // com.apple.windowserver.active 'b' port
8504 case 29624:
8505 case 29625:
8506 case 29506:
8507 case 29504:
8508 case 29509:
8509 case 29315:
8510 case 29236:
8511 case 29473:
8512 case 29268:
8513 case 29237: // contains a ool mem
8514 case 29360:
8515 case 29301:
8516 case 29287:
8517 case 29568:
8518 case 29570: // contains a ool mem
8519 case 29211:
8520 case 29569: // contains a ool mem
8521 case 29374:
8522 case 29246:
8523 case 29239:
8524 case 29272:
8525 if (mh->msgh_id == 29820 ||
8526 mh->msgh_id == 29876)
8527 do_mapping_update = True;
8529 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8530 mh->msgh_id, name_for_port(mh->msgh_request_port),
8531 mh->msgh_reply_port);
8532 break;
8534 // com.apple.FontServer
8535 case 13024:
8536 PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
8537 mh->msgh_id, name_for_port(mh->msgh_request_port),
8538 mh->msgh_reply_port);
8539 break;
8541 // com.apple.system.notification_center
8542 case 78945698:
8543 case 78945701:
8544 case 78945695: // contains a ool mem
8545 case 78945694:
8546 case 78945700:
8547 if (mh->msgh_id == 78945695)
8548 do_mapping_update = False;
8549 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8550 mh->msgh_id, name_for_port(mh->msgh_request_port),
8551 mh->msgh_reply_port);
8552 break;
8554 // com.apple.CoreServices.coreservicesd
8555 case 10000:
8556 case 10019:
8557 case 10002: // adds vm mappings
8558 case 10003: // adds vm mappings
8559 case 14007:
8560 case 13000:
8561 case 13001:
8562 case 13011:
8563 case 13016: // contains a ool mem
8564 if (mh->msgh_id == 10002||
8565 mh->msgh_id == 10003)
8566 do_mapping_update = True;
8567 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8568 mh->msgh_id, name_for_port(mh->msgh_request_port),
8569 mh->msgh_reply_port);
8570 break;
8572 // com.apple.system.logger
8573 case 118:
8574 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8575 mh->msgh_id, name_for_port(mh->msgh_request_port),
8576 mh->msgh_reply_port);
8577 break;
8579 // com.apple.coreservices.launchservicesd, and others
8580 case 1999646836: // might adds vm mapping
8581 if (mh->msgh_id == 1999646836)
8582 do_mapping_update = True;
8583 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8584 mh->msgh_id, name_for_port(mh->msgh_request_port),
8585 mh->msgh_reply_port);
8586 break;
8588 // com.apple.ocspd
8589 case 33012:
8590 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8591 mh->msgh_id, name_for_port(mh->msgh_request_port),
8592 mh->msgh_reply_port);
8594 default:
8595 // arbitrary message to arbitrary port
8596 do_mapping_update = True;
8597 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
8598 mh->msgh_id, name_for_port(mh->msgh_request_port),
8599 mh->msgh_reply_port);
8602 // this is an optimization, don't check mapping on known mach_msg
8603 if (do_mapping_update)
8604 AFTER = POST_FN(mach_msg_unhandled);
8605 else
8606 AFTER = POST_FN(mach_msg_unhandled_check);
8607 #else
8608 AFTER = POST_FN(mach_msg_unhandled);
8609 #endif
8611 // Assume the entire message body may be read.
8612 // GrP fixme generates false positives for unknown protocols
8614 PRE_MEM_READ("mach_msg(payload)",
8615 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8616 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8618 return;
8622 POST(mach_msg)
8624 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8625 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8627 if (option & MACH_RCV_MSG) {
8628 if (RES != 0) {
8629 // error during send or receive
8630 // GrP fixme need to clean up port rights?
8631 } else {
8632 mach_msg_trailer_t *mt =
8633 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
8635 // Assume the entire received message and trailer is initialized
8636 // GrP fixme would being more specific catch any bugs?
8637 POST_MEM_WRITE((Addr)mh,
8638 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
8640 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8641 // Update memory map for out-of-line message data
8642 import_complex_message(tid, mh);
8647 // Call handler chosen by PRE(mach_msg)
8648 if (AFTER) {
8649 (*AFTER)(tid, arrghs, status);
8654 POST(mach_msg_unhandled)
8656 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8657 ML_(sync_mappings)("after", "mach_msg_receive-UNHANDLED", mh->msgh_id);
8660 POST(mach_msg_unhandled_check)
8662 if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
8663 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
8667 /* ---------------------------------------------------------------------
8668 other Mach traps
8669 ------------------------------------------------------------------ */
8671 PRE(mach_reply_port)
8673 PRINT("mach_reply_port()");
8676 POST(mach_reply_port)
8678 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
8679 PRINT("reply port %s", name_for_port(RES));
8683 PRE(mach_thread_self)
8685 PRINT("mach_thread_self()");
8688 POST(mach_thread_self)
8690 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
8691 PRINT("thread %#lx", RES);
8695 PRE(mach_host_self)
8697 PRINT("mach_host_self()");
8700 POST(mach_host_self)
8702 vg_host_port = RES;
8703 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
8704 PRINT("host %#lx", RES);
8708 PRE(mach_task_self)
8710 PRINT("mach_task_self()");
8713 POST(mach_task_self)
8715 vg_task_port = RES;
8716 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
8717 PRINT("task %#lx", RES);
8721 PRE(syscall_thread_switch)
8723 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8724 name_for_port(ARG1), SARG2, SARG3);
8725 PRE_REG_READ3(long, "syscall_thread_switch",
8726 mach_port_t,"thread", int,"option", natural_t,"timeout");
8728 *flags |= SfMayBlock;
8732 PRE(semaphore_signal)
8734 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
8735 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8739 PRE(semaphore_signal_all)
8741 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
8742 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
8746 PRE(semaphore_signal_thread)
8748 PRINT("semaphore_signal_thread(%s, %s)",
8749 name_for_port(ARG1), name_for_port(ARG2));
8750 PRE_REG_READ2(long, "semaphore_signal_thread",
8751 semaphore_t,"semaphore", mach_port_t,"thread");
8755 PRE(semaphore_wait)
8757 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
8758 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8760 *flags |= SfMayBlock;
8764 PRE(semaphore_wait_signal)
8766 PRINT("semaphore_wait_signal(%s, %s)",
8767 name_for_port(ARG1), name_for_port(ARG2));
8768 PRE_REG_READ2(long, "semaphore_wait_signal",
8769 semaphore_t,"wait_semaphore",
8770 semaphore_t,"signal_semaphore");
8772 *flags |= SfMayBlock;
8776 PRE(semaphore_timedwait)
8778 PRINT("semaphore_timedwait(%s, %g seconds)",
8779 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
8780 PRE_REG_READ3(long, "semaphore_wait_signal",
8781 semaphore_t,"semaphore",
8782 int,"wait_time_hi",
8783 int,"wait_time_lo");
8785 *flags |= SfMayBlock;
8789 PRE(semaphore_timedwait_signal)
8791 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8792 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
8793 PRE_REG_READ4(long, "semaphore_wait_signal",
8794 semaphore_t,"wait_semaphore",
8795 semaphore_t,"signal_semaphore",
8796 int,"wait_time_hi",
8797 int,"wait_time_lo");
8799 *flags |= SfMayBlock;
8803 PRE(__semwait_signal)
8805 /* 10.5 args: int cond_sem, int mutex_sem,
8806 int timeout, int relative,
8807 time_t tv_sec, time_t tv_nsec */
8808 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8809 name_for_port(ARG1), name_for_port(ARG2), SARG3, SARG4, SARG5, SARG6);
8810 PRE_REG_READ6(long, "__semwait_signal",
8811 int,"cond_sem", int,"mutex_sem",
8812 int,"timeout", int,"relative",
8813 vki_time_t,"tv_sec", int,"tv_nsec");
8815 *flags |= SfMayBlock;
8817 // GrP provided this alternative version for 10.6, but NjN
8818 // reckons the 10.5 is is still correct for 10.6. So, retaining
8819 // Greg's version as a comment just in case we need it later.
8820 //PRE(__old_semwait_signal)
8822 // /* 10.5 args: int cond_sem, int mutex_sem,
8823 // int timeout, int relative,
8824 // const timespec *ts */
8825 // PRINT("__old_semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8826 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8827 // PRE_REG_READ5(int, "__old_semwait_signal",
8828 // int,cond_sem, int,mutex_sem,
8829 // int,timeout, int,relative,
8830 // const struct vki_timespec *,ts);
8832 // if (ARG5) PRE_MEM_READ ("__old_semwait_signal(ts)",
8833 // ARG5, sizeof(struct vki_timespec));
8835 // *flags |= SfMayBlock;
8839 PRE(task_for_pid)
8841 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), SARG2, ARG3);
8842 PRE_REG_READ3(long, "task_for_pid",
8843 mach_port_t,"target",
8844 vki_pid_t, "pid", mach_port_t *,"task");
8845 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
8848 POST(task_for_pid)
8850 mach_port_t task;
8852 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
8854 task = *(mach_port_t *)ARG3;
8855 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
8856 PRINT("task 0x%x", task);
8860 PRE(pid_for_task)
8862 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
8863 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
8864 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
8867 POST(pid_for_task)
8869 vki_pid_t pid;
8871 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
8873 pid = *(vki_pid_t *)ARG2;
8874 PRINT("pid %u", pid);
8878 PRE(mach_timebase_info)
8880 PRINT("mach_timebase_info(%#lx)", ARG1);
8881 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8882 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
8885 POST(mach_timebase_info)
8887 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
8891 PRE(mach_wait_until)
8893 #if VG_WORDSIZE == 8
8894 PRINT("mach_wait_until(%lu)", ARG1);
8895 PRE_REG_READ1(long, "mach_wait_until",
8896 unsigned long long,"deadline");
8897 #else
8898 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
8899 PRE_REG_READ2(long, "mach_wait_until",
8900 int,"deadline_hi", int,"deadline_lo");
8901 #endif
8902 *flags |= SfMayBlock;
8906 PRE(mk_timer_create)
8908 PRINT("mk_timer_create()");
8909 PRE_REG_READ0(long, "mk_timer_create");
8912 POST(mk_timer_create)
8914 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
8918 PRE(mk_timer_destroy)
8920 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
8921 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
8923 // Must block to prevent race (other thread allocates and
8924 // notifies after we deallocate but before we notify)
8925 *flags &= ~SfMayBlock;
8928 POST(mk_timer_destroy)
8930 // Must have cleared SfMayBlock in PRE to prevent race
8931 record_port_destroy(ARG1);
8935 PRE(mk_timer_arm)
8937 #if VG_WORDSIZE == 8
8938 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
8939 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
8940 unsigned long,"expire_time");
8941 #else
8942 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
8943 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
8944 int,"expire_time_hi", int,"expire_time_lo");
8945 #endif
8949 PRE(mk_timer_cancel)
8951 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
8952 PRE_REG_READ2(long, "mk_timer_cancel",
8953 mach_port_t,"name", Addr,"result_time");
8954 if (ARG2) {
8955 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
8959 POST(mk_timer_cancel)
8961 if (ARG2) {
8962 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
8967 PRE(iokit_user_client_trap)
8969 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
8970 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
8971 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
8972 mach_port_t,connect, unsigned int,index,
8973 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
8974 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
8976 // can't do anything else with this in general
8977 // might be able to use connect+index to choose something sometimes
8980 POST(iokit_user_client_trap)
8982 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
8986 PRE(swtch)
8988 PRINT("swtch ( )");
8989 PRE_REG_READ0(long, "swtch");
8991 *flags |= SfMayBlock;
8995 PRE(swtch_pri)
8997 PRINT("swtch_pri ( %ld )", SARG1);
8998 PRE_REG_READ1(long, "swtch_pri", int,"pri");
9000 *flags |= SfMayBlock;
9004 PRE(FAKE_SIGRETURN)
9006 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
9007 an explanation of what follows. */
9008 /* This handles the fake signal-return system call created by
9009 sigframe-x86-darwin.c. */
9010 /* See also comments just below on PRE(sigreturn). */
9012 PRINT("FAKE_SIGRETURN ( )");
9014 vg_assert(VG_(is_valid_tid)(tid));
9015 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9016 vg_assert(VG_(is_running_thread)(tid));
9018 /* Remove the signal frame from this thread's (guest) stack,
9019 in the process restoring the pre-signal guest state. */
9020 VG_(sigframe_destroy)(tid, True);
9022 /* Tell the driver not to update the guest state with the "result",
9023 and set a bogus result to keep it happy. */
9024 *flags |= SfNoWriteResult;
9025 SET_STATUS_Success(0);
9027 /* Check to see if any signals arose as a result of this. */
9028 *flags |= SfPollAfter;
9032 PRE(sigreturn)
9034 /* This is the "real" sigreturn. But because we construct all the
9035 signal frames ourselves (of course, in m_sigframe), this cannot
9036 happen as a result of normal signal delivery. I think it
9037 happens only when doing siglongjmp, in which case Darwin's Libc
9038 appears to use it for two different purposes: to mess with the
9039 per-thread sigaltstack flags (as per arg 2), or to restore the
9040 thread's state from a ucontext* (as per arg 1). */
9042 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
9044 vg_assert(VG_(is_valid_tid)(tid));
9045 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9046 vg_assert(VG_(is_running_thread)(tid));
9048 if (ARG2 == VKI_UC_SET_ALT_STACK) {
9049 /* This is confusing .. the darwin kernel sources imply there is
9050 a per-thread on-altstack/not-on-altstack flag, which is set
9051 by this flag. Just ignore it and claim success for the time
9052 being. */
9053 VG_(debugLog)(0, "syswrap-darwin",
9054 "WARNING: Ignoring sigreturn( ..., "
9055 "UC_SET_ALT_STACK );\n");
9056 SET_STATUS_Success(0);
9057 return;
9059 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
9060 /* Ditto */
9061 VG_(debugLog)(0, "syswrap-darwin",
9062 "WARNING: Ignoring sigreturn( ..., "
9063 "UC_RESET_ALT_STACK );\n");
9064 SET_STATUS_Success(0);
9065 return;
9068 /* Otherwise claim this isn't supported. (Could be
9069 catastrophic).
9071 What do we have to do if we do need to support it?
9073 1. Change the second argument of VG_(sigframe_destroy) from
9074 "Bool isRT" to "UInt sysno", so we can pass the syscall
9075 number, so it can distinguish this case from the
9076 __NR_DARWIN_FAKE_SIGRETURN case.
9078 2. In VG_(sigframe_destroy), look at sysno to distinguish the
9079 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
9080 For this case, restore the thread's CPU state (or at least
9081 the integer regs) from the ucontext in ARG1 (and do all the
9082 other "signal-returns" stuff too).
9084 3. For (2), how do we know where the ucontext is? One way is to
9085 temporarily copy ARG1 into this thread's guest_EBX (or any
9086 other int reg), and have VG_(sigframe_destroy) read
9087 guest_EBX. Why is it ok to trash guest_EBX (or any other int
9088 reg)? Because VG_(sigframe_destroy) is just about to
9089 overwrite all the regs anyway -- since the primary purpose of
9090 calling it is to restore the register state from the ucontext
9091 pointed to by ARG1.
9093 Hey, it's uggerly. But at least it's documented.
9095 /* But in the meantime ... */
9096 VG_(debugLog)(0, "syswrap-darwin",
9097 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
9098 VG_(debugLog)(0, "syswrap-darwin",
9099 "WARNING: Thread/program/Valgrind "
9100 "will likely segfault now.\n");
9101 VG_(debugLog)(0, "syswrap-darwin",
9102 "WARNING: Please file a bug report at "
9103 "http://www.valgrind.org.\n");
9104 SET_STATUS_Failure( VKI_ENOSYS );
9108 /* ---------------------------------------------------------------------
9109 machine-dependent traps
9110 ------------------------------------------------------------------ */
9112 #if defined(VGA_x86)
9113 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
9115 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
9116 return VG_(calloc)("syswrap-darwin.ldt", nbytes, 1);
9118 #endif
9120 PRE(thread_fast_set_cthread_self)
9122 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
9123 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
9125 #if defined(VGA_x86)
9126 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
9128 VexGuestX86SegDescr *ldt;
9129 ThreadState *tst = VG_(get_ThreadState)(tid);
9130 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
9131 if (!ldt) {
9132 ldt = alloc_zeroed_x86_LDT();
9133 tst->arch.vex.guest_LDT = (HWord)ldt;
9135 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
9136 ldt[6].LdtEnt.Bits.LimitLow = 1;
9137 ldt[6].LdtEnt.Bits.LimitHi = 0;
9138 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
9139 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
9140 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
9141 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
9142 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
9143 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
9144 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
9145 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
9147 tst->os_state.pthread = ARG1;
9148 tst->arch.vex.guest_GS = 0x37;
9150 // What we would like to do is:
9151 // SET_STATUS_Success(0x37);
9152 // but that doesn't work, because this is a MDEP-class syscall,
9153 // and SET_STATUS_Success creates a UNIX-class syscall result.
9154 // Hence we have to laboriously construct the full SysRes "by hand"
9155 // and use that to set the syscall return status.
9156 SET_STATUS_from_SysRes(
9157 VG_(mk_SysRes_x86_darwin)(
9158 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9159 False, 0, 0x37
9164 #elif defined(VGA_amd64)
9165 // GrP fixme bigger hack than x86
9167 ThreadState *tst = VG_(get_ThreadState)(tid);
9168 tst->os_state.pthread = ARG1;
9169 tst->arch.vex.guest_GS_CONST = ARG1;
9170 // SET_STATUS_Success(0x60);
9171 // see comments on x86 case just above
9172 SET_STATUS_from_SysRes(
9173 VG_(mk_SysRes_amd64_darwin)(
9174 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9175 False, 0, 0x60
9180 #else
9181 #error unknown architecture
9182 #endif
9186 /* ---------------------------------------------------------------------
9187 Added for OSX 10.6 (Snow Leopard)
9188 ------------------------------------------------------------------ */
9190 #if DARWIN_VERS >= DARWIN_10_6
9192 PRE(psynch_mutexwait)
9194 PRINT("psynch_mutexwait(BOGUS)");
9195 *flags |= SfMayBlock;
9197 POST(psynch_mutexwait)
9201 PRE(psynch_mutexdrop)
9203 PRINT("psynch_mutexdrop(BOGUS)");
9204 *flags |= SfMayBlock;
9206 POST(psynch_mutexdrop)
9210 PRE(psynch_cvbroad)
9212 PRINT("psynch_cvbroad(BOGUS)");
9214 POST(psynch_cvbroad)
9218 PRE(psynch_cvsignal)
9220 PRINT("psynch_cvsignal(BOGUS)");
9222 POST(psynch_cvsignal)
9226 PRE(psynch_cvwait)
9228 PRINT("psynch_cvwait(BOGUS)");
9229 *flags |= SfMayBlock;
9231 POST(psynch_cvwait)
9235 PRE(psynch_rw_rdlock)
9237 PRINT("psynch_rw_rdlock(BOGUS)");
9238 *flags |= SfMayBlock;
9240 POST(psynch_rw_rdlock)
9244 PRE(psynch_rw_wrlock)
9246 PRINT("psynch_rw_wrlock(BOGUS)");
9247 *flags |= SfMayBlock;
9249 POST(psynch_rw_wrlock)
9253 PRE(psynch_rw_unlock)
9255 PRINT("psynch_rw_unlock(BOGUS)");
9257 POST(psynch_rw_unlock)
9261 PRE(__thread_selfid)
9263 PRINT("__thread_selfid ()");
9264 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
9267 PRE(fsgetpath)
9269 #if VG_WORDSIZE == 4
9270 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
9271 ARG1, ARG2, ARG3,
9272 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
9273 LOHI64(ARG4, ARG5));
9274 PRE_REG_READ5(ssize_t, "fsgetpath",
9275 void*,"buf", size_t,"bufsize",
9276 fsid_t *,"fsid",
9277 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
9278 #else
9279 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
9280 ARG1, ARG2, ARG3,
9281 ((unsigned int *)ARG3)[0],
9282 ((unsigned int *)ARG3)[1], ARG4);
9283 PRE_REG_READ4(ssize_t, "fsgetpath",
9284 void*,"buf", size_t,"bufsize",
9285 fsid_t *,"fsid", uint64_t,"objid");
9286 #endif
9287 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
9288 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
9291 POST(fsgetpath)
9293 POST_MEM_WRITE(ARG1, RES);
9296 PRE(audit_session_self)
9298 PRINT("audit_session_self()");
9300 POST(audit_session_self)
9302 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
9303 PRINT("audit-session %#lx", RES);
9306 #endif /* DARWIN_VERS >= DARWIN_10_6 */
9309 /* ---------------------------------------------------------------------
9310 Added for OSX 10.7 (Lion)
9311 ------------------------------------------------------------------ */
9313 #if DARWIN_VERS >= DARWIN_10_7
9315 PRE(psynch_cvclrprepost)
9317 PRINT("psynch_cvclrprepost(BOGUS)");
9318 *flags |= SfMayBlock;
9320 POST(psynch_cvclrprepost)
9324 #endif /* DARWIN_VERS >= DARWIN_10_7 */
9327 /* ---------------------------------------------------------------------
9328 Added for OSX 10.8 (Mountain Lion)
9329 ------------------------------------------------------------------ */
9331 /* About munge tags, eg munge_wllww.
9333 Means the syscall takes 5 args. For a 64 bit process each arg
9334 occupies one 64-bit value and so the mapping to ARGn macros is
9335 direct. For a 32 bit process, this is more complex: 'w' denotes a
9336 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
9337 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
9338 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
9339 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
9340 in order to get sane values for the arguments in 32-bit
9341 processes. */
9343 static void munge_wwl(UWord* a1, UWord* a2, ULong* a3,
9344 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4)
9346 # if defined(VGA_x86)
9347 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4);
9348 # else
9349 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9350 # endif
9353 static void munge_wll(UWord* a1, ULong* a2, ULong* a3,
9354 UWord aRG1, UWord aRG2, UWord aRG3,
9355 UWord aRG4, UWord aRG5)
9357 # if defined(VGA_x86)
9358 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9359 # else
9360 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9361 # endif
9364 static void munge_wwlw(UWord* a1, UWord* a2, ULong* a3, UWord* a4,
9365 UWord aRG1, UWord aRG2, UWord aRG3,
9366 UWord aRG4, UWord aRG5)
9368 # if defined(VGA_x86)
9369 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4); *a4 = aRG5;
9370 # else
9371 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9372 # endif
9375 static void munge_wwwl(UWord* a1, UWord* a2, UWord* a3, ULong* a4,
9376 UWord aRG1, UWord aRG2, UWord aRG3,
9377 UWord aRG4, UWord aRG5)
9379 # if defined(VGA_x86)
9380 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = LOHI64(aRG4,aRG5);
9381 # else
9382 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9383 # endif
9386 static void munge_wllww(UWord* a1, ULong* a2, ULong* a3, UWord* a4, UWord* a5,
9387 UWord aRG1, UWord aRG2, UWord aRG3,
9388 UWord aRG4, UWord aRG5, UWord aRG6, UWord aRG7)
9390 # if defined(VGA_x86)
9391 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9392 *a4 = aRG6; *a5 = aRG7;
9393 # else
9394 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5;
9395 # endif
9398 static void munge_wwllww(UWord* a1, UWord* a2, ULong* a3,
9399 ULong* a4, UWord* a5, UWord* a6,
9400 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4,
9401 UWord aRG5, UWord aRG6, UWord aRG7, UWord aRG8)
9403 # if defined(VGA_x86)
9404 *a1 = aRG1; *a2 = aRG2;
9405 *a3 = LOHI64(aRG3,aRG4); *a4 = LOHI64(aRG5,aRG6);
9406 *a5 = aRG7; *a6 = aRG8;
9407 # else
9408 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5; *a6 = aRG6;
9409 # endif
9412 #if DARWIN_VERS >= DARWIN_10_8
9414 PRE(kernelrpc_mach_vm_allocate_trap)
9416 UWord a1; UWord a2; ULong a3; UWord a4;
9417 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9418 PRINT("kernelrpc_mach_vm_allocate_trap"
9419 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
9420 name_for_port(a1), *(void**)a2, a3, a4);
9421 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
9422 a2, sizeof(void*));
9424 POST(kernelrpc_mach_vm_allocate_trap)
9426 UWord a1; UWord a2; ULong a3; UWord a4;
9427 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9428 PRINT("address:%p size:%#llx", *(void**)a2, a3);
9429 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9430 POST_MEM_WRITE(a2, sizeof(void*));
9432 if (a1 == mach_task_self()) {
9433 # if 1
9434 ML_(sync_mappings)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
9435 # else
9436 /* This is nearly right, but not always -- sometimes the mapping
9437 appears to be r--, for some reason. Hence resync. */
9438 ML_(notify_core_and_tool_of_mmap)(
9439 *(UWord*)a2, a3,
9440 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9441 # endif
9445 PRE(kernelrpc_mach_vm_deallocate_trap)
9447 UWord a1; ULong a2; ULong a3;
9448 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9449 PRINT("kernelrpc_mach_vm_deallocate_trap"
9450 "(target:%#lx, address:%#llx, size:%#llx)", a1, a2, a3);
9452 POST(kernelrpc_mach_vm_deallocate_trap)
9454 UWord a1; ULong a2; ULong a3;
9455 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9456 // kernelrpc_mach_vm_deallocate_trap could be call with
9457 // address ==0 && size == 0,
9458 // we shall not notify any unmap then
9459 if (a3)
9460 ML_(notify_core_and_tool_of_munmap)(a2, a3);
9463 PRE(kernelrpc_mach_vm_protect_trap)
9465 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9466 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9467 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9468 PRINT("kernelrpc_mach_vm_protect_trap"
9469 "(task:%#lx, address:%#llx, size:%#llx,"
9470 " set_maximum:%#lx, new_prot:%#lx)", a1, a2, a3, a4, a5);
9472 POST(kernelrpc_mach_vm_protect_trap)
9474 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9475 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9476 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9477 if (/*a4 set_maximum == 0 && */a1 == mach_task_self()) {
9478 ML_(notify_core_and_tool_of_mprotect)((Addr)a2, (SizeT)a3, (Int)a5);
9479 VG_(di_notify_vm_protect)((Addr)a2, (SizeT)a3, (UInt)a5);
9483 PRE(kernelrpc_mach_port_allocate_trap)
9485 // munge_www -- no need to call helper
9486 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9487 ARG1, ARG2);
9488 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9489 ARG3, sizeof(mach_port_name_t));
9491 POST(kernelrpc_mach_port_allocate_trap)
9493 // munge_www -- no need to call helper
9494 POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
9495 PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
9496 record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
9499 PRE(kernelrpc_mach_port_destroy_trap)
9501 // munge_ww -- no need to call helper
9502 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
9503 record_port_destroy(ARG2);
9506 PRE(kernelrpc_mach_port_deallocate_trap)
9508 // munge_ww -- no need to call helper
9509 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9510 ARG1, ARG2);
9512 POST(kernelrpc_mach_port_deallocate_trap)
9514 // munge_ww -- no need to call helper
9517 PRE(kernelrpc_mach_port_mod_refs_trap)
9519 // munge_wwww -- no need to call helper
9520 PRINT("kernelrpc_mach_port_mod_refs_trap"
9521 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9522 ARG1, ARG2, ARG3, ARG4);
9525 PRE(kernelrpc_mach_port_move_member_trap)
9527 // munge_www -- no need to call helper
9528 PRINT("kernelrpc_mach_port_move_member_trap"
9529 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9530 ARG1, ARG2, ARG3);
9533 PRE(kernelrpc_mach_port_insert_right_trap)
9535 //munge_wwww -- no need to call helper
9536 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9537 "(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9540 PRE(kernelrpc_mach_port_insert_member_trap)
9542 // munge_www -- no need to call helper
9543 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9544 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9547 PRE(kernelrpc_mach_port_extract_member_trap)
9549 // munge_www -- no need to call helper
9550 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9551 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9554 PRE(iopolicysys)
9556 // munge_???
9557 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
9558 /* mem effects unknown */
9560 POST(iopolicysys)
9562 // munge_???
9565 PRE(process_policy)
9567 // munge_???
9568 PRINT("process_policy(FIXME)("
9569 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9570 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9571 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9572 /* mem effects unknown */
9574 POST(process_policy)
9576 // munge_???
9579 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9582 /* ---------------------------------------------------------------------
9583 Added for OSX 10.9 (Mavericks)
9584 ------------------------------------------------------------------ */
9586 #if DARWIN_VERS >= DARWIN_10_9
9588 PRE(kernelrpc_mach_vm_map_trap)
9590 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9591 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9592 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9593 PRINT("kernelrpc_mach_vm_map_trap"
9594 "(target:%#lx, address:%p, size:%#llx,"
9595 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9596 a1, *(void**)a2, a3, a4, a5, a6);
9597 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2, sizeof(void*));
9599 POST(kernelrpc_mach_vm_map_trap)
9601 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9602 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9603 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9604 PRINT("-> address:%p", *(void**)a2);
9605 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9606 POST_MEM_WRITE(a2, sizeof(void*));
9608 ML_(notify_core_and_tool_of_mmap)(
9609 *(mach_vm_address_t*)a2, a3,
9610 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9611 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9614 PRE(kernelrpc_mach_port_construct_trap)
9616 UWord a1; UWord a2; ULong a3; UWord a4;
9617 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9618 PRINT("kernelrpc_mach_port_construct_trap"
9619 "(target: %s, options: %#lx, content: %llx, name: %p)",
9620 name_for_port(a1), a2, a3, *(mach_port_name_t**)a4);
9621 PRE_MEM_WRITE("kernelrpc_mach_port_construct_trap(name)", a4,
9622 sizeof(mach_port_name_t*));
9624 POST(kernelrpc_mach_port_construct_trap)
9626 UWord a1; UWord a2; ULong a3; UWord a4;
9627 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9628 PRINT("-> name:%p", *(mach_port_name_t**)a4);
9629 if (ML_(safe_to_deref)((mach_port_name_t*)a4, sizeof(mach_port_name_t*))) {
9630 POST_MEM_WRITE(a4, sizeof(mach_port_name_t*));
9634 PRE(kernelrpc_mach_port_destruct_trap)
9636 UWord a1; UWord a2; UWord a3; ULong a4;
9637 munge_wwwl(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9638 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9639 "(%lx,%lx,%lx,%llx)", a1, a2, a3, a4);
9642 PRE(kernelrpc_mach_port_guard_trap)
9644 UWord a1; UWord a2; ULong a3; UWord a4;
9645 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9646 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9647 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9650 PRE(kernelrpc_mach_port_unguard_trap)
9652 // munge_wwl
9653 UWord a1; UWord a2; ULong a3;
9654 munge_wwl(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4);
9655 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9656 "(%lx,%lx,%llx)", a1, a2, a3);
9659 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9662 /* ---------------------------------------------------------------------
9663 Added for OSX 10.10 (Yosemite)
9664 ------------------------------------------------------------------ */
9666 #if DARWIN_VERS >= DARWIN_10_10
9668 PRE(necp_match_policy)
9670 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9671 // struct necp_aggregate_result *returned_result)
9672 PRINT("necp_match_policy(FIXME)(%lx,%lu, %lx)", ARG1, ARG2, ARG3);
9673 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
9674 size_t, parameters_size, struct necp_aggregate_result*,
9675 returned_result);
9676 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
9678 POST(necp_match_policy)
9680 POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
9683 PRE(sysctlbyname)
9685 UWord name = ARG1;
9686 UWord namelen = ARG2;
9687 UWord oldp = ARG3;
9688 UWord oldlenp = ARG4;
9689 UWord newp = ARG5;
9690 UWord newlen = ARG6; // FIXME: or newlenp ??
9692 PRINT( "sysctlbyname ( %#lx,%lu, %#lx,%#lx, %#lx,%lu )",
9693 name, namelen, oldp, oldlenp, newp, newlen );
9695 PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
9696 void*, oldp, vki_size_t *, oldlenp,
9697 void*, newp, vki_size_t *, newlenp); // <---<<
9699 // reads name[0..namelen-1]
9700 PRE_MEM_READ("sysctlbyname(name)", name, namelen);
9702 if (VG_(clo_trace_syscalls)) {
9703 UInt i;
9704 const HChar* t_name = (const HChar*)name;
9705 VG_(printf)(" name: ");
9706 for (i = 0; i < namelen; i++) {
9707 VG_(printf)("%c", t_name[i]);
9709 VG_(printf)(" ");
9712 Bool is_kern_dot_userstack
9713 = False;
9715 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
9716 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
9718 POST(sysctlbyname)
9720 UWord oldp = ARG3;
9721 UWord oldlenp = ARG4;
9723 if (SUCCESS || ERR == VKI_ENOMEM) {
9724 // sysctl can write truncated data and return VKI_ENOMEM
9725 if (oldlenp) {
9726 POST_MEM_WRITE(oldlenp, sizeof(size_t));
9728 if (oldp && oldlenp) {
9729 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
9734 PRE(getattrlistbulk)
9736 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9737 // void *attributeBuffer, size_t bufferSize,
9738 // uint64_t options);
9739 // Presumably the last arg is value-pair in the 32 bit case.
9740 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9741 SARG1, ARG2, ARG3, ARG4, ARG5);
9742 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
9743 void*, attributeBuffer, size_t, bufferSize,
9744 uint32_t, options_lo32);
9745 PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
9746 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
9748 POST(getattrlistbulk)
9750 // FIXME: this isn't right. It seems as if what is returned is a
9751 // set of variable-length records -- see complication in
9752 // POST(getattrlist). For now, just paint the entire result buffer
9753 // as defined. Sigh.
9754 vg_assert(SUCCESS);
9755 if (ARG3 && /* "at least one output element was written" */RES > 0)
9756 POST_MEM_WRITE(ARG3, ARG4);
9759 PRE(faccessat)
9761 PRINT("faccessat(FIXME)(fd:%ld, path:%#lx(%s), amode:%#lx, flag:%#lx)",
9762 ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
9763 PRE_REG_READ4(int, "faccessat",
9764 int, fd, user_addr_t, path, int, amode, int, flag);
9767 PRE(fstatat64)
9769 PRINT("fstatat64(FIXME)(fd:%ld, path:%#lx(%s), ub:%#lx, flag:%#lx)",
9770 ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
9771 PRE_REG_READ4(int, "fstatat64",
9772 int, fd, user_addr_t, path, user_addr_t, ub, int, flag);
9775 PRE(readlinkat)
9777 Word saved = SYSNO;
9779 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %ld )",
9780 SARG1, ARG2, (HChar*)ARG2, ARG3, SARG4);
9781 PRE_REG_READ4(long, "readlinkat",
9782 int, dfd, const char *, path, char *, buf, int, bufsiz);
9783 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
9784 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
9787 * Refer to coregrind/m_syswrap/syswrap-linux.c
9790 /* Normal case */
9791 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
9794 if (SUCCESS && RES > 0)
9795 POST_MEM_WRITE( ARG3, RES );
9798 PRE(bsdthread_ctl)
9800 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9801 // user_addr_t arg2, user_addr_t arg3)
9802 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9803 PRE_REG_READ4(int, "bsdthreadctl",
9804 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
9807 PRE(csrctl)
9809 PRINT("csrctl(op:%ld, useraddr:%#lx, usersize:%#lx) FIXME", ARG1, ARG2, ARG3);
9810 PRE_REG_READ3(int, "csrctl",
9811 uint32_t, op, user_addr_t, useraddr, user_addr_t, usersize);
9814 PRE(guarded_open_dprotected_np)
9816 PRINT("guarded_open_dprotected_np("
9817 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9818 "dpclass:%#lx, dpflags: %#lx) FIXME",
9819 ARG1, (HChar*)ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
9822 PRE(guarded_write_np)
9824 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9825 ARG1, ARG2, ARG3, (ULong)ARG4);
9828 PRE(guarded_pwrite_np)
9830 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9831 ARG1, ARG2, ARG3, (ULong)ARG4, (Long)ARG5);
9834 PRE(guarded_writev_np)
9836 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9837 ARG1, ARG2, ARG3, (ULong)ARG4);
9840 #endif /* DARWIN_VERS >= DARWIN_10_10 */
9843 /* ---------------------------------------------------------------------
9844 Added for OSX 10.11 (El Capitan)
9845 ------------------------------------------------------------------ */
9847 #if DARWIN_VERS >= DARWIN_10_11
9849 PRE(kevent_qos)
9851 PRINT("kevent_qos( %ld, %#lx, %ld, %#lx, %ld, %#lx, %ld, %ld )",
9852 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6, SARG7, ARG8);
9853 PRE_REG_READ8(int,"kevent_qos",
9854 int,kq,
9855 const struct vki_kevent_qos_s *,changelist,
9856 int,nchanges,
9857 struct vki_kevent_qos_s *,eventlist,
9858 int,nevents,
9859 void*,data_out,
9860 size_t*,data_available,
9861 unsigned int,flags);
9863 if (ARG3) PRE_MEM_READ ("kevent_qos(changelist)",
9864 ARG2, ARG3 * sizeof(struct vki_kevent_qos_s));
9865 if (ARG5) PRE_MEM_WRITE("kevent_qos(eventlist)",
9866 ARG4, ARG5 * sizeof(struct vki_kevent_qos_s));
9867 if (ARG7) PRE_MEM_WRITE("kevent_qos(data_out)",
9868 ARG6, ARG7 * sizeof(void*));
9870 *flags |= SfMayBlock;
9873 POST(kevent_qos)
9875 PRINT("kevent_qos ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent_qos_s));
9876 if (RES > 0) {
9877 ML_(sync_mappings)("after", "kevent_qos", 0);
9878 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent_qos_s));
9883 PRE(pselect)
9885 *flags |= SfMayBlock;
9886 PRINT("pselect ( %ld, %#lx, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
9887 ARG4, ARG5, ARG6);
9888 PRE_REG_READ5(long, "pselect",
9889 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
9890 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
9891 // XXX: this possibly understates how much memory is read.
9892 if (ARG2 != 0)
9893 PRE_MEM_READ( "pselect(readfds)",
9894 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
9895 if (ARG3 != 0)
9896 PRE_MEM_READ( "pselect(writefds)",
9897 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
9898 if (ARG4 != 0)
9899 PRE_MEM_READ( "pselect(exceptfds)",
9900 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
9901 if (ARG5 != 0)
9902 PRE_timeval_READ( "pselect(timeout)", ARG5 );
9903 if (ARG6 != 0)
9904 PRE_MEM_READ( "pselect(sigmask)", ARG6, sizeof(vki_sigset_t) );
9907 #endif /* DARWIN_VERS >= DARWIN_10_11 */
9910 /* ---------------------------------------------------------------------
9911 Added for macOS 10.12 (Sierra)
9912 ------------------------------------------------------------------ */
9914 #if DARWIN_VERS >= DARWIN_10_12
9916 PRE(getentropy)
9918 PRINT("getentropy(buffer:%#lx, size:%ld) FIXME", ARG1, ARG2);
9919 PRE_REG_READ2(int, "getentropy",
9920 void*, buffer, size_t, size);
9923 static const HChar *ulop_name(int op)
9925 switch (op) {
9926 case VKI_UL_UNFAIR_LOCK: return "UL_UNFAIR_LOCK";
9927 case VKI_UL_COMPARE_AND_WAIT: return "UL_COMPARE_AND_WAIT";
9928 default: return "??";
9932 PRE(ulock_wake)
9934 PRINT("ulock_wake(operation:%ld, addr:%#lx, wake_value:%ld) FIXME",
9935 ARG1, ARG2, ARG3);
9936 PRE_REG_READ3(int, "ulock_wake",
9937 uint32_t, operation, void*, addr, uint64_t, wake_value);
9940 PRE(ulock_wait)
9942 uint ul_opcode = ARG1 & VKI_UL_OPCODE_MASK;
9943 uint ul_flags = ARG1 & VKI_UL_FLAGS_MASK;
9945 switch (ul_opcode) {
9946 case VKI_UL_UNFAIR_LOCK:
9947 case VKI_UL_COMPARE_AND_WAIT: {
9948 const char* name = ulop_name(ul_opcode);
9949 PRINT("ulock_wait(operation:%s (flags: %#x), addr:%#lx, value:%ld, timeout:%ld)",
9950 name, ul_flags, ARG2, ARG3, ARG4);
9951 PRE_REG_READ4(int, "ulock_wait",
9952 uint32_t, operation, void*, addr, uint64_t, value, uint32_t, timeout);
9953 PRE_MEM_READ("ulock_wait(addr)", ARG2, 4 );
9954 break;
9957 default:
9958 PRINT("ulock_wait(operation:%ld (opcode: %u [??], flags: %#x), addr:%#lx, value:%ld, timeout:%ld)", ARG1, ul_opcode, ul_flags, ARG2, ARG3, ARG4);
9959 log_decaying("UNKNOWN ulock_wait %ld (opcode: %u [??], flags: %#x)!", ARG1, ul_opcode, ul_flags);
9960 break;
9964 PRE(host_create_mach_voucher_trap)
9966 // munge_wwww -- no need to call helper
9967 PRINT("host_create_mach_voucher_trap"
9968 "(host:%#lx, recipes:%#lx, recipes_size:%ld, voucher:%#lx) FIXME",
9969 ARG1, ARG2, ARG3, ARG4);
9972 PRE(task_register_dyld_image_infos)
9974 #pragma pack(4)
9975 typedef struct {
9976 mach_msg_header_t Head;
9977 /* start of the kernel processed data */
9978 mach_msg_body_t msgh_body;
9979 mach_msg_ool_descriptor_t dyld_images;
9980 /* end of the kernel processed data */
9981 NDR_record_t NDR;
9982 mach_msg_type_number_t dyld_imagesCnt;
9983 } Request;
9984 #pragma pack()
9986 // Request *req = (Request *)ARG1;
9988 PRINT("task_register_dyld_image_infos(%s)", name_for_port(MACH_REMOTE));
9990 AFTER = POST_FN(task_register_dyld_image_infos);
9993 POST(task_register_dyld_image_infos)
9995 #pragma pack(4)
9996 typedef struct {
9997 mach_msg_header_t Head;
9998 NDR_record_t NDR;
9999 kern_return_t RetCode;
10000 } Reply;
10001 #pragma pack()
10003 Reply *reply = (Reply *)ARG1;
10004 if (!reply->RetCode) {
10005 } else {
10006 PRINT("mig return %d", reply->RetCode);
10010 PRE(task_register_dyld_shared_cache_image_info)
10012 #pragma pack(4)
10013 typedef struct {
10014 mach_msg_header_t Head;
10015 NDR_record_t NDR;
10016 dyld_kernel_image_info_t dyld_cache_image;
10017 boolean_t no_cache;
10018 boolean_t private_cache;
10019 } Request;
10020 #pragma pack()
10022 // Request *req = (Request *)ARG1;
10024 PRINT("task_register_dyld_shared_cache_image_info(%s)",
10025 name_for_port(MACH_REMOTE));
10027 AFTER = POST_FN(task_register_dyld_shared_cache_image_info);
10030 POST(task_register_dyld_shared_cache_image_info)
10032 #pragma pack(4)
10033 typedef struct {
10034 mach_msg_header_t Head;
10035 NDR_record_t NDR;
10036 kern_return_t RetCode;
10037 } Reply;
10038 #pragma pack()
10040 Reply *reply = (Reply *)ARG1;
10041 if (!reply->RetCode) {
10042 } else {
10043 PRINT("mig return %d", reply->RetCode);
10047 PRE(mach_generate_activity_id)
10049 // munge_www -- no need to call helper
10050 PRINT("mach_generate_activity_id"
10051 "(target:%s, count:%ld)",
10052 name_for_port(ARG1), ARG2);
10053 PRE_REG_READ3(long, "mach_generate_activity_id",
10054 mach_port_name_t, target, int, count, uint64_t *, activity_id);
10055 if (ARG2 <= 0 || ARG2 > MACH_ACTIVITY_ID_COUNT_MAX) {
10056 SET_STATUS_Failure( VKI_EINVAL );
10058 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10059 PRE_MEM_WRITE( "mach_generate_activity_id(activity_id)", ARG3, sizeof(vki_uint64_t) );
10060 } else {
10061 SET_STATUS_Failure( VKI_EFAULT );
10065 POST(mach_generate_activity_id)
10067 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10068 POST_MEM_WRITE( ARG3, sizeof(vki_uint64_t) );
10069 PRINT("-> activity_id:%#llx", *(uint64_t*)ARG3);
10073 #endif /* DARWIN_VERS >= DARWIN_10_12 */
10076 /* ---------------------------------------------------------------------
10077 syscall tables
10078 ------------------------------------------------------------------ */
10080 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
10082 #define MACX_(sysno, name) \
10083 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10085 #define MACXY(sysno, name) \
10086 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10088 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
10091 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
10092 unfortunately misused for Mach too, causing assertion failures
10093 // _____ : unimplemented in valgrind
10094 GEN : handlers are in syswrap-generic.c
10095 MAC : handlers are in this file
10096 X_ : PRE handler only
10097 XY : PRE and POST handlers
10099 const SyscallTableEntry ML_(syscall_table)[] = {
10100 // _____(__NR_syscall), // 0
10101 MACX_(__NR_exit, exit),
10102 GENX_(__NR_fork, sys_fork),
10103 GENXY(__NR_read, sys_read),
10104 GENX_(__NR_write, sys_write),
10105 GENXY(__NR_open, sys_open),
10106 GENXY(__NR_close, sys_close),
10107 GENXY(__NR_wait4, sys_wait4),
10108 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
10109 GENX_(__NR_link, sys_link),
10110 GENX_(__NR_unlink, sys_unlink),
10111 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
10112 GENX_(__NR_chdir, sys_chdir),
10113 GENX_(__NR_fchdir, sys_fchdir),
10114 GENX_(__NR_mknod, sys_mknod),
10115 GENX_(__NR_chmod, sys_chmod),
10116 GENX_(__NR_chown, sys_chown),
10117 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
10118 MACXY(__NR_getfsstat, getfsstat),
10119 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
10120 GENX_(__NR_getpid, sys_getpid), // 20
10121 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
10122 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
10123 GENX_(__NR_setuid, sys_setuid),
10124 GENX_(__NR_getuid, sys_getuid),
10125 GENX_(__NR_geteuid, sys_geteuid),
10126 MACX_(__NR_ptrace, ptrace),
10127 MACXY(__NR_recvmsg, recvmsg),
10128 MACX_(__NR_sendmsg, sendmsg),
10129 MACXY(__NR_recvfrom, recvfrom),
10130 MACXY(__NR_accept, accept),
10131 MACXY(__NR_getpeername, getpeername),
10132 MACXY(__NR_getsockname, getsockname),
10133 GENX_(__NR_access, sys_access),
10134 MACX_(__NR_chflags, chflags),
10135 MACX_(__NR_fchflags, fchflags),
10136 GENX_(__NR_sync, sys_sync),
10137 GENX_(__NR_kill, sys_kill),
10138 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
10139 GENX_(__NR_getppid, sys_getppid),
10140 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
10141 GENXY(__NR_dup, sys_dup),
10142 MACXY(__NR_pipe, pipe),
10143 GENX_(__NR_getegid, sys_getegid),
10144 #if DARWIN_VERS >= DARWIN_10_7
10145 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
10146 #else
10147 // _____(__NR_profil),
10148 #endif
10149 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
10150 MACXY(__NR_sigaction, sigaction),
10151 GENX_(__NR_getgid, sys_getgid),
10152 MACXY(__NR_sigprocmask, sigprocmask),
10153 MACXY(__NR_getlogin, getlogin),
10154 // _____(__NR_setlogin),
10155 // _____(__NR_acct),
10156 MACXY(__NR_sigpending, sigpending),
10157 GENXY(__NR_sigaltstack, sys_sigaltstack),
10158 MACXY(__NR_ioctl, ioctl),
10159 // _____(__NR_reboot),
10160 // _____(__NR_revoke),
10161 GENX_(__NR_symlink, sys_symlink), // 57
10162 GENX_(__NR_readlink, sys_readlink),
10163 GENX_(__NR_execve, sys_execve),
10164 GENX_(__NR_umask, sys_umask), // 60
10165 GENX_(__NR_chroot, sys_chroot),
10166 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
10167 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
10168 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
10169 GENX_(__NR_msync, sys_msync),
10170 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
10171 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
10172 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
10173 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
10174 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
10175 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
10176 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
10177 GENXY(__NR_munmap, sys_munmap),
10178 GENXY(__NR_mprotect, sys_mprotect),
10179 GENX_(__NR_madvise, sys_madvise),
10180 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
10181 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
10182 GENXY(__NR_mincore, sys_mincore),
10183 GENXY(__NR_getgroups, sys_getgroups),
10184 // _____(__NR_setgroups), // 80
10185 GENX_(__NR_getpgrp, sys_getpgrp),
10186 GENX_(__NR_setpgid, sys_setpgid),
10187 GENXY(__NR_setitimer, sys_setitimer),
10188 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
10189 // _____(__NR_swapon),
10190 GENXY(__NR_getitimer, sys_getitimer),
10191 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
10192 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
10193 MACXY(__NR_getdtablesize, getdtablesize),
10194 GENXY(__NR_dup2, sys_dup2),
10195 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
10196 MACXY(__NR_fcntl, fcntl),
10197 GENX_(__NR_select, sys_select),
10198 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
10199 GENX_(__NR_fsync, sys_fsync),
10200 GENX_(__NR_setpriority, sys_setpriority),
10201 MACXY(__NR_socket, socket),
10202 MACX_(__NR_connect, connect),
10203 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
10204 GENX_(__NR_getpriority, sys_getpriority), // 100
10205 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
10206 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
10207 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
10208 MACX_(__NR_bind, bind),
10209 MACX_(__NR_setsockopt, setsockopt),
10210 MACX_(__NR_listen, listen),
10211 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
10212 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
10213 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
10214 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
10215 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
10216 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
10217 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
10218 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
10219 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
10220 GENXY(__NR_gettimeofday, sys_gettimeofday),
10221 GENXY(__NR_getrusage, sys_getrusage),
10222 MACXY(__NR_getsockopt, getsockopt),
10223 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
10224 GENXY(__NR_readv, sys_readv), // 120
10225 GENX_(__NR_writev, sys_writev),
10226 // _____(__NR_settimeofday),
10227 GENX_(__NR_fchown, sys_fchown),
10228 GENX_(__NR_fchmod, sys_fchmod),
10229 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
10230 // _____(__NR_setreuid),
10231 // _____(__NR_setregid),
10232 GENX_(__NR_rename, sys_rename),
10233 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
10234 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
10235 GENX_(__NR_flock, sys_flock),
10236 MACXY(__NR_mkfifo, mkfifo),
10237 MACX_(__NR_sendto, sendto),
10238 MACX_(__NR_shutdown, shutdown),
10239 MACXY(__NR_socketpair, socketpair),
10240 GENX_(__NR_mkdir, sys_mkdir),
10241 GENX_(__NR_rmdir, sys_rmdir),
10242 GENX_(__NR_utimes, sys_utimes),
10243 MACX_(__NR_futimes, futimes),
10244 // _____(__NR_adjtime), // 140
10245 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
10246 MACXY(__NR_gethostuuid, gethostuuid),
10247 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
10248 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
10249 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
10250 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
10251 GENX_(__NR_setsid, sys_setsid),
10252 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
10253 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
10254 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
10255 // _____(__NR_getpgid),
10256 // _____(__NR_setprivexec),
10257 GENXY(__NR_pread, sys_pread64),
10258 GENX_(__NR_pwrite, sys_pwrite64),
10259 // _____(__NR_nfssvc),
10260 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
10261 GENXY(__NR_statfs, sys_statfs),
10262 GENXY(__NR_fstatfs, sys_fstatfs),
10263 // _____(__NR_unmount),
10264 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
10265 // _____(__NR_getfh),
10266 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
10267 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
10268 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
10269 // _____(__NR_quotactl),
10270 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
10271 MACX_(__NR_mount, mount),
10272 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
10273 MACXY(__NR_csops, csops), // code-signing ops
10274 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
10275 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
10276 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
10277 // _____(__NR_waitid),
10278 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
10279 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
10280 // _____(__NR_add_profil),
10281 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
10282 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
10283 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
10284 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
10285 GENX_(__NR_setgid, sys_setgid),
10286 MACX_(__NR_setegid, setegid),
10287 MACX_(__NR_seteuid, seteuid),
10288 MACX_(__NR_sigreturn, sigreturn),
10289 // _____(__NR_chud),
10290 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
10291 #if DARWIN_VERS >= DARWIN_10_6
10292 // _____(__NR_fdatasync),
10293 #else
10294 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
10295 #endif
10296 GENXY(__NR_stat, sys_newstat),
10297 GENXY(__NR_fstat, sys_newfstat),
10298 GENXY(__NR_lstat, sys_newlstat),
10299 MACX_(__NR_pathconf, pathconf),
10300 MACX_(__NR_fpathconf, fpathconf),
10301 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
10302 GENXY(__NR_getrlimit, sys_getrlimit),
10303 GENX_(__NR_setrlimit, sys_setrlimit),
10304 MACXY(__NR_getdirentries, getdirentries),
10305 MACXY(__NR_mmap, mmap),
10306 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
10307 MACX_(__NR_lseek, lseek),
10308 GENX_(__NR_truncate, sys_truncate64), // 200
10309 GENX_(__NR_ftruncate, sys_ftruncate64),
10310 MACXY(__NR___sysctl, __sysctl),
10311 GENX_(__NR_mlock, sys_mlock),
10312 GENX_(__NR_munlock, sys_munlock),
10313 // _____(__NR_undelete),
10314 // _____(__NR_ATsocket),
10315 // _____(__NR_ATgetmsg),
10316 // _____(__NR_ATputmsg),
10317 // _____(__NR_ATPsndreq),
10318 // _____(__NR_ATPsndrsp),
10319 // _____(__NR_ATPgetreq),
10320 // _____(__NR_ATPgetrsp),
10321 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
10322 #if DARWIN_VERS >= DARWIN_10_6
10323 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
10324 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
10325 #else
10326 // _____(__NR_kqueue_from_portset_np),
10327 // _____(__NR_kqueue_portset_np),
10328 #endif
10329 // _____(__NR_mkcomplex),
10330 // _____(__NR_statv),
10331 // _____(__NR_lstatv),
10332 // _____(__NR_fstatv),
10333 MACXY(__NR_getattrlist, getattrlist), // 220
10334 MACX_(__NR_setattrlist, setattrlist),
10335 MACXY(__NR_getdirentriesattr, getdirentriesattr),
10336 MACX_(__NR_exchangedata, exchangedata),
10337 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
10338 // _____(__NR_searchfs),
10339 GENX_(__NR_delete, sys_unlink),
10340 // _____(__NR_copyfile),
10341 #if DARWIN_VERS >= DARWIN_10_6
10342 // _____(__NR_fgetattrlist),
10343 // _____(__NR_fsetattrlist),
10344 #else
10345 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
10346 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
10347 #endif
10348 GENXY(__NR_poll, sys_poll),
10349 MACX_(__NR_watchevent, watchevent),
10350 MACXY(__NR_waitevent, waitevent),
10351 MACX_(__NR_modwatch, modwatch),
10352 MACXY(__NR_getxattr, getxattr),
10353 MACXY(__NR_fgetxattr, fgetxattr),
10354 MACX_(__NR_setxattr, setxattr),
10355 MACX_(__NR_fsetxattr, fsetxattr),
10356 MACX_(__NR_removexattr, removexattr),
10357 MACX_(__NR_fremovexattr, fremovexattr),
10358 MACXY(__NR_listxattr, listxattr), // 240
10359 MACXY(__NR_flistxattr, flistxattr),
10360 MACXY(__NR_fsctl, fsctl),
10361 MACX_(__NR_initgroups, initgroups),
10362 MACXY(__NR_posix_spawn, posix_spawn),
10363 #if DARWIN_VERS >= DARWIN_10_6
10364 // _____(__NR_ffsctl),
10365 #else
10366 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
10367 #endif
10368 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
10369 // _____(__NR_nfsclnt),
10370 // _____(__NR_fhopen),
10371 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
10372 // _____(__NR_minherit),
10373 // _____(__NR_semsys),
10374 // _____(__NR_msgsys),
10375 // _____(__NR_shmsys),
10376 MACXY(__NR_semctl, semctl),
10377 MACX_(__NR_semget, semget),
10378 MACX_(__NR_semop, semop),
10379 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
10380 // _____(__NR_msgctl),
10381 // _____(__NR_msgget),
10382 // _____(__NR_msgsnd), // 260
10383 // _____(__NR_msgrcv),
10384 MACXY(__NR_shmat, shmat),
10385 MACXY(__NR_shmctl, shmctl),
10386 MACXY(__NR_shmdt, shmdt),
10387 MACX_(__NR_shmget, shmget),
10388 MACXY(__NR_shm_open, shm_open),
10389 MACXY(__NR_shm_unlink, shm_unlink),
10390 MACX_(__NR_sem_open, sem_open),
10391 MACX_(__NR_sem_close, sem_close),
10392 MACX_(__NR_sem_unlink, sem_unlink),
10393 MACX_(__NR_sem_wait, sem_wait),
10394 MACX_(__NR_sem_trywait, sem_trywait),
10395 MACX_(__NR_sem_post, sem_post),
10396 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
10397 // has become sysctlbyname. See below.
10398 MACXY(__NR_sem_init, sem_init),
10399 MACX_(__NR_sem_destroy, sem_destroy),
10400 MACX_(__NR_open_extended, open_extended), // 277
10401 // _____(__NR_umask_extended),
10402 MACXY(__NR_stat_extended, stat_extended),
10403 MACXY(__NR_lstat_extended, lstat_extended), // 280
10404 MACXY(__NR_fstat_extended, fstat_extended),
10405 MACX_(__NR_chmod_extended, chmod_extended),
10406 MACX_(__NR_fchmod_extended,fchmod_extended),
10407 MACXY(__NR_access_extended,access_extended),
10408 MACX_(__NR_settid, settid),
10409 #if DARWIN_VERS >= DARWIN_10_8
10410 MACX_(__NR_gettid, gettid), // 286
10411 #endif
10412 // _____(__NR_setsgroups),
10413 // _____(__NR_getsgroups),
10414 // _____(__NR_setwgroups),
10415 // _____(__NR_getwgroups),
10416 // _____(__NR_mkfifo_extended),
10417 // _____(__NR_mkdir_extended),
10418 // _____(__NR_identitysvc),
10419 // _____(__NR_shared_region_check_np),
10420 // _____(__NR_shared_region_map_np),
10421 #if DARWIN_VERS >= DARWIN_10_6
10422 // _____(__NR_vm_pressure_monitor),
10423 // _____(__NR_psynch_rw_longrdlock),
10424 // _____(__NR_psynch_rw_yieldwrlock),
10425 // _____(__NR_psynch_rw_downgrade),
10426 // _____(__NR_psynch_rw_upgrade),
10427 MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
10428 MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
10429 MACXY(__NR_psynch_cvbroad, psynch_cvbroad), // 303
10430 MACXY(__NR_psynch_cvsignal, psynch_cvsignal), // 304
10431 MACXY(__NR_psynch_cvwait, psynch_cvwait), // 305
10432 MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
10433 MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
10434 MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
10435 // _____(__NR_psynch_rw_unlock2),
10436 #else
10437 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
10438 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
10439 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
10440 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
10441 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
10442 // _____(__NR___pthread_mutex_destroy),
10443 // _____(__NR___pthread_mutex_init),
10444 // _____(__NR___pthread_mutex_lock),
10445 // _____(__NR___pthread_mutex_trylock),
10446 // _____(__NR___pthread_mutex_unlock),
10447 // _____(__NR___pthread_cond_init),
10448 // _____(__NR___pthread_cond_destroy),
10449 // _____(__NR___pthread_cond_broadcast),
10450 // _____(__NR___pthread_cond_signal),
10451 #endif
10452 // _____(__NR_getsid),
10453 // _____(__NR_settid_with_pid),
10454 #if DARWIN_VERS >= DARWIN_10_7
10455 MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
10456 #else
10457 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // old __pthread_cond_timedwait
10458 #endif
10459 // _____(__NR_aio_fsync),
10460 MACXY(__NR_aio_return, aio_return),
10461 MACX_(__NR_aio_suspend, aio_suspend),
10462 // _____(__NR_aio_cancel),
10463 MACX_(__NR_aio_error, aio_error),
10464 MACXY(__NR_aio_read, aio_read),
10465 MACX_(__NR_aio_write, aio_write),
10466 // _____(__NR_lio_listio), // 320
10467 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
10469 #if DARWIN_VERS >= DARWIN_10_8
10470 MACXY(__NR_iopolicysys, iopolicysys),
10471 MACXY(__NR_process_policy, process_policy),
10472 #else
10473 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
10474 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
10475 #endif
10476 // _____(__NR_mlockall),
10477 // _____(__NR_munlockall),
10478 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
10479 MACX_(__NR_issetugid, issetugid),
10480 MACX_(__NR___pthread_kill, __pthread_kill),
10481 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
10482 // _____(__NR___sigwait),
10483 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
10484 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
10485 MACX_(__NR___pthread_canceled, __pthread_canceled),
10486 MACX_(__NR___semwait_signal, __semwait_signal),
10487 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
10488 MACXY(__NR_proc_info, proc_info), // 336
10489 MACXY(__NR_sendfile, sendfile),
10490 MACXY(__NR_stat64, stat64),
10491 MACXY(__NR_fstat64, fstat64),
10492 MACXY(__NR_lstat64, lstat64), // 340
10493 MACXY(__NR_stat64_extended, stat64_extended),
10494 MACXY(__NR_lstat64_extended, lstat64_extended),
10495 MACXY(__NR_fstat64_extended, fstat64_extended),
10496 MACXY(__NR_getdirentries64, getdirentries64),
10497 MACXY(__NR_statfs64, statfs64),
10498 MACXY(__NR_fstatfs64, fstatfs64),
10499 MACXY(__NR_getfsstat64, getfsstat64),
10500 MACX_(__NR___pthread_chdir, __pthread_chdir),
10501 MACX_(__NR___pthread_fchdir, __pthread_fchdir),
10502 // _____(__NR_audit),
10503 MACXY(__NR_auditon, auditon),
10504 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
10505 // _____(__NR_getauid),
10506 // _____(__NR_setauid),
10507 // _____(__NR_getaudit),
10508 // _____(__NR_setaudit),
10509 MACXY(__NR_getaudit_addr, getaudit_addr),
10510 // _____(__NR_setaudit_addr),
10511 // _____(__NR_auditctl),
10512 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
10513 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
10514 MACXY(__NR_kqueue, kqueue),
10515 MACXY(__NR_kevent, kevent),
10516 GENX_(__NR_lchown, sys_lchown),
10517 // _____(__NR_stack_snapshot),
10518 MACX_(__NR_bsdthread_register, bsdthread_register),
10519 MACX_(__NR_workq_open, workq_open),
10520 MACXY(__NR_workq_ops, workq_ops),
10521 #if DARWIN_VERS >= DARWIN_10_6
10522 MACXY(__NR_kevent64, kevent64),
10523 #else
10524 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
10525 #endif
10526 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // old semwait_signal
10527 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // old semwait_signal_nocancel
10528 #if DARWIN_VERS >= DARWIN_10_6
10529 MACX_(__NR___thread_selfid, __thread_selfid),
10530 #else
10531 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
10532 #endif
10533 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
10534 #if DARWIN_VERS < DARWIN_10_11
10535 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
10536 #endif
10537 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
10538 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
10539 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
10540 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
10541 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
10542 // _____(__NR___mac_execve), // 380
10543 MACX_(__NR___mac_syscall, __mac_syscall),
10544 // _____(__NR___mac_get_file),
10545 // _____(__NR___mac_set_file),
10546 // _____(__NR___mac_get_link),
10547 // _____(__NR___mac_set_link),
10548 // _____(__NR___mac_get_proc),
10549 // _____(__NR___mac_set_proc),
10550 // _____(__NR___mac_get_fd),
10551 // _____(__NR___mac_set_fd),
10552 // _____(__NR___mac_get_pid),
10553 // _____(__NR___mac_get_lcid),
10554 // _____(__NR___mac_get_lctx),
10555 // _____(__NR___mac_set_lctx),
10556 // _____(__NR_setlcid),
10557 // _____(__NR_getlcid),
10558 // GrP fixme need any special nocancel handling?
10559 GENXY(__NR_read_nocancel, sys_read),
10560 GENX_(__NR_write_nocancel, sys_write),
10561 GENXY(__NR_open_nocancel, sys_open),
10562 GENXY(__NR_close_nocancel, sys_close),
10563 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
10564 MACXY(__NR_recvmsg_nocancel, recvmsg),
10565 MACX_(__NR_sendmsg_nocancel, sendmsg),
10566 MACXY(__NR_recvfrom_nocancel, recvfrom),
10567 MACXY(__NR_accept_nocancel, accept),
10568 GENX_(__NR_msync_nocancel, sys_msync),
10569 MACXY(__NR_fcntl_nocancel, fcntl),
10570 GENX_(__NR_select_nocancel, sys_select),
10571 GENX_(__NR_fsync_nocancel, sys_fsync),
10572 MACX_(__NR_connect_nocancel, connect),
10573 MACX_(__NR_sigsuspend_nocancel, sigsuspend),
10574 GENXY(__NR_readv_nocancel, sys_readv),
10575 GENX_(__NR_writev_nocancel, sys_writev),
10576 MACX_(__NR_sendto_nocancel, sendto),
10577 GENXY(__NR_pread_nocancel, sys_pread64),
10578 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
10579 // _____(__NR_waitid_nocancel),
10580 GENXY(__NR_poll_nocancel, sys_poll),
10581 // _____(__NR_msgsnd_nocancel),
10582 // _____(__NR_msgrcv_nocancel),
10583 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
10584 // _____(__NR_aio_suspend_nocancel),
10585 // _____(__NR___sigwait_nocancel),
10586 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
10587 // _____(__NR___mac_mount),
10588 // _____(__NR___mac_get_mount),
10589 // _____(__NR___mac_getfsstat),
10590 #if DARWIN_VERS >= DARWIN_10_6
10591 MACXY(__NR_fsgetpath, fsgetpath),
10592 MACXY(__NR_audit_session_self, audit_session_self),
10593 // _____(__NR_audit_session_join),
10594 #endif
10595 #if DARWIN_VERS >= DARWIN_10_9
10596 MACX_(__NR_fileport_makeport, fileport_makeport),
10597 // _____(__NR_fileport_makefd), // 431
10598 // _____(__NR_audit_session_port), // 432
10599 // _____(__NR_pid_suspend), // 433
10600 // _____(__NR_pid_resume), // 434
10601 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(435)), // ???
10602 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(436)), // ???
10603 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(437)), // ???
10604 // _____(__NR_shared_region_map_and_slide_np), // 438
10605 // _____(__NR_kas_info), // 439
10606 // _____(__NR_memorystatus_control), // 440
10607 MACX_(__NR_guarded_open_np, guarded_open_np),
10608 MACX_(__NR_guarded_close_np, guarded_close_np),
10609 MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
10610 MACX_(__NR_change_fdguard_np, change_fdguard_np),
10611 MACX_(__NR_connectx, connectx),
10612 MACX_(__NR_disconnectx, disconnectx),
10613 #endif
10614 #if DARWIN_VERS >= DARWIN_10_10
10615 MACXY(__NR_sysctlbyname, sysctlbyname), // 274
10616 MACXY(__NR_necp_match_policy, necp_match_policy), // 460
10617 MACXY(__NR_getattrlistbulk, getattrlistbulk), // 461
10618 MACX_(__NR_faccessat, faccessat), // 466
10619 MACX_(__NR_fstatat64, fstatat64), // 470
10620 MACX_(__NR_readlinkat, readlinkat), // 473
10621 MACX_(__NR_bsdthread_ctl, bsdthread_ctl), // 478
10622 MACX_(__NR_csrctl, csrctl), // 483
10623 MACX_(__NR_guarded_open_dprotected_np, guarded_open_dprotected_np), // 484
10624 MACX_(__NR_guarded_write_np, guarded_write_np), // 485
10625 MACX_(__NR_guarded_pwrite_np, guarded_pwrite_np), // 486
10626 MACX_(__NR_guarded_writev_np, guarded_writev_np), // 487
10627 // _____(__NR___mremap_encrypted), // 489
10628 #endif
10629 #if DARWIN_VERS >= DARWIN_10_11
10630 // _____(__NR_kdebug_trace_string), // 178
10631 MACXY(__NR_kevent_qos, kevent_qos), // 374
10632 MACX_(__NR_pselect, pselect), // 394
10633 // _____(__NR_netagent_trigger), // 490
10634 // _____(__NR_stack_snapshot_with_config), // 491
10635 // _____(__NR_microstackshot), // 492
10636 // _____(__NR_grab_pgo_data), // 493
10637 // _____(__NR_persona), // 494
10638 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(495)), // ???
10639 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(496)), // ???
10640 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(497)), // ???
10641 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(498)), // ???
10642 // _____(__NR_work_interval_ctl), // 499
10643 #endif
10644 #if DARWIN_VERS >= DARWIN_10_12
10645 // _____(__NR_kdebug_typefilter), // 177
10646 // _____(__NR_clonefileat), // 462
10647 // _____(__NR_renameatx_np), // 488
10648 MACX_(__NR_getentropy, getentropy), // 500
10649 // _____(__NR_necp_open), // 501
10650 // _____(__NR_necp_client_action), // 502
10651 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(503)), // ???
10652 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(504)), // ???
10653 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(505)), // ???
10654 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(506)), // ???
10655 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(507)), // ???
10656 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(508)), // ???
10657 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(509)), // ???
10658 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(510)), // ???
10659 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(511)), // ???
10660 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(512)), // ???
10661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(513)), // ???
10662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(514)), // ???
10663 MACX_(__NR_ulock_wait, ulock_wait), // 515
10664 MACX_(__NR_ulock_wake, ulock_wake), // 516
10665 // _____(__NR_fclonefileat), // 517
10666 // _____(__NR_fs_snapshot), // 518
10667 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(519)), // ???
10668 // _____(__NR_terminate_with_payload), // 520
10669 // _____(__NR_abort_with_payload), // 521
10670 #endif
10671 #if DARWIN_VERS >= DARWIN_10_13
10672 // _____(__NR_thread_selfcounts), // 186
10673 // _____(__NR_kevent_id, // 375
10674 // _____(__NR_necp_session_open), // 522
10675 // _____(__NR_necp_session_action), // 523
10676 // _____(__NR_setattrlistat), // 524
10677 // _____(__NR_net_qos_guideline), // 525
10678 // _____(__NR_fmount), // 526
10679 // _____(__NR_ntp_adjtime), // 527
10680 // _____(__NR_ntp_gettime), // 528
10681 // _____(__NR_os_fault_with_payload), // 529
10682 #endif
10683 // _____(__NR_MAXSYSCALL)
10684 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
10688 // Mach traps use negative syscall numbers.
10689 // Use ML_(mach_trap_table)[-mach_trap_number] .
10690 // cf xnu sources osfmk/kern/syscall_sw.c
10692 const SyscallTableEntry ML_(mach_trap_table)[] = {
10693 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
10694 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
10695 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
10696 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
10697 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
10698 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
10699 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
10700 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
10701 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
10702 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
10704 # if DARWIN_VERS >= DARWIN_10_8
10705 MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
10706 # else
10707 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
10708 # endif
10710 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
10712 # if DARWIN_VERS >= DARWIN_10_8
10713 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
10714 # else
10715 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
10716 # endif
10718 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
10720 # if DARWIN_VERS >= DARWIN_10_8
10721 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
10722 # endif
10724 # if DARWIN_VERS >= DARWIN_10_9
10725 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
10726 # endif
10728 # if DARWIN_VERS < DARWIN_10_8
10729 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
10730 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
10731 # endif
10733 # if DARWIN_VERS >= DARWIN_10_8
10734 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
10735 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
10736 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
10737 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
10738 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
10739 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
10740 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
10741 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
10742 # else
10743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
10744 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
10745 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
10746 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
10747 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
10748 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
10749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
10750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
10751 # endif
10753 # if DARWIN_VERS >= DARWIN_10_9
10754 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
10755 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
10756 # else
10757 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
10758 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
10759 # endif
10761 MACXY(__NR_mach_reply_port, mach_reply_port),
10762 MACXY(__NR_thread_self_trap, mach_thread_self),
10763 MACXY(__NR_task_self_trap, mach_task_self),
10764 MACXY(__NR_host_self_trap, mach_host_self),
10765 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
10766 MACXY(__NR_mach_msg_trap, mach_msg),
10767 // _____(__NR_mach_msg_overwrite_trap),
10768 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
10769 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
10770 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
10771 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
10772 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
10773 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
10774 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
10775 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
10777 # if DARWIN_VERS >= DARWIN_10_9
10778 MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
10779 MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
10780 # else
10781 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
10782 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
10783 # endif
10785 # if DARWIN_VERS >= DARWIN_10_12
10786 MACXY(__NR_mach_generate_activity_id, mach_generate_activity_id),
10787 # elif DARWIN_VERS >= DARWIN_10_10
10788 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10789 # elif defined(VGA_x86) || DARWIN_VERS == DARWIN_10_9
10790 // _____(__NR_map_fd),
10791 # else
10792 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10793 # endif
10795 // _____(__NR_task_name_for_pid),
10796 MACXY(__NR_task_for_pid, task_for_pid),
10797 MACXY(__NR_pid_for_task, pid_for_task),
10798 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
10799 #if defined(VGA_x86)
10800 // _____(__NR_macx_swapon),
10801 // _____(__NR_macx_swapoff),
10802 #else
10803 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
10804 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
10805 #endif
10806 #if DARWIN_VERS >= DARWIN_10_13
10807 // _____(__NR_thread_get_special_reply_port, // 50
10808 #else
10809 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10810 #endif /* DARWIN_VERS >= DARWIN_10_13 */
10811 #if defined(VGA_x86)
10812 // _____(__NR_macx_triggers),
10813 // _____(__NR_macx_backing_store_suspend),
10814 // _____(__NR_macx_backing_store_recovery),
10815 #else
10816 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
10817 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
10818 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
10819 #endif
10820 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
10821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
10822 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
10823 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
10824 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
10825 MACX_(__NR_swtch_pri, swtch_pri),
10826 MACX_(__NR_swtch, swtch), // -60
10827 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
10828 // _____(__NR_clock_sleep_trap),
10829 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
10830 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
10831 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
10832 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
10833 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
10834 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
10835 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
10836 #if DARWIN_VERS >= DARWIN_10_12
10837 MACX_(__NR_host_create_mach_voucher_trap, host_create_mach_voucher_trap),
10838 #else
10839 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
10840 #endif
10841 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
10842 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
10843 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
10844 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
10845 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
10846 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
10847 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
10848 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
10849 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
10850 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
10851 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
10852 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
10853 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
10854 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
10855 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
10856 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
10857 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
10858 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
10859 MACXY(__NR_mach_timebase_info, mach_timebase_info),
10860 MACX_(__NR_mach_wait_until, mach_wait_until),
10861 MACXY(__NR_mk_timer_create, mk_timer_create),
10862 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
10863 MACX_(__NR_mk_timer_arm, mk_timer_arm),
10864 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
10865 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
10866 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
10867 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
10868 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
10869 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
10870 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
10874 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
10875 // calling convention instead of the syscall convention.
10876 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
10878 #if defined(VGA_x86)
10879 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10880 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10882 #elif defined(VGA_amd64)
10883 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10884 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10886 #else
10887 #error unknown architecture
10888 #endif
10890 const UInt ML_(syscall_table_size) =
10891 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
10893 const UInt ML_(mach_trap_table_size) =
10894 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
10896 const UInt ML_(mdep_trap_table_size) =
10897 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
10899 #endif // defined(VGO_darwin)
10901 /*--------------------------------------------------------------------*/
10902 /*--- end ---*/
10903 /*--------------------------------------------------------------------*/