tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_syswrap / syswrap-darwin.c
blobb957b049f2fa04d15d11dece45562e9b46ecc342
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-2013 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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGO_darwin)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_vkiscnums.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_xarray.h"
39 #include "pub_core_clientstate.h"
40 #include "pub_core_debuglog.h"
41 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
42 #include "pub_core_transtab.h" // VG_(discard_translations)
43 #include "pub_core_libcbase.h"
44 #include "pub_core_libcassert.h"
45 #include "pub_core_libcfile.h"
46 #include "pub_core_libcprint.h"
47 #include "pub_core_libcproc.h"
48 #include "pub_core_libcsignal.h"
49 #include "pub_core_machine.h" // VG_(get_SP)
50 #include "pub_core_mallocfree.h"
51 #include "pub_core_options.h"
52 #include "pub_core_oset.h"
53 #include "pub_core_scheduler.h"
54 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
55 #include "pub_core_signals.h"
56 #include "pub_core_syscall.h"
57 #include "pub_core_syswrap.h"
58 #include "pub_core_tooliface.h"
59 #include "pub_core_wordfm.h"
61 #include "priv_types_n_macros.h"
62 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
63 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
64 #include "priv_syswrap-main.h"
66 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
67 #include <mach/mach.h>
68 #include <mach/mach_vm.h>
69 #include <semaphore.h>
70 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
72 #define msgh_request_port msgh_remote_port
73 #define msgh_reply_port msgh_local_port
74 #define BOOTSTRAP_MAX_NAME_LEN 128
75 typedef HChar name_t[BOOTSTRAP_MAX_NAME_LEN];
77 typedef uint64_t mig_addr_t;
80 // Saved ports
81 static mach_port_t vg_host_port = 0;
82 static mach_port_t vg_task_port = 0;
83 static mach_port_t vg_bootstrap_port = 0;
85 // Run a thread from beginning to end and return the thread's
86 // scheduler-return-code.
87 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
89 VgSchedReturnCode ret;
90 ThreadId tid = (ThreadId)tidW;
91 ThreadState* tst = VG_(get_ThreadState)(tid);
93 VG_(debugLog)(1, "syswrap-darwin",
94 "thread_wrapper(tid=%lld): entry\n",
95 (ULong)tidW);
97 vg_assert(tst->status == VgTs_Init);
99 /* make sure we get the CPU lock before doing anything significant */
100 VG_(acquire_BigLock)(tid, "thread_wrapper");
102 if (0)
103 VG_(printf)("thread tid %d started: stack = %p\n",
104 tid, &tid);
106 /* Make sure error reporting is enabled in the new thread. */
107 tst->err_disablement_level = 0;
109 VG_TRACK(pre_thread_first_insn, tid);
111 tst->os_state.lwpid = VG_(gettid)();
112 tst->os_state.threadgroup = VG_(getpid)();
114 /* Thread created with all signals blocked; scheduler will set the
115 appropriate mask */
117 ret = VG_(scheduler)(tid);
119 vg_assert(VG_(is_exiting)(tid));
121 vg_assert(tst->status == VgTs_Runnable);
122 vg_assert(VG_(is_running_thread)(tid));
124 VG_(debugLog)(1, "syswrap-darwin",
125 "thread_wrapper(tid=%lld): done\n",
126 (ULong)tidW);
128 /* Return to caller, still holding the lock. */
129 return ret;
134 /* Allocate a stack for this thread, if it doesn't already have one.
135 Returns the initial stack pointer value to use, or 0 if allocation
136 failed. */
138 Addr allocstack ( ThreadId tid )
140 ThreadState* tst = VG_(get_ThreadState)(tid);
141 VgStack* stack;
142 Addr initial_SP;
144 /* Either the stack_base and stack_init_SP are both zero (in which
145 case a stack hasn't been allocated) or they are both non-zero,
146 in which case it has. */
148 if (tst->os_state.valgrind_stack_base == 0)
149 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
151 if (tst->os_state.valgrind_stack_base != 0)
152 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
154 /* If no stack is present, allocate one. */
156 if (tst->os_state.valgrind_stack_base == 0) {
157 stack = VG_(am_alloc_VgStack)( &initial_SP );
158 if (stack) {
159 tst->os_state.valgrind_stack_base = (Addr)stack;
160 tst->os_state.valgrind_stack_init_SP = initial_SP;
164 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
165 tid,
166 (void*)tst->os_state.valgrind_stack_base,
167 (void*)tst->os_state.valgrind_stack_init_SP );
169 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
171 return tst->os_state.valgrind_stack_init_SP;
175 void find_stack_segment(ThreadId tid, Addr sp)
177 ML_(guess_and_register_stack) (sp, VG_(get_ThreadState)(tid));
181 /* Run a thread all the way to the end, then do appropriate exit actions
182 (this is the last-one-out-turn-off-the-lights bit).
184 static void run_a_thread_NORETURN ( Word tidW )
186 Int c;
187 VgSchedReturnCode src;
188 ThreadId tid = (ThreadId)tidW;
189 ThreadState* tst;
191 VG_(debugLog)(1, "syswrap-darwin",
192 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
193 (ULong)tidW);
195 tst = VG_(get_ThreadState)(tid);
196 vg_assert(tst);
198 /* Run the thread all the way through. */
199 src = thread_wrapper(tid);
201 VG_(debugLog)(1, "syswrap-darwin",
202 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
203 (ULong)tidW);
205 c = VG_(count_living_threads)();
206 vg_assert(c >= 1); /* stay sane */
208 // Tell the tool this thread is exiting
209 VG_TRACK( pre_thread_ll_exit, tid );
211 /* If the thread is exiting with errors disabled, complain loudly;
212 doing so is bad (does the user know this has happened?) Also,
213 in all cases, be paranoid and clear the flag anyway so that the
214 thread slot is safe in this respect if later reallocated. This
215 should be unnecessary since the flag should be cleared when the
216 slot is reallocated, in thread_wrapper(). */
217 if (tst->err_disablement_level > 0) {
218 VG_(umsg)(
219 "WARNING: exiting thread has error reporting disabled.\n"
220 "WARNING: possibly as a result of some mistake in the use\n"
221 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
223 VG_(debugLog)(
224 1, "syswrap-linux",
225 "run_a_thread_NORETURN(tid=%lld): "
226 "WARNING: exiting thread has err_disablement_level = %u\n",
227 (ULong)tidW, tst->err_disablement_level
230 tst->err_disablement_level = 0;
232 if (c == 1) {
234 VG_(debugLog)(1, "syswrap-darwin",
235 "run_a_thread_NORETURN(tid=%lld): "
236 "last one standing\n",
237 (ULong)tidW);
239 /* We are the last one standing. Keep hold of the lock and
240 carry on to show final tool results, then exit the entire system.
241 Use the continuation pointer set at startup in m_main. */
242 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
244 } else {
246 mach_msg_header_t msg;
248 VG_(debugLog)(1, "syswrap-darwin",
249 "run_a_thread_NORETURN(tid=%lld): "
250 "not last one standing\n",
251 (ULong)tidW);
253 /* OK, thread is dead, but others still exist. Just exit. */
255 /* This releases the run lock */
256 VG_(exit_thread)(tid);
257 vg_assert(tst->status == VgTs_Zombie);
259 /* tid is now invalid. */
261 // GrP fixme exit race
262 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
263 msg.msgh_request_port = VG_(gettid)();
264 msg.msgh_reply_port = 0;
265 msg.msgh_id = 3600; // thread_terminate
267 tst->status = VgTs_Empty;
268 // GrP fixme race here! new thread may claim this V thread stack
269 // before we get out here!
270 // GrP fixme use bsdthread_terminate for safe cleanup?
271 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
272 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
274 // DDD: This is reached sometimes on none/tests/manythreads, maybe
275 // because of the race above.
276 VG_(core_panic)("Thread exit failed?\n");
279 /*NOTREACHED*/
280 vg_assert(0);
284 /* Allocate a stack for the main thread, and run it all the way to the
285 end. Although we already have a working VgStack
286 (VG_(interim_stack)) it's better to allocate a new one, so that
287 overflow detection works uniformly for all threads.
289 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
291 Addr sp;
292 VG_(debugLog)(1, "syswrap-darwin",
293 "entering VG_(main_thread_wrapper_NORETURN)\n");
295 sp = allocstack(tid);
297 /* If we can't even allocate the first thread's stack, we're hosed.
298 Give up. */
299 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
301 /* shouldn't be any other threads around yet */
302 vg_assert( VG_(count_living_threads)() == 1 );
304 call_on_new_stack_0_1(
305 (Addr)sp, /* stack */
306 0, /*bogus return address*/
307 run_a_thread_NORETURN, /* fn to call */
308 (Word)tid /* arg to give it */
311 /*NOTREACHED*/
312 vg_assert(0);
316 void start_thread_NORETURN ( Word arg )
318 ThreadState* tst = (ThreadState*)arg;
319 ThreadId tid = tst->tid;
321 run_a_thread_NORETURN ( (Word)tid );
322 /*NOTREACHED*/
323 vg_assert(0);
327 void VG_(cleanup_thread) ( ThreadArchState* arch )
332 /* ---------------------------------------------------------------------
333 Message reporting, with duplicate removal
334 ------------------------------------------------------------------ */
336 static WordFM* decaying_string_table = NULL; /* HChar* -> UWord */
338 static Word decaying_string_table_cmp ( UWord s1, UWord s2 ) {
339 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
342 static void log_decaying ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
343 static void log_decaying ( const HChar* format, ... )
345 // get the message into a stack-allocated string.
346 HChar buf[256];
347 VG_(memset)(buf, 0, sizeof(buf));
348 va_list vargs;
349 va_start(vargs,format);
350 (void) VG_(vsnprintf)(buf, sizeof(buf), format, vargs);
351 va_end(vargs);
352 buf[sizeof(buf)-1] = 0;
354 // Now see if it already exists in the table of strings that we have.
355 if (!decaying_string_table) {
356 decaying_string_table
357 = VG_(newFM)( VG_(malloc), "syswrap-darwin.pd.1",
358 VG_(free), decaying_string_table_cmp );
361 const HChar* key = NULL;
362 UWord val = 0;
363 if (!VG_(lookupFM)(decaying_string_table,
364 (UWord*)&key, &val, (UWord)&buf[0])) {
365 // We haven't seen this string before, so strdup it and add
366 // it to the table.
367 vg_assert(key == NULL && val == 0);
368 key = VG_(strdup)("syswrap-darwin.pd.2", buf);
369 VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)0);
372 vg_assert(key != NULL && key != &buf[0]);
374 // So, finally, |key| is in the tree, and |val| is what it is
375 // currently associated with. Increment that counter.
376 val++;
377 Bool b = VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)val);
378 vg_assert(b);
380 if (-1 != VG_(log2)( (UInt)val )) {
381 if (val == 1)
382 VG_(dmsg)("%s\n", key);
383 else
384 VG_(dmsg)("%s (repeated %lu times)\n", key, val);
389 /* ---------------------------------------------------------------------
390 Mach port tracking (based on syswrap-generic's fd tracker)
391 ------------------------------------------------------------------ */
393 /* One of these is allocated for each open port. */
394 typedef struct OpenPort
396 mach_port_t port;
397 mach_port_type_t type; /* right type(s) */
398 Int send_count; /* number of send rights */
399 HChar *name; /* bootstrap name or NULL */
400 ExeContext *where; /* first allocation only */
401 struct OpenPort *next, *prev;
402 } OpenPort;
404 // strlen("0x12345678")
405 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
407 /* List of allocated ports. */
408 static OpenPort *allocated_ports;
410 /* Count of open ports. */
411 static Int allocated_port_count = 0;
413 /* Create an entry for |port|, with no other info. Assumes it doesn't
414 already exist. */
415 static void port_create_vanilla(mach_port_t port)
417 OpenPort* op
418 = VG_(calloc)("syswrap-darwin.port_create_vanilla", sizeof(OpenPort), 1);
419 op->port = port;
420 /* Add it to the list. */
421 op->next = allocated_ports;
422 if (allocated_ports) allocated_ports->prev = op;
423 allocated_ports = op;
424 allocated_port_count++;
427 __attribute__((unused))
428 static Bool port_exists(mach_port_t port)
430 OpenPort *i;
432 /* Check to see if this port is already open. */
433 i = allocated_ports;
434 while (i) {
435 if (i->port == port) {
436 return True;
438 i = i->next;
441 return False;
444 static OpenPort *info_for_port(mach_port_t port)
446 OpenPort *i;
447 if (!port) return NULL;
449 i = allocated_ports;
450 while (i) {
451 if (i->port == port) {
452 return i;
454 i = i->next;
457 return NULL;
461 // Give a port a name, without changing its refcount
462 // GrP fixme don't override name if it already has a specific one
463 __private_extern__ void assign_port_name(mach_port_t port, const HChar *name)
465 OpenPort *i;
466 if (!port) return;
467 vg_assert(name);
469 i = info_for_port(port);
470 vg_assert(i);
472 if (i->name) VG_(free)(i->name);
473 i->name =
474 VG_(malloc)("syswrap-darwin.mach-port-name",
475 VG_(strlen)(name) + PORT_STRLEN + 1);
476 VG_(sprintf)(i->name, name, port);
480 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
481 static const HChar *name_for_port(mach_port_t port)
483 static HChar buf[8 + PORT_STRLEN + 1];
484 OpenPort *i;
486 // hack
487 if (port == VG_(gettid)()) return "mach_thread_self()";
488 if (port == 0) return "NULL";
490 i = allocated_ports;
491 while (i) {
492 if (i->port == port) {
493 return i->name;
495 i = i->next;
498 VG_(sprintf)(buf, "NONPORT-%#x", port);
499 return buf;
502 /* Note the fact that a port was just deallocated. */
504 static
505 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
507 OpenPort *i = allocated_ports;
508 if (!port) return;
510 while(i) {
511 if(i->port == port) {
512 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
513 if (right & MACH_PORT_TYPE_SEND) {
514 // send rights are refcounted
515 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
516 i->send_count += delta;
517 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
518 else i->type &= ~MACH_PORT_TYPE_SEND;
520 right = right & ~MACH_PORT_TYPE_SEND;
521 if (right) {
522 // other rights are not refcounted
523 if (delta > 0) {
524 i->type |= right;
525 } else if (delta < 0) {
526 i->type &= ~right;
530 if (i->type != 0) return;
532 // Port has no rights left. Kill it.
533 // VG_(printf)("deleting port %p %s", i->port, i->name);
534 if(i->prev)
535 i->prev->next = i->next;
536 else
537 allocated_ports = i->next;
538 if(i->next)
539 i->next->prev = i->prev;
540 if(i->name)
541 VG_(free) (i->name);
542 VG_(free) (i);
543 allocated_port_count--;
544 return;
546 i = i->next;
549 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
552 static
553 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
555 switch (type) {
556 case MACH_MSG_TYPE_PORT_NAME:
557 // this task has no rights for the name
558 break;
559 case MACH_MSG_TYPE_PORT_RECEIVE:
560 // this task gets receive rights
561 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
562 break;
563 case MACH_MSG_TYPE_PORT_SEND:
564 // this task gets a send right
565 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
566 break;
567 case MACH_MSG_TYPE_PORT_SEND_ONCE:
568 // this task gets send-once rights
569 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
570 break;
571 default:
572 vg_assert(0);
573 break;
577 static
578 void record_port_dealloc(mach_port_t port)
580 // deletes 1 send or send-once right (port can't have both)
581 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
584 static
585 void record_port_destroy(mach_port_t port)
587 // deletes all rights to port
588 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
592 /* Note the fact that a Mach port was just allocated or transferred.
593 If the port is already known, increment its reference count. */
594 void record_named_port(ThreadId tid, mach_port_t port,
595 mach_port_right_t right, const HChar *name)
597 OpenPort *i;
598 if (!port) return;
600 /* Check to see if this port is already open. */
601 i = allocated_ports;
602 while (i) {
603 if (i->port == port) {
604 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
605 return;
607 i = i->next;
610 /* Not already one: allocate an OpenPort */
611 if (i == NULL) {
612 i = VG_(malloc)("syswrap-darwin.mach-port", sizeof(OpenPort));
614 i->prev = NULL;
615 i->next = allocated_ports;
616 if(allocated_ports) allocated_ports->prev = i;
617 allocated_ports = i;
618 allocated_port_count++;
620 i->port = port;
621 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
622 i->name = NULL;
623 if (right != -1) {
624 i->type = MACH_PORT_TYPE(right);
625 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
626 } else {
627 i->type = 0;
628 i->send_count = 0;
631 assign_port_name(port, name);
636 // Record opening of a nameless port.
637 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
639 record_named_port(tid, port, right, "unnamed-%p");
643 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
644 void VG_(show_open_ports)(void)
646 OpenPort *i;
648 VG_(message)(Vg_UserMsg,
649 "MACH PORTS: %d open at exit.\n", allocated_port_count);
651 for (i = allocated_ports; i; i = i->next) {
652 if (i->name) {
653 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s\n", i->port,
654 i->name);
655 } else {
656 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x\n", i->port);
659 if (i->where) {
660 VG_(pp_ExeContext)(i->where);
661 VG_(message)(Vg_UserMsg, "\n");
665 VG_(message)(Vg_UserMsg, "\n");
669 /* ---------------------------------------------------------------------
670 sync_mappings
671 ------------------------------------------------------------------ */
673 typedef
674 enum { CheckAlways=1, CheckEvery20, CheckNever }
675 CheckHowOften;
677 static const HChar* show_CheckHowOften ( CheckHowOften cho ) {
678 switch (cho) {
679 case CheckAlways: return "Always ";
680 case CheckEvery20: return "Every20";
681 case CheckNever: return "Never ";
682 default: vg_assert(0);
686 /* Statistics for one particular resync-call set of arguments,
687 as specified by key1, key2 and key3. */
688 typedef
689 struct {
690 CheckHowOften cho;
691 const HChar* key1;
692 const HChar* key2;
693 UWord key3;
694 ULong n_checks;
695 ULong n_mappings_added;
696 ULong n_mappings_removed;
698 SyncStats;
700 static Bool cmp_eqkeys_SyncStats ( SyncStats* ss1, SyncStats* ss2 ) {
701 return ss1->key3 == ss2->key3
702 && 0 == VG_(strcmp)(ss1->key1, ss2->key1)
703 && 0 == VG_(strcmp)(ss1->key2, ss2->key2);
706 /* The filter data. */
707 #define N_SYNCSTATS 1000
708 static Int syncstats_used = 0;
709 static SyncStats syncstats[N_SYNCSTATS];
711 /* Statistics overall, for the filter. */
712 static ULong n_syncsRequested = 0; // Total number requested
713 static ULong n_syncsPerformed = 0; // Number carried out (the rest skipped)
716 static
717 void update_syncstats ( CheckHowOften cho,
718 const HChar* key1, const HChar* key2,
719 UWord key3,
720 UInt n_mappings_added, UInt n_mappings_removed )
722 SyncStats dummy = { CheckAlways, key1, key2, key3, 0, 0, 0 };
723 Int i;
724 for (i = 0; i < syncstats_used; i++) {
725 if (cmp_eqkeys_SyncStats(&syncstats[i], &dummy))
726 break;
728 vg_assert(i >= 0 && i <= syncstats_used);
729 if (i == syncstats_used) {
730 // alloc new
731 vg_assert(syncstats_used < N_SYNCSTATS);
732 syncstats_used++;
733 syncstats[i] = dummy;
734 syncstats[i].cho = cho;
736 vg_assert(cmp_eqkeys_SyncStats(&syncstats[i], &dummy));
737 syncstats[i].n_checks++;
738 syncstats[i].n_mappings_added += (ULong)n_mappings_added;
739 syncstats[i].n_mappings_removed += (ULong)n_mappings_removed;
740 // reorder
741 static UInt reorder_ctr = 0;
742 if (i > 0 && 0 == (1 & reorder_ctr++)) {
743 SyncStats tmp = syncstats[i-1];
744 syncstats[i-1] = syncstats[i];
745 syncstats[i] = tmp;
750 static void maybe_show_syncstats ( void )
752 Int i;
754 // display
755 if (0 == (n_syncsRequested & 0xFF)) {
756 VG_(printf)("Resync filter: %'llu requested, %'llu performed (%llu%%)\n",
757 n_syncsRequested, n_syncsPerformed,
758 (100 * n_syncsPerformed) /
759 (n_syncsRequested == 0 ? 1 : n_syncsRequested));
760 for (i = 0; i < syncstats_used; i++) {
761 if (i >= 40) break; // just show the top 40
762 VG_(printf)(" [%3d] (%s) upd %6llu diff %4llu+,%3llu-"
763 " %s %s 0x%08llx\n",
764 i, show_CheckHowOften(syncstats[i].cho),
765 syncstats[i].n_checks,
766 syncstats[i].n_mappings_added,
767 syncstats[i].n_mappings_removed,
768 syncstats[i].key1, syncstats[i].key2,
769 (ULong)syncstats[i].key3);
771 if (i < syncstats_used) {
772 VG_(printf)(" and %d more entries not shown.\n", syncstats_used - i);
774 VG_(printf)("\n");
779 Bool ML_(sync_mappings)(const HChar* when, const HChar* where, UWord num)
781 // If VG(clo_resync_filter) == 0, the filter is disabled, and
782 // we must always honour the resync request.
784 // If VG(clo_resync_filter) == 1, the filter is enabled,
785 // so we try to avoid doing the sync if possible, but keep
786 // quiet.
788 // If VG(clo_resync_filter) == 2, the filter is enabled,
789 // so we try to avoid doing the sync if possible, and also
790 // periodically show stats, so that the filter can be updated.
791 // (by hand).
793 if (VG_(clo_resync_filter) >= 2)
794 maybe_show_syncstats();
796 n_syncsRequested++;
798 // Usually the number of segments added/removed in a single call is very
799 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
800 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
801 // because we can't do dynamic allocation within VG_(get_changed_segments),
802 // because it's in m_aspacemgr.
803 ChangedSeg* css = NULL;
804 Int css_size;
805 Int css_used;
806 Int i;
807 Bool ok;
809 // -------------- BEGIN resync-filter-kludge --------------
811 // Some kludges to try and avoid the worst case cost hit of doing
812 // zillions of resyncs (huge). The idea is that many of the most
813 // common resyncs never appear to cause a delta, so we just ignore
814 // them (CheckNever). Then, a bunch of them also happen a lot, but
815 // only very occasionally cause a delta. We resync after 20 of those
816 // (CheckEvery20). Finally, the rest form a long tail, so we always
817 // resync after those (CheckAlways).
819 // Assume this is kernel-version and word-size specific, so develop
820 // filters accordingly. This might be overly conservative --
821 // I don't know.
823 # define STREQ(_s1, _s2) (0 == VG_(strcmp)((_s1),(_s2)))
824 Bool when_in = STREQ(when, "in");
825 Bool when_after = STREQ(when, "after");
826 Bool where_mmr = STREQ(where, "mach_msg_receive");
827 Bool where_mmrU = STREQ(where, "mach_msg_receive-UNHANDLED");
828 Bool where_iuct = STREQ(where, "iokit_user_client_trap");
829 Bool where_MwcN = STREQ(where, "ML_(wqthread_continue_NORETURN)");
830 Bool where_woQR = STREQ(where, "workq_ops(QUEUE_REQTHREADS)");
831 Bool where_woTR = STREQ(where, "workq_ops(THREAD_RETURN)");
832 Bool where_ke64 = STREQ(where, "kevent64");
833 # undef STREQ
835 vg_assert(
836 1 >= ( (where_mmr ? 1 : 0) + (where_mmrU ? 1 : 0)
837 + (where_iuct ? 1 : 0) + (where_MwcN ? 1 : 0)
838 + (where_woQR ? 1 : 0) + (where_woTR ? 1 : 0)
839 + (where_ke64 ? 1 : 0)
841 // merely to stop gcc complaining of non-use in the case where
842 // there's no filter:
843 vg_assert(when_in == True || when_in == False);
844 vg_assert(when_after == True || when_after == False);
846 CheckHowOften check = CheckAlways;
848 # if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
849 /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
850 if (when_after && where_mmr) {
851 // "after mach_msg_receive <number>"
852 switch (num) {
853 case 0x00000000: // upd 12414 diff 36+,0-
854 check = CheckEvery20;
855 break;
856 default:
857 break;
860 else
861 if (when_after && where_mmrU) {
862 // "after mach_msg_receive-UNHANDLED <number>"
863 switch (num) {
864 case 0x00000000: // upd 16687 diff 73+,0-
865 case 0x00000001: // upd 5106 diff 89+,0-
866 case 0x00000002: // upd 1609 diff 1+,0-
867 case 0x00000003: // upd 1987 diff 6+,0-
868 // case 0x00000b95: // upd 2894 diff 57+,1- <==dangerous
869 case 0x000072d9: // upd 2616 diff 11+,0-
870 case 0x000072cb: // upd 2616 diff 9+,0-
871 case 0x000074d5: // upd 172 diff 0+,0-
872 check = CheckEvery20;
873 break;
874 default:
875 break;
878 else
879 if (when_in && where_MwcN && num == 0x00000000) {
880 // in ML_(wqthread_continue_NORETURN) 0x00000000
881 // upd 4346 diff 0+,0-
882 check = CheckEvery20;
884 else
885 if (when_after && where_woQR && num == 0x00000000) {
886 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
887 // upd 14434 diff 102+,0-
888 check = CheckEvery20;
890 else
891 if (when_after && where_woTR && num == 0x00000000) {
892 // after workq_ops(THREAD_RETURN) 0x00000000
893 // upd 14434 diff 102+,0-
894 check = CheckEvery20;
896 else
897 if (when_after && where_ke64 && num == 0x00000000) {
898 // after kevent64 0x00000000
899 // upd 1736 diff 78+,0-
900 check = CheckEvery20;
902 /* ----------- END filter for 64-bit 10.9.x ----------- */
903 # endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
905 # if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
906 /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
907 if (when_after && where_mmr) {
908 // "after mach_msg_receive <number>"
909 switch (num) {
910 case 0x00000000: // upd 2380 diff 23+,0-
911 check = CheckEvery20;
912 break;
913 default:
914 break;
917 else
918 if (when_after && where_mmrU) {
919 // "after mach_msg_receive-UNHANDLED <number>"
920 switch (num) {
921 case 0x00000000: // upd 2370 diff 93+,1- <==dangerous
922 case 0x0000004f: // upd 212 diff 2+,0-
923 case 0x00000b95: // upd 9826 diff 163+,1- diff scale, dangerous
924 case 0x00000ba5: // upd 304 diff 0+,0-
925 case 0x0000157f: // upd 201 diff 2+,0-
926 case 0x0000157d: // upd 197 diff 1+,0-
927 case 0x0000333d: // upd 112 diff 0+,0-
928 case 0x0000333f: // upd 223 diff 10+,0-
929 case 0x000072cd: // upd 8286 diff 98+,0- diff scale
930 case 0x000072ae: // upd 193 diff 10+,0-
931 case 0x000072ec: // upd 319 diff 7+,0-
932 case 0x77303074: // upd 113 diff 3+,0-
933 case 0x10000000: // upd 314 diff 6+,0-
934 check = CheckEvery20;
935 break;
936 default:
937 break;
940 else
941 if (when_in && where_MwcN && num == 0x00000000) {
942 // in ML_(wqthread_continue_NORETURN) 0x00000000
943 // upd 1110 diff 37+,0-
944 check = CheckEvery20;
946 else
947 if (when_after && where_woQR && num == 0x00000000) {
948 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
949 // upd 1099 diff 37+,0-
950 check = CheckEvery20;
952 else
953 if (when_after && where_woTR && num == 0x00000000) {
954 // after workq_ops(THREAD_RETURN) 0x00000000
955 // 1239 diff 53+,0-
956 check = CheckEvery20;
958 else
959 if (when_after && where_ke64 && num == 0x00000000) {
960 // after kevent64 0x00000000
961 // upd 1463 diff 15+,0-
962 check = CheckEvery20;
964 /* ----------- END filter for 64-bit 10.10.x ----------- */
965 # endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
967 /* Regardless of what the filter says, force a sync every 1 time in
968 1000, to stop things getting too far out of sync. */
970 static UInt ctr1k = 0;
971 ctr1k++;
972 if ((ctr1k % 1000) == 0)
973 check = CheckAlways;
976 /* If the filter is disabled, we must always check. */
977 if (VG_(clo_resync_filter) == 0)
978 check = CheckAlways;
980 switch (check) {
981 case CheckAlways:
982 break;
983 case CheckEvery20: {
984 // only resync once every 20th time
985 static UInt ctr10 = 0;
986 ctr10++;
987 if ((ctr10 % 20) != 0) return False;
988 break;
990 case CheckNever:
991 return False;
992 default:
993 vg_assert(0);
996 // --------------- END resync-filter-kludge ---------------
998 if (0 || VG_(clo_trace_syscalls)) {
999 VG_(debugLog)(0, "syswrap-darwin",
1000 "sync_mappings (%s) (\"%s\", \"%s\", 0x%llx)\n",
1001 show_CheckHowOften(check), when, where, (ULong)num);
1004 // 16 is enough for most cases, but small enough that overflow happens
1005 // occasionally and thus the overflow path gets some test coverage.
1006 css_size = 16;
1007 ok = False;
1008 while (!ok) {
1009 VG_(free)(css); // css is NULL on first iteration; that's ok.
1010 css = VG_(calloc)("sys_wrap.sync_mappings",
1011 css_size, sizeof(ChangedSeg));
1012 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
1013 css_size *= 2;
1016 UInt css_added = 0, css_removed = 0;
1018 // Now add/remove them.
1019 for (i = 0; i < css_used; i++) {
1020 ChangedSeg* cs = &css[i];
1021 if (cs->is_added) {
1022 css_added++;
1023 ML_(notify_core_and_tool_of_mmap)(
1024 cs->start, cs->end - cs->start + 1,
1025 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
1026 // should this call VG_(di_notify_mmap) also?
1027 } else {
1028 css_removed++;
1029 ML_(notify_core_and_tool_of_munmap)(
1030 cs->start, cs->end - cs->start + 1);
1032 if (VG_(clo_trace_syscalls)) {
1033 if (cs->is_added) {
1034 VG_(debugLog)(0, "syswrap-darwin",
1035 " added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
1036 cs->start, cs->end + 1, (UInt)cs->prot, where, when);
1037 } else {
1038 VG_(debugLog)(0, "syswrap-darwin",
1039 " removed region 0x%010lx..0x%010lx at %s (%s)\n",
1040 cs->start, cs->end + 1, where, when);
1045 VG_(free)(css);
1047 if (0)
1048 VG_(debugLog)(0, "syswrap-darwin", "SYNC: %d %s %s\n",
1049 css_used, when, where);
1051 // Update the stats, so we can derive the filter above.
1052 n_syncsPerformed++;
1053 update_syncstats(check, when, where, num, css_added, css_removed);
1055 return css_used > 0;
1058 /* ---------------------------------------------------------------------
1059 wrappers
1060 ------------------------------------------------------------------ */
1062 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
1063 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
1065 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
1066 #define POST_FN(name) vgSysWrap_darwin_##name##_after
1068 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
1069 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
1071 #if VG_WORDSIZE == 4
1072 // Combine two 32-bit values into a 64-bit value
1073 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
1074 # if defined(VGA_x86)
1075 # define LOHI64(lo,hi) ( ((ULong)(UInt)(lo)) | (((ULong)(UInt)(hi)) << 32) )
1076 # else
1077 # error unknown architecture
1078 # endif
1079 #endif
1081 // Retrieve the current Mach thread
1082 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1084 // Set the POST handler for a mach_msg derivative
1085 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1087 // Set or get values saved from Mach messages
1088 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
1089 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
1090 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
1092 /* ---------------------------------------------------------------------
1093 darwin ioctl wrapper
1094 ------------------------------------------------------------------ */
1096 PRE(ioctl)
1098 *flags |= SfMayBlock;
1100 /* Handle ioctls that don't take an arg first */
1101 switch (ARG2 /* request */) {
1102 case VKI_TIOCSCTTY:
1103 case VKI_TIOCEXCL:
1104 case VKI_TIOCSBRK:
1105 case VKI_TIOCCBRK:
1106 case VKI_TIOCPTYGRANT:
1107 case VKI_TIOCPTYUNLK:
1108 case VKI_DTRACEHIOC_REMOVE:
1109 PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
1110 PRE_REG_READ2(long, "ioctl",
1111 unsigned int, fd, unsigned int, request);
1112 return;
1113 default:
1114 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
1115 PRE_REG_READ3(long, "ioctl",
1116 unsigned int, fd, unsigned int, request, unsigned long, arg);
1119 switch (ARG2 /* request */) {
1120 case VKI_TIOCGWINSZ:
1121 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
1122 break;
1123 case VKI_TIOCSWINSZ:
1124 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
1125 break;
1126 case VKI_TIOCMBIS:
1127 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
1128 break;
1129 case VKI_TIOCMBIC:
1130 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
1131 break;
1132 case VKI_TIOCMSET:
1133 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
1134 break;
1135 case VKI_TIOCMGET:
1136 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
1137 break;
1138 case VKI_TIOCGPGRP:
1139 /* Get process group ID for foreground processing group. */
1140 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1141 break;
1142 case VKI_TIOCSPGRP:
1143 /* Set a process group ID? */
1144 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1145 break;
1146 case VKI_FIONBIO:
1147 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
1148 break;
1149 case VKI_FIOASYNC:
1150 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
1151 break;
1152 case VKI_FIONREAD: /* identical to SIOCINQ */
1153 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1154 break;
1157 /* These all use struct ifreq AFAIK */
1158 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1159 case VKI_SIOCGIFFLAGS: /* get flags */
1160 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1161 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1162 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
1163 break;
1164 case VKI_SIOCGIFMTU: /* get MTU size */
1165 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1166 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1167 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
1168 break;
1169 case VKI_SIOCGIFADDR: /* get PA address */
1170 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1171 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1172 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
1173 break;
1174 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1175 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1176 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1177 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
1178 break;
1179 case VKI_SIOCGIFMETRIC: /* get metric */
1180 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1181 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1182 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
1183 break;
1184 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1185 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1186 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1187 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
1188 break;
1189 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1190 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1191 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1192 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
1193 break;
1194 case VKI_SIOCGIFCONF: /* get iface list */
1195 /* WAS:
1196 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1197 KERNEL_DO_SYSCALL(tid,RES);
1198 if (!VG_(is_kerror)(RES) && RES == 0)
1199 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1201 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1202 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
1203 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
1204 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1205 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
1206 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
1207 if ( ARG3 ) {
1208 // TODO len must be readable and writable
1209 // buf pointer only needs to be readable
1210 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1211 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1212 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1214 break;
1216 case VKI_SIOCSIFFLAGS: /* set flags */
1217 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1218 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1219 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1220 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1221 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1222 break;
1223 case VKI_SIOCSIFADDR: /* set PA address */
1224 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1225 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1226 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1227 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1228 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1229 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1230 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1231 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1232 break;
1233 case VKI_SIOCSIFMETRIC: /* set metric */
1234 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1235 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1236 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1237 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1238 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1239 break;
1240 case VKI_SIOCSIFMTU: /* set MTU size */
1241 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1242 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1243 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1244 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1245 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1246 break;
1247 /* Routing table calls. */
1248 #ifdef VKI_SIOCADDRT
1249 case VKI_SIOCADDRT: /* add routing table entry */
1250 case VKI_SIOCDELRT: /* delete routing table entry */
1251 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
1252 sizeof(struct vki_rtentry));
1253 break;
1254 #endif
1256 case VKI_SIOCGPGRP:
1257 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
1258 break;
1259 case VKI_SIOCSPGRP:
1260 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
1261 //tst->sys_flags &= ~SfMayBlock;
1262 break;
1264 case VKI_FIODTYPE:
1265 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1266 break;
1268 case VKI_DTRACEHIOC_ADDDOF:
1269 break;
1271 // ttycom.h
1272 case VKI_TIOCGETA:
1273 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
1274 break;
1275 case VKI_TIOCSETA:
1276 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
1277 break;
1278 case VKI_TIOCGETD:
1279 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
1280 break;
1281 case VKI_TIOCSETD:
1282 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
1283 break;
1284 case VKI_TIOCPTYGNAME:
1285 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
1286 break;
1288 // filio.h
1289 case VKI_FIOCLEX:
1290 break;
1291 case VKI_FIONCLEX:
1292 break;
1294 default:
1295 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
1296 break;
1301 POST(ioctl)
1303 vg_assert(SUCCESS);
1304 switch (ARG2 /* request */) {
1305 case VKI_TIOCGWINSZ:
1306 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
1307 break;
1308 case VKI_TIOCSWINSZ:
1309 case VKI_TIOCMBIS:
1310 case VKI_TIOCMBIC:
1311 case VKI_TIOCMSET:
1312 break;
1313 case VKI_TIOCMGET:
1314 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
1315 break;
1316 case VKI_TIOCGPGRP:
1317 /* Get process group ID for foreground processing group. */
1318 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1319 break;
1320 case VKI_TIOCSPGRP:
1321 /* Set a process group ID? */
1322 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1323 break;
1324 case VKI_TIOCSCTTY:
1325 break;
1326 case VKI_FIONBIO:
1327 break;
1328 case VKI_FIOASYNC:
1329 break;
1330 case VKI_FIONREAD: /* identical to SIOCINQ */
1331 POST_MEM_WRITE( ARG3, sizeof(int) );
1332 break;
1334 /* These all use struct ifreq AFAIK */
1335 case VKI_SIOCGIFFLAGS: /* get flags */
1336 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1337 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1338 break;
1339 case VKI_SIOCGIFMTU: /* get MTU size */
1340 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1341 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1342 break;
1343 case VKI_SIOCGIFADDR: /* get PA address */
1344 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1345 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1346 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1347 POST_MEM_WRITE(
1348 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1349 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1350 break;
1351 case VKI_SIOCGIFMETRIC: /* get metric */
1352 POST_MEM_WRITE(
1353 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1354 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1355 break;
1356 case VKI_SIOCGIFCONF: /* get iface list */
1357 /* WAS:
1358 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1359 KERNEL_DO_SYSCALL(tid,RES);
1360 if (!VG_(is_kerror)(RES) && RES == 0)
1361 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1363 if (RES == 0 && ARG3 ) {
1364 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1365 if (ifc->vki_ifc_buf != NULL)
1366 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1368 break;
1370 case VKI_SIOCSIFFLAGS: /* set flags */
1371 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1372 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1373 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1374 case VKI_SIOCSIFMETRIC: /* set metric */
1375 case VKI_SIOCSIFADDR: /* set PA address */
1376 case VKI_SIOCSIFMTU: /* set MTU size */
1377 break;
1379 #ifdef VKI_SIOCADDRT
1380 /* Routing table calls. */
1381 case VKI_SIOCADDRT: /* add routing table entry */
1382 case VKI_SIOCDELRT: /* delete routing table entry */
1383 break;
1384 #endif
1386 case VKI_SIOCGPGRP:
1387 POST_MEM_WRITE(ARG3, sizeof(int));
1388 break;
1389 case VKI_SIOCSPGRP:
1390 break;
1392 case VKI_FIODTYPE:
1393 POST_MEM_WRITE( ARG3, sizeof(int) );
1394 break;
1396 case VKI_DTRACEHIOC_REMOVE:
1397 case VKI_DTRACEHIOC_ADDDOF:
1398 break;
1400 // ttycom.h
1401 case VKI_TIOCGETA:
1402 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1403 break;
1404 case VKI_TIOCSETA:
1405 break;
1406 case VKI_TIOCGETD:
1407 POST_MEM_WRITE( ARG3, sizeof(int) );
1408 break;
1409 case VKI_TIOCSETD:
1410 break;
1411 case VKI_TIOCPTYGNAME:
1412 POST_MEM_WRITE( ARG3, 128);
1413 break;
1414 case VKI_TIOCSBRK: /* set break bit */
1415 case VKI_TIOCCBRK: /* clear break bit */
1416 case VKI_TIOCPTYGRANT:
1417 case VKI_TIOCPTYUNLK:
1418 break;
1420 default:
1421 break;
1426 /* ---------------------------------------------------------------------
1427 darwin fcntl wrapper
1428 ------------------------------------------------------------------ */
1429 static const HChar *name_for_fcntl(UWord cmd) {
1430 #define F(n) case VKI_##n: return #n
1431 switch (cmd) {
1432 F(F_CHKCLEAN);
1433 F(F_RDAHEAD);
1434 F(F_NOCACHE);
1435 F(F_FULLFSYNC);
1436 F(F_FREEZE_FS);
1437 F(F_THAW_FS);
1438 F(F_GLOBAL_NOCACHE);
1439 F(F_PREALLOCATE);
1440 F(F_SETSIZE);
1441 F(F_RDADVISE);
1442 # if DARWIN_VERS < DARWIN_10_9
1443 F(F_READBOOTSTRAP);
1444 F(F_WRITEBOOTSTRAP);
1445 # endif
1446 F(F_LOG2PHYS);
1447 F(F_GETPATH);
1448 F(F_PATHPKG_CHECK);
1449 F(F_ADDSIGS);
1450 # if DARWIN_VERS >= DARWIN_10_9
1451 F(F_ADDFILESIGS);
1452 # endif
1453 default:
1454 return "UNKNOWN";
1456 #undef F
1459 PRE(fcntl)
1461 switch (ARG2) {
1462 // These ones ignore ARG3.
1463 case VKI_F_GETFD:
1464 case VKI_F_GETFL:
1465 case VKI_F_GETOWN:
1466 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1467 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1468 break;
1470 // These ones use ARG3 as "arg".
1471 case VKI_F_DUPFD:
1472 case VKI_F_SETFD:
1473 case VKI_F_SETFL:
1474 case VKI_F_SETOWN:
1475 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1476 PRE_REG_READ3(long, "fcntl",
1477 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1478 break;
1480 // These ones use ARG3 as "lock".
1481 case VKI_F_GETLK:
1482 case VKI_F_SETLK:
1483 case VKI_F_SETLKW:
1484 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1485 PRE_REG_READ3(long, "fcntl",
1486 unsigned int, fd, unsigned int, cmd,
1487 struct flock64 *, lock);
1488 // GrP fixme mem read sizeof(flock64)
1489 if (ARG2 == VKI_F_SETLKW)
1490 *flags |= SfMayBlock;
1491 break;
1492 # if DARWIN_VERS >= DARWIN_10_10
1493 case VKI_F_SETLKWTIMEOUT:
1494 PRINT("fcntl[ARG3=='locktimeout'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1495 PRE_REG_READ3(long, "fcntl",
1496 unsigned int, fd, unsigned int, cmd,
1497 struct flocktimeout *, lock);
1498 *flags |= SfMayBlock;
1499 break;
1500 # endif
1502 // none
1503 case VKI_F_CHKCLEAN:
1504 case VKI_F_RDAHEAD:
1505 case VKI_F_NOCACHE:
1506 case VKI_F_FULLFSYNC:
1507 case VKI_F_FREEZE_FS:
1508 case VKI_F_THAW_FS:
1509 case VKI_F_GLOBAL_NOCACHE:
1510 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1511 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1512 break;
1514 // struct fstore
1515 case VKI_F_PREALLOCATE:
1516 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1517 PRE_REG_READ3(long, "fcntl",
1518 unsigned int, fd, unsigned int, cmd,
1519 struct fstore *, fstore);
1521 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1522 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1523 fstore->fst_flags );
1524 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1525 fstore->fst_posmode );
1526 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1527 fstore->fst_offset );
1528 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1529 fstore->fst_length );
1530 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1531 fstore->fst_bytesalloc);
1533 break;
1535 // off_t
1536 case VKI_F_SETSIZE:
1537 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1538 PRE_REG_READ3(long, "fcntl",
1539 unsigned int, fd, unsigned int, cmd,
1540 vki_off_t *, offset);
1541 break;
1543 // struct radvisory
1544 case VKI_F_RDADVISE:
1545 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1546 PRE_REG_READ3(long, "fcntl",
1547 unsigned int, fd, unsigned int, cmd,
1548 struct vki_radvisory *, radvisory);
1550 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1551 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1552 radvisory->ra_offset );
1553 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1554 radvisory->ra_count );
1556 break;
1558 # if DARWIN_VERS < DARWIN_10_9
1559 // struct fbootstraptransfer
1560 case VKI_F_READBOOTSTRAP:
1561 case VKI_F_WRITEBOOTSTRAP:
1562 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1563 PRE_REG_READ3(long, "fcntl",
1564 unsigned int, fd, unsigned int, cmd,
1565 struct fbootstraptransfer *, bootstrap);
1566 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1567 ARG3, sizeof(struct vki_fbootstraptransfer) );
1568 break;
1569 # endif
1571 // struct log2phys (out)
1572 case VKI_F_LOG2PHYS:
1573 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1574 PRE_REG_READ3(long, "fcntl",
1575 unsigned int, fd, unsigned int, cmd,
1576 struct log2phys *, l2p);
1577 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1578 ARG3, sizeof(struct vki_log2phys) );
1579 break;
1581 // char[maxpathlen] (out)
1582 case VKI_F_GETPATH:
1583 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1584 PRE_REG_READ3(long, "fcntl",
1585 unsigned int, fd, unsigned int, cmd,
1586 char *, pathbuf);
1587 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1588 ARG3, VKI_MAXPATHLEN );
1589 break;
1591 // char[maxpathlen] (in)
1592 case VKI_F_PATHPKG_CHECK:
1593 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1594 (char *)ARG3);
1595 PRE_REG_READ3(long, "fcntl",
1596 unsigned int, fd, unsigned int, cmd,
1597 char *, pathbuf);
1598 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1599 break;
1601 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1602 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1603 PRE_REG_READ3(long, "fcntl",
1604 unsigned int, fd, unsigned int, cmd,
1605 vki_fsignatures_t *, sigs);
1608 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1609 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1610 fsigs->fs_blob_start);
1611 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1612 fsigs->fs_blob_size);
1614 if (fsigs->fs_blob_start)
1615 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1616 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1618 break;
1620 case VKI_F_ADDFILESIGS: /* Add signature from same file (used by dyld for shared libs) */
1621 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2));
1622 PRE_REG_READ3(long, "fcntl",
1623 unsigned int, fd, unsigned int, cmd,
1624 vki_fsignatures_t *, sigs);
1627 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1628 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1629 fsigs->fs_blob_start);
1630 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1631 fsigs->fs_blob_size);
1633 break;
1635 default:
1636 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1637 log_decaying("UNKNOWN fcntl %ld!", ARG2);
1638 break;
1642 POST(fcntl)
1644 vg_assert(SUCCESS);
1645 switch (ARG2) {
1646 case VKI_F_DUPFD:
1647 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1648 VG_(close)(RES);
1649 SET_STATUS_Failure( VKI_EMFILE );
1650 } else {
1651 if (VG_(clo_track_fds))
1652 ML_(record_fd_open_named)(tid, RES);
1654 break;
1656 case VKI_F_GETFD:
1657 case VKI_F_GETFL:
1658 case VKI_F_GETOWN:
1659 case VKI_F_SETFD:
1660 case VKI_F_SETFL:
1661 case VKI_F_SETOWN:
1662 case VKI_F_GETLK:
1663 case VKI_F_SETLK:
1664 case VKI_F_SETLKW:
1665 # if DARWIN_VERS >= DARWIN_10_10
1666 case VKI_F_SETLKWTIMEOUT:
1667 break;
1668 # endif
1670 case VKI_F_PREALLOCATE:
1672 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1673 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1675 break;
1677 case VKI_F_LOG2PHYS:
1678 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1679 break;
1681 case VKI_F_GETPATH:
1682 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1683 PRINT("\"%s\"", (char*)ARG3);
1684 break;
1686 default:
1687 // DDD: ugh, missing lots of cases here, not nice
1688 break;
1692 /* ---------------------------------------------------------------------
1693 unix syscalls
1694 ------------------------------------------------------------------ */
1696 PRE(futimes)
1698 PRINT("futimes ( %ld, %#lx )", ARG1,ARG2);
1699 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1700 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1701 SET_STATUS_Failure( VKI_EBADF );
1702 } else if (ARG2 != 0) {
1703 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1704 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1708 PRE(semget)
1710 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1711 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1714 PRE(semop)
1716 *flags |= SfMayBlock;
1717 PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
1718 PRE_REG_READ3(long, "semop",
1719 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1720 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1723 PRE(semctl)
1725 switch (ARG3) {
1726 case VKI_IPC_STAT:
1727 case VKI_IPC_SET:
1728 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1729 PRE_REG_READ4(long, "semctl",
1730 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1731 break;
1732 case VKI_GETALL:
1733 case VKI_SETALL:
1734 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1735 PRE_REG_READ4(long, "semctl",
1736 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1737 break;
1738 case VKI_SETVAL:
1739 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1740 PRE_REG_READ4(long, "semctl",
1741 int, semid, int, semnum, int, cmd, int, arg);
1742 break;
1743 default:
1744 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1745 PRE_REG_READ3(long, "semctl",
1746 int, semid, int, semnum, int, cmd);
1747 break;
1749 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1751 POST(semctl)
1753 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1756 PRE(sem_open)
1758 if (ARG2 & VKI_O_CREAT) {
1759 // 4-arg version
1760 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1761 ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1762 PRE_REG_READ4(vki_sem_t *, "sem_open",
1763 const char *, name, int, oflag, vki_mode_t, mode,
1764 unsigned int, value);
1765 } else {
1766 // 2-arg version
1767 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1768 PRE_REG_READ2(vki_sem_t *, "sem_open",
1769 const char *, name, int, oflag);
1771 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1773 /* Otherwise handle normally */
1774 *flags |= SfMayBlock;
1777 PRE(sem_close)
1779 PRINT("sem_close( %#lx )", ARG1);
1780 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1783 PRE(sem_unlink)
1785 PRINT("sem_unlink( %#lx(%s) )", ARG1,(char*)ARG1);
1786 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1787 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1790 PRE(sem_post)
1792 PRINT("sem_post( %#lx )", ARG1);
1793 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1794 *flags |= SfMayBlock;
1797 PRE(sem_destroy)
1799 PRINT("sem_destroy( %#lx )", ARG1);
1800 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1801 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1804 PRE(sem_init)
1806 PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3);
1807 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1808 int, pshared, unsigned int, value);
1809 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1812 POST(sem_init)
1814 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1817 PRE(sem_wait)
1819 PRINT("sem_wait( %#lx )", ARG1);
1820 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1821 *flags |= SfMayBlock;
1824 PRE(sem_trywait)
1826 PRINT("sem_trywait( %#lx )", ARG1);
1827 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1828 *flags |= SfMayBlock;
1831 PRE(kqueue)
1833 PRINT("kqueue()");
1836 POST(kqueue)
1838 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1839 VG_(close)(RES);
1840 SET_STATUS_Failure( VKI_EMFILE );
1841 } else {
1842 if (VG_(clo_track_fds)) {
1843 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1848 PRE(fileport_makeport)
1850 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1851 ARG1, ARG2);
1854 PRE(guarded_open_np)
1856 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1857 ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1860 PRE(guarded_kqueue_np)
1862 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1863 ARG1, ARG2);
1866 POST(guarded_kqueue_np)
1868 if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1869 VG_(close)(RES);
1870 SET_STATUS_Failure( VKI_EMFILE );
1871 } else {
1872 if (VG_(clo_track_fds)) {
1873 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1878 PRE(guarded_close_np)
1880 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1881 ARG1, ARG2);
1884 PRE(change_fdguard_np)
1886 PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
1887 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1890 PRE(connectx)
1892 PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
1893 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
1896 PRE(disconnectx)
1898 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
1899 ARG1, ARG2, ARG3);
1903 PRE(kevent)
1905 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1906 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1907 PRE_REG_READ6(int,"kevent", int,kq,
1908 const struct vki_kevent *,changelist, int,nchanges,
1909 struct vki_kevent *,eventlist, int,nevents,
1910 const struct vki_timespec *,timeout);
1912 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
1913 ARG2, ARG3 * sizeof(struct vki_kevent));
1914 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
1915 ARG4, ARG5 * sizeof(struct vki_kevent));
1916 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
1917 ARG6, sizeof(struct vki_timespec));
1919 *flags |= SfMayBlock;
1922 POST(kevent)
1924 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
1925 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
1929 PRE(kevent64)
1931 PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
1932 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1933 PRE_REG_READ6(int,"kevent64", int,kq,
1934 const struct vki_kevent64 *,changelist, int,nchanges,
1935 struct vki_kevent64 *,eventlist, int,nevents,
1936 const struct vki_timespec *,timeout);
1938 if (ARG3) PRE_MEM_READ ("kevent64(changelist)",
1939 ARG2, ARG3 * sizeof(struct vki_kevent64));
1940 if (ARG5) PRE_MEM_WRITE("kevent64(eventlist)",
1941 ARG4, ARG5 * sizeof(struct vki_kevent64));
1942 if (ARG6) PRE_MEM_READ ("kevent64(timeout)",
1943 ARG6, sizeof(struct vki_timespec));
1945 *flags |= SfMayBlock;
1948 POST(kevent64)
1950 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
1951 if (RES > 0) {
1952 ML_(sync_mappings)("after", "kevent64", 0);
1953 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
1958 Addr pthread_starter = 0;
1959 Addr wqthread_starter = 0;
1960 SizeT pthread_structsize = 0;
1962 PRE(bsdthread_register)
1964 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
1965 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
1966 void *,"wqthread", size_t,"pthsize");
1968 pthread_starter = ARG1;
1969 wqthread_starter = ARG2;
1970 pthread_structsize = ARG3;
1971 ARG1 = (Word)&pthread_hijack_asm;
1972 ARG2 = (Word)&wqthread_hijack_asm;
1975 PRE(workq_open)
1977 PRINT("workq_open()");
1978 PRE_REG_READ0(int, "workq_open");
1980 // This creates lots of threads and thread stacks under the covers,
1981 // but we ignore them all until some work item starts running on it.
1984 static const HChar *workqop_name(int op)
1986 switch (op) {
1987 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
1988 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
1989 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
1990 case VKI_WQOPS_THREAD_SETCONC: return "THREAD_SETCONC";
1991 case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
1992 case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
1993 default: return "?";
1998 PRE(workq_ops)
2000 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
2001 ARG3);
2002 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2003 int,"priority");
2005 switch (ARG1) {
2006 case VKI_WQOPS_QUEUE_ADD:
2007 case VKI_WQOPS_QUEUE_REMOVE:
2008 // GrP fixme need anything here?
2009 // GrP fixme may block?
2010 break;
2011 case VKI_WQOPS_QUEUE_NEWSPISUPP:
2012 // JRS don't think we need to do anything here -- this just checks
2013 // whether some newer functionality is supported
2014 break;
2015 case VKI_WQOPS_QUEUE_REQTHREADS:
2016 // JRS uh, looks like it queues up a bunch of threads, or some such?
2017 *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
2018 break;
2019 case VKI_WQOPS_THREAD_RETURN: {
2020 // The interesting case. The kernel will do one of two things:
2021 // 1. Return normally. We continue; libc proceeds to stop the thread.
2022 // V does nothing special here.
2023 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2024 // new work item, and never returns from workq_ops.
2025 // V handles this by longjmp() from wqthread_hijack back to the
2026 // scheduler, which continues at the new client SP/IP/state.
2027 // This works something like V's signal handling.
2028 // To the tool, this looks like workq_ops() sometimes returns
2029 // to a strange address.
2030 ThreadState *tst = VG_(get_ThreadState)(tid);
2031 tst->os_state.wq_jmpbuf_valid = True;
2032 *flags |= SfMayBlock; // GrP fixme true?
2033 break;
2035 default:
2036 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
2037 break;
2040 POST(workq_ops)
2042 ThreadState *tst = VG_(get_ThreadState)(tid);
2043 tst->os_state.wq_jmpbuf_valid = False;
2044 switch (ARG1) {
2045 case VKI_WQOPS_THREAD_RETURN:
2046 ML_(sync_mappings)("after", "workq_ops(THREAD_RETURN)", 0);
2047 break;
2048 case VKI_WQOPS_QUEUE_REQTHREADS:
2049 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2050 break;
2051 default:
2052 break;
2058 PRE(__mac_syscall)
2060 PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
2061 ARG1, (HChar*)ARG1, ARG2, ARG3);
2062 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
2063 int,"call", void *,"arg");
2065 // GrP fixme check call's arg?
2066 // GrP fixme check policy?
2070 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2071 More like syswrap-generic's sys_exit_group. */
2072 PRE(exit)
2074 ThreadId t;
2075 ThreadState* tst;
2077 PRINT("darwin exit( %ld )", ARG1);
2078 PRE_REG_READ1(void, "exit", int, status);
2080 tst = VG_(get_ThreadState)(tid);
2082 /* A little complex; find all the threads with the same threadgroup
2083 as this one (including this one), and mark them to exit */
2084 for (t = 1; t < VG_N_THREADS; t++) {
2085 if ( /* not alive */
2086 VG_(threads)[t].status == VgTs_Empty
2087 /* GrP fixme zombie? */
2089 continue;
2091 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
2092 VG_(threads)[t].os_state.exitcode = ARG1;
2094 if (t != tid)
2095 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
2098 /* We have to claim the syscall already succeeded. */
2099 SET_STATUS_Success(0);
2103 PRE(sigaction)
2105 PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3);
2106 PRE_REG_READ3(long, "sigaction",
2107 int, signum, vki_sigaction_toK_t *, act,
2108 vki_sigaction_fromK_t *, oldact);
2110 if (ARG2 != 0) {
2111 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
2112 PRE_MEM_READ( "sigaction(act->sa_handler)",
2113 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2114 PRE_MEM_READ( "sigaction(act->sa_mask)",
2115 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2116 PRE_MEM_READ( "sigaction(act->sa_flags)",
2117 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2119 if (ARG3 != 0)
2120 PRE_MEM_WRITE( "sigaction(oldact)",
2121 ARG3, sizeof(vki_sigaction_fromK_t));
2123 SET_STATUS_from_SysRes(
2124 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
2125 (vki_sigaction_fromK_t *)ARG3)
2128 POST(sigaction)
2130 vg_assert(SUCCESS);
2131 if (RES == 0 && ARG3 != 0)
2132 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
2136 PRE(__pthread_kill)
2138 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
2139 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
2143 PRE(__pthread_sigmask)
2145 // arguments are identical to sigprocmask (how, sigset_t*, sigset_t*).
2146 UWord arg1;
2147 PRINT("__pthread_sigmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
2148 PRE_REG_READ3(long, "__pthread_sigmask",
2149 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
2150 if (ARG2 != 0)
2151 PRE_MEM_READ( "__pthread_sigmask(set)", ARG2, sizeof(vki_sigset_t));
2152 if (ARG3 != 0)
2153 PRE_MEM_WRITE( "__pthread_sigmask(oldset)", ARG3, sizeof(vki_sigset_t));
2155 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
2156 value of 'how' is irrelevant, and it appears that Darwin's libc
2157 passes zero, which is not equal to any of
2158 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
2159 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
2160 value independently of the other args. Solution: in this case,
2161 simply pass a valid (but irrelevant) value for 'how'. */
2162 /* Also, in this case the new set is passed to the kernel by
2163 reference, not value, as in some other sigmask related Darwin
2164 syscalls. */
2165 arg1 = ARG1;
2166 if (ARG2 == 0 /* the new-set is NULL */
2167 && ARG1 != VKI_SIG_BLOCK
2168 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
2169 arg1 = VKI_SIG_SETMASK;
2171 SET_STATUS_from_SysRes(
2172 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
2173 (vki_sigset_t*)ARG3 )
2176 if (SUCCESS)
2177 *flags |= SfPollAfter;
2179 POST(__pthread_sigmask)
2181 vg_assert(SUCCESS);
2182 if (RES == 0 && ARG3 != 0)
2183 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2187 PRE(__pthread_canceled)
2189 *flags |= SfMayBlock; /* might kill this thread??? */
2190 /* I don't think so -- I think it just changes the cancellation
2191 state. But taking no chances. */
2192 PRINT("__pthread_canceled ( %ld )", ARG1);
2193 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
2197 PRE(__pthread_markcancel)
2199 *flags |= SfMayBlock; /* might kill this thread??? */
2200 PRINT("__pthread_markcancel ( %#lx )", ARG1);
2201 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
2202 /* Just let it go through. No idea if this is correct. */
2206 PRE(__disable_threadsignal)
2208 vki_sigset_t set;
2209 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
2210 /* I don't think this really looks at its arguments. So don't
2211 bother to check them. */
2213 VG_(sigfillset)( &set );
2214 SET_STATUS_from_SysRes(
2215 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
2218 /* We don't expect that blocking all signals for this thread could
2219 cause any more to be delivered (how could it?), but just in case
2220 .. */
2221 if (SUCCESS)
2222 *flags |= SfPollAfter;
2226 PRE(__pthread_chdir)
2228 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1, (char*)ARG1);
2229 PRE_REG_READ1(long, "__pthread_chdir", const char *, path);
2230 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1 );
2235 PRE(__pthread_fchdir)
2237 PRINT("__pthread_fchdir ( %ld )", ARG1);
2238 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd);
2242 PRE(kdebug_trace)
2244 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2245 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2247 Don't check anything - some clients pass fewer arguments.
2248 PRE_REG_READ6(long, "kdebug_trace",
2249 int,"code", int,"arg1", int,"arg2",
2250 int,"arg3", int,"arg4", int,"arg5");
2255 PRE(seteuid)
2257 PRINT("seteuid(%ld)", ARG1);
2258 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
2262 PRE(setegid)
2264 PRINT("setegid(%ld)", ARG1);
2265 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
2268 PRE(settid)
2270 PRINT("settid(%ld, %ld)", ARG1, ARG2);
2271 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
2274 PRE(gettid)
2276 PRINT("gettid()");
2277 PRE_REG_READ0(long, gettid);
2280 /* XXX need to check whether we need POST operations for
2281 * waitevent, watchevent, modwatch -- jpeach
2283 PRE(watchevent)
2285 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
2286 PRE_REG_READ2(long, "watchevent",
2287 vki_eventreq *, "event", unsigned int, "eventmask");
2289 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
2290 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
2291 *flags |= SfMayBlock;
2294 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
2295 PRE(waitevent)
2297 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
2298 PRE_REG_READ2(long, "waitevent",
2299 vki_eventreq *, "event", struct timeval *, "timeout");
2300 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
2302 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
2303 PRE_timeval_READ("waitevent(timeout)", ARG2);
2306 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2307 *flags |= SfMayBlock;
2310 POST(waitevent)
2312 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
2315 PRE(modwatch)
2317 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
2318 PRE_REG_READ2(long, "modwatch",
2319 vki_eventreq *, "event", unsigned int, "eventmask");
2321 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
2322 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
2325 PRE(getxattr)
2327 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2328 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
2330 PRE_REG_READ6(vki_ssize_t, "getxattr",
2331 const char *, path, char *, name, void *, value,
2332 vki_size_t, size, uint32_t, position, int, options);
2333 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
2334 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2335 if (ARG3)
2336 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2339 POST(getxattr)
2341 vg_assert((vki_ssize_t)RES >= 0);
2342 if (ARG3)
2343 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2346 PRE(fgetxattr)
2348 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2349 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
2351 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
2352 int, fd, char *, name, void *, value,
2353 vki_size_t, size, uint32_t, position, int, options);
2354 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2355 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2358 POST(fgetxattr)
2360 vg_assert((vki_ssize_t)RES >= 0);
2361 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2364 PRE(setxattr)
2366 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2367 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
2368 PRE_REG_READ6(int, "setxattr",
2369 const char *,"path", char *,"name", void *,"value",
2370 vki_size_t,"size", uint32_t,"position", int,"options" );
2372 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
2373 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
2374 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
2378 PRE(fsetxattr)
2380 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2381 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
2382 PRE_REG_READ6(int, "fsetxattr",
2383 int,"fd", char *,"name", void *,"value",
2384 vki_size_t,"size", uint32_t,"position", int,"options" );
2386 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
2387 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
2391 PRE(removexattr)
2393 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2394 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 );
2395 PRE_REG_READ3(int, "removexattr",
2396 const char*, "path", char*, "attrname", int, "options");
2397 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
2398 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2402 PRE(fremovexattr)
2404 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2405 ARG1, ARG2, (HChar*)ARG2, ARG3 );
2406 PRE_REG_READ3(int, "fremovexattr",
2407 int, "fd", char*, "attrname", int, "options");
2408 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2412 PRE(listxattr)
2414 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2415 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
2416 PRE_REG_READ4 (long, "listxattr",
2417 const char *,"path", char *,"namebuf",
2418 vki_size_t,"size", int,"options" );
2420 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
2421 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
2422 *flags |= SfMayBlock;
2424 POST(listxattr)
2426 vg_assert(SUCCESS);
2427 vg_assert((vki_ssize_t)RES >= 0);
2428 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2432 PRE(flistxattr)
2434 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2435 ARG1, ARG2, ARG3, ARG4 );
2436 PRE_REG_READ4 (long, "flistxattr",
2437 int, "fd", char *,"namebuf",
2438 vki_size_t,"size", int,"options" );
2439 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2440 *flags |= SfMayBlock;
2442 POST(flistxattr)
2444 vg_assert(SUCCESS);
2445 vg_assert((vki_ssize_t)RES >= 0);
2446 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2450 PRE(shmat)
2452 UWord arg2tmp;
2453 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2454 PRE_REG_READ3(long, "shmat",
2455 int, shmid, const void *, shmaddr, int, shmflg);
2456 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2457 if (arg2tmp == 0)
2458 SET_STATUS_Failure( VKI_EINVAL );
2459 else
2460 ARG2 = arg2tmp; // used in POST
2462 POST(shmat)
2464 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2467 PRE(shmctl)
2469 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
2470 PRE_REG_READ3(long, "shmctl",
2471 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2472 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2474 POST(shmctl)
2476 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2479 PRE(shmdt)
2481 PRINT("shmdt ( %#lx )",ARG1);
2482 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2483 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2484 SET_STATUS_Failure( VKI_EINVAL );
2486 POST(shmdt)
2488 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2491 PRE(shmget)
2493 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2494 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2497 PRE(shm_open)
2499 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
2500 PRE_REG_READ3(long, "shm_open",
2501 const char *,"name", int,"flags", vki_mode_t,"mode");
2503 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2505 *flags |= SfMayBlock;
2507 POST(shm_open)
2509 vg_assert(SUCCESS);
2510 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2511 VG_(close)(RES);
2512 SET_STATUS_Failure( VKI_EMFILE );
2513 } else {
2514 if (VG_(clo_track_fds))
2515 ML_(record_fd_open_with_given_name)(tid, RES, (char*)ARG1);
2519 PRE(shm_unlink)
2521 *flags |= SfMayBlock;
2522 PRINT("shm_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
2523 PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2524 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2526 POST(shm_unlink)
2528 /* My reading of the man page suggests that a call may cause memory
2529 mappings to change: "if no references exist at the time of the
2530 call to shm_unlink(), the resources are reclaimed immediately".
2531 So we need to resync here, sigh. */
2532 ML_(sync_mappings)("after", "shm_unlink", 0);
2535 PRE(stat_extended)
2537 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2538 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2539 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2540 void *, fsacl, vki_size_t *, fsacl_size);
2541 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
2542 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2543 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2544 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2545 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2547 POST(stat_extended)
2549 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2550 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2551 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2552 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2556 PRE(lstat_extended)
2558 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2559 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2560 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2561 void *, fsacl, vki_size_t *, fsacl_size);
2562 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
2563 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2564 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2565 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2566 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2568 POST(lstat_extended)
2570 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2571 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2572 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2573 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2577 PRE(fstat_extended)
2579 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2580 ARG1, ARG2, ARG3, ARG4);
2581 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2582 void *, fsacl, vki_size_t *, fsacl_size);
2583 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2584 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2585 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2586 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2588 POST(fstat_extended)
2590 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2591 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2592 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2593 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2597 PRE(stat64_extended)
2599 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2600 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2601 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2602 void *, fsacl, vki_size_t *, fsacl_size);
2603 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
2604 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2605 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2606 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2607 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2609 POST(stat64_extended)
2611 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2612 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2613 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2614 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2618 PRE(lstat64_extended)
2620 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2621 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2622 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2623 void *, fsacl, vki_size_t *, fsacl_size);
2624 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2625 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2626 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2627 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2628 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2630 POST(lstat64_extended)
2632 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2633 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2634 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2635 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2639 PRE(fstat64_extended)
2641 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2642 ARG1, ARG2, ARG3, ARG4);
2643 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2644 void *, fsacl, vki_size_t *, fsacl_size);
2645 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2646 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2647 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2648 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2650 POST(fstat64_extended)
2652 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2653 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2654 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2655 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2659 PRE(fchmod_extended)
2661 /* DDD: Note: this is not really correct. Handling of
2662 chmod_extended is broken in the same way. */
2663 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2664 ARG1, ARG2, ARG3, ARG4, ARG5);
2665 PRE_REG_READ5(long, "fchmod_extended",
2666 unsigned int, fildes,
2667 uid_t, uid,
2668 gid_t, gid,
2669 vki_mode_t, mode,
2670 void* /*really,user_addr_t*/, xsecurity);
2671 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2672 is just way wrong. [The trouble is with the size, which depends on a
2673 non-trival kernel computation] */
2674 if (ARG5) {
2675 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2676 sizeof(struct vki_kauth_filesec) );
2680 PRE(chmod_extended)
2682 /* DDD: Note: this is not really correct. Handling of
2683 fchmod_extended is broken in the same way. */
2684 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2685 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2686 PRE_REG_READ5(long, "chmod_extended",
2687 unsigned int, fildes,
2688 uid_t, uid,
2689 gid_t, gid,
2690 vki_mode_t, mode,
2691 void* /*really,user_addr_t*/, xsecurity);
2692 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2693 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2694 is just way wrong. [The trouble is with the size, which depends on a
2695 non-trival kernel computation] */
2696 if (ARG5) {
2697 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2698 sizeof(struct vki_kauth_filesec) );
2702 PRE(open_extended)
2704 /* DDD: Note: this is not really correct. Handling of
2705 {,f}chmod_extended is broken in the same way. */
2706 PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )",
2707 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2708 ARG2, ARG3, ARG4, ARG5, ARG6);
2709 PRE_REG_READ6(long, "open_extended",
2710 char*, path,
2711 int, flags,
2712 uid_t, uid,
2713 gid_t, gid,
2714 vki_mode_t, mode,
2715 void* /*really,user_addr_t*/, xsecurity);
2716 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2717 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2718 is just way wrong. [The trouble is with the size, which depends on a
2719 non-trival kernel computation] */
2720 if (ARG6)
2721 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2722 sizeof(struct vki_kauth_filesec) );
2725 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2726 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2727 // by one or more strings. Each accessx_descriptor contains a field,
2728 // 'ad_name_offset', which points to one of the strings (or it can contain
2729 // zero which means "reuse the string from the previous accessx_descriptor").
2731 // What's really ridiculous is that we are only given the size of the overall
2732 // buffer, not the number of accessx_descriptors, nor the number of strings.
2733 // The kernel determines the number of accessx_descriptors by walking through
2734 // them one by one, checking that the ad_name_offset points within the buffer,
2735 // past the current point (or that it's a zero, unless its the first
2736 // descriptor); if so, we assume that this really is an accessx_descriptor,
2737 // if not, we assume we've hit the strings section. Gah.
2739 // This affects us here because number of entries in the 'results' buffer is
2740 // determined by the number of accessx_descriptors. So we have to know that
2741 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2742 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2743 // computation after the syscall has succeeded, because the kernel will have
2744 // checked for all the zillion different ways this syscall can fail, and we'll
2745 // know we have a well-formed 'entries' buffer. This means we might miss some
2746 // uses of unaddressable memory but oh well.
2748 PRE(access_extended)
2750 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2751 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2752 // XXX: the accessx_descriptor struct contains padding, so this can cause
2753 // unnecessary undefined value errors. But you arguably shouldn't be
2754 // passing undefined values to the kernel anyway...
2755 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2756 vki_errno_t *, results, vki_uid_t *, uid);
2757 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2759 // XXX: as mentioned above, this check is too hard to do before the
2760 // syscall.
2761 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2763 POST(access_extended)
2765 // 'n_descs' is the number of descriptors we think are in the buffer. We
2766 // start with the maximum possible value, which occurs if we have the
2767 // shortest possible string section. The shortest string section allowed
2768 // consists of a single one-char string (plus the NUL char). Hence the
2769 // '2'.
2770 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2771 SizeT size = ARG2;
2772 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2773 Int i; // Current position in the descriptors section array.
2774 Int u; // Upper bound on the length of the descriptors array
2775 // (recomputed each time around the loop)
2776 vg_assert(n_descs > 0);
2778 // Step through the descriptors, lowering 'n_descs' until we know we've
2779 // reached the string section.
2780 for (i = 0; True; i++) {
2781 // If we're past our estimate, we must be one past the end of the
2782 // descriptors section (ie. at the start of the string section). Stop.
2783 if (i >= n_descs)
2784 break;
2786 // Get the array index for the string, but pretend momentarily that it
2787 // is actually another accessx_descriptor. That gives us an upper bound
2788 // on the length of the descriptors section. (Unless the index is zero,
2789 // in which case we have no new info.)
2790 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2791 if (u == 0) {
2792 vg_assert(i != 0);
2793 continue;
2796 // If the upper bound is below our current estimate, revise that
2797 // estimate downwards.
2798 if (u < n_descs)
2799 n_descs = u;
2802 // Sanity check.
2803 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2805 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2809 PRE(chflags)
2811 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2812 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2813 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2815 // GrP fixme sanity-check flags value?
2818 PRE(fchflags)
2820 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2821 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2823 // GrP fixme sanity-check flags value?
2826 PRE(stat64)
2828 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2829 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2830 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2831 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2833 POST(stat64)
2835 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2838 PRE(lstat64)
2840 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2841 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2842 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2843 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2845 POST(lstat64)
2847 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2850 PRE(fstat64)
2852 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2853 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2854 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2856 POST(fstat64)
2858 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2861 PRE(getfsstat)
2863 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2864 PRE_REG_READ3(int, "getfsstat",
2865 struct vki_statfs *, buf, int, bufsize, int, flags);
2866 if (ARG1) {
2867 // ARG2 is a BYTE SIZE
2868 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2871 POST(getfsstat)
2873 if (ARG1) {
2874 // RES is a STRUCT COUNT
2875 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2879 PRE(getfsstat64)
2881 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2882 PRE_REG_READ3(int, "getfsstat64",
2883 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2884 if (ARG1) {
2885 // ARG2 is a BYTE SIZE
2886 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2889 POST(getfsstat64)
2891 if (ARG1) {
2892 // RES is a STRUCT COUNT
2893 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2897 PRE(mount)
2899 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2900 // We are conservative and check everything, except the memory pointed to
2901 // by 'data'.
2902 *flags |= SfMayBlock;
2903 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2904 ARG1,(char*)ARG1, ARG2,(char*)ARG2, ARG3, ARG4);
2905 PRE_REG_READ4(long, "mount",
2906 const char *, type, const char *, dir,
2907 int, flags, void *, data);
2908 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2909 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2913 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2914 void *attrBuf, SizeT attrBufSize,
2915 void (*fn)(ThreadId, void *attrData, SizeT size)
2918 typedef struct {
2919 uint32_t attrBit;
2920 int32_t attrSize;
2921 } attrspec;
2922 static const attrspec commonattr[] = {
2923 // This order is important.
2924 #if DARWIN_VERS >= DARWIN_10_6
2925 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
2926 #endif
2927 { ATTR_CMN_NAME, -1 },
2928 { ATTR_CMN_DEVID, sizeof(dev_t) },
2929 { ATTR_CMN_FSID, sizeof(fsid_t) },
2930 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
2931 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
2932 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
2933 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
2934 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
2935 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
2936 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
2937 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
2938 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
2939 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
2940 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
2941 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2942 { ATTR_CMN_OWNERID, sizeof(uid_t) },
2943 { ATTR_CMN_GRPID, sizeof(gid_t) },
2944 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
2945 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
2946 { ATTR_CMN_NAMEDATTRLIST, -1 },
2947 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
2948 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
2949 { ATTR_CMN_EXTENDED_SECURITY, -1 },
2950 { ATTR_CMN_UUID, sizeof(guid_t) },
2951 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
2952 { ATTR_CMN_FILEID, sizeof(uint64_t) },
2953 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
2954 #if DARWIN_VERS >= DARWIN_10_6
2955 { ATTR_CMN_FULLPATH, -1 },
2956 #endif
2957 #if DARWIN_VERS >= DARWIN_10_8
2958 { ATTR_CMN_ADDEDTIME, -1 },
2959 #endif
2960 { 0, 0 }
2962 static const attrspec volattr[] = {
2963 // This order is important.
2964 { ATTR_VOL_INFO, 0 },
2965 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
2966 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
2967 { ATTR_VOL_SIZE, sizeof(off_t) },
2968 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
2969 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
2970 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
2971 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2972 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
2973 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
2974 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
2975 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
2976 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
2977 { ATTR_VOL_MOUNTPOINT, -1 },
2978 { ATTR_VOL_NAME, -1 },
2979 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
2980 { ATTR_VOL_MOUNTEDDEVICE, -1 },
2981 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
2982 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
2983 #if DARWIN_VERS >= DARWIN_10_6
2984 { ATTR_VOL_UUID, sizeof(uuid_t) },
2985 #endif
2986 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
2987 { 0, 0 }
2989 static const attrspec dirattr[] = {
2990 // This order is important.
2991 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
2992 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
2993 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
2994 { 0, 0 }
2996 static const attrspec fileattr[] = {
2997 // This order is important.
2998 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
2999 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
3000 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
3001 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
3002 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
3003 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
3004 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
3005 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
3006 { ATTR_FILE_FORKLIST, -1 },
3007 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
3008 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
3009 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
3010 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
3011 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
3012 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
3013 { 0, 0 }
3015 static const attrspec forkattr[] = {
3016 // This order is important.
3017 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
3018 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
3019 { 0, 0 }
3022 static const attrspec *attrdefs[5] = {
3023 commonattr, volattr, dirattr, fileattr, forkattr
3025 attrgroup_t a[5];
3026 uint8_t *d, *dend;
3027 int g, i;
3029 vg_assert(attrList->bitmapcount == 5);
3030 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
3031 d = attrBuf;
3032 dend = d + attrBufSize;
3034 #if DARWIN_VERS >= DARWIN_10_6
3035 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3036 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
3037 // fixme range check this?
3038 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
3039 fn(tid, d, sizeof(attribute_set_t));
3040 VG_(memcpy)(a, d, sizeof(a));
3042 #endif
3044 for (g = 0; g < 5; g++) {
3045 for (i = 0; attrdefs[g][i].attrBit; i++) {
3046 uint32_t bit = attrdefs[g][i].attrBit;
3047 int32_t size = attrdefs[g][i].attrSize;
3049 if (a[g] & bit) {
3050 a[g] &= ~bit; // clear bit for error check later
3051 if (size == -1) {
3052 attrreference_t *ref = (attrreference_t *)d;
3053 size = MIN(sizeof(attrreference_t), dend - d);
3054 fn(tid, d, size);
3055 if (size >= sizeof(attrreference_t) &&
3056 d + ref->attr_dataoffset < dend)
3058 fn(tid, d + ref->attr_dataoffset,
3059 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
3061 d += size;
3063 else {
3064 size = MIN(size, dend - d);
3065 fn(tid, d, size);
3066 d += size;
3069 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
3070 if (d > dend) d = dend;
3074 // Known bits are cleared. Die if any bits are left.
3075 if (a[g] != 0) {
3076 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
3081 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3083 POST_MEM_WRITE((Addr)attrData, attrDataSize);
3086 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3088 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
3091 PRE(getattrlist)
3093 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3094 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
3095 PRE_REG_READ5(int, "getattrlist",
3096 const char *,path, struct vki_attrlist *,attrList,
3097 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3098 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
3099 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3100 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
3103 POST(getattrlist)
3105 if (ARG4 > sizeof(vki_uint32_t)) {
3106 // attrBuf is uint32_t size followed by attr data
3107 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
3108 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
3109 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
3110 // *sizep is bytes required for return value, including *sizep
3111 } else {
3112 // *sizep is actual bytes returned, including *sizep
3114 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
3119 PRE(setattrlist)
3121 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3122 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
3123 PRE_REG_READ5(int, "setattrlist",
3124 const char *,path, struct vki_attrlist *,attrList,
3125 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3126 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
3127 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3128 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
3132 PRE(getdirentriesattr)
3134 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
3135 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
3136 PRE_REG_READ8(int, "getdirentriesattr",
3137 int,fd, struct vki_attrlist *,attrList,
3138 void *,attrBuf, size_t,attrBufSize,
3139 unsigned int *,count, unsigned int *,basep,
3140 unsigned int *,newState, unsigned int,options);
3141 PRE_MEM_READ("getdirentriesattr(attrList)",
3142 ARG2, sizeof(struct vki_attrlist));
3143 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
3144 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3145 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3146 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
3147 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
3149 POST(getdirentriesattr)
3151 char *p, *end;
3152 unsigned int count;
3153 unsigned int i;
3155 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
3156 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
3157 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
3159 // return buffer is concatenation of variable-size structs
3160 count = *(unsigned int *)ARG5;
3161 p = (char *)ARG3;
3162 end = (char *)ARG3 + ARG4;
3163 for (i = 0; i < count; i++) {
3164 vg_assert(p < end); // failure is kernel bug or Valgrind bug
3165 p += *(unsigned int *)p;
3168 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
3170 PRINT("got %d records, %ld/%lu bytes\n",
3171 count, (Addr)p-(Addr)ARG3, ARG4);
3175 PRE(fsgetpath)
3177 #if VG_WORDSIZE == 4
3178 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
3179 ARG1, ARG2, ARG3,
3180 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
3181 LOHI64(ARG4, ARG5));
3182 PRE_REG_READ5(ssize_t, "fsgetpath",
3183 void*,"buf", size_t,"bufsize",
3184 fsid_t *,"fsid",
3185 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
3186 #else
3187 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
3188 ARG1, ARG2, ARG3,
3189 ((unsigned int *)ARG3)[0],
3190 ((unsigned int *)ARG3)[1], ARG4);
3191 PRE_REG_READ4(ssize_t, "fsgetpath",
3192 void*,"buf", size_t,"bufsize",
3193 fsid_t *,"fsid", uint64_t,"objid");
3194 #endif
3195 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
3196 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
3199 POST(fsgetpath)
3201 POST_MEM_WRITE(ARG1, RES);
3204 PRE(audit_session_self)
3206 PRINT("audit_session_self()");
3209 POST(audit_session_self)
3211 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
3212 PRINT("audit-session %#lx", RES);
3215 PRE(exchangedata)
3217 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3218 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
3219 PRE_REG_READ3(int, "exchangedata",
3220 char *, path1, char *, path2, unsigned long, options);
3221 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
3222 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
3225 PRE(fsctl)
3227 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
3228 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
3229 PRE_REG_READ4( long, "fsctl",
3230 char *,"path", unsigned int,"request",
3231 void *,"data", unsigned int,"options");
3233 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
3235 switch (ARG2) {
3236 case VKI_afpfsByteRangeLock2FSCTL: {
3237 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3238 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3239 pb->offset);
3240 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3241 pb->length);
3242 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3243 pb->unLockFlag);
3244 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3245 pb->startEndFlag);
3246 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3247 pb->fd);
3249 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3250 pb->retRangeStart);
3252 // GrP fixme check fd
3253 break;
3255 case VKI_FSIOC_SYNC_VOLUME:
3256 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
3257 break;
3259 default:
3260 // fsctl requests use ioctl encoding
3261 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3262 break;
3266 POST(fsctl)
3268 switch (ARG2) {
3269 case VKI_afpfsByteRangeLock2FSCTL: {
3270 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3271 POST_FIELD_WRITE(pb->retRangeStart);
3272 break;
3274 case VKI_FSIOC_SYNC_VOLUME:
3275 break;
3277 default:
3278 // fsctl requests use ioctl encoding
3279 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
3280 break;
3284 PRE(initgroups)
3286 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
3287 PRE_REG_READ3(long, "initgroups",
3288 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
3289 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
3293 //--------- posix_spawn ---------//
3294 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3295 the simpler AIX equivalent (syswrap-aix5.c). */
3296 // Pre_read a char** argument.
3297 static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
3299 while (True) {
3300 Addr a_deref;
3301 Addr* a_p = (Addr*)a;
3302 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
3303 a_deref = *a_p;
3304 if (0 == a_deref)
3305 break;
3306 PRE_MEM_RASCIIZ( s2, a_deref );
3307 a += sizeof(char*);
3310 static SysRes simple_pre_exec_check ( const HChar* exe_name,
3311 Bool trace_this_child )
3313 Int fd, ret;
3314 SysRes res;
3315 Bool setuid_allowed;
3317 // Check it's readable
3318 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
3319 if (sr_isError(res)) {
3320 return res;
3322 fd = sr_Res(res);
3323 VG_(close)(fd);
3325 // Check we have execute permissions. We allow setuid executables
3326 // to be run only in the case when we are not simulating them, that
3327 // is, they to be run natively.
3328 setuid_allowed = trace_this_child ? False : True;
3329 ret = VG_(check_executable)(NULL/*&is_setuid*/,
3330 exe_name, setuid_allowed);
3331 if (0 != ret) {
3332 return VG_(mk_SysRes_Error)(ret);
3334 return VG_(mk_SysRes_Success)(0);
3336 PRE(posix_spawn)
3338 HChar* path = NULL; /* path to executable */
3339 HChar** envp = NULL;
3340 HChar** argv = NULL;
3341 HChar** arg2copy;
3342 HChar* launcher_basename = NULL;
3343 Int i, j, tot_args;
3344 SysRes res;
3345 Bool trace_this_child;
3347 /* args: pid_t* pid
3348 char* path
3349 posix_spawn_file_actions_t* file_actions
3350 char** argv
3351 char** envp
3353 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3354 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3356 /* Standard pre-syscall checks */
3358 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
3359 void*, file_actions, char**, argv, char**, envp );
3360 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
3361 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
3362 // DDD: check file_actions
3363 if (ARG4 != 0)
3364 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
3365 "posix_spawn(argv[i])" );
3366 if (ARG5 != 0)
3367 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
3368 "posix_spawn(envp[i])" );
3370 if (0)
3371 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3372 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3374 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3375 syswrap-generic.c. */
3377 /* Check that the name at least begins in client-accessible storage. */
3378 if (ARG2 == 0 /* obviously bogus */
3379 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
3380 SET_STATUS_Failure( VKI_EFAULT );
3381 return;
3384 // Decide whether or not we want to follow along
3385 { // Make 'child_argv' be a pointer to the child's arg vector
3386 // (skipping the exe name)
3387 const HChar** child_argv = (const HChar**)ARG4;
3388 if (child_argv && child_argv[0] == NULL)
3389 child_argv = NULL;
3390 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
3393 // Do the important checks: it is a file, is executable, permissions are
3394 // ok, etc. We allow setuid executables to run only in the case when
3395 // we are not simulating them, that is, they to be run natively.
3396 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
3397 if (sr_isError(res)) {
3398 SET_STATUS_Failure( sr_Err(res) );
3399 return;
3402 /* If we're tracing the child, and the launcher name looks bogus
3403 (possibly because launcher.c couldn't figure it out, see
3404 comments therein) then we have no option but to fail. */
3405 if (trace_this_child
3406 && (VG_(name_of_launcher) == NULL
3407 || VG_(name_of_launcher)[0] != '/')) {
3408 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
3409 return;
3412 /* Ok. So let's give it a try. */
3413 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
3415 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3416 So, we should not terminate gdbserver : this is still the parent
3417 running, which will terminate its gdbserver when exiting.
3418 If the child process is traced, it will start a fresh gdbserver
3419 after posix_spawn. */
3421 // Set up the child's exe path.
3423 if (trace_this_child) {
3425 // We want to exec the launcher. Get its pre-remembered path.
3426 path = VG_(name_of_launcher);
3427 // VG_(name_of_launcher) should have been acquired by m_main at
3428 // startup. The following two assertions should be assured by
3429 // the "If we're tracking the child .." test just above here.
3430 vg_assert(path);
3431 vg_assert(path[0] == '/');
3432 launcher_basename = path;
3434 } else {
3435 path = (HChar*)ARG2;
3438 // Set up the child's environment.
3440 // Remove the valgrind-specific stuff from the environment so the
3441 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3442 // This is done unconditionally, since if we are tracing the child,
3443 // the child valgrind will set up the appropriate client environment.
3444 // Nb: we make a copy of the environment before trying to mangle it
3445 // as it might be in read-only memory (this was bug #101881).
3447 // Then, if tracing the child, set VALGRIND_LIB for it.
3449 if (ARG5 == 0) {
3450 envp = NULL;
3451 } else {
3452 envp = VG_(env_clone)( (HChar**)ARG5 );
3453 vg_assert(envp);
3454 VG_(env_remove_valgrind_env_stuff)( envp, /* ro_strings */ False, NULL);
3457 if (trace_this_child) {
3458 // Set VALGRIND_LIB in ARG5 (the environment)
3459 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3462 // Set up the child's args. If not tracing it, they are
3463 // simply ARG4. Otherwise, they are
3465 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3467 // except that the first VG_(args_for_valgrind_noexecpass) args
3468 // are omitted.
3470 if (!trace_this_child) {
3471 argv = (HChar**)ARG4;
3472 } else {
3473 vg_assert( VG_(args_for_valgrind) );
3474 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3475 vg_assert( VG_(args_for_valgrind_noexecpass)
3476 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3477 /* how many args in total will there be? */
3478 // launcher basename
3479 tot_args = 1;
3480 // V's args
3481 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3482 tot_args -= VG_(args_for_valgrind_noexecpass);
3483 // name of client exe
3484 tot_args++;
3485 // args for client exe, skipping [0]
3486 arg2copy = (HChar**)ARG4;
3487 if (arg2copy && arg2copy[0]) {
3488 for (i = 1; arg2copy[i]; i++)
3489 tot_args++;
3491 // allocate
3492 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3493 (tot_args+1) * sizeof(HChar*) );
3494 // copy
3495 j = 0;
3496 argv[j++] = launcher_basename;
3497 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3498 if (i < VG_(args_for_valgrind_noexecpass))
3499 continue;
3500 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3502 argv[j++] = (HChar*)ARG2;
3503 if (arg2copy && arg2copy[0])
3504 for (i = 1; arg2copy[i]; i++)
3505 argv[j++] = arg2copy[i];
3506 argv[j++] = NULL;
3507 // check
3508 vg_assert(j == tot_args+1);
3511 /* DDD: sort out the signal state. What signal
3512 state does the child inherit from the parent? */
3514 if (0) {
3515 HChar **cpp;
3516 VG_(printf)("posix_spawn: %s\n", path);
3517 for (cpp = argv; cpp && *cpp; cpp++)
3518 VG_(printf)("argv: %s\n", *cpp);
3519 if (1)
3520 for (cpp = envp; cpp && *cpp; cpp++)
3521 VG_(printf)("env: %s\n", *cpp);
3524 /* Let the call go through as usual. However, we have to poke
3525 the altered arguments back into the argument slots. */
3526 ARG2 = (UWord)path;
3527 ARG4 = (UWord)argv;
3528 ARG5 = (UWord)envp;
3530 /* not to mention .. */
3531 *flags |= SfMayBlock;
3533 POST(posix_spawn)
3535 vg_assert(SUCCESS);
3536 if (ARG1 != 0) {
3537 POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3542 PRE(socket)
3544 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
3545 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3548 POST(socket)
3550 SysRes r;
3551 vg_assert(SUCCESS);
3552 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3553 SET_STATUS_from_SysRes(r);
3557 PRE(setsockopt)
3559 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3560 ARG1,ARG2,ARG3,ARG4,ARG5);
3561 PRE_REG_READ5(long, "setsockopt",
3562 int, s, int, level, int, optname,
3563 const void *, optval, vki_socklen_t, optlen);
3564 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3568 PRE(getsockopt)
3570 Addr optval_p = ARG4;
3571 Addr optlen_p = ARG5;
3572 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3573 ARG1,ARG2,ARG3,ARG4,ARG5);
3574 PRE_REG_READ5(long, "getsockopt",
3575 int, s, int, level, int, optname,
3576 void *, optval, vki_socklen_t *, optlen);
3577 /* int getsockopt(int socket, int level, int option_name,
3578 void *restrict option_value,
3579 socklen_t *restrict option_len); */
3580 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3581 if (optval_p != (Addr)NULL) {
3582 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3583 "socketcall.getsockopt(optval)",
3584 "socketcall.getsockopt(optlen)" );
3586 // DDD: #warning GrP fixme darwin-specific sockopts
3589 POST(getsockopt)
3591 Addr optval_p = ARG4;
3592 Addr optlen_p = ARG5;
3593 vg_assert(SUCCESS);
3594 if (optval_p != (Addr)NULL) {
3595 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3596 optval_p, optlen_p,
3597 "socketcall.getsockopt(optlen_out)" );
3598 // DDD: #warning GrP fixme darwin-specific sockopts
3603 PRE(connect)
3605 *flags |= SfMayBlock;
3606 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3607 PRE_REG_READ3(long, "connect",
3608 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3609 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3613 PRE(accept)
3615 *flags |= SfMayBlock;
3616 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3617 PRE_REG_READ3(long, "accept",
3618 int, s, struct sockaddr *, addr, int, *addrlen);
3619 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3622 POST(accept)
3624 SysRes r;
3625 vg_assert(SUCCESS);
3626 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3627 ARG1,ARG2,ARG3);
3628 SET_STATUS_from_SysRes(r);
3631 PRE(mkfifo)
3633 *flags |= SfMayBlock;
3634 PRINT("mkfifo ( %#lx(%s), %lld )",ARG1,(char *)ARG1,(ULong)ARG2);
3635 PRE_REG_READ2(long, "mkfifo", const char *, path, vki_mode_t, mode);
3636 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1 );
3639 POST(mkfifo)
3641 vg_assert(SUCCESS);
3642 if (!ML_(fd_allowed)(RES, "mkfifo", tid, True)) {
3643 VG_(close)(RES);
3644 SET_STATUS_Failure( VKI_EMFILE );
3645 } else {
3646 if (VG_(clo_track_fds))
3647 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3651 PRE(sendto)
3653 *flags |= SfMayBlock;
3654 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3655 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
3656 PRE_REG_READ6(long, "sendto",
3657 int, s, const void *, msg, int, len,
3658 unsigned int, flags,
3659 const struct sockaddr *, to, int, tolen);
3660 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3663 PRE(sendfile)
3665 #if VG_WORDSIZE == 4
3666 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3667 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
3669 PRE_REG_READ7(long, "sendfile",
3670 int, fromfd, int, tofd,
3671 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3672 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3673 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3674 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3675 #else
3676 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
3677 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
3679 PRE_REG_READ6(long, "sendfile",
3680 int, fromfd, int, tofd,
3681 vki_uint64_t, offset,
3682 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3683 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3684 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3685 #endif
3687 *flags |= SfMayBlock;
3689 POST(sendfile)
3691 #if VG_WORDSIZE == 4
3692 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3693 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3694 #else
3695 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3696 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3697 #endif
3700 PRE(recvfrom)
3702 *flags |= SfMayBlock;
3703 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3704 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3705 PRE_REG_READ6(long, "recvfrom",
3706 int, s, void *, buf, int, len, unsigned int, flags,
3707 struct sockaddr *, from, int *, fromlen);
3708 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3711 POST(recvfrom)
3713 vg_assert(SUCCESS);
3714 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3715 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3719 PRE(sendmsg)
3721 *flags |= SfMayBlock;
3722 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3723 PRE_REG_READ3(long, "sendmsg",
3724 int, s, const struct msghdr *, msg, int, flags);
3725 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3729 PRE(recvmsg)
3731 *flags |= SfMayBlock;
3732 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3733 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3734 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3737 POST(recvmsg)
3739 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3743 PRE(shutdown)
3745 *flags |= SfMayBlock;
3746 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
3747 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3751 PRE(bind)
3753 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3754 PRE_REG_READ3(long, "bind",
3755 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3756 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3760 PRE(listen)
3762 PRINT("listen ( %ld, %ld )",ARG1,ARG2);
3763 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3767 PRE(getsockname)
3769 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3770 PRE_REG_READ3(long, "getsockname",
3771 int, s, struct sockaddr *, name, int *, namelen);
3772 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3775 POST(getsockname)
3777 vg_assert(SUCCESS);
3778 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3779 ARG1,ARG2,ARG3);
3783 PRE(getpeername)
3785 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3786 PRE_REG_READ3(long, "getpeername",
3787 int, s, struct sockaddr *, name, int *, namelen);
3788 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3791 POST(getpeername)
3793 vg_assert(SUCCESS);
3794 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3795 ARG1,ARG2,ARG3);
3799 PRE(socketpair)
3801 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3802 PRE_REG_READ4(long, "socketpair",
3803 int, d, int, type, int, protocol, int *, sv);
3804 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3807 POST(socketpair)
3809 vg_assert(SUCCESS);
3810 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3811 ARG1,ARG2,ARG3,ARG4);
3815 PRE(gethostuuid)
3817 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3818 PRE_REG_READ2(int,"gethostuuid",
3819 char *,"uuid_buf",
3820 const struct vki_timespec *,"timeout");
3822 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3823 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3825 *flags |= SfMayBlock;
3829 POST(gethostuuid)
3831 POST_MEM_WRITE(ARG1, 16);
3834 /* Darwin pipe() returns the two descriptors in two registers. */
3835 PRE(pipe)
3837 PRINT("pipe ( )");
3838 PRE_REG_READ0(int, "pipe");
3841 POST(pipe)
3843 Int p0, p1;
3844 vg_assert(SUCCESS);
3845 p0 = RES;
3846 p1 = RESHI;
3848 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3849 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3850 VG_(close)(p0);
3851 VG_(close)(p1);
3852 SET_STATUS_Failure( VKI_EMFILE );
3853 } else {
3854 if (VG_(clo_track_fds)) {
3855 ML_(record_fd_open_nameless)(tid, p0);
3856 ML_(record_fd_open_nameless)(tid, p1);
3862 PRE(getlogin)
3864 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3865 PRE_REG_READ2(long, "getlogin",
3866 char *,"namebuf", unsigned int,"namelen");
3868 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3871 POST(getlogin)
3873 POST_MEM_WRITE(ARG1, ARG2);
3877 PRE(ptrace)
3879 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3880 PRE_REG_READ4(long, "ptrace",
3881 int,"request", vki_pid_t,"pid",
3882 vki_caddr_t,"addr", int,"data");
3884 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3886 // GrP fixme anything needed?
3890 PRE(issetugid)
3892 PRINT("issetugid ( )");
3893 PRE_REG_READ0(long, "issetugid");
3897 PRE(getdtablesize)
3899 PRINT("getdtablesize ( )");
3900 PRE_REG_READ0(long, "getdtablesize");
3903 POST(getdtablesize)
3905 // Subtract Valgrind's fd range from client's dtable
3906 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3909 PRE(lseek)
3911 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3912 PRE_REG_READ4(vki_off_t, "lseek",
3913 unsigned int,fd, int,offset_hi, int,offset_lo,
3914 unsigned int,whence);
3918 PRE(pathconf)
3920 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3921 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3922 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3926 PRE(fpathconf)
3928 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3929 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3931 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3932 SET_STATUS_Failure( VKI_EBADF );
3936 PRE(getdirentries)
3938 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3939 PRE_REG_READ4(int, "getdirentries",
3940 int, fd, char *, buf, int, nbytes, long *, basep);
3941 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3942 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3945 POST(getdirentries)
3947 POST_MEM_WRITE(ARG4, sizeof(long));
3948 // GrP fixme be specific about d_name?
3949 POST_MEM_WRITE(ARG2, RES);
3953 PRE(getdirentries64)
3955 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3956 PRE_REG_READ4(vki_ssize_t, "getdirentries",
3957 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3958 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
3959 to valid memory and the kernel doesn't modify it. I can't
3960 determine the conditions under which that happens. But it
3961 causes Memcheck to complain, confusingly. So disable this check
3962 for the time being.
3964 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
3966 PRE_MEM_WRITE("getdirentries64(buf)", ARG2, ARG3);
3968 POST(getdirentries64)
3970 /* Disabled; see coments in the PRE wrapper.
3971 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3973 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3974 POST_MEM_WRITE(ARG2, RES);
3978 PRE(statfs64)
3980 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3981 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3982 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3983 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3985 POST(statfs64)
3987 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3991 PRE(fstatfs64)
3993 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3994 PRE_REG_READ2(long, "fstatfs64",
3995 unsigned int, fd, struct statfs *, buf);
3996 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3998 POST(fstatfs64)
4000 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4003 PRE(csops)
4005 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
4006 PRE_REG_READ4(int, "csops",
4007 vki_pid_t, pid, uint32_t, ops,
4008 void *, useraddr, vki_size_t, usersize);
4010 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
4012 // If the pid is ours, don't mark the program as KILL or HARD
4013 // Maybe we should keep track of this for later calls to STATUS
4014 if (!ARG1 || VG_(getpid)() == ARG1) {
4015 switch (ARG2) {
4016 case VKI_CS_OPS_MARKINVALID:
4017 case VKI_CS_OPS_MARKHARD:
4018 case VKI_CS_OPS_MARKKILL:
4019 SET_STATUS_Success(0);
4023 POST(csops)
4025 POST_MEM_WRITE( ARG3, ARG4 );
4028 PRE(auditon)
4030 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
4031 PRE_REG_READ3(int,"auditon",
4032 int,"cmd", void*,"data", unsigned int,"length");
4034 switch (ARG1) {
4036 case VKI_A_SETPOLICY:
4037 case VKI_A_SETKMASK:
4038 case VKI_A_SETQCTRL:
4039 case VKI_A_SETCOND:
4040 case VKI_A_SETCLASS:
4041 case VKI_A_SETPMASK:
4042 case VKI_A_SETFSIZE:
4043 #if DARWIN_VERS >= DARWIN_10_6
4044 case VKI_A_SENDTRIGGER:
4045 #endif
4046 // kernel reads data..data+length
4047 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4048 break;
4050 case VKI_A_GETKMASK:
4051 case VKI_A_GETPOLICY:
4052 case VKI_A_GETQCTRL:
4053 case VKI_A_GETFSIZE:
4054 case VKI_A_GETCOND:
4055 // kernel writes data..data+length
4056 // GrP fixme be precise about what gets written
4057 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4058 break;
4061 case VKI_A_GETCLASS:
4062 case VKI_A_GETPINFO:
4063 case VKI_A_GETPINFO_ADDR:
4064 #if DARWIN_VERS >= DARWIN_10_6
4065 case VKI_A_GETSINFO_ADDR:
4066 #endif
4067 // kernel reads and writes data..data+length
4068 // GrP fixme be precise about what gets read and written
4069 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4070 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4071 break;
4073 case VKI_A_SETKAUDIT:
4074 case VKI_A_SETSTAT:
4075 case VKI_A_SETUMASK:
4076 case VKI_A_SETSMASK:
4077 case VKI_A_GETKAUDIT:
4078 case VKI_A_GETCWD:
4079 case VKI_A_GETCAR:
4080 case VKI_A_GETSTAT:
4081 // unimplemented on darwin
4082 break;
4084 default:
4085 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld\n", ARG1);
4086 break;
4089 POST(auditon)
4091 switch (ARG1) {
4093 case VKI_A_SETPOLICY:
4094 case VKI_A_SETKMASK:
4095 case VKI_A_SETQCTRL:
4096 case VKI_A_SETCOND:
4097 case VKI_A_SETCLASS:
4098 case VKI_A_SETPMASK:
4099 case VKI_A_SETFSIZE:
4100 #if DARWIN_VERS >= DARWIN_10_6
4101 case VKI_A_SENDTRIGGER:
4102 #endif
4103 // kernel reads data..data+length
4104 break;
4106 case VKI_A_GETKMASK:
4107 case VKI_A_GETPOLICY:
4108 case VKI_A_GETQCTRL:
4109 case VKI_A_GETFSIZE:
4110 case VKI_A_GETCOND:
4111 // kernel writes data..data+length
4112 // GrP fixme be precise about what gets written
4113 POST_MEM_WRITE(ARG2, ARG3);
4114 break;
4117 case VKI_A_GETCLASS:
4118 case VKI_A_GETPINFO:
4119 case VKI_A_GETPINFO_ADDR:
4120 #if DARWIN_VERS >= DARWIN_10_6
4121 case VKI_A_GETSINFO_ADDR:
4122 #endif
4123 // kernel reads and writes data..data+length
4124 // GrP fixme be precise about what gets read and written
4125 POST_MEM_WRITE(ARG2, ARG3);
4126 break;
4128 case VKI_A_SETKAUDIT:
4129 case VKI_A_SETSTAT:
4130 case VKI_A_SETUMASK:
4131 case VKI_A_SETSMASK:
4132 case VKI_A_GETKAUDIT:
4133 case VKI_A_GETCWD:
4134 case VKI_A_GETCAR:
4135 case VKI_A_GETSTAT:
4136 // unimplemented on darwin
4137 break;
4139 default:
4140 break;
4145 PRE(mmap)
4147 // SysRes r;
4148 if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
4150 #if VG_WORDSIZE == 4
4151 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
4152 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
4153 PRE_REG_READ7(Addr, "mmap",
4154 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4155 unsigned long,offset_hi, unsigned long,offset_lo);
4156 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4157 // V's mechanism for now
4158 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4159 // (Off64T)LOHI64(ARG6, ARG7) );
4160 #else
4161 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4162 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4163 PRE_REG_READ6(long, "mmap",
4164 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4165 Off64T,offset);
4166 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4168 #endif
4170 // SET_STATUS_from_SysRes(r);
4173 POST(mmap)
4175 if (RES != -1) {
4176 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
4177 // Try to load symbols from the region
4178 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
4179 -1/*don't use_fd*/ );
4180 ML_(sync_mappings)("after", "mmap", 0);
4185 /* This function holds common elements of PRE(__sysctl) and
4186 PRE(sysctlbyname). */
4187 static void common_PRE_sysctl (
4188 /*IMPLICIT ARGS*/
4189 ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
4190 /*!IMPLICIT ARGS*/
4191 Bool is_kern_dot_userstack,
4192 UWord oldp, UWord oldlenp,
4193 UWord newp, UWord newlen )
4195 if (oldlenp) {
4196 // writes *oldlenp
4197 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4198 if (oldp) {
4199 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4200 PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4201 PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
4204 if (newp) {
4205 PRE_MEM_READ("sysctl(newp)", newp, newlen);
4208 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4209 // (executable path and arguments and environment
4211 if (is_kern_dot_userstack) {
4212 // Intercept sysctl(kern.usrstack). The kernel's reply
4213 // would be Valgrind's stack, not the client's stack.
4214 // GrP fixme kern_usrstack64 */
4215 if (newp || newlen) {
4216 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
4217 } else {
4218 Addr* t_oldp = (Addr*)oldp;
4219 size_t* t_oldlenp = (size_t*)oldlenp;
4220 if (t_oldlenp) {
4221 // According to some searches on the net, it looks like
4222 // USRSTACK gives the address of the byte following the
4223 // highest byte of the stack. As VG_(clstk_end) is the
4224 // address of the highest addressable byte, we add 1.
4225 Addr stack_end = VG_(clstk_end)+1;
4226 size_t oldlen = *t_oldlenp;
4227 // always return actual size
4228 *t_oldlenp = sizeof(Addr);
4229 if (t_oldp && oldlen >= sizeof(Addr)) {
4230 // oldp is big enough. copy value and return 0
4231 *t_oldp = stack_end;
4232 SET_STATUS_Success(0);
4233 } else {
4234 // oldp isn't big enough. copy as much as possible
4235 // and return ENOMEM
4236 if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
4237 SET_STATUS_Failure(VKI_ENOMEM);
4243 if (!SUCCESS && !FAILURE) {
4244 // Don't set SfPostOnFail if we've already handled it locally.
4245 *flags |= SfPostOnFail;
4250 PRE(__sysctl)
4252 UWord name = ARG1;
4253 UWord namelen = ARG2;
4254 UWord oldp = ARG3;
4255 UWord oldlenp = ARG4;
4256 UWord newp = ARG5;
4257 UWord newlen = ARG6;
4259 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
4260 name, namelen, oldp, oldlenp, newp, newlen );
4262 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
4263 void*, oldp, vki_size_t *, oldlenp,
4264 void*, newp, vki_size_t *, newlenp);
4266 PRE_MEM_READ("sysctl(name)", name, namelen); // reads name[0..namelen-1]
4268 if (VG_(clo_trace_syscalls)) {
4269 UInt i;
4270 Int* t_name = (Int*)name;
4271 VG_(printf)(" mib: [ ");
4272 for (i = 0; i < namelen; i++) {
4273 VG_(printf)("%d ", t_name[i]);
4275 VG_(printf)("]");
4278 Int vKI_KERN_USRSTACKXX
4279 = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64;
4280 Bool is_kern_dot_userstack
4281 = name && namelen == 2
4282 && ((Int*)name)[0] == VKI_CTL_KERN
4283 && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
4285 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
4286 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
4289 POST(__sysctl)
4291 UWord oldp = ARG3;
4292 UWord oldlenp = ARG4;
4294 if (SUCCESS || ERR == VKI_ENOMEM) {
4295 // sysctl can write truncated data and return VKI_ENOMEM
4296 if (oldlenp) {
4297 POST_MEM_WRITE(oldlenp, sizeof(size_t));
4299 if (oldp && oldlenp) {
4300 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
4306 PRE(sigpending)
4308 PRINT( "sigpending ( %#lx )", ARG1 );
4309 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
4310 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
4312 POST(sigpending)
4314 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
4318 PRE(sigprocmask)
4320 UWord arg1;
4321 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
4322 PRE_REG_READ3(long, "sigprocmask",
4323 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
4324 if (ARG2 != 0)
4325 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4326 if (ARG3 != 0)
4327 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
4329 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4330 value of 'how' is irrelevant, and it appears that Darwin's libc
4331 passes zero, which is not equal to any of
4332 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4333 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4334 value independently of the other args. Solution: in this case,
4335 simply pass a valid (but irrelevant) value for 'how'. */
4336 /* Also, in this case the new set is passed to the kernel by
4337 reference, not value, as in some other sigmask related Darwin
4338 syscalls. */
4339 arg1 = ARG1;
4340 if (ARG2 == 0 /* the new-set is NULL */
4341 && ARG1 != VKI_SIG_BLOCK
4342 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
4343 arg1 = VKI_SIG_SETMASK;
4345 SET_STATUS_from_SysRes(
4346 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
4347 (vki_sigset_t*)ARG3 )
4350 if (SUCCESS)
4351 *flags |= SfPollAfter;
4354 POST(sigprocmask)
4356 vg_assert(SUCCESS);
4357 if (RES == 0 && ARG3 != 0)
4358 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
4362 PRE(sigsuspend)
4364 /* Just hand this off to the kernel. Is that really correct? And
4365 shouldn't we at least set SfPollAfter? These questions apply to
4366 all the Linux versions too. */
4367 /* I think the first arg is the 32-bit signal mask (by value), and
4368 the other two args are ignored. */
4369 *flags |= SfMayBlock;
4370 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
4371 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
4375 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4376 and 32-bit wrappers are different.
4378 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4379 length in the usual way. I have seen values NULL, 0 passed in some
4380 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4381 basis that they don't do anything if the length is zero, so it's OK
4382 for the buffer pointer to be NULL in that case (meaning they don't
4383 complain).
4385 int proc_info(int32_t callnum, int32_t pid,
4386 uint32_t flavor, uint64_t arg,
4387 user_addr_t buffer, int32_t buffersize)
4389 #if DARWIN_VERS >= DARWIN_10_6
4390 PRE(proc_info)
4392 #if VG_WORDSIZE == 4
4393 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4394 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
4395 PRE_REG_READ7(int, "proc_info",
4396 int, callnum, int, pid, unsigned int, flavor,
4397 vki_uint32_t, arg_low32,
4398 vki_uint32_t, arg_high32,
4399 void*, buffer, int, buffersize);
4400 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
4401 #else
4402 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4403 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
4404 PRE_REG_READ6(int, "proc_info",
4405 int, callnum, int, pid, unsigned int, flavor,
4406 unsigned long long int, arg,
4407 void*, buffer, int, buffersize);
4408 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
4409 #endif
4412 POST(proc_info)
4414 #if VG_WORDSIZE == 4
4415 vg_assert(SUCCESS);
4417 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4418 if (ARG1 == 5 && ARG3 == 2 && LOHI64(ARG4,ARG5) == 0 )
4420 const HChar* new_name = (const HChar*) ARG6;
4421 if (new_name) { // Paranoia
4422 ThreadState* tst = VG_(get_ThreadState)(tid);
4423 SizeT new_len = VG_(strlen)(new_name);
4425 /* Don't bother reusing the memory. This is a rare event. */
4426 tst->thread_name =
4427 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4428 VG_(strcpy)(tst->thread_name, new_name);
4432 POST_MEM_WRITE(ARG6, ARG7);
4433 #else
4434 vg_assert(SUCCESS);
4436 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4437 if (ARG1 == 5 && ARG3 == 2 && ARG4 == 0 )
4439 const HChar* new_name = (const HChar*) ARG5;
4440 if (new_name) { // Paranoia
4441 ThreadState* tst = VG_(get_ThreadState)(tid);
4442 SizeT new_len = VG_(strlen)(new_name);
4444 /* Don't bother reusing the memory. This is a rare event. */
4445 tst->thread_name =
4446 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4447 VG_(strcpy)(tst->thread_name, new_name);
4451 POST_MEM_WRITE(ARG5, ARG6);
4452 #endif
4455 #endif /* DARWIN_VERS >= DARWIN_10_6 */
4457 /* ---------------------------------------------------------------------
4458 aio_*
4459 ------------------------------------------------------------------ */
4461 // We must record the aiocbp for each aio_read() in a table so that when
4462 // aio_return() is called we can mark the memory written asynchronously by
4463 // aio_read() as having been written. We don't have to do this for
4464 // aio_write(). See bug 197227 for more details.
4465 static OSet* aiocbp_table = NULL;
4466 static Bool aio_init_done = False;
4468 static void aio_init(void)
4470 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
4471 aio_init_done = True;
4474 static Bool was_a_successful_aio_read = False;
4476 PRE(aio_return)
4478 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4479 // This assumes that the kernel looks at the struct pointer, but not the
4480 // contents of the struct.
4481 PRINT( "aio_return ( %#lx )", ARG1 );
4482 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
4484 if (!aio_init_done) aio_init();
4485 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
4487 POST(aio_return)
4489 // If we found the aiocbp in our own table it must have been an aio_read(),
4490 // so mark the buffer as written. If we didn't find it, it must have been
4491 // an aio_write() or a bogus aio_return() (eg. a second one on the same
4492 // aiocbp). Either way, the buffer won't have been written so we don't
4493 // have to mark the buffer as written.
4494 if (was_a_successful_aio_read) {
4495 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4496 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4497 was_a_successful_aio_read = False;
4501 PRE(aio_suspend)
4503 // This assumes that the kernel looks at the struct pointers in the list,
4504 // but not the contents of the structs.
4505 PRINT( "aio_suspend ( %#lx )", ARG1 );
4506 PRE_REG_READ3(long, "aio_suspend",
4507 const struct vki_aiocb *, aiocbp, int, nent,
4508 const struct vki_timespec *, timeout);
4509 if (ARG2 > 0)
4510 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
4511 if (ARG3)
4512 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
4515 PRE(aio_error)
4517 // This assumes that the kernel looks at the struct pointer, but not the
4518 // contents of the struct.
4519 PRINT( "aio_error ( %#lx )", ARG1 );
4520 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
4523 PRE(aio_read)
4525 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4527 PRINT( "aio_read ( %#lx )", ARG1 );
4528 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4529 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4531 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4532 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4533 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4534 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4535 } else {
4536 SET_STATUS_Failure( VKI_EBADF );
4538 } else {
4539 SET_STATUS_Failure( VKI_EINVAL );
4542 POST(aio_read)
4544 // We have to record the fact that there is an asynchronous read request
4545 // pending. When a successful aio_return() occurs for this aiocb, then we
4546 // will mark the memory as having been defined.
4547 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4548 if (!aio_init_done) aio_init();
4549 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4550 // should have caused the aio_read() to fail and we shouldn't have reached
4551 // here.
4552 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4555 PRE(aio_write)
4557 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4559 PRINT( "aio_write ( %#lx )", ARG1 );
4560 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4561 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4563 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4564 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4565 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4566 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4567 } else {
4568 SET_STATUS_Failure( VKI_EBADF );
4570 } else {
4571 SET_STATUS_Failure( VKI_EINVAL );
4575 /* ---------------------------------------------------------------------
4576 mach_msg: formatted messages
4577 ------------------------------------------------------------------ */
4579 static size_t desc_size(mach_msg_descriptor_t *desc)
4581 switch (desc->type.type) {
4582 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
4583 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
4584 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
4585 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
4586 default:
4587 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4588 return sizeof(desc->type); // guess
4593 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4594 const char *name)
4596 mach_msg_size_t i;
4597 mach_port_t *ports = (mach_port_t *)desc->address;
4598 for (i = 0; i < desc->count; i++) {
4599 assign_port_name(ports[i], name);
4604 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4606 mach_msg_body_t *body;
4607 mach_msg_size_t count, i;
4608 uint8_t *p;
4609 mach_msg_descriptor_t *desc;
4611 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4613 body = (mach_msg_body_t *)(mh+1);
4614 count = body->msgh_descriptor_count;
4615 p = (uint8_t *)(body+1);
4617 for (i = 0; i < count; i++) {
4618 desc = (mach_msg_descriptor_t *)p;
4619 p += desc_size(desc);
4621 switch (desc->type.type) {
4622 case MACH_MSG_PORT_DESCRIPTOR:
4623 // single port
4624 record_unnamed_port(tid, desc->port.name, -1);
4625 record_port_insert_rights(desc->port.name, desc->port.disposition);
4626 PRINT("got port %s;\n", name_for_port(desc->port.name));
4627 break;
4629 case MACH_MSG_OOL_DESCRIPTOR:
4630 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4631 // out-of-line memory - map it
4632 // GrP fixme how is VOLATILE different? do we care?
4633 // GrP fixme do other flags tell us anything? assume shared for now
4634 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4635 // GrP fixme protection
4636 if (desc->out_of_line.size > 0) {
4637 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4638 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4639 (Addr)desc->out_of_line.size);
4640 PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4641 (char*)desc->out_of_line.address+desc->out_of_line.size);
4643 ML_(notify_core_and_tool_of_mmap)(
4644 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4645 VKI_MAP_PRIVATE, -1, 0);
4647 // GrP fixme mark only un-rounded part as initialized
4648 break;
4650 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4651 // out-of-line array of ports - map it
4652 // GrP fixme see fixmes above
4653 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));
4655 if (desc->ool_ports.count > 0) {
4656 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4657 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4658 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4660 ML_(notify_core_and_tool_of_mmap)(
4661 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4662 VKI_MAP_PRIVATE, -1, 0);
4664 PRINT(":");
4665 for (i = 0; i < desc->ool_ports.count; i++) {
4666 record_unnamed_port(tid, ports[i], -1);
4667 record_port_insert_rights(ports[i], desc->port.disposition);
4668 PRINT(" %s", name_for_port(ports[i]));
4671 PRINT(";\n");
4672 break;
4674 default:
4675 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4676 break;
4682 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4684 #pragma pack(4)
4685 struct {
4686 mach_port_t name;
4687 mach_msg_size_t pad1;
4688 uint16_t pad2;
4689 uint8_t disposition;
4690 uint8_t type;
4691 } *desc = (void*)desc2;
4692 #pragma pack()
4694 PRE_FIELD_READ("msg->desc.port.name", desc->name);
4695 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4696 PRE_FIELD_READ("msg->desc.port.type", desc->type);
4700 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4702 #pragma pack(4)
4703 struct {
4704 Addr address;
4705 #if VG_WORDSIZE != 8
4706 mach_msg_size_t size;
4707 #endif
4708 uint8_t deallocate;
4709 uint8_t copy;
4710 uint8_t pad1;
4711 uint8_t type;
4712 #if VG_WORDSIZE == 8
4713 mach_msg_size_t size;
4714 #endif
4715 } *desc = (void*)desc2;
4716 #pragma pack()
4718 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4719 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4720 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4721 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4722 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4725 static void pre_oolports_desc_read(ThreadId tid,
4726 mach_msg_ool_ports_descriptor_t *desc2)
4728 #pragma pack(4)
4729 struct {
4730 Addr address;
4731 #if VG_WORDSIZE != 8
4732 mach_msg_size_t size;
4733 #endif
4734 uint8_t deallocate;
4735 uint8_t copy;
4736 uint8_t disposition;
4737 uint8_t type;
4738 #if VG_WORDSIZE == 8
4739 mach_msg_size_t size;
4740 #endif
4741 } *desc = (void*)desc2;
4742 #pragma pack()
4744 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4745 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4746 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4747 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4748 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4749 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4753 // Returns the size of the descriptor area
4754 // (mach_msg_body_t + any mach_msg_descriptor_t)
4755 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4757 mach_msg_body_t *body;
4758 mach_msg_size_t count, i;
4759 uint8_t *p;
4760 mach_msg_descriptor_t *desc;
4762 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4764 body = (mach_msg_body_t *)(mh+1);
4765 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4767 count = body->msgh_descriptor_count;
4768 p = (uint8_t *)(body+1);
4770 for (i = 0; i < count; i++) {
4771 desc = (mach_msg_descriptor_t *)p;
4772 p += desc_size(desc);
4774 switch (desc->type.type) {
4775 case MACH_MSG_PORT_DESCRIPTOR:
4776 // single port; no memory map effects
4777 pre_port_desc_read(tid, &desc->port);
4778 break;
4780 case MACH_MSG_OOL_DESCRIPTOR:
4781 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4782 // out-of-line memory - unmap it if it's marked dealloc
4783 // GrP fixme need to remap if message fails?
4784 // GrP fixme how is VOLATILE different? do we care?
4785 // GrP fixme struct is different for lp64
4786 pre_ool_desc_read(tid, &desc->out_of_line);
4788 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4789 vm_size_t size = desc->out_of_line.size;
4790 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4791 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4792 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4793 (Addr)desc->out_of_line.address + size);
4794 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4796 break;
4798 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4799 // out-of-line array of ports - unmap it if it's marked dealloc
4800 // GrP fixme need to remap if message fails?
4801 // GrP fixme struct different for lp64
4802 pre_oolports_desc_read(tid, &desc->ool_ports);
4804 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4805 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4806 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4807 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4808 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4809 (Addr)desc->ool_ports.address + size);
4810 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4812 break;
4813 default:
4814 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4815 break;
4819 return (size_t)((Addr)p - (Addr)body);
4823 /* ---------------------------------------------------------------------
4824 mach_msg: host-related messages
4825 ------------------------------------------------------------------ */
4828 POST(host_info)
4830 #pragma pack(4)
4831 typedef struct {
4832 mach_msg_header_t Head;
4833 NDR_record_t NDR;
4834 kern_return_t RetCode;
4835 mach_msg_type_number_t host_info_outCnt;
4836 integer_t host_info_out[14];
4837 } Reply;
4838 #pragma pack()
4840 Reply *reply = (Reply *)ARG1;
4842 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4845 PRE(host_info)
4847 #pragma pack(4)
4848 typedef struct {
4849 mach_msg_header_t Head;
4850 NDR_record_t NDR;
4851 host_flavor_t flavor;
4852 mach_msg_type_number_t host_info_outCnt;
4853 } Request;
4854 #pragma pack()
4856 Request *req = (Request *)ARG1;
4858 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4860 AFTER = POST_FN(host_info);
4864 POST(host_page_size)
4866 #pragma pack(4)
4867 typedef struct {
4868 mach_msg_header_t Head;
4869 NDR_record_t NDR;
4870 kern_return_t RetCode;
4871 vm_size_t out_page_size;
4872 } Reply;
4873 #pragma pack()
4875 Reply *reply = (Reply *)ARG1;
4877 if (!reply->RetCode) {
4878 PRINT("page size %llu", (ULong)reply->out_page_size);
4879 } else {
4880 PRINT("mig return %d", reply->RetCode);
4884 PRE(host_page_size)
4886 PRINT("host_page_size(mach_host_self(), ...)");
4888 AFTER = POST_FN(host_page_size);
4892 POST(host_get_io_master)
4894 #pragma pack(4)
4895 typedef struct {
4896 mach_msg_header_t Head;
4897 /* start of the kernel processed data */
4898 mach_msg_body_t msgh_body;
4899 mach_msg_port_descriptor_t io_master;
4900 /* end of the kernel processed data */
4901 } Reply;
4902 #pragma pack()
4904 Reply *reply = (Reply *)ARG1;
4906 assign_port_name(reply->io_master.name, "io_master-%p");
4907 PRINT("%s", name_for_port(reply->io_master.name));
4910 PRE(host_get_io_master)
4912 #pragma pack(4)
4913 typedef struct {
4914 mach_msg_header_t Head;
4915 } Request;
4916 #pragma pack()
4918 // Request *req = (Request *)ARG1;
4920 PRINT("host_get_io_master(mach_host_self())");
4922 AFTER = POST_FN(host_get_io_master);
4926 POST(host_get_clock_service)
4928 #pragma pack(4)
4929 typedef struct {
4930 mach_msg_header_t Head;
4931 /* start of the kernel processed data */
4932 mach_msg_body_t msgh_body;
4933 mach_msg_port_descriptor_t clock_serv;
4934 /* end of the kernel processed data */
4935 } Reply;
4936 #pragma pack()
4938 Reply *reply = (Reply *)ARG1;
4940 assign_port_name(reply->clock_serv.name, "clock-%p");
4941 PRINT("%s", name_for_port(reply->clock_serv.name));
4944 PRE(host_get_clock_service)
4946 #pragma pack(4)
4947 typedef struct {
4948 mach_msg_header_t Head;
4949 NDR_record_t NDR;
4950 clock_id_t clock_id;
4951 } Request;
4952 #pragma pack()
4954 Request *req = (Request *)ARG1;
4956 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4958 AFTER = POST_FN(host_get_clock_service);
4962 PRE(host_request_notification)
4964 #pragma pack(4)
4965 typedef struct {
4966 mach_msg_header_t Head;
4967 /* start of the kernel processed data */
4968 mach_msg_body_t msgh_body;
4969 mach_msg_port_descriptor_t notify_port;
4970 /* end of the kernel processed data */
4971 NDR_record_t NDR;
4972 host_flavor_t notify_type;
4973 } Request;
4974 #pragma pack()
4976 Request *req = (Request *)ARG1;
4978 if (MACH_REMOTE == mach_task_self()) {
4979 if (req->notify_type == 0) {
4980 PRINT("host_request_notification(mach_host_self(), %s, %s)",
4981 "HOST_NOTIFY_CALENDAR_CHANGE",
4982 name_for_port(req->notify_port.name));
4983 } else {
4984 PRINT("host_request_notification(mach_host_self(), %d, %s)",
4985 req->notify_type,
4986 name_for_port(req->notify_port.name));
4988 } else {
4989 PRINT("host_request_notification(%s, %d, %s)",
4990 name_for_port(MACH_REMOTE),
4991 req->notify_type,
4992 name_for_port(req->notify_port.name));
4995 // GrP fixme only do this on success
4996 assign_port_name(req->notify_port.name, "host_notify-%p");
5000 PRE(host_create_mach_voucher)
5002 #pragma pack(4)
5003 typedef struct {
5004 mach_msg_header_t Head;
5005 NDR_record_t NDR;
5006 mach_msg_type_number_t recipesCnt;
5007 uint8_t recipes[5120];
5008 } Request;
5009 #pragma pack()
5011 Request *req = (Request *)ARG1;
5013 PRINT("host_create_mach_voucher(count %u)",
5014 req->recipesCnt);
5016 AFTER = POST_FN(host_create_mach_voucher);
5020 POST(host_create_mach_voucher)
5022 #pragma pack(4)
5023 typedef struct {
5024 mach_msg_header_t Head;
5025 /* start of the kernel processed data */
5026 mach_msg_body_t msgh_body;
5027 mach_msg_port_descriptor_t voucher;
5028 /* end of the kernel processed data */
5029 } Reply;
5030 #pragma pack()
5032 Reply *reply = (Reply *)ARG1;
5034 // RK fixme properly parse this return type
5035 PRINT("got voucher %#x ", reply->voucher.name);
5039 PRE(host_get_special_port)
5041 #pragma pack(4)
5042 typedef struct {
5043 mach_msg_header_t Head;
5044 NDR_record_t NDR;
5045 int node;
5046 int which;
5047 } Request;
5048 #pragma pack()
5050 Request *req = (Request *)ARG1;
5052 PRINT("host_get_special_port(node %d)", req->node);
5054 switch (req->which) {
5055 case HOST_PORT:
5056 PRINT("host_get_special_port(%s, HOST_PORT)",
5057 name_for_port(MACH_REMOTE));
5058 break;
5059 case HOST_PRIV_PORT:
5060 PRINT("host_get_special_port(%s, HOST_PRIV_PORT)",
5061 name_for_port(MACH_REMOTE));
5062 break;
5063 case HOST_IO_MASTER_PORT:
5064 PRINT("host_get_special_port(%s, HOST_IO_MASTER_PORT)",
5065 name_for_port(MACH_REMOTE));
5066 break;
5067 // Not provided by kernel
5068 case HOST_DYNAMIC_PAGER_PORT:
5069 PRINT("host_get_special_port(%s, HOST_DYNAMIC_PAGER_PORT)",
5070 name_for_port(MACH_REMOTE));
5071 break;
5072 case HOST_AUDIT_CONTROL_PORT:
5073 PRINT("host_get_special_port(%s, HOST_AUDIT_CONTROL_PORT)",
5074 name_for_port(MACH_REMOTE));
5075 break;
5076 case HOST_USER_NOTIFICATION_PORT:
5077 PRINT("host_get_special_port(%s, HOST_USER_NOTIFICATION_PORT)",
5078 name_for_port(MACH_REMOTE));
5079 break;
5080 // ...
5082 default:
5083 PRINT("host_get_special_port(%s, %d)",
5084 name_for_port(MACH_REMOTE), req->which);
5085 break;
5088 MACH_ARG(host_get_special_port.which) = req->which;
5090 AFTER = POST_FN(host_get_special_port);
5094 POST(host_get_special_port)
5096 #pragma pack(4)
5097 typedef struct {
5098 mach_msg_header_t Head;
5099 /* start of the kernel processed data */
5100 mach_msg_body_t msgh_body;
5101 mach_msg_port_descriptor_t port;
5102 /* end of the kernel processed data */
5103 } Reply;
5104 #pragma pack()
5106 Reply *reply = (Reply *)ARG1;
5108 PRINT("got port %#x ", reply->port.name);
5110 /* The required entry in the allocated_ports list (mapping) might
5111 not exist, due perhaps to broken syscall wrappers (mach__N etc).
5112 Create a minimal entry so that assign_port_name below doesn't
5113 cause an assertion. */
5114 if (!port_exists(reply->port.name)) {
5115 port_create_vanilla(reply->port.name);
5118 switch (MACH_ARG(host_get_special_port.which)) {
5119 case HOST_PORT:
5120 assign_port_name(reply->port.name, "port-%p");
5121 break;
5122 case HOST_PRIV_PORT:
5123 assign_port_name(reply->port.name, "priv-%p");
5124 break;
5125 case HOST_IO_MASTER_PORT:
5126 assign_port_name(reply->port.name, "io-master-%p");
5127 break;
5128 // Not provided by kernel
5129 case HOST_DYNAMIC_PAGER_PORT:
5130 assign_port_name(reply->port.name, "dynamic-pager-%p");
5131 break;
5132 case HOST_AUDIT_CONTROL_PORT:
5133 assign_port_name(reply->port.name, "audit-control-%p");
5134 break;
5135 case HOST_USER_NOTIFICATION_PORT:
5136 assign_port_name(reply->port.name, "user-notification-%p");
5137 break;
5138 // ...
5140 default:
5141 assign_port_name(reply->port.name, "special-%p");
5142 break;
5145 PRINT("%s", name_for_port(reply->port.name));
5148 /* ---------------------------------------------------------------------
5149 mach_msg: messages to a task
5150 ------------------------------------------------------------------ */
5152 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
5153 // these structs are derived. They obviously relate to the various
5154 // .def files in the xnu sources, and can also be found in some
5155 // form in /usr/include/mach/*.h, but not sure how these all
5156 // relate to each other.
5158 PRE(mach_port_set_context)
5160 #pragma pack(4)
5161 typedef struct {
5162 mach_msg_header_t Head;
5163 NDR_record_t NDR;
5164 mach_port_name_t name;
5165 mach_vm_address_t context;
5166 } Request;
5167 #pragma pack()
5169 Request *req = (Request *)ARG1;
5171 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
5172 name_for_port(MACH_REMOTE),
5173 name_for_port(req->name), req->context);
5175 AFTER = POST_FN(mach_port_set_context);
5178 POST(mach_port_set_context)
5180 #pragma pack(4)
5181 typedef struct {
5182 mach_msg_header_t Head;
5183 NDR_record_t NDR;
5184 kern_return_t RetCode;
5185 } Reply;
5186 #pragma pack()
5190 // JRS 2011-Aug-25 FIXME completely bogus
5191 PRE(task_get_exception_ports)
5193 #pragma pack(4)
5194 typedef struct {
5195 mach_msg_header_t Head;
5196 NDR_record_t NDR;
5197 exception_mask_t exception_mask;
5198 } Request;
5199 #pragma pack()
5201 PRINT("task_get_exception_ports(BOGUS)");
5202 AFTER = POST_FN(task_get_exception_ports);
5205 POST(task_get_exception_ports)
5207 #pragma pack(4)
5208 typedef struct {
5209 mach_msg_header_t Head;
5210 /* start of the kernel processed data */
5211 mach_msg_body_t msgh_body;
5212 mach_msg_port_descriptor_t old_handlers[32];
5213 /* end of the kernel processed data */
5214 NDR_record_t NDR;
5215 mach_msg_type_number_t masksCnt;
5216 exception_mask_t masks[32];
5217 exception_behavior_t old_behaviors[32];
5218 thread_state_flavor_t old_flavors[32];
5219 } Reply;
5220 #pragma pack()
5224 ///////////////////////////////////////////////////
5226 PRE(mach_port_type)
5228 #pragma pack(4)
5229 typedef struct {
5230 mach_msg_header_t Head;
5231 NDR_record_t NDR;
5232 mach_port_name_t name;
5233 } Request;
5234 #pragma pack()
5236 Request *req = (Request *)ARG1;
5238 PRINT("mach_port_type(%s, %s, ...)",
5239 name_for_port(MACH_REMOTE), name_for_port(req->name));
5241 AFTER = POST_FN(mach_port_type);
5244 POST(mach_port_type)
5249 PRE(mach_port_extract_member)
5251 #pragma pack(4)
5252 typedef struct {
5253 mach_msg_header_t Head;
5254 NDR_record_t NDR;
5255 mach_port_name_t name;
5256 mach_port_name_t pset;
5257 } Request;
5258 #pragma pack()
5260 Request *req = (Request *)ARG1;
5262 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5263 name_for_port(MACH_REMOTE),
5264 req->name, req->pset);
5266 AFTER = POST_FN(mach_port_extract_member);
5268 // GrP fixme port tracker?
5271 POST(mach_port_extract_member)
5273 #pragma pack(4)
5274 typedef struct {
5275 mach_msg_header_t Head;
5276 NDR_record_t NDR;
5277 kern_return_t RetCode;
5278 } Reply;
5279 #pragma pack()
5281 Reply *reply = (Reply *)ARG1;
5283 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
5287 PRE(mach_port_allocate)
5289 #pragma pack(4)
5290 typedef struct {
5291 mach_msg_header_t Head;
5292 NDR_record_t NDR;
5293 mach_port_right_t right;
5294 } Request;
5295 #pragma pack()
5297 Request *req = (Request *)ARG1;
5299 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
5301 MACH_ARG(mach_port_allocate.right) = req->right;
5303 AFTER = POST_FN(mach_port_allocate);
5306 POST(mach_port_allocate)
5308 #pragma pack(4)
5309 typedef struct {
5310 mach_msg_header_t Head;
5311 NDR_record_t NDR;
5312 kern_return_t RetCode;
5313 mach_port_name_t name;
5314 } Reply;
5315 #pragma pack()
5317 Reply *reply = (Reply *)ARG1;
5319 if (!reply->RetCode) {
5320 if (MACH_REMOTE == vg_task_port) {
5321 // GrP fixme port tracking is too imprecise
5322 // vg_assert(!port_exists(reply->name));
5323 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
5324 PRINT("got port 0x%x", reply->name);
5325 } else {
5326 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
5328 } else {
5329 PRINT("mig return %d", reply->RetCode);
5334 PRE(mach_port_deallocate)
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_deallocate(%s, %s)",
5347 name_for_port(MACH_REMOTE),
5348 name_for_port(req->name));
5350 MACH_ARG(mach_port.port) = req->name;
5352 AFTER = POST_FN(mach_port_deallocate);
5354 // Must block to prevent race (other thread allocates and
5355 // notifies after we deallocate but before we notify)
5356 *flags &= ~SfMayBlock;
5359 POST(mach_port_deallocate)
5361 #pragma pack(4)
5362 typedef struct {
5363 mach_msg_header_t Head;
5364 NDR_record_t NDR;
5365 kern_return_t RetCode;
5366 } Reply;
5367 #pragma pack()
5369 Reply *reply = (Reply *)ARG1;
5371 if (!reply->RetCode) {
5372 if (MACH_REMOTE == vg_task_port) {
5373 // Must have cleared SfMayBlock in PRE to prevent race
5374 record_port_dealloc(MACH_ARG(mach_port.port));
5375 } else {
5376 VG_(printf)("UNKNOWN remote port dealloc\n");
5378 } else {
5379 PRINT("mig return %d", reply->RetCode);
5384 PRE(mach_port_get_refs)
5386 #pragma pack(4)
5387 typedef struct {
5388 mach_msg_header_t Head;
5389 NDR_record_t NDR;
5390 mach_port_name_t name;
5391 mach_port_right_t right;
5392 } Request;
5393 #pragma pack()
5395 Request *req = (Request *)ARG1;
5397 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5398 name_for_port(MACH_REMOTE),
5399 name_for_port(req->name), req->right);
5401 MACH_ARG(mach_port_mod_refs.port) = req->name;
5402 MACH_ARG(mach_port_mod_refs.right) = req->right;
5404 AFTER = POST_FN(mach_port_get_refs);
5407 POST(mach_port_get_refs)
5409 #pragma pack(4)
5410 typedef struct {
5411 mach_msg_header_t Head;
5412 NDR_record_t NDR;
5413 kern_return_t RetCode;
5414 mach_port_urefs_t refs;
5415 } Reply;
5416 #pragma pack()
5418 Reply *reply = (Reply *)ARG1;
5420 if (!reply->RetCode) {
5421 PRINT("got refs=%d", reply->refs);
5422 } else {
5423 PRINT("mig return %d", reply->RetCode);
5428 PRE(mach_port_mod_refs)
5430 #pragma pack(4)
5431 typedef struct {
5432 mach_msg_header_t Head;
5433 NDR_record_t NDR;
5434 mach_port_name_t name;
5435 mach_port_right_t right;
5436 mach_port_delta_t delta;
5437 } Request;
5438 #pragma pack()
5440 Request *req = (Request *)ARG1;
5442 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5443 name_for_port(MACH_REMOTE),
5444 name_for_port(req->name), req->right, req->delta);
5446 MACH_ARG(mach_port_mod_refs.port) = req->name;
5447 MACH_ARG(mach_port_mod_refs.right) = req->right;
5448 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
5450 AFTER = POST_FN(mach_port_mod_refs);
5452 // Must block to prevent race (other thread allocates and
5453 // notifies after we deallocate but before we notify)
5454 *flags &= ~SfMayBlock;
5457 POST(mach_port_mod_refs)
5459 #pragma pack(4)
5460 typedef struct {
5461 mach_msg_header_t Head;
5462 NDR_record_t NDR;
5463 kern_return_t RetCode;
5464 } Reply;
5465 #pragma pack()
5467 Reply *reply = (Reply *)ARG1;
5469 if (!reply->RetCode) {
5470 if (MACH_REMOTE == vg_task_port) {
5471 // Must have cleared SfMayBlock in PRE to prevent race
5472 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
5473 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
5474 MACH_ARG(mach_port_mod_refs.delta));
5475 } else {
5476 VG_(printf)("UNKNOWN remote port mod refs\n");
5478 } else {
5479 PRINT("mig return %d", reply->RetCode);
5484 PRE(mach_port_get_set_status)
5486 #pragma pack(4)
5487 typedef struct {
5488 mach_msg_header_t Head;
5489 NDR_record_t NDR;
5490 mach_port_name_t name;
5491 } Request;
5492 #pragma pack()
5494 Request *req = (Request *)ARG1;
5496 PRINT("mach_port_get_set_status(%s, %s)",
5497 name_for_port(MACH_REMOTE),
5498 name_for_port(req->name));
5500 AFTER = POST_FN(mach_port_get_set_status);
5503 POST(mach_port_get_set_status)
5505 #pragma pack(4)
5506 typedef struct {
5507 mach_msg_header_t Head;
5508 /* start of the kernel processed data */
5509 mach_msg_body_t msgh_body;
5510 mach_msg_ool_descriptor_t members;
5511 /* end of the kernel processed data */
5512 NDR_record_t NDR;
5513 mach_msg_type_number_t membersCnt;
5514 mach_msg_trailer_t trailer;
5515 } Reply;
5516 #pragma pack()
5518 // Reply *reply = (Reply *)ARG1;
5520 // GrP fixme nothing to do?
5524 PRE(mach_port_move_member)
5526 #pragma pack(4)
5527 typedef struct {
5528 mach_msg_header_t Head;
5529 NDR_record_t NDR;
5530 mach_port_name_t member;
5531 mach_port_name_t after;
5532 } Request;
5533 #pragma pack()
5535 Request *req = (Request *)ARG1;
5537 PRINT("mach_port_move_member(%s, %s, %s)",
5538 name_for_port(MACH_REMOTE),
5539 name_for_port(req->member),
5540 name_for_port(req->after));
5542 MACH_ARG(mach_port_move_member.member) = req->member;
5543 MACH_ARG(mach_port_move_member.after) = req->after;
5545 AFTER = POST_FN(mach_port_move_member);
5548 POST(mach_port_move_member)
5550 #pragma pack(4)
5551 typedef struct {
5552 mach_msg_header_t Head;
5553 NDR_record_t NDR;
5554 kern_return_t RetCode;
5555 mach_msg_trailer_t trailer;
5556 } Reply;
5557 #pragma pack()
5559 Reply *reply = (Reply *)ARG1;
5561 if (!reply->RetCode) {
5562 // fixme port set tracker?
5563 } else {
5564 PRINT("mig return %d", reply->RetCode);
5569 PRE(mach_port_destroy)
5571 #pragma pack(4)
5572 typedef struct {
5573 mach_msg_header_t Head;
5574 NDR_record_t NDR;
5575 mach_port_name_t name;
5576 } Request;
5577 #pragma pack()
5579 Request *req = (Request *)ARG1;
5581 PRINT("mach_port_destroy(%s, %s)",
5582 name_for_port(MACH_REMOTE),
5583 name_for_port(req->name));
5585 MACH_ARG(mach_port.port) = req->name;
5587 AFTER = POST_FN(mach_port_destroy);
5589 // Must block to prevent race (other thread allocates and
5590 // notifies after we deallocate but before we notify)
5591 *flags &= ~SfMayBlock;
5594 POST(mach_port_destroy)
5596 #pragma pack(4)
5597 typedef struct {
5598 mach_msg_header_t Head;
5599 NDR_record_t NDR;
5600 kern_return_t RetCode;
5601 } Reply;
5602 #pragma pack()
5604 Reply *reply = (Reply *)ARG1;
5606 if (!reply->RetCode) {
5607 if (MACH_REMOTE == vg_task_port) {
5608 // Must have cleared SfMayBlock in PRE to prevent race
5609 record_port_destroy(MACH_ARG(mach_port.port));
5610 } else {
5611 VG_(printf)("UNKNOWN remote port destroy\n");
5613 } else {
5614 PRINT("mig return %d", reply->RetCode);
5619 PRE(mach_port_request_notification)
5621 #pragma pack(4)
5622 typedef struct {
5623 mach_msg_header_t Head;
5624 /* start of the kernel processed data */
5625 mach_msg_body_t msgh_body;
5626 mach_msg_port_descriptor_t notify;
5627 /* end of the kernel processed data */
5628 NDR_record_t NDR;
5629 mach_port_name_t name;
5630 mach_msg_id_t msgid;
5631 mach_port_mscount_t sync;
5632 } Request;
5633 #pragma pack()
5635 Request *req = (Request *)ARG1;
5637 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5638 name_for_port(MACH_REMOTE),
5639 name_for_port(req->name), req->msgid, req->sync,
5640 req->notify.name, req->notify.disposition);
5642 AFTER = POST_FN(mach_port_request_notification);
5645 POST(mach_port_request_notification)
5647 // GrP fixme port tracker? not sure
5651 PRE(mach_port_insert_right)
5653 #pragma pack(4)
5654 typedef struct {
5655 mach_msg_header_t Head;
5656 /* start of the kernel processed data */
5657 mach_msg_body_t msgh_body;
5658 mach_msg_port_descriptor_t poly;
5659 /* end of the kernel processed data */
5660 NDR_record_t NDR;
5661 mach_port_name_t name;
5662 } Request;
5663 #pragma pack()
5665 Request *req = (Request *)ARG1;
5667 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5668 name_for_port(MACH_REMOTE),
5669 name_for_port(req->name), req->poly.name, req->poly.disposition);
5671 AFTER = POST_FN(mach_port_insert_right);
5673 if (MACH_REMOTE == mach_task_self()) {
5674 // GrP fixme import_complex_message handles everything?
5675 // what about export_complex_message for MOVE variants?
5676 } else {
5677 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5678 // GrP fixme also may remove rights from this task?
5681 // GrP fixme port tracker?
5684 POST(mach_port_insert_right)
5689 PRE(mach_port_extract_right)
5691 #pragma pack(4)
5692 typedef struct {
5693 mach_msg_header_t Head;
5694 NDR_record_t NDR;
5695 mach_port_name_t name;
5696 mach_msg_type_name_t msgt_name;
5697 } Request;
5698 #pragma pack()
5700 Request *req = (Request *)ARG1;
5702 PRINT("mach_port_extract_right(%s, %s, %d)",
5703 name_for_port(MACH_REMOTE),
5704 name_for_port(req->name), req->msgt_name);
5706 AFTER = POST_FN(mach_port_extract_right);
5708 // fixme port tracker?
5711 POST(mach_port_extract_right)
5713 // fixme import_complex_message handles the returned result, right?
5717 PRE(mach_port_get_attributes)
5719 #pragma pack(4)
5720 typedef struct {
5721 mach_msg_header_t Head;
5722 NDR_record_t NDR;
5723 mach_port_name_t name;
5724 mach_port_flavor_t flavor;
5725 mach_msg_type_number_t port_info_outCnt;
5726 } Request;
5727 #pragma pack()
5729 Request *req = (Request *)ARG1;
5731 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5732 name_for_port(MACH_REMOTE),
5733 name_for_port(req->name), req->flavor, req->port_info_outCnt);
5735 AFTER = POST_FN(mach_port_get_attributes);
5738 POST(mach_port_get_attributes)
5743 PRE(mach_port_set_attributes)
5745 #pragma pack(4)
5746 typedef struct {
5747 mach_msg_header_t Head;
5748 NDR_record_t NDR;
5749 mach_port_name_t name;
5750 mach_port_flavor_t flavor;
5751 mach_msg_type_number_t port_infoCnt;
5752 integer_t port_info[10];
5753 } Request;
5754 #pragma pack()
5756 Request *req = (Request *)ARG1;
5758 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5759 name_for_port(MACH_REMOTE),
5760 name_for_port(req->name), req->flavor, req->port_infoCnt);
5762 AFTER = POST_FN(mach_port_set_attributes);
5765 POST(mach_port_set_attributes)
5770 PRE(mach_port_insert_member)
5772 #pragma pack(4)
5773 typedef struct {
5774 mach_msg_header_t Head;
5775 NDR_record_t NDR;
5776 mach_port_name_t name;
5777 mach_port_name_t pset;
5778 } Request;
5779 #pragma pack()
5781 Request *req = (Request *)ARG1;
5783 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5784 name_for_port(MACH_REMOTE), req->name, req->pset);
5786 AFTER = POST_FN(mach_port_insert_member);
5788 // GrP fixme port tracker?
5791 POST(mach_port_insert_member)
5796 PRE(task_get_special_port)
5798 #pragma pack(4)
5799 typedef struct {
5800 mach_msg_header_t Head;
5801 NDR_record_t NDR;
5802 int which_port;
5803 } Request;
5804 #pragma pack()
5806 Request *req = (Request *)ARG1;
5808 switch (req->which_port) {
5809 case TASK_KERNEL_PORT:
5810 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5811 name_for_port(MACH_REMOTE));
5812 break;
5813 case TASK_HOST_PORT:
5814 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5815 name_for_port(MACH_REMOTE));
5816 break;
5817 case TASK_BOOTSTRAP_PORT:
5818 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5819 name_for_port(MACH_REMOTE));
5820 break;
5821 #if DARWIN_VERS < DARWIN_10_8
5822 /* These disappeared in 10.8 */
5823 case TASK_WIRED_LEDGER_PORT:
5824 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5825 name_for_port(MACH_REMOTE));
5826 break;
5827 case TASK_PAGED_LEDGER_PORT:
5828 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5829 name_for_port(MACH_REMOTE));
5830 break;
5831 #endif
5832 default:
5833 PRINT("task_get_special_port(%s, %d)",
5834 name_for_port(MACH_REMOTE), req->which_port);
5835 break;
5838 MACH_ARG(task_get_special_port.which_port) = req->which_port;
5840 AFTER = POST_FN(task_get_special_port);
5843 POST(task_get_special_port)
5845 #pragma pack(4)
5846 typedef struct {
5847 mach_msg_header_t Head;
5848 /* start of the kernel processed data */
5849 mach_msg_body_t msgh_body;
5850 mach_msg_port_descriptor_t special_port;
5851 /* end of the kernel processed data */
5852 } Reply;
5853 #pragma pack()
5855 Reply *reply = (Reply *)ARG1;
5857 PRINT("got port %#x ", reply->special_port.name);
5859 switch (MACH_ARG(task_get_special_port.which_port)) {
5860 case TASK_BOOTSTRAP_PORT:
5861 vg_bootstrap_port = reply->special_port.name;
5862 assign_port_name(reply->special_port.name, "bootstrap");
5863 break;
5864 case TASK_KERNEL_PORT:
5865 assign_port_name(reply->special_port.name, "kernel");
5866 break;
5867 case TASK_HOST_PORT:
5868 assign_port_name(reply->special_port.name, "host");
5869 break;
5870 #if DARWIN_VERS < DARWIN_10_8
5871 /* These disappeared in 10.8 */
5872 case TASK_WIRED_LEDGER_PORT:
5873 assign_port_name(reply->special_port.name, "wired-ledger");
5874 break;
5875 case TASK_PAGED_LEDGER_PORT:
5876 assign_port_name(reply->special_port.name, "paged-ledger");
5877 break;
5878 #endif
5879 default:
5880 assign_port_name(reply->special_port.name, "special-%p");
5881 break;
5884 PRINT("%s", name_for_port(reply->special_port.name));
5888 PRE(task_set_special_port)
5890 #pragma pack(4)
5891 typedef struct {
5892 mach_msg_header_t Head;
5893 /* start of the kernel processed data */
5894 mach_msg_body_t msgh_body;
5895 mach_msg_port_descriptor_t special_port;
5896 /* end of the kernel processed data */
5897 NDR_record_t NDR;
5898 int which_port;
5899 } Request;
5900 #pragma pack()
5902 Request *req = (Request *)ARG1;
5904 PRINT("got port %#x ", req->special_port.name);
5906 // MACH_ARG(task_set_special_port.which_port) = req->which_port;
5907 PRINT("%s", name_for_port(req->special_port.name));
5909 AFTER = POST_FN(task_set_special_port);
5912 POST(task_set_special_port)
5914 #pragma pack(4)
5915 typedef struct {
5916 mach_msg_header_t Head;
5917 NDR_record_t NDR;
5918 kern_return_t RetCode;
5919 } Reply;
5920 #pragma pack()
5922 Reply *reply = (Reply *)ARG1;
5923 if (!reply->RetCode) {
5924 } else {
5925 PRINT("mig return %d", reply->RetCode);
5930 PRE(semaphore_create)
5932 #pragma pack(4)
5933 typedef struct {
5934 mach_msg_header_t Head;
5935 NDR_record_t NDR;
5936 int policy;
5937 int value;
5938 } Request;
5939 #pragma pack()
5941 Request *req = (Request *)ARG1;
5943 PRINT("semaphore_create(%s, ..., %d, %d)",
5944 name_for_port(MACH_REMOTE), req->policy, req->value);
5946 AFTER = POST_FN(semaphore_create);
5949 POST(semaphore_create)
5951 #pragma pack(4)
5952 typedef struct {
5953 mach_msg_header_t Head;
5954 /* start of the kernel processed data */
5955 mach_msg_body_t msgh_body;
5956 mach_msg_port_descriptor_t semaphore;
5957 /* end of the kernel processed data */
5958 mach_msg_trailer_t trailer;
5959 } Reply;
5960 #pragma pack()
5962 Reply *reply = (Reply *)ARG1;
5964 assign_port_name(reply->semaphore.name, "semaphore-%p");
5965 PRINT("%s", name_for_port(reply->semaphore.name));
5969 PRE(semaphore_destroy)
5971 #pragma pack(4)
5972 typedef struct {
5973 mach_msg_header_t Head;
5974 /* start of the kernel processed data */
5975 mach_msg_body_t msgh_body;
5976 mach_msg_port_descriptor_t semaphore;
5977 /* end of the kernel processed data */
5978 mach_msg_trailer_t trailer;
5979 } Request;
5980 #pragma pack()
5982 Request *req = (Request *)ARG1;
5984 PRINT("semaphore_destroy(%s, %s)",
5985 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
5987 record_port_destroy(req->semaphore.name);
5989 AFTER = POST_FN(semaphore_destroy);
5992 POST(semaphore_destroy)
5994 #pragma pack(4)
5995 typedef struct {
5996 mach_msg_header_t Head;
5997 NDR_record_t NDR;
5998 kern_return_t RetCode;
5999 mach_msg_trailer_t trailer;
6000 } Reply;
6001 #pragma pack()
6003 Reply *reply = (Reply *)ARG1;
6004 if (!reply->RetCode) {
6005 } else {
6006 PRINT("mig return %d", reply->RetCode);
6010 PRE(task_policy_set)
6012 #pragma pack(4)
6013 typedef struct {
6014 mach_msg_header_t Head;
6015 NDR_record_t NDR;
6016 task_policy_flavor_t flavor;
6017 mach_msg_type_number_t policy_infoCnt;
6018 integer_t policy_info[16];
6019 } Request;
6020 #pragma pack()
6022 Request *req = (Request *)ARG1;
6024 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6026 AFTER = POST_FN(task_policy_set);
6029 POST(task_policy_set)
6031 #pragma pack(4)
6032 typedef struct {
6033 mach_msg_header_t Head;
6034 NDR_record_t NDR;
6035 kern_return_t RetCode;
6036 } Reply;
6037 #pragma pack()
6039 Reply *reply = (Reply *)ARG1;
6040 if (!reply->RetCode) {
6041 } else {
6042 PRINT("mig return %d", reply->RetCode);
6047 PRE(mach_ports_register)
6049 #pragma pack(4)
6050 typedef struct {
6051 mach_msg_header_t Head;
6052 /* start of the kernel processed data */
6053 mach_msg_body_t msgh_body;
6054 mach_msg_ool_ports_descriptor_t init_port_set;
6055 /* end of the kernel processed data */
6056 NDR_record_t NDR;
6057 mach_msg_type_number_t init_port_setCnt;
6058 } Request;
6059 #pragma pack()
6061 // Request *req = (Request *)ARG1;
6063 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE));
6065 AFTER = POST_FN(mach_ports_register);
6068 POST(mach_ports_register)
6070 #pragma pack(4)
6071 typedef struct {
6072 mach_msg_header_t Head;
6073 NDR_record_t NDR;
6074 kern_return_t RetCode;
6075 } Reply;
6076 #pragma pack()
6078 Reply *reply = (Reply *)ARG1;
6079 if (!reply->RetCode) {
6080 } else {
6081 PRINT("mig return %d", reply->RetCode);
6086 PRE(mach_ports_lookup)
6088 #pragma pack(4)
6089 typedef struct {
6090 mach_msg_header_t Head;
6091 } Request;
6092 #pragma pack()
6094 // Request *req = (Request *)ARG1;
6096 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
6098 AFTER = POST_FN(mach_ports_lookup);
6101 POST(mach_ports_lookup)
6103 #pragma pack(4)
6104 typedef struct {
6105 mach_msg_header_t Head;
6106 /* start of the kernel processed data */
6107 mach_msg_body_t msgh_body;
6108 mach_msg_ool_ports_descriptor_t init_port_set;
6109 /* end of the kernel processed data */
6110 NDR_record_t NDR;
6111 mach_msg_type_number_t init_port_setCnt;
6112 } Reply;
6113 #pragma pack()
6115 // Reply *reply = (Reply *)ARG1;
6119 PRE(task_info)
6121 #pragma pack(4)
6122 typedef struct {
6123 mach_msg_header_t Head;
6124 NDR_record_t NDR;
6125 task_flavor_t flavor;
6126 mach_msg_type_number_t task_info_outCnt;
6127 } Request;
6128 #pragma pack()
6130 Request *req = (Request *)ARG1;
6132 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6134 AFTER = POST_FN(task_info);
6137 POST(task_info)
6139 #pragma pack(4)
6140 typedef struct {
6141 mach_msg_header_t Head;
6142 NDR_record_t NDR;
6143 kern_return_t RetCode;
6144 mach_msg_type_number_t task_info_outCnt;
6145 integer_t task_info_out[52];
6146 } Reply;
6147 #pragma pack()
6149 Reply *reply = (Reply *)ARG1;
6150 if (!reply->RetCode) {
6151 } else {
6152 PRINT("mig return %d", reply->RetCode);
6157 PRE(task_set_info)
6159 #pragma pack(4)
6160 typedef struct {
6161 mach_msg_header_t Head;
6162 NDR_record_t NDR;
6163 task_flavor_t flavor;
6164 mach_msg_type_number_t task_info_inCnt;
6165 integer_t task_info_in[52];
6166 } Request;
6167 #pragma pack()
6169 Request *req = (Request *)ARG1;
6171 PRINT("task_set_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6173 AFTER = POST_FN(task_set_info);
6176 POST(task_set_info)
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);
6193 PRE(task_threads)
6195 #pragma pack(4)
6196 typedef struct {
6197 mach_msg_header_t Head;
6198 } Request;
6199 #pragma pack()
6201 // Request *req = (Request *)ARG1;
6203 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
6205 AFTER = POST_FN(task_threads);
6208 POST(task_threads)
6210 #pragma pack(4)
6211 typedef struct {
6212 mach_msg_header_t Head;
6213 /* start of the kernel processed data */
6214 mach_msg_body_t msgh_body;
6215 mach_msg_ool_ports_descriptor_t act_list;
6216 /* end of the kernel processed data */
6217 NDR_record_t NDR;
6218 mach_msg_type_number_t act_listCnt;
6219 mach_msg_trailer_t trailer;
6220 } Reply;
6221 #pragma pack()
6223 Reply *reply = (Reply *)ARG1;
6225 if (MACH_REMOTE == vg_task_port) {
6226 assign_port_names(&reply->act_list, "thread-%p");
6227 } else {
6228 assign_port_names(&reply->act_list, "remote-thread-%p");
6233 PRE(task_suspend)
6235 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
6237 if (MACH_REMOTE == vg_task_port) {
6238 // GrP fixme self-suspend
6239 vg_assert(0);
6240 } else {
6241 // suspend other - no problem
6244 AFTER = POST_FN(task_suspend);
6247 POST(task_suspend)
6252 PRE(task_resume)
6254 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
6256 if (MACH_REMOTE == vg_task_port) {
6257 // GrP fixme self-resume
6258 vg_assert(0);
6259 } else {
6260 // resume other - no problem
6263 AFTER = POST_FN(task_resume);
6266 POST(task_resume)
6271 PRE(vm_allocate)
6273 #pragma pack(4)
6274 typedef struct {
6275 mach_msg_header_t Head;
6276 NDR_record_t NDR;
6277 vm_address_t address;
6278 vm_size_t size;
6279 int flags;
6280 } Request;
6281 #pragma pack()
6283 Request *req = (Request *)ARG1;
6285 PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
6286 name_for_port(MACH_REMOTE),
6287 (ULong)req->address, (ULong)req->size, req->flags);
6289 MACH_ARG(vm_allocate.size) = req->size;
6290 MACH_ARG(vm_allocate.flags) = req->flags;
6292 AFTER = POST_FN(vm_allocate);
6295 POST(vm_allocate)
6297 #pragma pack(4)
6298 typedef struct {
6299 mach_msg_header_t Head;
6300 NDR_record_t NDR;
6301 kern_return_t RetCode;
6302 vm_address_t address;
6303 mach_msg_trailer_t trailer;
6304 } Reply;
6305 #pragma pack()
6307 Reply *reply = (Reply *)ARG1;
6309 if (!reply->RetCode) {
6310 if (MACH_REMOTE == vg_task_port) {
6311 PRINT("allocated at %#llx", (ULong)reply->address);
6312 // requesting 0 bytes returns address 0 with no error
6313 if (MACH_ARG(vm_allocate.size)) {
6314 ML_(notify_core_and_tool_of_mmap)(
6315 reply->address, MACH_ARG(vm_allocate.size),
6316 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6318 } else {
6319 PRINT("allocated at %#llx in remote task %s",
6320 (ULong)reply->address,
6321 name_for_port(MACH_REMOTE));
6323 } else {
6324 PRINT("mig return %d", reply->RetCode);
6329 PRE(vm_deallocate)
6331 #pragma pack(4)
6332 typedef struct {
6333 mach_msg_header_t Head;
6334 NDR_record_t NDR;
6335 vm_address_t address;
6336 vm_size_t size;
6337 } Request;
6338 #pragma pack()
6340 Request *req = (Request *)ARG1;
6342 PRINT("vm_deallocate(%s, at %#llx, size %lld)",
6343 name_for_port(MACH_REMOTE),
6344 (ULong)req->address, (ULong)req->size);
6346 MACH_ARG(vm_deallocate.address) = req->address;
6347 MACH_ARG(vm_deallocate.size) = req->size;
6349 AFTER = POST_FN(vm_deallocate);
6351 // Must block to prevent race (other thread allocates and
6352 // notifies after we deallocate but before we notify)
6353 *flags &= ~SfMayBlock;
6356 POST(vm_deallocate)
6358 #pragma pack(4)
6359 typedef struct {
6360 mach_msg_header_t Head;
6361 NDR_record_t NDR;
6362 kern_return_t RetCode;
6363 mach_msg_trailer_t trailer;
6364 } Reply;
6365 #pragma pack()
6367 Reply *reply = (Reply *)ARG1;
6369 if (!reply->RetCode) {
6370 if (MACH_REMOTE == vg_task_port) {
6371 if (MACH_ARG(vm_deallocate.size)) {
6372 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
6373 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
6374 MACH_ARG(vm_deallocate.size));
6375 // Must have cleared SfMayBlock in PRE to prevent race
6376 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6379 } else {
6380 PRINT("mig return %d", reply->RetCode);
6385 PRE(vm_protect)
6387 #pragma pack(4)
6388 typedef struct {
6389 mach_msg_header_t Head;
6390 NDR_record_t NDR;
6391 vm_address_t address;
6392 vm_size_t size;
6393 boolean_t set_maximum;
6394 vm_prot_t new_protection;
6395 } Request;
6396 #pragma pack()
6398 Request *req = (Request *)ARG1;
6400 PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
6401 name_for_port(MACH_REMOTE),
6402 (ULong)req->address, (ULong)req->size,
6403 req->set_maximum, req->new_protection);
6405 MACH_ARG(vm_protect.address) = req->address;
6406 MACH_ARG(vm_protect.size) = req->size;
6407 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
6408 MACH_ARG(vm_protect.new_protection) = req->new_protection;
6410 AFTER = POST_FN(vm_protect);
6413 POST(vm_protect)
6415 #pragma pack(4)
6416 typedef struct {
6417 mach_msg_header_t Head;
6418 NDR_record_t NDR;
6419 kern_return_t RetCode;
6420 mach_msg_trailer_t trailer;
6421 } Reply;
6422 #pragma pack()
6424 Reply *reply = (Reply *)ARG1;
6426 if (!reply->RetCode) {
6427 if (MACH_REMOTE == vg_task_port) {
6428 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
6429 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
6430 MACH_ARG(vm_protect.size));
6431 UInt prot = MACH_ARG(vm_protect.new_protection);
6432 if (MACH_ARG(vm_protect.set_maximum)) {
6433 // GrP fixme mprotect max
6434 VG_(printf)("UNKNOWN vm_protect set maximum");
6435 //VG_(mprotect_max_range)(start, end-start, prot);
6436 } else {
6437 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6438 VG_(di_notify_vm_protect)(start, end-start, prot);
6441 } else {
6442 PRINT("mig return %d", reply->RetCode);
6447 PRE(vm_inherit)
6449 #pragma pack(4)
6450 typedef struct {
6451 mach_msg_header_t Head;
6452 NDR_record_t NDR;
6453 vm_address_t address;
6454 vm_size_t size;
6455 vm_inherit_t new_inheritance;
6456 } Request;
6457 #pragma pack()
6459 Request *req = (Request *)ARG1;
6461 PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
6462 name_for_port(MACH_REMOTE),
6463 (ULong)req->address, (ULong)req->size,
6464 req->new_inheritance);
6466 AFTER = POST_FN(vm_inherit);
6469 POST(vm_inherit)
6471 #pragma pack(4)
6472 typedef struct {
6473 mach_msg_header_t Head;
6474 NDR_record_t NDR;
6475 kern_return_t RetCode;
6476 mach_msg_trailer_t trailer;
6477 } Reply;
6478 #pragma pack()
6480 Reply *reply = (Reply *)ARG1;
6482 if (!reply->RetCode) {
6483 if (MACH_REMOTE == vg_task_port) {
6484 // GrP fixme do something?
6486 } else {
6487 PRINT("mig return %d", reply->RetCode);
6492 PRE(vm_read)
6494 #pragma pack(4)
6495 typedef struct {
6496 mach_msg_header_t Head;
6497 NDR_record_t NDR;
6498 vm_address_t address;
6499 vm_size_t size;
6500 } Request;
6501 #pragma pack()
6503 Request *req = (Request *)ARG1;
6505 PRINT("vm_read(from %s at %#llx size %llu)",
6506 name_for_port(MACH_REMOTE),
6507 (ULong)req->address, (ULong)req->size);
6509 MACH_ARG(vm_read.addr) = req->address;
6510 MACH_ARG(vm_read.size) = req->size;
6512 AFTER = POST_FN(vm_read);
6515 POST(vm_read)
6517 #pragma pack(4)
6518 typedef struct {
6519 mach_msg_header_t Head;
6520 /* start of the kernel processed data */
6521 mach_msg_body_t msgh_body;
6522 mach_msg_ool_descriptor_t data;
6523 /* end of the kernel processed data */
6524 NDR_record_t NDR;
6525 mach_msg_type_number_t dataCnt;
6526 } Reply;
6527 #pragma pack()
6529 // Reply *reply = (Reply *)ARG1;
6531 if (MACH_REMOTE == vg_task_port) {
6532 // vm_read from self
6533 // GrP fixme copy initialized state
6539 PRE(mach_vm_read)
6541 #pragma pack(4)
6542 typedef struct {
6543 mach_msg_header_t Head;
6544 NDR_record_t NDR;
6545 mach_vm_address_t address;
6546 mach_vm_size_t size;
6547 } Request;
6548 #pragma pack()
6550 Request *req = (Request *)ARG1;
6552 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6553 name_for_port(MACH_REMOTE), req->address, req->size);
6555 MACH_ARG(mach_vm_read.addr) = req->address;
6556 MACH_ARG(mach_vm_read.size) = req->size;
6558 AFTER = POST_FN(mach_vm_read);
6561 POST(mach_vm_read)
6563 #pragma pack(4)
6564 typedef struct {
6565 mach_msg_header_t Head;
6566 /* start of the kernel processed data */
6567 mach_msg_body_t msgh_body;
6568 mach_msg_ool_descriptor_t data;
6569 /* end of the kernel processed data */
6570 NDR_record_t NDR;
6571 mach_msg_type_number_t dataCnt;
6572 } Reply;
6573 #pragma pack()
6575 // Reply *reply = (Reply *)ARG1;
6577 if (MACH_REMOTE == vg_task_port) {
6578 // vm_read from self
6579 // GrP fixme copy initialized state
6584 PRE(vm_read_overwrite)
6586 #pragma pack(4)
6587 typedef struct {
6588 mach_msg_header_t Head;
6589 NDR_record_t NDR;
6590 vm_address_t address;
6591 vm_size_t size;
6592 vm_address_t data;
6593 } Request;
6594 #pragma pack()
6596 Request *req = (Request *)ARG1;
6598 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6599 name_for_port(MACH_REMOTE),
6600 (ULong)req->address, (ULong)req->size, (ULong)req->data);
6602 MACH_ARG(vm_read_overwrite.addr) = req->address;
6603 MACH_ARG(vm_read_overwrite.size) = req->size;
6604 MACH_ARG(vm_read_overwrite.data) = req->data;
6606 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
6608 AFTER = POST_FN(vm_read_overwrite);
6611 POST(vm_read_overwrite)
6613 #pragma pack(4)
6614 typedef struct {
6615 mach_msg_header_t Head;
6616 NDR_record_t NDR;
6617 kern_return_t RetCode;
6618 vm_size_t outsize;
6619 } Reply;
6620 #pragma pack()
6622 Reply *reply = (Reply *)ARG1;
6624 if (reply->RetCode) {
6625 PRINT("mig return %d", reply->RetCode);
6626 } else {
6627 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
6628 if (MACH_REMOTE == vg_task_port) {
6629 // vm_read_overwrite from self
6630 // GrP fixme copy initialized state
6631 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6632 } else {
6633 // vm_read_overwrite from remote
6634 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6640 PRE(vm_copy)
6642 #pragma pack(4)
6643 typedef struct {
6644 mach_msg_header_t Head;
6645 NDR_record_t NDR;
6646 vm_address_t source_address;
6647 vm_size_t size;
6648 vm_address_t dest_address;
6649 } Request;
6650 #pragma pack()
6652 Request *req = (Request *)ARG1;
6654 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6655 name_for_port(MACH_REMOTE),
6656 (ULong)req->source_address,
6657 (ULong)req->size, (ULong)req->dest_address);
6659 MACH_ARG(vm_copy.src) = req->source_address;
6660 MACH_ARG(vm_copy.dst) = req->dest_address;
6661 MACH_ARG(vm_copy.size) = req->size;
6663 AFTER = POST_FN(vm_copy);
6666 POST(vm_copy)
6668 #pragma pack(4)
6669 typedef struct {
6670 mach_msg_header_t Head;
6671 NDR_record_t NDR;
6672 kern_return_t RetCode;
6673 mach_msg_trailer_t trailer;
6674 } Reply;
6675 #pragma pack()
6677 Reply *reply = (Reply *)ARG1;
6679 if (!reply->RetCode) {
6680 if (MACH_REMOTE == vg_task_port) {
6681 // GrP fixme set dst's initialization equal to src's
6682 // and wipe any symbols or translations in dst
6684 } else {
6685 PRINT("mig return %d", reply->RetCode);
6690 PRE(vm_map)
6692 #pragma pack(4)
6693 typedef struct {
6694 mach_msg_header_t Head;
6695 /* start of the kernel processed data */
6696 mach_msg_body_t msgh_body;
6697 mach_msg_port_descriptor_t object;
6698 /* end of the kernel processed data */
6699 NDR_record_t NDR;
6700 vm_address_t address;
6701 vm_size_t size;
6702 vm_address_t mask;
6703 int flags;
6704 vm_offset_t offset;
6705 boolean_t copy;
6706 vm_prot_t cur_protection;
6707 vm_prot_t max_protection;
6708 vm_inherit_t inheritance;
6709 } Request;
6710 #pragma pack()
6712 Request *req = (Request *)ARG1;
6714 // GrP fixme check these
6715 PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)",
6716 name_for_port(MACH_REMOTE),
6717 (ULong)req->address, (ULong)req->size,
6718 name_for_port(req->object.name));
6720 MACH_ARG(vm_map.size) = req->size;
6721 MACH_ARG(vm_map.copy) = req->copy;
6722 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
6724 AFTER = POST_FN(vm_map);
6727 POST(vm_map)
6729 #pragma pack(4)
6730 typedef struct {
6731 mach_msg_header_t Head;
6732 NDR_record_t NDR;
6733 kern_return_t RetCode;
6734 vm_address_t address;
6735 mach_msg_trailer_t trailer;
6736 } Reply;
6737 #pragma pack()
6739 Reply *reply = (Reply *)ARG1;
6741 if (!reply->RetCode) {
6742 // GrP fixme check src and dest tasks
6743 PRINT("mapped at %#llx", (ULong)reply->address);
6744 // GrP fixme max prot
6745 ML_(notify_core_and_tool_of_mmap)(
6746 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
6747 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
6748 // GrP fixme VKI_MAP_PRIVATE if !copy?
6749 } else {
6750 PRINT("mig return %d", reply->RetCode);
6755 PRE(vm_remap)
6757 #pragma pack(4)
6758 typedef struct {
6759 mach_msg_header_t Head;
6760 /* start of the kernel processed data */
6761 mach_msg_body_t msgh_body;
6762 mach_msg_port_descriptor_t src_task;
6763 /* end of the kernel processed data */
6764 NDR_record_t NDR;
6765 vm_address_t target_address;
6766 vm_size_t size;
6767 vm_address_t mask;
6768 boolean_t anywhere;
6769 vm_address_t src_address;
6770 boolean_t copy;
6771 vm_inherit_t inheritance;
6772 } Request;
6773 #pragma pack()
6775 Request *req = (Request *)ARG1;
6777 // GrP fixme check src and dest tasks
6779 if (VG_(clo_trace_syscalls)) {
6780 mach_port_name_t source_task = req->src_task.name;
6781 if (source_task == mach_task_self()) {
6782 PRINT("vm_remap(mach_task_self(), "
6783 "to %#llx size %lld, from mach_task_self() at %#llx, ...)",
6784 (ULong)req->target_address,
6785 (ULong)req->size, (ULong)req->src_address);
6786 } else {
6787 PRINT("vm_remap(mach_task_self(), "
6788 "to %#llx size %lld, from task %u at %#llx, ...)",
6789 (ULong)req->target_address, (ULong)req->size,
6790 source_task, (ULong)req->src_address);
6794 // arg1 is task
6795 // vt->syscall_arg2 = req->target_address;
6796 MACH_ARG(vm_remap.size) = req->size;
6797 // vt->syscall_arg4 = req->copy;
6799 AFTER = POST_FN(vm_remap);
6802 POST(vm_remap)
6804 #pragma pack(4)
6805 typedef struct {
6806 mach_msg_header_t Head;
6807 NDR_record_t NDR;
6808 kern_return_t RetCode;
6809 vm_address_t target_address;
6810 vm_prot_t cur_protection;
6811 vm_prot_t max_protection;
6812 mach_msg_trailer_t trailer;
6813 } Reply;
6814 #pragma pack()
6816 Reply *reply = (Reply *)ARG1;
6818 if (!reply->RetCode) {
6819 // GrP fixme check src and dest tasks
6820 UInt prot = reply->cur_protection & reply->max_protection;
6821 // GrP fixme max prot
6822 PRINT("mapped at %#llx", (ULong)reply->target_address);
6823 ML_(notify_core_and_tool_of_mmap)(
6824 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
6825 prot, VKI_MAP_SHARED, -1, 0);
6826 // GrP fixme VKI_MAP_FIXED if !copy?
6827 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6828 } else {
6829 PRINT("mig return %d", reply->RetCode);
6834 PRE(mach_make_memory_entry_64)
6836 #pragma pack(4)
6837 typedef struct {
6838 mach_msg_header_t Head;
6839 /* start of the kernel processed data */
6840 mach_msg_body_t msgh_body;
6841 mach_msg_port_descriptor_t parent_entry;
6842 /* end of the kernel processed data */
6843 NDR_record_t NDR;
6844 memory_object_size_t size;
6845 memory_object_offset_t offset;
6846 vm_prot_t permission;
6847 } Request;
6848 #pragma pack()
6850 Request *req = (Request *)ARG1;
6852 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6853 name_for_port(MACH_REMOTE),
6854 req->size, req->offset, req->permission, req->parent_entry.type);
6856 AFTER = POST_FN(mach_make_memory_entry_64);
6859 POST(mach_make_memory_entry_64)
6861 #pragma pack(4)
6862 typedef struct {
6863 mach_msg_header_t Head;
6864 mach_msg_body_t msgh_body;
6865 mach_msg_port_descriptor_t object;
6866 NDR_record_t NDR;
6867 memory_object_size_t size;
6868 } Reply;
6869 #pragma pack()
6871 Reply *reply = (Reply *)ARG1;
6873 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6874 assign_port_name(reply->object.name, "memory-%p");
6875 PRINT("%s", name_for_port(reply->object.name));
6880 PRE(vm_purgable_control)
6882 #pragma pack(4)
6883 typedef struct {
6884 mach_msg_header_t Head;
6885 NDR_record_t NDR;
6886 vm_address_t address;
6887 vm_purgable_t control;
6888 int state;
6889 } Request;
6890 #pragma pack()
6892 Request *req = (Request *)ARG1;
6894 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
6895 name_for_port(MACH_REMOTE),
6896 (ULong)req->address, req->control, req->state);
6898 // GrP fixme verify address?
6900 AFTER = POST_FN(vm_purgable_control);
6903 POST(vm_purgable_control)
6905 #pragma pack(4)
6906 typedef struct {
6907 mach_msg_header_t Head;
6908 NDR_record_t NDR;
6909 kern_return_t RetCode;
6910 int state;
6911 } Reply;
6912 #pragma pack()
6914 Reply *reply = (Reply *)ARG1;
6916 if (!reply->RetCode) {
6917 } else {
6918 PRINT("mig return %d", reply->RetCode);
6923 PRE(mach_vm_purgable_control)
6925 #pragma pack(4)
6926 typedef struct {
6927 mach_msg_header_t Head;
6928 NDR_record_t NDR;
6929 mach_vm_address_t address;
6930 vm_purgable_t control;
6931 int state;
6932 } Request;
6933 #pragma pack()
6935 Request *req = (Request *)ARG1;
6937 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
6938 name_for_port(MACH_REMOTE),
6939 (unsigned long long)req->address, req->control, req->state);
6941 // GrP fixme verify address?
6943 AFTER = POST_FN(mach_vm_purgable_control);
6946 POST(mach_vm_purgable_control)
6948 #pragma pack(4)
6949 typedef struct {
6950 mach_msg_header_t Head;
6951 NDR_record_t NDR;
6952 kern_return_t RetCode;
6953 int state;
6954 } Reply;
6955 #pragma pack()
6957 Reply *reply = (Reply *)ARG1;
6959 if (!reply->RetCode) {
6960 } else {
6961 PRINT("mig return %d", reply->RetCode);
6966 PRE(mach_vm_allocate)
6968 #pragma pack(4)
6969 typedef struct {
6970 mach_msg_header_t Head;
6971 NDR_record_t NDR;
6972 mach_vm_address_t address;
6973 mach_vm_size_t size;
6974 int flags;
6975 } Request;
6976 #pragma pack()
6978 Request *req = (Request *)ARG1;
6980 PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
6981 name_for_port(MACH_REMOTE),
6982 req->address, req->size, req->flags);
6984 MACH_ARG(mach_vm_allocate.size) = req->size;
6985 MACH_ARG(mach_vm_allocate.flags) = req->flags;
6987 AFTER = POST_FN(mach_vm_allocate);
6990 POST(mach_vm_allocate)
6992 #pragma pack(4)
6993 typedef struct {
6994 mach_msg_header_t Head;
6995 NDR_record_t NDR;
6996 kern_return_t RetCode;
6997 mach_vm_address_t address;
6998 mach_msg_trailer_t trailer;
6999 } Reply;
7000 #pragma pack()
7002 Reply *reply = (Reply *)ARG1;
7004 if (!reply->RetCode) {
7005 if (MACH_REMOTE == vg_task_port) {
7006 PRINT("allocated at 0x%llx", reply->address);
7007 // requesting 0 bytes returns address 0 with no error
7008 if (MACH_ARG(mach_vm_allocate.size)) {
7009 ML_(notify_core_and_tool_of_mmap)(
7010 reply->address, MACH_ARG(mach_vm_allocate.size),
7011 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
7013 } else {
7014 PRINT("allocated at 0x%llx in remote task %s", reply->address,
7015 name_for_port(MACH_REMOTE));
7017 } else {
7018 PRINT("mig return %d", reply->RetCode);
7023 PRE(mach_vm_deallocate)
7025 #pragma pack(4)
7026 typedef struct {
7027 mach_msg_header_t Head;
7028 NDR_record_t NDR;
7029 mach_vm_address_t address;
7030 mach_vm_size_t size;
7031 } Request;
7032 #pragma pack()
7034 Request *req = (Request *)ARG1;
7036 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
7037 name_for_port(MACH_REMOTE),
7038 req->address, req->size);
7040 MACH_ARG(mach_vm_deallocate.address) = req->address;
7041 MACH_ARG(mach_vm_deallocate.size) = req->size;
7043 AFTER = POST_FN(mach_vm_deallocate);
7045 // Must block to prevent race (other thread allocates and
7046 // notifies after we deallocate but before we notify)
7047 *flags &= ~SfMayBlock;
7050 POST(mach_vm_deallocate)
7052 #pragma pack(4)
7053 typedef struct {
7054 mach_msg_header_t Head;
7055 NDR_record_t NDR;
7056 kern_return_t RetCode;
7057 mach_msg_trailer_t trailer;
7058 } Reply;
7059 #pragma pack()
7061 Reply *reply = (Reply *)ARG1;
7063 if (!reply->RetCode) {
7064 if (MACH_REMOTE == vg_task_port) {
7065 if (MACH_ARG(mach_vm_deallocate.size)) {
7066 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
7067 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
7068 MACH_ARG(mach_vm_deallocate.size));
7069 // Must have cleared SfMayBlock in PRE to prevent race
7070 ML_(notify_core_and_tool_of_munmap)(start, end - start);
7073 } else {
7074 PRINT("mig return %d", reply->RetCode);
7079 PRE(mach_vm_protect)
7081 #pragma pack(4)
7082 typedef struct {
7083 mach_msg_header_t Head;
7084 NDR_record_t NDR;
7085 mach_vm_address_t address;
7086 mach_vm_size_t size;
7087 boolean_t set_maximum;
7088 vm_prot_t new_protection;
7089 } Request;
7090 #pragma pack()
7092 Request *req = (Request *)ARG1;
7094 PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
7095 name_for_port(MACH_REMOTE), req->address, req->size,
7096 req->set_maximum, req->new_protection);
7098 MACH_ARG(mach_vm_protect.address) = req->address;
7099 MACH_ARG(mach_vm_protect.size) = req->size;
7100 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
7101 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
7103 AFTER = POST_FN(mach_vm_protect);
7106 POST(mach_vm_protect)
7108 #pragma pack(4)
7109 typedef struct {
7110 mach_msg_header_t Head;
7111 NDR_record_t NDR;
7112 kern_return_t RetCode;
7113 mach_msg_trailer_t trailer;
7114 } Reply;
7115 #pragma pack()
7117 Reply *reply = (Reply *)ARG1;
7119 if (!reply->RetCode) {
7120 if (MACH_REMOTE == vg_task_port) {
7121 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
7122 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
7123 MACH_ARG(mach_vm_protect.size));
7124 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
7125 if (MACH_ARG(mach_vm_protect.set_maximum)) {
7126 // DDD: #warning GrP fixme mprotect max
7127 //VG_(mprotect_max_range)(start, end-start, prot);
7128 } else {
7129 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
7132 } else {
7133 PRINT("mig return %d", reply->RetCode);
7138 PRE(mach_vm_inherit)
7140 #pragma pack(4)
7141 typedef struct {
7142 mach_msg_header_t Head;
7143 NDR_record_t NDR;
7144 mach_vm_address_t address;
7145 mach_vm_size_t size;
7146 vm_inherit_t new_inheritance;
7147 } Request;
7148 #pragma pack()
7150 Request *req = (Request *)ARG1;
7152 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
7153 name_for_port(MACH_REMOTE),
7154 req->address, req->size, req->new_inheritance);
7156 AFTER = POST_FN(mach_vm_inherit);
7159 POST(mach_vm_inherit)
7161 #pragma pack(4)
7162 typedef struct {
7163 mach_msg_header_t Head;
7164 NDR_record_t NDR;
7165 kern_return_t RetCode;
7166 mach_msg_trailer_t trailer;
7167 } Reply;
7168 #pragma pack()
7170 Reply *reply = (Reply *)ARG1;
7172 if (!reply->RetCode) {
7173 // no V-visible side effects
7174 // GrP fixme except maybe fork/exec
7175 } else {
7176 PRINT("mig return %d", reply->RetCode);
7181 PRE(mach_vm_copy)
7183 #pragma pack(4)
7184 typedef struct {
7185 mach_msg_header_t Head;
7186 NDR_record_t NDR;
7187 mach_vm_address_t source_address;
7188 mach_vm_size_t size;
7189 mach_vm_address_t dest_address;
7190 } Request;
7191 #pragma pack()
7193 Request *req = (Request *)ARG1;
7195 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
7196 name_for_port(MACH_REMOTE),
7197 req->source_address, req->size, req->dest_address);
7199 // arg1 is task
7200 // vt->syscall_arg2 = req->source_address;
7201 // vt->syscall_arg3 = req->size;
7202 // vt->syscall_arg4 = req->dest_address;
7204 AFTER = POST_FN(mach_vm_copy);
7207 POST(mach_vm_copy)
7209 #pragma pack(4)
7210 typedef struct {
7211 mach_msg_header_t Head;
7212 NDR_record_t NDR;
7213 kern_return_t RetCode;
7214 mach_msg_trailer_t trailer;
7215 } Reply;
7216 #pragma pack()
7218 Reply *reply = (Reply *)ARG1;
7220 if (!reply->RetCode) {
7221 if (MACH_REMOTE == vg_task_port) {
7222 // GrP fixme set dest's initialization equal to src's
7223 // BUT vm_copy allocates no memory
7225 } else {
7226 PRINT("mig return %d", reply->RetCode);
7230 PRE(mach_vm_read_overwrite)
7232 #pragma pack(4)
7233 typedef struct {
7234 mach_msg_header_t Head;
7235 NDR_record_t NDR;
7236 mach_vm_address_t address;
7237 mach_vm_size_t size;
7238 mach_vm_address_t data;
7239 } Request;
7240 #pragma pack()
7242 Request *req = (Request *)ARG1;
7244 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
7245 name_for_port(MACH_REMOTE),
7246 req->address, req->size, req->data);
7248 AFTER = POST_FN(mach_vm_read_overwrite);
7251 POST(mach_vm_read_overwrite)
7253 #pragma pack(4)
7254 typedef struct {
7255 mach_msg_header_t Head;
7256 NDR_record_t NDR;
7257 kern_return_t RetCode;
7258 mach_vm_size_t outsize;
7259 } Reply;
7260 #pragma pack()
7262 Reply *reply = (Reply *)ARG1;
7264 if (!reply->RetCode) {
7265 if (MACH_REMOTE == vg_task_port) {
7266 // GrP fixme set dest's initialization equal to src's
7267 // BUT vm_copy allocates no memory
7269 } else {
7270 PRINT("mig return %d", reply->RetCode);
7274 PRE(mach_vm_map)
7276 #pragma pack(4)
7277 typedef struct {
7278 mach_msg_header_t Head;
7279 /* start of the kernel processed data */
7280 mach_msg_body_t msgh_body;
7281 mach_msg_port_descriptor_t object;
7282 /* end of the kernel processed data */
7283 NDR_record_t NDR;
7284 mach_vm_address_t address;
7285 mach_vm_size_t size;
7286 mach_vm_address_t mask;
7287 int flags;
7288 memory_object_offset_t offset;
7289 boolean_t copy;
7290 vm_prot_t cur_protection;
7291 vm_prot_t max_protection;
7292 vm_inherit_t inheritance;
7293 } Request;
7294 #pragma pack()
7296 Request *req = (Request *)ARG1;
7298 // GrP fixme check these
7299 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7300 name_for_port(req->Head.msgh_remote_port),
7301 name_for_port(req->object.name),
7302 req->address, req->size,
7303 req->cur_protection,
7304 req->max_protection);
7306 MACH_ARG(mach_vm_map.size) = req->size;
7307 MACH_ARG(mach_vm_map.copy) = req->copy;
7308 MACH_ARG(mach_vm_map.protection) =
7309 (req->cur_protection & req->max_protection);
7311 AFTER = POST_FN(mach_vm_map);
7314 POST(mach_vm_map)
7316 #pragma pack(4)
7317 typedef struct {
7318 mach_msg_header_t Head;
7319 NDR_record_t NDR;
7320 kern_return_t RetCode;
7321 mach_vm_address_t address;
7322 mach_msg_trailer_t trailer;
7323 } Reply;
7324 #pragma pack()
7326 Reply *reply = (Reply *)ARG1;
7328 if (!reply->RetCode) {
7329 // GrP fixme check src and dest tasks
7330 PRINT("mapped at 0x%llx", reply->address);
7331 # if 0
7332 // GrP fixme max prot
7333 ML_(notify_core_and_tool_of_mmap)(
7334 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
7335 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
7336 // GrP fixme VKI_MAP_PRIVATE if !copy?
7337 # else
7338 ML_(sync_mappings)("after", "mach_vm_map", 0);
7339 # endif
7340 } else {
7341 PRINT("mig return %d", reply->RetCode);
7346 PRE(mach_vm_remap)
7348 #pragma pack(4)
7349 typedef struct {
7350 mach_msg_header_t Head;
7351 /* start of the kernel processed data */
7352 mach_msg_body_t msgh_body;
7353 mach_msg_port_descriptor_t src_task;
7354 /* end of the kernel processed data */
7355 NDR_record_t NDR;
7356 mach_vm_address_t target_address;
7357 mach_vm_size_t size;
7358 mach_vm_offset_t mask;
7359 int flags;
7360 mach_vm_address_t src_address;
7361 boolean_t copy;
7362 vm_inherit_t inheritance;
7363 } Request;
7364 #pragma pack()
7366 Request *req = (Request *)ARG1;
7368 // GrP fixme check these
7369 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7370 name_for_port(MACH_REMOTE),
7371 req->target_address, req->size,
7372 name_for_port(req->src_task.name));
7374 MACH_ARG(mach_vm_remap.size) = req->size;
7375 MACH_ARG(mach_vm_remap.copy) = req->copy;
7377 AFTER = POST_FN(mach_vm_remap);
7380 POST(mach_vm_remap)
7382 #pragma pack(4)
7383 typedef struct {
7384 mach_msg_header_t Head;
7385 NDR_record_t NDR;
7386 kern_return_t RetCode;
7387 mach_vm_address_t target_address;
7388 vm_prot_t cur_protection;
7389 vm_prot_t max_protection;
7390 } Reply;
7391 #pragma pack()
7393 Reply *reply = (Reply *)ARG1;
7395 if (!reply->RetCode) {
7396 // GrP fixme check src and dest tasks
7397 PRINT("mapped at 0x%llx", reply->target_address);
7398 // GrP fixme max prot
7399 ML_(notify_core_and_tool_of_mmap)(
7400 reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
7401 reply->cur_protection, VKI_MAP_SHARED, -1, 0);
7402 // GrP fixme VKI_MAP_PRIVATE if !copy?
7403 } else {
7404 PRINT("mig return %d", reply->RetCode);
7409 PRE(mach_vm_region_recurse)
7411 #pragma pack(4)
7412 typedef struct {
7413 mach_msg_header_t Head;
7414 NDR_record_t NDR;
7415 mach_vm_address_t address;
7416 natural_t nesting_depth;
7417 mach_msg_type_number_t infoCnt;
7418 } Request;
7419 #pragma pack()
7421 Request *req = (Request *)ARG1;
7423 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7424 name_for_port(MACH_REMOTE),
7425 req->address, req->nesting_depth, req->infoCnt);
7427 AFTER = POST_FN(mach_vm_region_recurse);
7430 POST(mach_vm_region_recurse)
7432 #pragma pack(4)
7433 typedef struct {
7434 mach_msg_header_t Head;
7435 NDR_record_t NDR;
7436 kern_return_t RetCode;
7437 mach_vm_address_t address;
7438 mach_vm_size_t size;
7439 natural_t nesting_depth;
7440 mach_msg_type_number_t infoCnt;
7441 int info[19];
7442 } Reply;
7443 #pragma pack()
7445 Reply *reply = (Reply *)ARG1;
7447 if (!reply->RetCode) {
7448 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7449 reply->address, reply->size,
7450 reply->nesting_depth, reply->infoCnt);
7451 // GrP fixme mark info contents beyond infoCnt as bogus
7452 } else {
7453 PRINT("mig return %d", reply->RetCode);
7458 /* ---------------------------------------------------------------------
7459 mach_msg: messages to thread
7460 ------------------------------------------------------------------ */
7464 POST(thread_terminate)
7469 PRE(thread_terminate)
7471 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7472 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
7474 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
7476 AFTER = POST_FN(thread_terminate);
7478 if (self_terminate) {
7479 // Terminating this thread.
7480 // Copied from sys_exit.
7481 ThreadState *tst = VG_(get_ThreadState)(tid);
7482 tst->exitreason = VgSrc_ExitThread;
7483 tst->os_state.exitcode = 0; // GrP fixme anything better?
7484 // What we would like to do is:
7485 // SET_STATUS_Success(0);
7486 // but that doesn't work, because this is a MACH-class syscall,
7487 // and SET_STATUS_Success creates a UNIX-class syscall result.
7488 // Hence we have to laboriously construct the full SysRes "by hand"
7489 // and use that to set the syscall return status.
7490 #if defined(VGA_x86)
7491 SET_STATUS_from_SysRes(
7492 VG_(mk_SysRes_x86_darwin)(
7493 VG_DARWIN_SYSCALL_CLASS_MACH,
7494 False/*success*/, 0, 0
7497 #elif defined(VGA_amd64)
7498 SET_STATUS_from_SysRes(
7499 VG_(mk_SysRes_amd64_darwin)(
7500 VG_DARWIN_SYSCALL_CLASS_MACH,
7501 False/*success*/, 0, 0
7504 #else
7505 #error unknown architecture
7506 #endif
7507 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
7508 } else {
7509 // Terminating some other thread.
7510 // Do keep the scheduler lock while terminating any other thread.
7511 // Otherwise we might halt the other thread while it holds the lock,
7512 // which would deadlock the process.
7513 // GrP fixme good enough?
7514 // GrP fixme need to clean up other thread's valgrind data?
7519 POST(thread_create)
7524 PRE(thread_create)
7526 PRINT("thread_create(mach_task_self(), ...)");
7528 AFTER = POST_FN(thread_create);
7530 // GrP fixme
7531 VG_(core_panic)("thread_create() unimplemented");
7535 PRE(thread_create_running)
7537 #pragma pack(4)
7538 typedef struct {
7539 mach_msg_header_t Head;
7540 NDR_record_t NDR;
7541 thread_state_flavor_t flavor;
7542 mach_msg_type_number_t new_stateCnt;
7543 natural_t new_state[144];
7544 } Request;
7545 #pragma pack()
7547 Request *req;
7548 thread_state_t regs;
7549 ThreadState *new_thread;
7551 PRINT("thread_create_running(mach_task_self(), ...)");
7553 // The new thread will immediately begin execution,
7554 // so we need to hijack the register state here.
7556 req = (Request *)ARG1;
7557 regs = (thread_state_t)req->new_state;
7559 // Build virtual thread.
7560 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
7562 // Edit the thread state to send to the real kernel.
7563 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
7565 AFTER = POST_FN(thread_create_running);
7569 POST(thread_create_running)
7571 #pragma pack(4)
7572 typedef struct {
7573 mach_msg_header_t Head;
7574 /* start of the kernel processed data */
7575 mach_msg_body_t msgh_body;
7576 mach_msg_port_descriptor_t child_act;
7577 /* end of the kernel processed data */
7578 } Reply;
7579 #pragma pack()
7581 Reply *reply = (Reply *)ARG1;
7583 assign_port_name(reply->child_act.name, "thread-%p");
7584 PRINT("%s", name_for_port(reply->child_act.name));
7588 PRE(bsdthread_create)
7590 ThreadState *tst;
7592 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7593 ARG1, ARG2, ARG3, ARG4, ARG5);
7594 PRE_REG_READ5(pthread_t,"bsdthread_create",
7595 void *,"func", void *,"func_arg", void *,"stack",
7596 pthread_t,"thread", unsigned int,"flags");
7598 // The kernel will call V's pthread_hijack() to launch the thread.
7599 // Here we allocate the thread state and pass it to pthread_hijack()
7600 // via the func_arg parameter.
7602 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
7603 allocstack(tst->tid);
7605 tst->os_state.func_arg = (Addr)ARG2;
7606 ARG2 = (Word)tst;
7608 // Create a semaphore that pthread_hijack will signal once it starts
7609 // POST(bsdthread_create) needs to wait for the new memory map to appear
7610 semaphore_create(mach_task_self(), &tst->os_state.child_go,
7611 SYNC_POLICY_FIFO, 0);
7612 semaphore_create(mach_task_self(), &tst->os_state.child_done,
7613 SYNC_POLICY_FIFO, 0);
7616 POST(bsdthread_create)
7618 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7619 // We hold V's lock on the child's behalf.
7620 // If we return before letting pthread_hijack do its thing, V thinks
7621 // the new pthread struct is still unmapped when we return to libc,
7622 // causing false errors.
7624 ThreadState *tst = (ThreadState *)ARG2;
7625 semaphore_signal(tst->os_state.child_go);
7626 semaphore_wait(tst->os_state.child_done);
7627 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
7628 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
7630 // GrP fixme semaphore destroy needed when thread creation fails
7631 // GrP fixme probably other cleanup too
7632 // GrP fixme spinlocks might be good enough?
7634 // DDD: I'm not at all sure this is the right spot for this. It probably
7635 // should be in pthread_hijack instead, just before the call to
7636 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7637 // parent tid value there...
7638 vg_assert(VG_(owns_BigLock_LL)(tid));
7639 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
7643 PRE(bsdthread_terminate)
7645 ThreadState *tst;
7647 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7648 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
7649 PRE_REG_READ4(int,"bsdthread_terminate",
7650 void *,"freeaddr", size_t,"freesize",
7651 mach_port_t,"kport", mach_port_t,"joinsem");
7653 // Free memory and signal semaphore.
7654 // GrP fixme errors?
7655 if (ARG4) semaphore_signal((semaphore_t)ARG4);
7656 if (ARG1 && ARG2) {
7657 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
7658 # if DARWIN_VERS >= DARWIN_10_8
7659 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7660 the mig output. Work around it for the time being. */
7661 VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
7662 # else
7663 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
7664 # endif
7667 // Tell V to terminate the thread.
7668 // Copied from sys_exit.
7669 tst = VG_(get_ThreadState)(tid);
7670 tst->exitreason = VgSrc_ExitThread;
7671 tst->os_state.exitcode = 0; // GrP fixme anything better?
7672 SET_STATUS_Success(0);
7676 POST(thread_suspend)
7680 PRE(thread_suspend)
7682 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7683 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
7685 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
7687 AFTER = POST_FN(thread_suspend);
7689 if (self_suspend) {
7690 // Don't keep the scheduler lock while self-suspending.
7691 // Otherwise we might halt while still holding the lock,
7692 // which would deadlock the process.
7693 *flags |= SfMayBlock;
7694 } else {
7695 // Do keep the scheduler lock while suspending any other thread.
7696 // Otherwise we might halt the other thread while it holds the lock,
7697 // which would deadlock the process.
7698 *flags &= ~SfMayBlock;
7703 POST(thread_resume)
7707 PRE(thread_resume)
7709 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7710 Bool self_resume = (mh->msgh_request_port == MACH_THREAD);
7712 PRINT("thread_resume(%s)", name_for_port(mh->msgh_request_port));
7714 AFTER = POST_FN(thread_resume);
7716 if (self_resume) {
7717 // This doesn't make much sense. If we are resuming ourself, we can't
7718 // already be running. So I don't see how we can ever get here.
7719 vg_assert(0);
7720 } else {
7721 // Resuming some other thread. It might not yet come back to life
7722 // (if the suspend count is still above zero) so make sure we keep
7723 // holding the lock.
7724 *flags &= ~SfMayBlock;
7729 POST(thread_get_state)
7731 #pragma pack(4)
7732 typedef struct {
7733 mach_msg_header_t Head;
7734 NDR_record_t NDR;
7735 kern_return_t RetCode;
7736 mach_msg_type_number_t old_stateCnt;
7737 natural_t old_state[144];
7738 mach_msg_trailer_t trailer;
7739 } Reply;
7740 #pragma pack()
7742 Reply *reply = (Reply *)ARG1;
7743 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7744 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
7746 if (!reply->RetCode) {
7747 thread_state_from_vex((thread_state_t)reply->old_state,
7748 flavor, reply->old_stateCnt,
7749 &VG_(get_ThreadState)(tid)->arch.vex);
7750 } else {
7751 PRINT("mig return %d", reply->RetCode);
7755 PRE(thread_get_state)
7757 #pragma pack(4)
7758 typedef struct {
7759 mach_msg_header_t Head;
7760 NDR_record_t NDR;
7761 thread_state_flavor_t flavor;
7762 mach_msg_type_number_t old_stateCnt;
7763 } Request;
7764 #pragma pack()
7766 Request *req = (Request *)ARG1;
7767 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7769 // GrP fixme if (self) {
7770 PRINT("thread_get_state(%s, %d)",
7771 name_for_port(req->Head.msgh_request_port), req->flavor);
7772 /*} else {
7773 PRINT("thread_get_state(0x%x, %d)",
7774 req->Head.msgh_request_port, req->flavor);
7777 // Hack the thread state after making the real call.
7778 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
7779 MACH_ARG(thread_get_state.flavor) = req->flavor;
7781 AFTER = POST_FN(thread_get_state);
7785 PRE(thread_policy)
7787 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7788 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7790 // GrP fixme if (self) {
7791 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
7792 /*} else {
7793 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7796 AFTER = POST_FN(thread_policy);
7799 POST(thread_policy)
7804 PRE(thread_policy_set)
7806 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7808 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
7810 AFTER = POST_FN(thread_policy_set);
7813 POST(thread_policy_set)
7818 PRE(thread_info)
7820 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7822 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
7823 // GrP fixme does any thread info need to be hijacked?
7825 AFTER = POST_FN(thread_info);
7828 POST(thread_info)
7830 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7835 /* ---------------------------------------------------------------------
7836 mach_msg: messages to bootstrap port
7837 ------------------------------------------------------------------ */
7840 POST(bootstrap_register)
7842 #pragma pack(4)
7843 typedef struct {
7844 mach_msg_header_t Head;
7845 NDR_record_t NDR;
7846 kern_return_t RetCode;
7847 mach_msg_trailer_t trailer;
7848 } Reply;
7849 #pragma pack()
7851 Reply *reply = (Reply *)ARG1;
7853 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
7856 PRE(bootstrap_register)
7858 #pragma pack(4)
7859 typedef struct {
7860 mach_msg_header_t Head;
7861 /* start of the kernel processed data */
7862 mach_msg_body_t msgh_body;
7863 mach_msg_port_descriptor_t service_port;
7864 /* end of the kernel processed data */
7865 NDR_record_t NDR;
7866 name_t service_name;
7867 } Request;
7868 #pragma pack()
7870 Request *req = (Request *)ARG1;
7872 PRINT("bootstrap_register(port 0x%x, \"%s\")",
7873 req->service_port.name, req->service_name);
7875 /* The required entry in the allocated_ports list (mapping) might
7876 not exist, due perhaps to broken syscall wrappers (mach__N etc).
7877 Create a minimal entry so that assign_port_name below doesn't
7878 cause an assertion. */
7879 if (!port_exists(req->service_port.name)) {
7880 port_create_vanilla(req->service_port.name);
7883 assign_port_name(req->service_port.name, req->service_name);
7885 AFTER = POST_FN(bootstrap_register);
7889 POST(bootstrap_look_up)
7891 #pragma pack(4)
7892 typedef struct {
7893 mach_msg_header_t Head;
7894 /* start of the kernel processed data */
7895 mach_msg_body_t msgh_body;
7896 mach_msg_port_descriptor_t service_port;
7897 /* end of the kernel processed data */
7898 mach_msg_trailer_t trailer;
7899 } Reply;
7900 #pragma pack()
7902 Reply *reply = (Reply *)ARG1;
7904 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
7905 reply->service_port.name)
7907 assign_port_name(reply->service_port.name,
7908 MACH_ARG(bootstrap_look_up.service_name));
7909 PRINT("%s", name_for_port(reply->service_port.name));
7910 } else {
7911 PRINT("not found");
7913 VG_(free)(MACH_ARG(bootstrap_look_up.service_name));
7916 PRE(bootstrap_look_up)
7918 #pragma pack(4)
7919 typedef struct {
7920 mach_msg_header_t Head;
7921 NDR_record_t NDR;
7922 name_t service_name;
7923 } Request;
7924 #pragma pack()
7926 Request *req = (Request *)ARG1;
7928 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
7930 MACH_ARG(bootstrap_look_up.service_name) =
7931 VG_(strdup)("syswrap-darwin.bootstrap-name", req->service_name);
7933 AFTER = POST_FN(bootstrap_look_up);
7937 /* ---------------------------------------------------------------------
7938 mach_msg: receiver-specific handlers
7939 ------------------------------------------------------------------ */
7942 POST(mach_msg_receive)
7944 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7946 // GrP fixme don't know of anything interesting here currently
7947 // import_complex_message handles everything
7948 // PRINT("UNHANDLED reply %d", mh->msgh_id);
7950 // Assume the call may have mapped or unmapped memory
7951 ML_(sync_mappings)("after", "mach_msg_receive", mh->msgh_id);
7954 PRE(mach_msg_receive)
7956 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7958 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
7960 AFTER = POST_FN(mach_msg_receive);
7962 // no message sent, only listening for a reply
7963 // assume message may block
7964 *flags |= SfMayBlock;
7968 PRE(mach_msg_bootstrap)
7970 // message to bootstrap port
7972 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7974 switch (mh->msgh_id) {
7975 case 403:
7976 CALL_PRE(bootstrap_register);
7977 return;
7978 case 404:
7979 CALL_PRE(bootstrap_look_up);
7980 return;
7982 default:
7983 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
7984 mh->msgh_id, name_for_port(mh->msgh_request_port),
7985 mh->msgh_reply_port);
7986 return;
7991 PRE(mach_msg_host)
7993 // message to host self - check for host-level kernel calls
7995 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7997 switch (mh->msgh_id) {
7998 case 200:
7999 CALL_PRE(host_info);
8000 return;
8001 case 202:
8002 CALL_PRE(host_page_size);
8003 return;
8004 case 205:
8005 CALL_PRE(host_get_io_master);
8006 return;
8007 case 206:
8008 CALL_PRE(host_get_clock_service);
8009 return;
8010 case 217:
8011 CALL_PRE(host_request_notification);
8012 return;
8013 case 222:
8014 CALL_PRE(host_create_mach_voucher);
8015 return;
8017 case 412:
8018 CALL_PRE(host_get_special_port);
8019 return;
8021 default:
8022 // unknown message to host self
8023 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
8024 mh->msgh_id, name_for_port(mh->msgh_request_port),
8025 mh->msgh_reply_port);
8026 return;
8030 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
8031 // /usr/include/mach/mach_port.h et al (grep in /usr/include
8032 // for them)
8033 PRE(mach_msg_task)
8035 // message to a task port
8037 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8039 switch (mh->msgh_id) {
8040 case 3201:
8041 CALL_PRE(mach_port_type);
8042 return;
8043 case 3204:
8044 CALL_PRE(mach_port_allocate);
8045 return;
8046 case 3205:
8047 CALL_PRE(mach_port_destroy);
8048 return;
8049 case 3206:
8050 CALL_PRE(mach_port_deallocate);
8051 return;
8052 case 3207:
8053 CALL_PRE(mach_port_get_refs);
8054 return;
8055 case 3208:
8056 CALL_PRE(mach_port_mod_refs);
8057 return;
8058 case 3211:
8059 CALL_PRE(mach_port_get_set_status);
8060 return;
8061 case 3212:
8062 CALL_PRE(mach_port_move_member);
8063 return;
8064 case 3213:
8065 CALL_PRE(mach_port_request_notification);
8066 return;
8067 case 3214:
8068 CALL_PRE(mach_port_insert_right);
8069 return;
8070 case 3215:
8071 CALL_PRE(mach_port_extract_right);
8072 return;
8073 case 3217:
8074 CALL_PRE(mach_port_get_attributes);
8075 return;
8076 case 3218:
8077 CALL_PRE(mach_port_set_attributes);
8078 return;
8079 case 3226:
8080 CALL_PRE(mach_port_insert_member);
8081 return;
8082 case 3227:
8083 CALL_PRE(mach_port_extract_member);
8084 return;
8086 case 3229:
8087 CALL_PRE(mach_port_set_context);
8088 return;
8090 case 3402:
8091 CALL_PRE(task_threads);
8092 return;
8093 case 3403:
8094 CALL_PRE(mach_ports_register);
8095 return;
8096 case 3404:
8097 CALL_PRE(mach_ports_lookup);
8098 return;
8099 case 3405:
8100 CALL_PRE(task_info);
8101 return;
8102 case 3406:
8103 CALL_PRE(task_set_info);
8104 return;
8105 case 3407:
8106 CALL_PRE(task_suspend);
8107 return;
8108 case 3408:
8109 CALL_PRE(task_resume);
8110 return;
8111 case 3409:
8112 CALL_PRE(task_get_special_port);
8113 return;
8114 case 3410:
8115 CALL_PRE(task_set_special_port);
8116 return;
8117 case 3411:
8118 CALL_PRE(thread_create);
8119 return;
8120 case 3412:
8121 CALL_PRE(thread_create_running);
8122 return;
8124 case 3414:
8125 CALL_PRE(task_get_exception_ports);
8126 return;
8128 case 3418:
8129 CALL_PRE(semaphore_create);
8130 return;
8131 case 3419:
8132 CALL_PRE(semaphore_destroy);
8133 return;
8134 case 3420:
8135 CALL_PRE(task_policy_set);
8136 return;
8138 case 3801:
8139 CALL_PRE(vm_allocate);
8140 return;
8141 case 3802:
8142 CALL_PRE(vm_deallocate);
8143 return;
8144 case 3803:
8145 CALL_PRE(vm_protect);
8146 return;
8147 case 3804:
8148 CALL_PRE(vm_inherit);
8149 return;
8150 case 3805:
8151 CALL_PRE(vm_read);
8152 return;
8153 case 3808:
8154 CALL_PRE(vm_copy);
8155 return;
8156 case 3809:
8157 CALL_PRE(vm_read_overwrite);
8158 return;
8159 case 3812:
8160 CALL_PRE(vm_map);
8161 return;
8162 case 3814:
8163 CALL_PRE(vm_remap);
8164 return;
8165 case 3825:
8166 CALL_PRE(mach_make_memory_entry_64);
8167 return;
8168 case 3830:
8169 CALL_PRE(vm_purgable_control);
8170 return;
8172 case 4800:
8173 CALL_PRE(mach_vm_allocate);
8174 return;
8175 case 4801:
8176 CALL_PRE(mach_vm_deallocate);
8177 return;
8178 case 4802:
8179 CALL_PRE(mach_vm_protect);
8180 return;
8181 case 4803:
8182 CALL_PRE(mach_vm_inherit);
8183 return;
8184 case 4804:
8185 CALL_PRE(mach_vm_read);
8186 return;
8187 case 4807:
8188 CALL_PRE(mach_vm_copy);
8189 return;
8190 case 4808:
8191 CALL_PRE(mach_vm_read_overwrite);
8192 return;
8193 case 4811:
8194 CALL_PRE(mach_vm_map);
8195 return;
8196 case 4813:
8197 CALL_PRE(mach_vm_remap);
8198 return;
8199 case 4815:
8200 CALL_PRE(mach_vm_region_recurse);
8201 return;
8202 case 4817:
8203 CALL_PRE(mach_make_memory_entry_64);
8204 return;
8205 case 4818:
8206 CALL_PRE(mach_vm_purgable_control);
8207 return;
8209 default:
8210 // unknown message to task self
8211 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
8212 mh->msgh_id, name_for_port(mh->msgh_remote_port),
8213 mh->msgh_reply_port);
8214 return;
8219 PRE(mach_msg_thread)
8221 // message to local thread - check for thread-level kernel calls
8223 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8225 switch (mh->msgh_id) {
8226 case 3600:
8227 CALL_PRE(thread_terminate);
8228 return;
8229 case 3603:
8230 CALL_PRE(thread_get_state);
8231 return;
8232 case 3605:
8233 CALL_PRE(thread_suspend);
8234 return;
8235 case 3606:
8236 CALL_PRE(thread_resume);
8237 return;
8238 case 3612:
8239 CALL_PRE(thread_info);
8240 return;
8241 case 3616:
8242 CALL_PRE(thread_policy);
8243 return;
8244 case 3617:
8245 CALL_PRE(thread_policy_set);
8246 return;
8247 default:
8248 // unknown message to a thread
8249 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
8250 mh->msgh_id, name_for_port(mh->msgh_request_port),
8251 mh->msgh_reply_port);
8252 return;
8257 static int is_thread_port(mach_port_t port)
8259 if (port == 0) return False;
8261 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
8265 static int is_task_port(mach_port_t port)
8267 if (port == 0) return False;
8269 if (port == vg_task_port) return True;
8271 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
8275 /* ---------------------------------------------------------------------
8276 mach_msg: base handlers
8277 ------------------------------------------------------------------ */
8279 PRE(mach_msg)
8281 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8282 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8283 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8284 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
8285 // mach_port_t rcv_name = (mach_port_t)ARG5;
8286 size_t complex_header_size = 0;
8288 PRE_REG_READ7(long, "mach_msg",
8289 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
8290 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
8291 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
8292 mach_port_t,"notify");
8294 // Assume default POST handler until specified otherwise
8295 AFTER = NULL;
8297 // Assume call may block unless specified otherwise
8298 *flags |= SfMayBlock;
8300 if (option & MACH_SEND_MSG) {
8301 // Validate outgoing message header
8302 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8303 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
8304 // msgh_size not required, use parameter instead
8305 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8306 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
8307 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8308 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
8309 // msgh_reserved not required
8310 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8311 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
8313 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8314 // Validate typed message data and handle memory map changes.
8315 complex_header_size = export_complex_message(tid, mh);
8318 // GrP fixme handle sender-specified message trailer
8319 // (but is this only for too-secure processes?)
8320 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8321 # if DARWIN_VERS >= DARWIN_10_10
8322 if (mh->msgh_bits & MACH_SEND_TRAILER) {
8323 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8325 # else
8326 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
8327 # endif
8329 MACH_REMOTE = mh->msgh_remote_port;
8330 MACH_MSGH_ID = mh->msgh_id;
8333 if (option & MACH_RCV_MSG) {
8334 // Pre-validate receive buffer
8335 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
8338 // Call a PRE handler. The PRE handler may set an AFTER handler.
8340 if (!(option & MACH_SEND_MSG)) {
8341 // no message sent, receive only
8342 CALL_PRE(mach_msg_receive);
8343 return;
8345 else if (mh->msgh_request_port == vg_host_port) {
8346 // message sent to mach_host_self()
8347 CALL_PRE(mach_msg_host);
8348 return;
8350 else if (is_task_port(mh->msgh_request_port)) {
8351 // message sent to a task
8352 CALL_PRE(mach_msg_task);
8353 return;
8355 else if (mh->msgh_request_port == vg_bootstrap_port) {
8356 // message sent to bootstrap port
8357 CALL_PRE(mach_msg_bootstrap);
8358 return;
8360 else if (is_thread_port(mh->msgh_request_port)) {
8361 // message sent to one of this process's threads
8362 CALL_PRE(mach_msg_thread);
8363 return;
8365 else {
8366 // this is an attempt to optimize mapping sync
8367 // but there are always some cases hard to find
8368 #if 0
8369 Bool do_mapping_update = False;
8370 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8371 // which is obviously not true...
8372 switch (mh->msgh_id) {
8373 // com.apple.windowserver.active
8374 case 29008: // this one opens a port type 'a'
8376 // com.apple.windowserver.active 'a' port
8377 case 29000:
8378 case 29822:
8379 case 29820: // adds a vm mapping
8380 case 29809: // contains a ool mem
8381 case 29800: // opens a port type 'b'
8382 case 29873:
8383 case 29876: // adds a vm mapping
8385 // com.apple.windowserver.active 'b' port
8386 case 29624:
8387 case 29625:
8388 case 29506:
8389 case 29504:
8390 case 29509:
8391 case 29315:
8392 case 29236:
8393 case 29473:
8394 case 29268:
8395 case 29237: // contains a ool mem
8396 case 29360:
8397 case 29301:
8398 case 29287:
8399 case 29568:
8400 case 29570: // contains a ool mem
8401 case 29211:
8402 case 29569: // contains a ool mem
8403 case 29374:
8404 case 29246:
8405 case 29239:
8406 case 29272:
8407 if (mh->msgh_id == 29820 ||
8408 mh->msgh_id == 29876)
8409 do_mapping_update = True;
8411 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8412 mh->msgh_id, name_for_port(mh->msgh_request_port),
8413 mh->msgh_reply_port);
8414 break;
8416 // com.apple.FontServer
8417 case 13024:
8418 PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
8419 mh->msgh_id, name_for_port(mh->msgh_request_port),
8420 mh->msgh_reply_port);
8421 break;
8423 // com.apple.system.notification_center
8424 case 78945698:
8425 case 78945701:
8426 case 78945695: // contains a ool mem
8427 case 78945694:
8428 case 78945700:
8429 if (mh->msgh_id == 78945695)
8430 do_mapping_update = False;
8431 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8432 mh->msgh_id, name_for_port(mh->msgh_request_port),
8433 mh->msgh_reply_port);
8434 break;
8436 // com.apple.CoreServices.coreservicesd
8437 case 10000:
8438 case 10019:
8439 case 10002: // adds vm mappings
8440 case 10003: // adds vm mappings
8441 case 14007:
8442 case 13000:
8443 case 13001:
8444 case 13011:
8445 case 13016: // contains a ool mem
8446 if (mh->msgh_id == 10002||
8447 mh->msgh_id == 10003)
8448 do_mapping_update = True;
8449 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8450 mh->msgh_id, name_for_port(mh->msgh_request_port),
8451 mh->msgh_reply_port);
8452 break;
8454 // com.apple.system.logger
8455 case 118:
8456 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8457 mh->msgh_id, name_for_port(mh->msgh_request_port),
8458 mh->msgh_reply_port);
8459 break;
8461 // com.apple.coreservices.launchservicesd, and others
8462 case 1999646836: // might adds vm mapping
8463 if (mh->msgh_id == 1999646836)
8464 do_mapping_update = True;
8465 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8466 mh->msgh_id, name_for_port(mh->msgh_request_port),
8467 mh->msgh_reply_port);
8468 break;
8470 // com.apple.ocspd
8471 case 33012:
8472 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8473 mh->msgh_id, name_for_port(mh->msgh_request_port),
8474 mh->msgh_reply_port);
8476 default:
8477 // arbitrary message to arbitrary port
8478 do_mapping_update = True;
8479 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
8480 mh->msgh_id, name_for_port(mh->msgh_request_port),
8481 mh->msgh_reply_port);
8484 // this is an optimization, don't check mapping on known mach_msg
8485 if (do_mapping_update)
8486 AFTER = POST_FN(mach_msg_unhandled);
8487 else
8488 AFTER = POST_FN(mach_msg_unhandled_check);
8489 #else
8490 AFTER = POST_FN(mach_msg_unhandled);
8491 #endif
8493 // Assume the entire message body may be read.
8494 // GrP fixme generates false positives for unknown protocols
8496 PRE_MEM_READ("mach_msg(payload)",
8497 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8498 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8500 return;
8504 POST(mach_msg)
8506 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8507 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8509 if (option & MACH_RCV_MSG) {
8510 if (RES != 0) {
8511 // error during send or receive
8512 // GrP fixme need to clean up port rights?
8513 } else {
8514 mach_msg_trailer_t *mt =
8515 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
8517 // Assume the entire received message and trailer is initialized
8518 // GrP fixme would being more specific catch any bugs?
8519 POST_MEM_WRITE((Addr)mh,
8520 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
8522 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8523 // Update memory map for out-of-line message data
8524 import_complex_message(tid, mh);
8529 // Call handler chosen by PRE(mach_msg)
8530 if (AFTER) {
8531 (*AFTER)(tid, arrghs, status);
8536 POST(mach_msg_unhandled)
8538 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8539 ML_(sync_mappings)("after", "mach_msg_receive-UNHANDLED", mh->msgh_id);
8542 POST(mach_msg_unhandled_check)
8544 if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
8545 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
8549 /* ---------------------------------------------------------------------
8550 other Mach traps
8551 ------------------------------------------------------------------ */
8553 PRE(mach_reply_port)
8555 PRINT("mach_reply_port()");
8558 POST(mach_reply_port)
8560 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
8561 PRINT("reply port %s", name_for_port(RES));
8565 PRE(mach_thread_self)
8567 PRINT("mach_thread_self()");
8570 POST(mach_thread_self)
8572 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
8573 PRINT("thread %#lx", RES);
8577 PRE(mach_host_self)
8579 PRINT("mach_host_self()");
8582 POST(mach_host_self)
8584 vg_host_port = RES;
8585 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
8586 PRINT("host %#lx", RES);
8590 PRE(mach_task_self)
8592 PRINT("mach_task_self()");
8595 POST(mach_task_self)
8597 vg_task_port = RES;
8598 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
8599 PRINT("task %#lx", RES);
8603 PRE(syscall_thread_switch)
8605 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8606 name_for_port(ARG1), ARG2, ARG3);
8607 PRE_REG_READ3(long, "syscall_thread_switch",
8608 mach_port_t,"thread", int,"option", natural_t,"timeout");
8610 *flags |= SfMayBlock;
8614 PRE(semaphore_signal)
8616 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
8617 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8621 PRE(semaphore_signal_all)
8623 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
8624 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
8628 PRE(semaphore_signal_thread)
8630 PRINT("semaphore_signal_thread(%s, %s)",
8631 name_for_port(ARG1), name_for_port(ARG2));
8632 PRE_REG_READ2(long, "semaphore_signal_thread",
8633 semaphore_t,"semaphore", mach_port_t,"thread");
8637 PRE(semaphore_wait)
8639 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
8640 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8642 *flags |= SfMayBlock;
8646 PRE(semaphore_wait_signal)
8648 PRINT("semaphore_wait_signal(%s, %s)",
8649 name_for_port(ARG1), name_for_port(ARG2));
8650 PRE_REG_READ2(long, "semaphore_wait_signal",
8651 semaphore_t,"wait_semaphore",
8652 semaphore_t,"signal_semaphore");
8654 *flags |= SfMayBlock;
8658 PRE(semaphore_timedwait)
8660 PRINT("semaphore_timedwait(%s, %g seconds)",
8661 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
8662 PRE_REG_READ3(long, "semaphore_wait_signal",
8663 semaphore_t,"semaphore",
8664 int,"wait_time_hi",
8665 int,"wait_time_lo");
8667 *flags |= SfMayBlock;
8671 PRE(semaphore_timedwait_signal)
8673 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8674 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
8675 PRE_REG_READ4(long, "semaphore_wait_signal",
8676 semaphore_t,"wait_semaphore",
8677 semaphore_t,"signal_semaphore",
8678 int,"wait_time_hi",
8679 int,"wait_time_lo");
8681 *flags |= SfMayBlock;
8685 PRE(__semwait_signal)
8687 /* 10.5 args: int cond_sem, int mutex_sem,
8688 int timeout, int relative,
8689 time_t tv_sec, time_t tv_nsec */
8690 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8691 name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
8692 PRE_REG_READ6(long, "__semwait_signal",
8693 int,"cond_sem", int,"mutex_sem",
8694 int,"timeout", int,"relative",
8695 vki_time_t,"tv_sec", int,"tv_nsec");
8697 *flags |= SfMayBlock;
8699 // GrP provided this alternative version for 10.6, but NjN
8700 // reckons the 10.5 is is still correct for 10.6. So, retaining
8701 // Greg's version as a comment just in case we need it later.
8702 //PRE(__semwait_signal)
8704 // /* 10.5 args: int cond_sem, int mutex_sem,
8705 // int timeout, int relative,
8706 // const timespec *ts */
8707 // PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8708 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8709 // PRE_REG_READ5(int, "__semwait_signal",
8710 // int,cond_sem, int,mutex_sem,
8711 // int,timeout, int,relative,
8712 // const struct vki_timespec *,ts);
8714 // if (ARG5) PRE_MEM_READ ("__semwait_signal(ts)",
8715 // ARG5, sizeof(struct vki_timespec));
8717 // *flags |= SfMayBlock;
8721 PRE(__thread_selfid)
8723 PRINT("__thread_selfid ()");
8724 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
8727 PRE(task_for_pid)
8729 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
8730 PRE_REG_READ3(long, "task_for_pid",
8731 mach_port_t,"target",
8732 vki_pid_t, "pid", mach_port_t *,"task");
8733 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
8736 POST(task_for_pid)
8738 mach_port_t task;
8740 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
8742 task = *(mach_port_t *)ARG3;
8743 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
8744 PRINT("task 0x%x", task);
8748 PRE(pid_for_task)
8750 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
8751 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
8752 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
8755 POST(pid_for_task)
8757 vki_pid_t pid;
8759 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
8761 pid = *(vki_pid_t *)ARG2;
8762 PRINT("pid %u", pid);
8766 PRE(mach_timebase_info)
8768 PRINT("mach_timebase_info(%#lx)", ARG1);
8769 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8770 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
8773 POST(mach_timebase_info)
8775 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
8779 PRE(mach_wait_until)
8781 #if VG_WORDSIZE == 8
8782 PRINT("mach_wait_until(%lu)", ARG1);
8783 PRE_REG_READ1(long, "mach_wait_until",
8784 unsigned long long,"deadline");
8785 #else
8786 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
8787 PRE_REG_READ2(long, "mach_wait_until",
8788 int,"deadline_hi", int,"deadline_lo");
8789 #endif
8790 *flags |= SfMayBlock;
8794 PRE(mk_timer_create)
8796 PRINT("mk_timer_create()");
8797 PRE_REG_READ0(long, "mk_timer_create");
8800 POST(mk_timer_create)
8802 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
8806 PRE(mk_timer_destroy)
8808 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
8809 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
8811 // Must block to prevent race (other thread allocates and
8812 // notifies after we deallocate but before we notify)
8813 *flags &= ~SfMayBlock;
8816 POST(mk_timer_destroy)
8818 // Must have cleared SfMayBlock in PRE to prevent race
8819 record_port_destroy(ARG1);
8823 PRE(mk_timer_arm)
8825 #if VG_WORDSIZE == 8
8826 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
8827 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
8828 unsigned long,"expire_time");
8829 #else
8830 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
8831 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
8832 int,"expire_time_hi", int,"expire_time_lo");
8833 #endif
8837 PRE(mk_timer_cancel)
8839 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
8840 PRE_REG_READ2(long, "mk_timer_cancel",
8841 mach_port_t,"name", Addr,"result_time");
8842 if (ARG2) {
8843 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
8847 POST(mk_timer_cancel)
8849 if (ARG2) {
8850 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
8855 PRE(iokit_user_client_trap)
8857 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
8858 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
8859 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
8860 mach_port_t,connect, unsigned int,index,
8861 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
8862 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
8864 // can't do anything else with this in general
8865 // might be able to use connect+index to choose something sometimes
8868 POST(iokit_user_client_trap)
8870 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
8874 PRE(swtch)
8876 PRINT("swtch ( )");
8877 PRE_REG_READ0(long, "swtch");
8879 *flags |= SfMayBlock;
8883 PRE(swtch_pri)
8885 PRINT("swtch_pri ( %ld )", ARG1);
8886 PRE_REG_READ1(long, "swtch_pri", int,"pri");
8888 *flags |= SfMayBlock;
8892 PRE(FAKE_SIGRETURN)
8894 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
8895 an explanation of what follows. */
8896 /* This handles the fake signal-return system call created by
8897 sigframe-x86-darwin.c. */
8898 /* See also comments just below on PRE(sigreturn). */
8900 PRINT("FAKE_SIGRETURN ( )");
8902 vg_assert(VG_(is_valid_tid)(tid));
8903 vg_assert(tid >= 1 && tid < VG_N_THREADS);
8904 vg_assert(VG_(is_running_thread)(tid));
8906 /* Remove the signal frame from this thread's (guest) stack,
8907 in the process restoring the pre-signal guest state. */
8908 VG_(sigframe_destroy)(tid, True);
8910 /* Tell the driver not to update the guest state with the "result",
8911 and set a bogus result to keep it happy. */
8912 *flags |= SfNoWriteResult;
8913 SET_STATUS_Success(0);
8915 /* Check to see if any signals arose as a result of this. */
8916 *flags |= SfPollAfter;
8920 PRE(sigreturn)
8922 /* This is the "real" sigreturn. But because we construct all the
8923 signal frames ourselves (of course, in m_sigframe), this cannot
8924 happen as a result of normal signal delivery. I think it
8925 happens only when doing siglongjmp, in which case Darwin's Libc
8926 appears to use it for two different purposes: to mess with the
8927 per-thread sigaltstack flags (as per arg 2), or to restore the
8928 thread's state from a ucontext* (as per arg 1). */
8930 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
8932 vg_assert(VG_(is_valid_tid)(tid));
8933 vg_assert(tid >= 1 && tid < VG_N_THREADS);
8934 vg_assert(VG_(is_running_thread)(tid));
8936 if (ARG2 == VKI_UC_SET_ALT_STACK) {
8937 /* This is confusing .. the darwin kernel sources imply there is
8938 a per-thread on-altstack/not-on-altstack flag, which is set
8939 by this flag. Just ignore it and claim success for the time
8940 being. */
8941 VG_(debugLog)(0, "syswrap-darwin",
8942 "WARNING: Ignoring sigreturn( ..., "
8943 "UC_SET_ALT_STACK );\n");
8944 SET_STATUS_Success(0);
8945 return;
8947 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
8948 /* Ditto */
8949 VG_(debugLog)(0, "syswrap-darwin",
8950 "WARNING: Ignoring sigreturn( ..., "
8951 "UC_RESET_ALT_STACK );\n");
8952 SET_STATUS_Success(0);
8953 return;
8956 /* Otherwise claim this isn't supported. (Could be
8957 catastrophic).
8959 What do we have to do if we do need to support it?
8961 1. Change the second argument of VG_(sigframe_destroy) from
8962 "Bool isRT" to "UInt sysno", so we can pass the syscall
8963 number, so it can distinguish this case from the
8964 __NR_DARWIN_FAKE_SIGRETURN case.
8966 2. In VG_(sigframe_destroy), look at sysno to distinguish the
8967 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
8968 For this case, restore the thread's CPU state (or at least
8969 the integer regs) from the ucontext in ARG1 (and do all the
8970 other "signal-returns" stuff too).
8972 3. For (2), how do we know where the ucontext is? One way is to
8973 temporarily copy ARG1 into this thread's guest_EBX (or any
8974 other int reg), and have VG_(sigframe_destroy) read
8975 guest_EBX. Why is it ok to trash guest_EBX (or any other int
8976 reg)? Because VG_(sigframe_destroy) is just about to
8977 overwrite all the regs anyway -- since the primary purpose of
8978 calling it is to restore the register state from the ucontext
8979 pointed to by ARG1.
8981 Hey, it's uggerly. But at least it's documented.
8983 /* But in the meantime ... */
8984 VG_(debugLog)(0, "syswrap-darwin",
8985 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
8986 VG_(debugLog)(0, "syswrap-darwin",
8987 "WARNING: Thread/program/Valgrind "
8988 "will likely segfault now.\n");
8989 VG_(debugLog)(0, "syswrap-darwin",
8990 "WARNING: Please file a bug report at "
8991 "http://www.valgrind.org.\n");
8992 SET_STATUS_Failure( VKI_ENOSYS );
8996 /* ---------------------------------------------------------------------
8997 machine-dependent traps
8998 ------------------------------------------------------------------ */
9000 #if defined(VGA_x86)
9001 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
9003 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
9004 return VG_(calloc)("syswrap-darwin.ldt", nbytes, 1);
9006 #endif
9008 PRE(thread_fast_set_cthread_self)
9010 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
9011 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
9013 #if defined(VGA_x86)
9014 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
9016 VexGuestX86SegDescr *ldt;
9017 ThreadState *tst = VG_(get_ThreadState)(tid);
9018 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
9019 if (!ldt) {
9020 ldt = alloc_zeroed_x86_LDT();
9021 tst->arch.vex.guest_LDT = (HWord)ldt;
9023 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
9024 ldt[6].LdtEnt.Bits.LimitLow = 1;
9025 ldt[6].LdtEnt.Bits.LimitHi = 0;
9026 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
9027 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
9028 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
9029 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
9030 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
9031 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
9032 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
9033 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
9035 tst->os_state.pthread = ARG1;
9036 tst->arch.vex.guest_GS = 0x37;
9038 // What we would like to do is:
9039 // SET_STATUS_Success(0x37);
9040 // but that doesn't work, because this is a MDEP-class syscall,
9041 // and SET_STATUS_Success creates a UNIX-class syscall result.
9042 // Hence we have to laboriously construct the full SysRes "by hand"
9043 // and use that to set the syscall return status.
9044 SET_STATUS_from_SysRes(
9045 VG_(mk_SysRes_x86_darwin)(
9046 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9047 False, 0, 0x37
9052 #elif defined(VGA_amd64)
9053 // GrP fixme bigger hack than x86
9055 ThreadState *tst = VG_(get_ThreadState)(tid);
9056 tst->os_state.pthread = ARG1;
9057 tst->arch.vex.guest_GS_CONST = ARG1;
9058 // SET_STATUS_Success(0x60);
9059 // see comments on x86 case just above
9060 SET_STATUS_from_SysRes(
9061 VG_(mk_SysRes_amd64_darwin)(
9062 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9063 False, 0, 0x60
9068 #else
9069 #error unknown architecture
9070 #endif
9074 /* ---------------------------------------------------------------------
9075 Added for OSX 10.7 (Lion)
9076 ------------------------------------------------------------------ */
9078 #if DARWIN_VERS >= DARWIN_10_7
9080 PRE(getaudit_addr)
9082 PRINT("getaudit_addr(%#lx, %lu)", ARG1, ARG2);
9083 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
9084 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
9086 POST(getaudit_addr)
9088 POST_MEM_WRITE(ARG1, ARG2);
9091 PRE(psynch_mutexwait)
9093 PRINT("psynch_mutexwait(BOGUS)");
9094 *flags |= SfMayBlock;
9096 POST(psynch_mutexwait)
9100 PRE(psynch_mutexdrop)
9102 PRINT("psynch_mutexdrop(BOGUS)");
9103 *flags |= SfMayBlock;
9105 POST(psynch_mutexdrop)
9109 PRE(psynch_cvbroad)
9111 PRINT("psynch_cvbroad(BOGUS)");
9113 POST(psynch_cvbroad)
9117 PRE(psynch_cvsignal)
9119 PRINT("psynch_cvsignal(BOGUS)");
9121 POST(psynch_cvsignal)
9125 PRE(psynch_cvwait)
9127 PRINT("psynch_cvwait(BOGUS)");
9128 *flags |= SfMayBlock;
9130 POST(psynch_cvwait)
9134 PRE(psynch_rw_rdlock)
9136 PRINT("psynch_rw_rdlock(BOGUS)");
9137 *flags |= SfMayBlock;
9139 POST(psynch_rw_rdlock)
9143 PRE(psynch_rw_wrlock)
9145 PRINT("psynch_rw_wrlock(BOGUS)");
9146 *flags |= SfMayBlock;
9148 POST(psynch_rw_wrlock)
9152 PRE(psynch_rw_unlock)
9154 PRINT("psynch_rw_unlock(BOGUS)");
9156 POST(psynch_rw_unlock)
9160 PRE(psynch_cvclrprepost)
9162 PRINT("psynch_cvclrprepost(BOGUS)");
9163 *flags |= SfMayBlock;
9165 POST(psynch_cvclrprepost)
9169 #endif /* DARWIN_VERS >= DARWIN_10_7 */
9172 /* ---------------------------------------------------------------------
9173 Added for OSX 10.8 (Mountain Lion)
9174 ------------------------------------------------------------------ */
9176 /* About munge tags, eg munge_wllww.
9178 Means the syscall takes 5 args. For a 64 bit process each arg
9179 occupies one 64-bit value and so the mapping to ARGn macros is
9180 direct. For a 32 bit process, this is more complex: 'w' denotes a
9181 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
9182 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
9183 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
9184 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
9185 in order to get sane values for the arguments in 32-bit
9186 processes. */
9188 static void munge_wwl(UWord* a1, UWord* a2, ULong* a3,
9189 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4)
9191 # if defined(VGA_x86)
9192 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4);
9193 # else
9194 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9195 # endif
9198 static void munge_wll(UWord* a1, ULong* a2, ULong* a3,
9199 UWord aRG1, UWord aRG2, UWord aRG3,
9200 UWord aRG4, UWord aRG5)
9202 # if defined(VGA_x86)
9203 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9204 # else
9205 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9206 # endif
9209 static void munge_wwlw(UWord* a1, UWord* a2, ULong* a3, UWord* a4,
9210 UWord aRG1, UWord aRG2, UWord aRG3,
9211 UWord aRG4, UWord aRG5)
9213 # if defined(VGA_x86)
9214 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4); *a4 = aRG5;
9215 # else
9216 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9217 # endif
9220 static void munge_wwwl(UWord* a1, UWord* a2, UWord* a3, ULong* a4,
9221 UWord aRG1, UWord aRG2, UWord aRG3,
9222 UWord aRG4, UWord aRG5)
9224 # if defined(VGA_x86)
9225 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = LOHI64(aRG4,aRG5);
9226 # else
9227 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9228 # endif
9231 static void munge_wllww(UWord* a1, ULong* a2, ULong* a3, UWord* a4, UWord* a5,
9232 UWord aRG1, UWord aRG2, UWord aRG3,
9233 UWord aRG4, UWord aRG5, UWord aRG6, UWord aRG7)
9235 # if defined(VGA_x86)
9236 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9237 *a4 = aRG6; *a5 = aRG7;
9238 # else
9239 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5;
9240 # endif
9243 static void munge_wwllww(UWord* a1, UWord* a2, ULong* a3,
9244 ULong* a4, UWord* a5, UWord* a6,
9245 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4,
9246 UWord aRG5, UWord aRG6, UWord aRG7, UWord aRG8)
9248 # if defined(VGA_x86)
9249 *a1 = aRG1; *a2 = aRG2;
9250 *a3 = LOHI64(aRG3,aRG4); *a4 = LOHI64(aRG5,aRG6);
9251 *a5 = aRG7; *a6 = aRG8;
9252 # else
9253 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5; *a6 = aRG6;
9254 # endif
9257 #if DARWIN_VERS >= DARWIN_10_8
9259 PRE(kernelrpc_mach_vm_allocate_trap)
9261 UWord a1; UWord a2; ULong a3; UWord a4;
9262 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9263 PRINT("kernelrpc_mach_vm_allocate_trap"
9264 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
9265 name_for_port(a1), *(void**)a2, a3, a4);
9266 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
9267 a2, sizeof(void*));
9269 POST(kernelrpc_mach_vm_allocate_trap)
9271 UWord a1; UWord a2; ULong a3; UWord a4;
9272 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9273 PRINT("address:%p size:%#llx", *(void**)a2, a3);
9274 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9275 POST_MEM_WRITE(a2, sizeof(void*));
9277 if (a1 == mach_task_self()) {
9278 # if 1
9279 ML_(sync_mappings)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
9280 # else
9281 /* This is nearly right, but not always -- sometimes the mapping
9282 appears to be r--, for some reason. Hence resync. */
9283 ML_(notify_core_and_tool_of_mmap)(
9284 *(UWord*)a2, a3,
9285 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9286 # endif
9290 PRE(kernelrpc_mach_vm_deallocate_trap)
9292 UWord a1; ULong a2; ULong a3;
9293 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9294 PRINT("kernelrpc_mach_vm_deallocate_trap"
9295 "(target:%#lx, address:%#llx, size:%#llx)", a1, a2, a3);
9297 POST(kernelrpc_mach_vm_deallocate_trap)
9299 UWord a1; ULong a2; ULong a3;
9300 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9301 // kernelrpc_mach_vm_deallocate_trap could be call with
9302 // address ==0 && size == 0,
9303 // we shall not notify any unmap then
9304 if (a3)
9305 ML_(notify_core_and_tool_of_munmap)(a2, a3);
9308 PRE(kernelrpc_mach_vm_protect_trap)
9310 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9311 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9312 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9313 PRINT("kernelrpc_mach_vm_protect_trap"
9314 "(task:%#lx, address:%#llx, size:%#llx,"
9315 " set_maximum:%#lx, new_prot:%#lx)", a1, a2, a3, a4, a5);
9317 POST(kernelrpc_mach_vm_protect_trap)
9319 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9320 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9321 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9322 if (/*a4 set_maximum == 0 && */a1 == mach_task_self()) {
9323 ML_(notify_core_and_tool_of_mprotect)((Addr)a2, (SizeT)a3, (Int)a5);
9324 VG_(di_notify_vm_protect)((Addr)a2, (SizeT)a3, (UInt)a5);
9328 PRE(kernelrpc_mach_port_allocate_trap)
9330 // munge_www -- no need to call helper
9331 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9332 ARG1, ARG2);
9333 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9334 ARG3, sizeof(mach_port_name_t));
9336 POST(kernelrpc_mach_port_allocate_trap)
9338 // munge_www -- no need to call helper
9339 POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
9340 PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
9341 record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
9344 PRE(kernelrpc_mach_port_destroy_trap)
9346 // munge_ww -- no need to call helper
9347 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
9348 record_port_destroy(ARG2);
9351 PRE(kernelrpc_mach_port_deallocate_trap)
9353 // munge_ww -- no need to call helper
9354 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9355 ARG1, ARG2);
9357 POST(kernelrpc_mach_port_deallocate_trap)
9359 // munge_ww -- no need to call helper
9362 PRE(kernelrpc_mach_port_mod_refs_trap)
9364 // munge_wwww -- no need to call helper
9365 PRINT("kernelrpc_mach_port_mod_refs_trap"
9366 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9367 ARG1, ARG2, ARG3, ARG4);
9370 PRE(kernelrpc_mach_port_move_member_trap)
9372 // munge_www -- no need to call helper
9373 PRINT("kernelrpc_mach_port_move_member_trap"
9374 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9375 ARG1, ARG2, ARG3);
9378 PRE(kernelrpc_mach_port_insert_right_trap)
9380 //munge_wwww -- no need to call helper
9381 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9382 "(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9385 PRE(kernelrpc_mach_port_insert_member_trap)
9387 // munge_www -- no need to call helper
9388 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9389 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9392 PRE(kernelrpc_mach_port_extract_member_trap)
9394 // munge_www -- no need to call helper
9395 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9396 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9399 PRE(iopolicysys)
9401 // munge_???
9402 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
9403 /* mem effects unknown */
9405 POST(iopolicysys)
9407 // munge_???
9410 PRE(process_policy)
9412 // munge_???
9413 PRINT("process_policy(FIXME)("
9414 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9415 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9416 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9417 /* mem effects unknown */
9419 POST(process_policy)
9421 // munge_???
9424 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9427 /* ---------------------------------------------------------------------
9428 Added for OSX 10.9 (Mavericks)
9429 ------------------------------------------------------------------ */
9431 #if DARWIN_VERS >= DARWIN_10_9
9433 PRE(kernelrpc_mach_vm_map_trap)
9435 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9436 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9437 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9438 PRINT("kernelrpc_mach_vm_map_trap"
9439 "(target:%#lx, address:%p, size:%#llx,"
9440 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9441 a1, *(void**)a2, a3, a4, a5, a6);
9442 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2, sizeof(void*));
9444 POST(kernelrpc_mach_vm_map_trap)
9446 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9447 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9448 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9449 PRINT("-> address:%p", *(void**)a2);
9450 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9451 POST_MEM_WRITE(a2, sizeof(void*));
9453 ML_(notify_core_and_tool_of_mmap)(
9454 *(mach_vm_address_t*)a2, a3,
9455 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9456 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9459 PRE(kernelrpc_mach_port_construct_trap)
9461 UWord a1; UWord a2; ULong a3; UWord a4;
9462 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9463 PRINT("kernelrpc_mach_port_construct_trap(FIXME)"
9464 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9467 PRE(kernelrpc_mach_port_destruct_trap)
9469 UWord a1; UWord a2; UWord a3; ULong a4;
9470 munge_wwwl(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9471 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9472 "(%lx,%lx,%lx,%llx)", a1, a2, a3, a4);
9475 PRE(kernelrpc_mach_port_guard_trap)
9477 UWord a1; UWord a2; ULong a3; UWord a4;
9478 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9479 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9480 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9483 PRE(kernelrpc_mach_port_unguard_trap)
9485 // munge_wwl
9486 UWord a1; UWord a2; ULong a3;
9487 munge_wwl(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4);
9488 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9489 "(%lx,%lx,%llx)", a1, a2, a3);
9492 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9495 /* ---------------------------------------------------------------------
9496 Added for OSX 10.10 (Yosemite)
9497 ------------------------------------------------------------------ */
9499 #if DARWIN_VERS >= DARWIN_10_10
9501 PRE(necp_match_policy)
9503 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9504 // struct necp_aggregate_result *returned_result)
9505 PRINT("necp_match_policy(FIXME)(%lx,%ld, %lx)", ARG1, ARG2, ARG3);
9506 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
9507 size_t, parameters_size, struct necp_aggregate_result*,
9508 returned_result);
9509 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
9511 POST(necp_match_policy)
9513 POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
9516 PRE(sysctlbyname)
9518 UWord name = ARG1;
9519 UWord namelen = ARG2;
9520 UWord oldp = ARG3;
9521 UWord oldlenp = ARG4;
9522 UWord newp = ARG5;
9523 UWord newlen = ARG6;
9525 PRINT( "sysctlbyname ( %#lx,%ld, %#lx,%#lx, %#lx,%ld )",
9526 name, namelen, oldp, oldlenp, newp, newlen );
9528 PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
9529 void*, oldp, vki_size_t *, oldlenp,
9530 void*, newp, vki_size_t *, newlenp);
9532 // reads name[0..namelen-1]
9533 PRE_MEM_READ("sysctlbyname(name)", name, namelen);
9535 if (VG_(clo_trace_syscalls)) {
9536 UInt i;
9537 const HChar* t_name = (const HChar*)name;
9538 VG_(printf)(" name: ");
9539 for (i = 0; i < namelen; i++) {
9540 VG_(printf)("%c", t_name[i]);
9542 VG_(printf)(" ");
9545 Bool is_kern_dot_userstack
9546 = False;
9548 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
9549 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
9551 POST(sysctlbyname)
9553 UWord oldp = ARG3;
9554 UWord oldlenp = ARG4;
9556 if (SUCCESS || ERR == VKI_ENOMEM) {
9557 // sysctl can write truncated data and return VKI_ENOMEM
9558 if (oldlenp) {
9559 POST_MEM_WRITE(oldlenp, sizeof(size_t));
9561 if (oldp && oldlenp) {
9562 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
9567 PRE(getattrlistbulk)
9569 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9570 // void *attributeBuffer, size_t bufferSize,
9571 // uint64_t options);
9572 // Presumably the last arg is value-pair in the 32 bit case.
9573 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9574 ARG1, ARG2, ARG3, ARG4, ARG5);
9575 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
9576 void*, attributeBuffer, size_t, bufferSize,
9577 uint32_t, options_lo32);
9578 PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
9579 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
9581 POST(getattrlistbulk)
9583 // FIXME: this isn't right. It seems as if what is returned is a
9584 // set of variable-length records -- see complication in
9585 // POST(getattrlist). For now, just paint the entire result buffer
9586 // as defined. Sigh.
9587 vg_assert(SUCCESS);
9588 if (ARG3 && /* "at least one output element was written" */RES > 0)
9589 POST_MEM_WRITE(ARG3, ARG4);
9592 PRE(readlinkat)
9594 Word saved = SYSNO;
9596 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %llu )", ARG1,ARG2,(char*)ARG2,ARG3,(ULong)ARG4);
9597 PRE_REG_READ4(long, "readlinkat",
9598 int, dfd, const char *, path, char *, buf, int, bufsiz);
9599 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
9600 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
9603 * Refer to coregrind/m_syswrap/syswrap-linux.c
9606 /* Normal case */
9607 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
9610 if (SUCCESS && RES > 0)
9611 POST_MEM_WRITE( ARG3, RES );
9614 PRE(bsdthread_ctl)
9616 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9617 // user_addr_t arg2, user_addr_t arg3)
9618 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9619 PRE_REG_READ4(int, "bsdthreadctl",
9620 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
9623 PRE(guarded_open_dprotected_np)
9625 PRINT("guarded_open_dprotected_np("
9626 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9627 "dpclass:%#lx, dpflags: %#lx) FIXME",
9628 ARG1, (char*)ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
9631 PRE(guarded_write_np)
9633 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9634 ARG1, ARG2, ARG3, (ULong)ARG4);
9637 PRE(guarded_pwrite_np)
9639 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9640 ARG1, ARG2, ARG3, (ULong)ARG4, (Long)ARG5);
9643 PRE(guarded_writev_np)
9645 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9646 ARG1, ARG2, ARG3, (ULong)ARG4);
9649 #endif /* DARWIN_VERS >= DARWIN_10_10 */
9652 /* ---------------------------------------------------------------------
9653 syscall tables
9654 ------------------------------------------------------------------ */
9656 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
9658 #define MACX_(sysno, name) \
9659 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
9661 #define MACXY(sysno, name) \
9662 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
9664 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
9667 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
9668 unfortunately misused for Mach too, causing assertion failures
9669 // _____ : unimplemented in valgrind
9670 GEN : handlers are in syswrap-generic.c
9671 MAC : handlers are in this file
9672 X_ : PRE handler only
9673 XY : PRE and POST handlers
9675 const SyscallTableEntry ML_(syscall_table)[] = {
9676 // _____(__NR_syscall), // 0
9677 MACX_(__NR_exit, exit),
9678 GENX_(__NR_fork, sys_fork),
9679 GENXY(__NR_read, sys_read),
9680 GENX_(__NR_write, sys_write),
9681 GENXY(__NR_open, sys_open),
9682 GENXY(__NR_close, sys_close),
9683 GENXY(__NR_wait4, sys_wait4),
9684 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
9685 GENX_(__NR_link, sys_link),
9686 GENX_(__NR_unlink, sys_unlink),
9687 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
9688 GENX_(__NR_chdir, sys_chdir),
9689 GENX_(__NR_fchdir, sys_fchdir),
9690 GENX_(__NR_mknod, sys_mknod),
9691 GENX_(__NR_chmod, sys_chmod),
9692 GENX_(__NR_chown, sys_chown),
9693 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
9694 MACXY(__NR_getfsstat, getfsstat),
9695 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
9696 GENX_(__NR_getpid, sys_getpid), // 20
9697 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
9698 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
9699 GENX_(__NR_setuid, sys_setuid),
9700 GENX_(__NR_getuid, sys_getuid),
9701 GENX_(__NR_geteuid, sys_geteuid),
9702 MACX_(__NR_ptrace, ptrace),
9703 MACXY(__NR_recvmsg, recvmsg),
9704 MACX_(__NR_sendmsg, sendmsg),
9705 MACXY(__NR_recvfrom, recvfrom),
9706 MACXY(__NR_accept, accept),
9707 MACXY(__NR_getpeername, getpeername),
9708 MACXY(__NR_getsockname, getsockname),
9709 GENX_(__NR_access, sys_access),
9710 MACX_(__NR_chflags, chflags),
9711 MACX_(__NR_fchflags, fchflags),
9712 GENX_(__NR_sync, sys_sync),
9713 GENX_(__NR_kill, sys_kill),
9714 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
9715 GENX_(__NR_getppid, sys_getppid),
9716 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
9717 GENXY(__NR_dup, sys_dup),
9718 MACXY(__NR_pipe, pipe),
9719 GENX_(__NR_getegid, sys_getegid),
9720 #if DARWIN_VERS >= DARWIN_10_7
9721 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
9722 #else
9723 // _____(__NR_profil),
9724 #endif
9725 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
9726 MACXY(__NR_sigaction, sigaction),
9727 GENX_(__NR_getgid, sys_getgid),
9728 MACXY(__NR_sigprocmask, sigprocmask),
9729 MACXY(__NR_getlogin, getlogin),
9730 // _____(__NR_setlogin),
9731 // _____(__NR_acct),
9732 MACXY(__NR_sigpending, sigpending),
9733 GENXY(__NR_sigaltstack, sys_sigaltstack),
9734 MACXY(__NR_ioctl, ioctl),
9735 // _____(__NR_reboot),
9736 // _____(__NR_revoke),
9737 GENX_(__NR_symlink, sys_symlink), // 57
9738 GENX_(__NR_readlink, sys_readlink),
9739 GENX_(__NR_execve, sys_execve),
9740 GENX_(__NR_umask, sys_umask), // 60
9741 GENX_(__NR_chroot, sys_chroot),
9742 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
9743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
9744 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
9745 GENX_(__NR_msync, sys_msync),
9746 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
9747 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
9748 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
9749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
9750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
9751 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
9752 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
9753 GENXY(__NR_munmap, sys_munmap),
9754 GENXY(__NR_mprotect, sys_mprotect),
9755 GENX_(__NR_madvise, sys_madvise),
9756 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
9757 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
9758 GENXY(__NR_mincore, sys_mincore),
9759 GENXY(__NR_getgroups, sys_getgroups),
9760 // _____(__NR_setgroups), // 80
9761 GENX_(__NR_getpgrp, sys_getpgrp),
9762 GENX_(__NR_setpgid, sys_setpgid),
9763 GENXY(__NR_setitimer, sys_setitimer),
9764 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
9765 // _____(__NR_swapon),
9766 GENXY(__NR_getitimer, sys_getitimer),
9767 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
9768 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
9769 MACXY(__NR_getdtablesize, getdtablesize),
9770 GENXY(__NR_dup2, sys_dup2),
9771 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
9772 MACXY(__NR_fcntl, fcntl),
9773 GENX_(__NR_select, sys_select),
9774 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
9775 GENX_(__NR_fsync, sys_fsync),
9776 GENX_(__NR_setpriority, sys_setpriority),
9777 MACXY(__NR_socket, socket),
9778 MACX_(__NR_connect, connect),
9779 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
9780 GENX_(__NR_getpriority, sys_getpriority), // 100
9781 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
9782 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
9783 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
9784 MACX_(__NR_bind, bind),
9785 MACX_(__NR_setsockopt, setsockopt),
9786 MACX_(__NR_listen, listen),
9787 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
9788 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
9789 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
9790 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
9791 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
9792 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
9793 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
9794 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
9795 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
9796 GENXY(__NR_gettimeofday, sys_gettimeofday),
9797 GENXY(__NR_getrusage, sys_getrusage),
9798 MACXY(__NR_getsockopt, getsockopt),
9799 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
9800 GENXY(__NR_readv, sys_readv), // 120
9801 GENX_(__NR_writev, sys_writev),
9802 // _____(__NR_settimeofday),
9803 GENX_(__NR_fchown, sys_fchown),
9804 GENX_(__NR_fchmod, sys_fchmod),
9805 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
9806 // _____(__NR_setreuid),
9807 // _____(__NR_setregid),
9808 GENX_(__NR_rename, sys_rename),
9809 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
9810 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
9811 GENX_(__NR_flock, sys_flock),
9812 MACXY(__NR_mkfifo, mkfifo),
9813 MACX_(__NR_sendto, sendto),
9814 MACX_(__NR_shutdown, shutdown),
9815 MACXY(__NR_socketpair, socketpair),
9816 GENX_(__NR_mkdir, sys_mkdir),
9817 GENX_(__NR_rmdir, sys_rmdir),
9818 GENX_(__NR_utimes, sys_utimes),
9819 MACX_(__NR_futimes, futimes),
9820 // _____(__NR_adjtime), // 140
9821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
9822 MACXY(__NR_gethostuuid, gethostuuid),
9823 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
9824 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
9825 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
9826 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
9827 GENX_(__NR_setsid, sys_setsid),
9828 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
9829 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
9830 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
9831 // _____(__NR_getpgid),
9832 // _____(__NR_setprivexec),
9833 GENXY(__NR_pread, sys_pread64),
9834 GENX_(__NR_pwrite, sys_pwrite64),
9835 // _____(__NR_nfssvc),
9836 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
9837 GENXY(__NR_statfs, sys_statfs),
9838 GENXY(__NR_fstatfs, sys_fstatfs),
9839 // _____(__NR_unmount),
9840 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
9841 // _____(__NR_getfh),
9842 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
9843 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
9844 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
9845 // _____(__NR_quotactl),
9846 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
9847 MACX_(__NR_mount, mount),
9848 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
9849 MACXY(__NR_csops, csops), // code-signing ops
9850 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
9851 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
9852 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
9853 // _____(__NR_waitid),
9854 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
9855 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
9856 // _____(__NR_add_profil),
9857 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
9858 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
9859 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
9860 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
9861 GENX_(__NR_setgid, sys_setgid),
9862 MACX_(__NR_setegid, setegid),
9863 MACX_(__NR_seteuid, seteuid),
9864 MACX_(__NR_sigreturn, sigreturn),
9865 // _____(__NR_chud),
9866 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
9867 #if DARWIN_VERS >= DARWIN_10_6
9868 // _____(__NR_fdatasync),
9869 #else
9870 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
9871 #endif
9872 GENXY(__NR_stat, sys_newstat),
9873 GENXY(__NR_fstat, sys_newfstat),
9874 GENXY(__NR_lstat, sys_newlstat),
9875 MACX_(__NR_pathconf, pathconf),
9876 MACX_(__NR_fpathconf, fpathconf),
9877 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
9878 GENXY(__NR_getrlimit, sys_getrlimit),
9879 GENX_(__NR_setrlimit, sys_setrlimit),
9880 MACXY(__NR_getdirentries, getdirentries),
9881 MACXY(__NR_mmap, mmap),
9882 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
9883 MACX_(__NR_lseek, lseek),
9884 GENX_(__NR_truncate, sys_truncate64), // 200
9885 GENX_(__NR_ftruncate, sys_ftruncate64),
9886 MACXY(__NR___sysctl, __sysctl),
9887 GENX_(__NR_mlock, sys_mlock),
9888 GENX_(__NR_munlock, sys_munlock),
9889 // _____(__NR_undelete),
9890 // _____(__NR_ATsocket),
9891 // _____(__NR_ATgetmsg),
9892 // _____(__NR_ATputmsg),
9893 // _____(__NR_ATPsndreq),
9894 // _____(__NR_ATPsndrsp),
9895 // _____(__NR_ATPgetreq),
9896 // _____(__NR_ATPgetrsp),
9897 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
9898 #if DARWIN_VERS >= DARWIN_10_6
9899 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
9900 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
9901 #else
9902 // _____(__NR_kqueue_from_portset_np),
9903 // _____(__NR_kqueue_portset_np),
9904 #endif
9905 // _____(__NR_mkcomplex),
9906 // _____(__NR_statv),
9907 // _____(__NR_lstatv),
9908 // _____(__NR_fstatv),
9909 MACXY(__NR_getattrlist, getattrlist), // 220
9910 MACX_(__NR_setattrlist, setattrlist),
9911 MACXY(__NR_getdirentriesattr, getdirentriesattr),
9912 MACX_(__NR_exchangedata, exchangedata),
9913 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
9914 // _____(__NR_searchfs),
9915 GENX_(__NR_delete, sys_unlink),
9916 // _____(__NR_copyfile),
9917 #if DARWIN_VERS >= DARWIN_10_6
9918 // _____(__NR_fgetattrlist),
9919 // _____(__NR_fsetattrlist),
9920 #else
9921 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
9922 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
9923 #endif
9924 GENXY(__NR_poll, sys_poll),
9925 MACX_(__NR_watchevent, watchevent),
9926 MACXY(__NR_waitevent, waitevent),
9927 MACX_(__NR_modwatch, modwatch),
9928 MACXY(__NR_getxattr, getxattr),
9929 MACXY(__NR_fgetxattr, fgetxattr),
9930 MACX_(__NR_setxattr, setxattr),
9931 MACX_(__NR_fsetxattr, fsetxattr),
9932 MACX_(__NR_removexattr, removexattr),
9933 MACX_(__NR_fremovexattr, fremovexattr),
9934 MACXY(__NR_listxattr, listxattr), // 240
9935 MACXY(__NR_flistxattr, flistxattr),
9936 MACXY(__NR_fsctl, fsctl),
9937 MACX_(__NR_initgroups, initgroups),
9938 MACXY(__NR_posix_spawn, posix_spawn),
9939 #if DARWIN_VERS >= DARWIN_10_6
9940 // _____(__NR_ffsctl),
9941 #else
9942 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
9943 #endif
9944 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
9945 // _____(__NR_nfsclnt),
9946 // _____(__NR_fhopen),
9947 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
9948 // _____(__NR_minherit),
9949 // _____(__NR_semsys),
9950 // _____(__NR_msgsys),
9951 // _____(__NR_shmsys),
9952 MACXY(__NR_semctl, semctl),
9953 MACX_(__NR_semget, semget),
9954 MACX_(__NR_semop, semop),
9955 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
9956 // _____(__NR_msgctl),
9957 // _____(__NR_msgget),
9958 // _____(__NR_msgsnd), // 260
9959 // _____(__NR_msgrcv),
9960 MACXY(__NR_shmat, shmat),
9961 MACXY(__NR_shmctl, shmctl),
9962 MACXY(__NR_shmdt, shmdt),
9963 MACX_(__NR_shmget, shmget),
9964 MACXY(__NR_shm_open, shm_open),
9965 MACXY(__NR_shm_unlink, shm_unlink),
9966 MACX_(__NR_sem_open, sem_open),
9967 MACX_(__NR_sem_close, sem_close),
9968 MACX_(__NR_sem_unlink, sem_unlink),
9969 MACX_(__NR_sem_wait, sem_wait),
9970 MACX_(__NR_sem_trywait, sem_trywait),
9971 MACX_(__NR_sem_post, sem_post),
9972 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
9973 // has become sysctlbyname. See below.
9974 MACXY(__NR_sem_init, sem_init),
9975 MACX_(__NR_sem_destroy, sem_destroy),
9976 MACX_(__NR_open_extended, open_extended), // 277
9977 // _____(__NR_umask_extended),
9978 MACXY(__NR_stat_extended, stat_extended),
9979 MACXY(__NR_lstat_extended, lstat_extended), // 280
9980 MACXY(__NR_fstat_extended, fstat_extended),
9981 MACX_(__NR_chmod_extended, chmod_extended),
9982 MACX_(__NR_fchmod_extended,fchmod_extended),
9983 MACXY(__NR_access_extended,access_extended),
9984 MACX_(__NR_settid, settid),
9985 #if DARWIN_VERS >= DARWIN_10_8
9986 MACX_(__NR_gettid, gettid), // 286
9987 #endif
9988 // _____(__NR_setsgroups),
9989 // _____(__NR_getsgroups),
9990 // _____(__NR_setwgroups),
9991 // _____(__NR_getwgroups),
9992 // _____(__NR_mkfifo_extended),
9993 // _____(__NR_mkdir_extended),
9994 // _____(__NR_identitysvc),
9995 // _____(__NR_shared_region_check_np),
9996 // _____(__NR_shared_region_map_np),
9997 #if DARWIN_VERS >= DARWIN_10_6
9998 // _____(__NR_vm_pressure_monitor),
9999 #else
10000 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
10001 #endif
10002 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
10003 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
10004 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
10005 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
10006 MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
10007 MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
10008 MACXY(__NR_psynch_cvbroad, psynch_cvbroad), // 303
10009 MACXY(__NR_psynch_cvsignal, psynch_cvsignal), // 304
10010 MACXY(__NR_psynch_cvwait, psynch_cvwait), // 305
10011 MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
10012 MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
10013 MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
10014 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(309)), // ???
10015 // _____(__NR_getsid),
10016 // _____(__NR_settid_with_pid),
10017 MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
10018 // _____(__NR_aio_fsync),
10019 MACXY(__NR_aio_return, aio_return),
10020 MACX_(__NR_aio_suspend, aio_suspend),
10021 // _____(__NR_aio_cancel),
10022 MACX_(__NR_aio_error, aio_error),
10023 MACXY(__NR_aio_read, aio_read),
10024 MACX_(__NR_aio_write, aio_write),
10025 // _____(__NR_lio_listio), // 320
10026 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
10028 #if DARWIN_VERS >= DARWIN_10_8
10029 MACXY(__NR_iopolicysys, iopolicysys),
10030 MACXY(__NR_process_policy, process_policy),
10031 #else
10032 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
10033 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
10034 #endif
10035 // _____(__NR_mlockall),
10036 // _____(__NR_munlockall),
10037 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
10038 MACX_(__NR_issetugid, issetugid),
10039 MACX_(__NR___pthread_kill, __pthread_kill),
10040 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
10041 // _____(__NR___sigwait),
10042 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
10043 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
10044 MACX_(__NR___pthread_canceled, __pthread_canceled),
10045 MACX_(__NR___semwait_signal, __semwait_signal),
10046 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
10047 #if DARWIN_VERS >= DARWIN_10_6
10048 MACXY(__NR_proc_info, proc_info), // 336
10049 #endif
10050 MACXY(__NR_sendfile, sendfile),
10051 MACXY(__NR_stat64, stat64),
10052 MACXY(__NR_fstat64, fstat64),
10053 MACXY(__NR_lstat64, lstat64), // 340
10054 MACXY(__NR_stat64_extended, stat64_extended),
10055 MACXY(__NR_lstat64_extended, lstat64_extended),
10056 MACXY(__NR_fstat64_extended, fstat64_extended),
10057 MACXY(__NR_getdirentries64, getdirentries64),
10058 MACXY(__NR_statfs64, statfs64),
10059 MACXY(__NR_fstatfs64, fstatfs64),
10060 MACXY(__NR_getfsstat64, getfsstat64),
10061 MACX_(__NR___pthread_chdir, __pthread_chdir),
10062 MACX_(__NR___pthread_fchdir, __pthread_fchdir),
10063 // _____(__NR_audit),
10064 MACXY(__NR_auditon, auditon),
10065 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
10066 // _____(__NR_getauid),
10067 // _____(__NR_setauid),
10068 // _____(__NR_getaudit),
10069 // _____(__NR_setaudit),
10070 #if DARWIN_VERS >= DARWIN_10_7
10071 MACXY(__NR_getaudit_addr, getaudit_addr),
10072 #endif
10073 // _____(__NR_setaudit_addr),
10074 // _____(__NR_auditctl),
10075 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
10076 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
10077 MACXY(__NR_kqueue, kqueue),
10078 MACXY(__NR_kevent, kevent),
10079 GENX_(__NR_lchown, sys_lchown),
10080 // _____(__NR_stack_snapshot),
10081 MACX_(__NR_bsdthread_register, bsdthread_register),
10082 MACX_(__NR_workq_open, workq_open),
10083 MACXY(__NR_workq_ops, workq_ops),
10084 #if DARWIN_VERS >= DARWIN_10_6
10085 MACXY(__NR_kevent64, kevent64),
10086 #else
10087 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
10088 #endif
10089 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // ???
10090 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // ???
10091 #if DARWIN_VERS >= DARWIN_10_6
10092 MACX_(__NR___thread_selfid, __thread_selfid),
10093 #else
10094 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
10095 #endif
10096 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
10097 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
10098 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
10099 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
10100 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
10101 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
10102 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
10103 // _____(__NR___mac_execve), // 380
10104 MACX_(__NR___mac_syscall, __mac_syscall),
10105 // _____(__NR___mac_get_file),
10106 // _____(__NR___mac_set_file),
10107 // _____(__NR___mac_get_link),
10108 // _____(__NR___mac_set_link),
10109 // _____(__NR___mac_get_proc),
10110 // _____(__NR___mac_set_proc),
10111 // _____(__NR___mac_get_fd),
10112 // _____(__NR___mac_set_fd),
10113 // _____(__NR___mac_get_pid),
10114 // _____(__NR___mac_get_lcid),
10115 // _____(__NR___mac_get_lctx),
10116 // _____(__NR___mac_set_lctx),
10117 // _____(__NR_setlcid),
10118 // _____(__NR_getlcid),
10119 // GrP fixme need any special nocancel handling?
10120 GENXY(__NR_read_nocancel, sys_read),
10121 GENX_(__NR_write_nocancel, sys_write),
10122 GENXY(__NR_open_nocancel, sys_open),
10123 GENXY(__NR_close_nocancel, sys_close),
10124 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
10125 MACXY(__NR_recvmsg_nocancel, recvmsg),
10126 MACX_(__NR_sendmsg_nocancel, sendmsg),
10127 MACXY(__NR_recvfrom_nocancel, recvfrom),
10128 MACXY(__NR_accept_nocancel, accept),
10129 GENX_(__NR_msync_nocancel, sys_msync),
10130 MACXY(__NR_fcntl_nocancel, fcntl),
10131 GENX_(__NR_select_nocancel, sys_select),
10132 GENX_(__NR_fsync_nocancel, sys_fsync),
10133 MACX_(__NR_connect_nocancel, connect),
10134 MACX_(__NR_sigsuspend_nocancel, sigsuspend),
10135 GENXY(__NR_readv_nocancel, sys_readv),
10136 GENX_(__NR_writev_nocancel, sys_writev),
10137 MACX_(__NR_sendto_nocancel, sendto),
10138 GENXY(__NR_pread_nocancel, sys_pread64),
10139 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
10140 // _____(__NR_waitid_nocancel),
10141 GENXY(__NR_poll_nocancel, sys_poll),
10142 // _____(__NR_msgsnd_nocancel),
10143 // _____(__NR_msgrcv_nocancel),
10144 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
10145 // _____(__NR_aio_suspend_nocancel),
10146 // _____(__NR___sigwait_nocancel),
10147 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
10148 // _____(__NR___mac_mount),
10149 // _____(__NR___mac_get_mount),
10150 // _____(__NR___mac_getfsstat),
10151 #if DARWIN_VERS >= DARWIN_10_6
10152 MACXY(__NR_fsgetpath, fsgetpath),
10153 MACXY(__NR_audit_session_self, audit_session_self),
10154 // _____(__NR_audit_session_join),
10155 #endif
10156 #if DARWIN_VERS >= DARWIN_10_9
10157 MACX_(__NR_fileport_makeport, fileport_makeport),
10158 MACX_(__NR_guarded_open_np, guarded_open_np),
10159 MACX_(__NR_guarded_close_np, guarded_close_np),
10160 MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
10161 MACX_(__NR_change_fdguard_np, change_fdguard_np),
10162 MACX_(__NR_connectx, connectx),
10163 MACX_(__NR_disconnectx, disconnectx),
10164 #endif
10165 #if DARWIN_VERS >= DARWIN_10_10
10166 MACXY(__NR_sysctlbyname, sysctlbyname), // 274
10167 MACXY(__NR_necp_match_policy, necp_match_policy), // 460
10168 MACXY(__NR_getattrlistbulk, getattrlistbulk), // 461
10169 MACX_(__NR_readlinkat, readlinkat), // 473
10170 MACX_(__NR_bsdthread_ctl, bsdthread_ctl), // 478
10171 MACX_(__NR_guarded_open_dprotected_np, guarded_open_dprotected_np),
10172 MACX_(__NR_guarded_write_np, guarded_write_np),
10173 MACX_(__NR_guarded_pwrite_np, guarded_pwrite_np),
10174 MACX_(__NR_guarded_writev_np, guarded_writev_np),
10175 #endif
10176 // _____(__NR_MAXSYSCALL)
10177 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
10181 // Mach traps use negative syscall numbers.
10182 // Use ML_(mach_trap_table)[-mach_trap_number] .
10183 // cf xnu sources osfmk/kern/syscall_sw.c
10185 const SyscallTableEntry ML_(mach_trap_table)[] = {
10186 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
10187 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
10188 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
10189 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
10190 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
10191 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
10192 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
10193 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
10194 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
10195 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
10197 # if DARWIN_VERS >= DARWIN_10_8
10198 MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
10199 # else
10200 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
10201 # endif
10203 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
10205 # if DARWIN_VERS >= DARWIN_10_8
10206 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
10207 # else
10208 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
10209 # endif
10211 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
10213 # if DARWIN_VERS >= DARWIN_10_8
10214 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
10215 # endif
10217 # if DARWIN_VERS >= DARWIN_10_9
10218 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
10219 # endif
10221 # if DARWIN_VERS < DARWIN_10_8
10222 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
10223 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
10224 # endif
10226 # if DARWIN_VERS >= DARWIN_10_8
10227 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
10228 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
10229 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
10230 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
10231 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
10232 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
10233 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
10234 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
10235 # else
10236 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
10237 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
10238 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
10239 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
10240 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
10241 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
10242 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
10243 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
10244 # endif
10246 # if DARWIN_VERS >= DARWIN_10_9
10247 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
10248 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
10249 # else
10250 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
10251 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
10252 # endif
10254 MACXY(__NR_mach_reply_port, mach_reply_port),
10255 MACXY(__NR_thread_self_trap, mach_thread_self),
10256 MACXY(__NR_task_self_trap, mach_task_self),
10257 MACXY(__NR_host_self_trap, mach_host_self),
10258 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
10259 MACXY(__NR_mach_msg_trap, mach_msg),
10260 // _____(__NR_mach_msg_overwrite_trap),
10261 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
10262 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
10263 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
10264 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
10265 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
10266 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
10267 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
10268 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
10270 # if DARWIN_VERS >= DARWIN_10_9
10271 MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
10272 MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
10273 # else
10274 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
10275 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
10276 # endif
10278 # if DARWIN_VERS >= DARWIN_10_10
10279 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10280 # else
10281 # if DARWIN_VERS == DARWIN_10_9
10282 // _____(__NR_map_fd),
10283 # else
10284 # if defined(VGA_x86)
10285 // _____(__NR_map_fd),
10286 # else
10287 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10288 # endif
10289 # endif
10290 # endif
10292 // _____(__NR_task_name_for_pid),
10293 MACXY(__NR_task_for_pid, task_for_pid),
10294 MACXY(__NR_pid_for_task, pid_for_task),
10295 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
10296 #if defined(VGA_x86)
10297 // _____(__NR_macx_swapon),
10298 // _____(__NR_macx_swapoff),
10299 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10300 // _____(__NR_macx_triggers),
10301 // _____(__NR_macx_backing_store_suspend),
10302 // _____(__NR_macx_backing_store_recovery),
10303 #else
10304 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
10305 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
10306 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10307 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
10308 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
10309 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
10310 #endif
10311 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
10312 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
10313 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
10314 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
10315 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
10316 MACX_(__NR_swtch_pri, swtch_pri),
10317 MACX_(__NR_swtch, swtch), // -60
10318 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
10319 // _____(__NR_clock_sleep_trap),
10320 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
10321 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
10322 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
10323 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
10324 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
10325 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
10326 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
10327 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
10328 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
10329 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
10330 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
10331 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
10332 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
10333 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
10334 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
10335 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
10336 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
10337 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
10338 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
10339 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
10340 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
10341 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
10342 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
10343 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
10344 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
10345 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
10346 MACXY(__NR_mach_timebase_info, mach_timebase_info),
10347 MACX_(__NR_mach_wait_until, mach_wait_until),
10348 MACXY(__NR_mk_timer_create, mk_timer_create),
10349 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
10350 MACX_(__NR_mk_timer_arm, mk_timer_arm),
10351 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
10352 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
10353 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
10354 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
10355 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
10356 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
10357 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
10361 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
10362 // calling convention instead of the syscall convention.
10363 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
10365 #if defined(VGA_x86)
10366 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10367 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10369 #elif defined(VGA_amd64)
10370 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10371 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10373 #else
10374 #error unknown architecture
10375 #endif
10377 const UInt ML_(syscall_table_size) =
10378 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
10380 const UInt ML_(mach_trap_table_size) =
10381 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
10383 const UInt ML_(mdep_trap_table_size) =
10384 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
10386 #endif // defined(VGO_darwin)
10388 /*--------------------------------------------------------------------*/
10389 /*--- end ---*/
10390 /*--------------------------------------------------------------------*/