vgdb: Handle EAGAIN in read_buf
[valgrind.git] / coregrind / m_syswrap / syswrap-darwin.c
blobc5c9b603b6f56732c55fdcd517b0adc417303da4
2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2005-2017 Apple Inc.
11 Greg Parker gparker@apple.com
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGO_darwin)
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_vkiscnums.h"
34 #include "pub_core_threadstate.h"
35 #include "pub_core_aspacemgr.h"
36 #include "pub_core_xarray.h"
37 #include "pub_core_clientstate.h"
38 #include "pub_core_debuglog.h"
39 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
40 #include "pub_core_transtab.h" // VG_(discard_translations)
41 #include "pub_core_libcbase.h"
42 #include "pub_core_libcassert.h"
43 #include "pub_core_libcfile.h"
44 #include "pub_core_libcprint.h"
45 #include "pub_core_libcproc.h"
46 #include "pub_core_libcsignal.h"
47 #include "pub_core_machine.h" // VG_(get_SP)
48 #include "pub_core_mallocfree.h"
49 #include "pub_core_options.h"
50 #include "pub_core_oset.h"
51 #include "pub_core_scheduler.h"
52 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
53 #include "pub_core_signals.h"
54 #include "pub_core_stacks.h"
55 #include "pub_core_syscall.h"
56 #include "pub_core_syswrap.h"
57 #include "pub_core_tooliface.h"
58 #include "pub_core_wordfm.h"
60 #include "priv_types_n_macros.h"
61 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
62 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
63 #include "priv_syswrap-main.h"
65 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
66 #include <mach/mach.h>
67 #include <mach/mach_vm.h>
68 #include <semaphore.h>
69 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
71 #define msgh_request_port msgh_remote_port
72 #define msgh_reply_port msgh_local_port
73 #define BOOTSTRAP_MAX_NAME_LEN 128
74 typedef HChar name_t[BOOTSTRAP_MAX_NAME_LEN];
76 typedef uint64_t mig_addr_t;
79 // Saved ports
80 static mach_port_t vg_host_port = 0;
81 static mach_port_t vg_task_port = 0;
82 static mach_port_t vg_bootstrap_port = 0;
84 // Run a thread from beginning to end and return the thread's
85 // scheduler-return-code.
86 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
88 VgSchedReturnCode ret;
89 ThreadId tid = (ThreadId)tidW;
90 Int lwpid = VG_(gettid)();
91 ThreadState* tst = VG_(get_ThreadState)(tid);
93 VG_(debugLog)(1, "syswrap-darwin",
94 "thread_wrapper(tid=%u,lwpid=%d): entry\n",
95 tid, lwpid);
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 %u started: stack = %p\n",
104 tid, (void *)&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 = lwpid;
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=%u,lwpid=%d): done\n",
126 tid, lwpid);
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 %u 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=%u): pre-thread_wrapper\n",
193 tid);
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=%u): post-thread_wrapper\n",
203 tid);
205 c = VG_(count_living_threads)();
206 vg_assert(c >= 1); /* stay sane */
208 /* Deregister thread's stack. */
209 if (tst->os_state.stk_id != NULL_STK_ID)
210 VG_(deregister_stack)(tst->os_state.stk_id);
212 // Tell the tool this thread is exiting
213 VG_TRACK( pre_thread_ll_exit, tid );
215 /* If the thread is exiting with errors disabled, complain loudly;
216 doing so is bad (does the user know this has happened?) Also,
217 in all cases, be paranoid and clear the flag anyway so that the
218 thread slot is safe in this respect if later reallocated. This
219 should be unnecessary since the flag should be cleared when the
220 slot is reallocated, in thread_wrapper(). */
221 if (tst->err_disablement_level > 0) {
222 VG_(umsg)(
223 "WARNING: exiting thread has error reporting disabled.\n"
224 "WARNING: possibly as a result of some mistake in the use\n"
225 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
227 VG_(debugLog)(
228 1, "syswrap-darwin",
229 "run_a_thread_NORETURN(tid=%u): "
230 "WARNING: exiting thread has err_disablement_level = %u\n",
231 tid, tst->err_disablement_level
234 tst->err_disablement_level = 0;
236 if (c == 1) {
238 VG_(debugLog)(1, "syswrap-darwin",
239 "run_a_thread_NORETURN(tid=%u): "
240 "last one standing\n",
241 tid);
243 /* We are the last one standing. Keep hold of the lock and
244 carry on to show final tool results, then exit the entire system.
245 Use the continuation pointer set at startup in m_main. */
246 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
248 } else {
250 mach_msg_header_t msg;
252 VG_(debugLog)(1, "syswrap-darwin",
253 "run_a_thread_NORETURN(tid=%u): "
254 "not last one standing\n",
255 tid);
257 /* OK, thread is dead, but others still exist. Just exit. */
259 /* This releases the run lock */
260 VG_(exit_thread)(tid);
261 vg_assert(tst->status == VgTs_Zombie);
263 /* tid is now invalid. */
265 // GrP fixme exit race
266 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE);
267 msg.msgh_request_port = VG_(gettid)();
268 msg.msgh_reply_port = 0;
269 msg.msgh_id = 3600; // thread_terminate
271 tst->status = VgTs_Empty;
272 // GrP fixme race here! new thread may claim this V thread stack
273 // before we get out here!
274 // GrP fixme use bsdthread_terminate for safe cleanup?
275 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
276 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0);
278 // DDD: This is reached sometimes on none/tests/manythreads, maybe
279 // because of the race above.
280 VG_(core_panic)("Thread exit failed?\n");
283 /*NOTREACHED*/
284 vg_assert(0);
288 /* Allocate a stack for the main thread, and run it all the way to the
289 end. Although we already have a working VgStack
290 (VG_(interim_stack)) it's better to allocate a new one, so that
291 overflow detection works uniformly for all threads.
293 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
295 Addr sp;
296 VG_(debugLog)(1, "syswrap-darwin",
297 "entering VG_(main_thread_wrapper_NORETURN)\n");
299 sp = allocstack(tid);
301 /* If we can't even allocate the first thread's stack, we're hosed.
302 Give up. */
303 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
305 /* shouldn't be any other threads around yet */
306 vg_assert( VG_(count_living_threads)() == 1 );
308 call_on_new_stack_0_1(
309 (Addr)sp, /* stack */
310 0, /*bogus return address*/
311 run_a_thread_NORETURN, /* fn to call */
312 (Word)tid /* arg to give it */
315 /*NOTREACHED*/
316 vg_assert(0);
320 void start_thread_NORETURN ( Word arg )
322 ThreadState* tst = (ThreadState*)arg;
323 ThreadId tid = tst->tid;
325 run_a_thread_NORETURN ( (Word)tid );
326 /*NOTREACHED*/
327 vg_assert(0);
331 void VG_(cleanup_thread) ( ThreadArchState* arch )
336 /* ---------------------------------------------------------------------
337 Message reporting, with duplicate removal
338 ------------------------------------------------------------------ */
340 static WordFM* decaying_string_table = NULL; /* HChar* -> UWord */
342 static Word decaying_string_table_cmp ( UWord s1, UWord s2 ) {
343 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
346 static void log_decaying ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
347 static void log_decaying ( const HChar* format, ... )
349 // get the message into a stack-allocated string.
350 HChar buf[256];
351 VG_(memset)(buf, 0, sizeof(buf));
352 va_list vargs;
353 va_start(vargs,format);
354 (void) VG_(vsnprintf)(buf, sizeof(buf), format, vargs);
355 va_end(vargs);
356 buf[sizeof(buf)-1] = 0;
358 // Now see if it already exists in the table of strings that we have.
359 if (!decaying_string_table) {
360 decaying_string_table
361 = VG_(newFM)( VG_(malloc), "syswrap-darwin.pd.1",
362 VG_(free), decaying_string_table_cmp );
365 const HChar* key = NULL;
366 UWord val = 0;
367 if (!VG_(lookupFM)(decaying_string_table,
368 (UWord*)&key, &val, (UWord)&buf[0])) {
369 // We haven't seen this string before, so strdup it and add
370 // it to the table.
371 vg_assert(key == NULL && val == 0);
372 key = VG_(strdup)("syswrap-darwin.pd.2", buf);
373 VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)0);
376 vg_assert(key != NULL && key != &buf[0]);
378 // So, finally, |key| is in the tree, and |val| is what it is
379 // currently associated with. Increment that counter.
380 val++;
381 Bool b = VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)val);
382 vg_assert(b);
384 if (-1 != VG_(log2)( (UInt)val )) {
385 if (val == 1)
386 VG_(dmsg)("%s\n", key);
387 else
388 VG_(dmsg)("%s (repeated %lu times)\n", key, val);
393 /* ---------------------------------------------------------------------
394 Mach port tracking (based on syswrap-generic's fd tracker)
395 ------------------------------------------------------------------ */
397 /* One of these is allocated for each open port. */
398 typedef struct OpenPort
400 mach_port_t port;
401 mach_port_type_t type; /* right type(s) */
402 Int send_count; /* number of send rights */
403 HChar *name; /* bootstrap name or NULL */
404 ExeContext *where; /* first allocation only */
405 struct OpenPort *next, *prev;
406 } OpenPort;
408 // strlen("0x12345678")
409 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
411 /* List of allocated ports. */
412 static OpenPort *allocated_ports;
414 /* Count of open ports. */
415 static Int allocated_port_count = 0;
417 /* Create an entry for |port|, with no other info. Assumes it doesn't
418 already exist. */
419 static void port_create_vanilla(mach_port_t port)
421 OpenPort* op
422 = VG_(calloc)("syswrap-darwin.port_create_vanilla", sizeof(OpenPort), 1);
423 op->port = port;
424 /* Add it to the list. */
425 op->next = allocated_ports;
426 if (allocated_ports) allocated_ports->prev = op;
427 allocated_ports = op;
428 allocated_port_count++;
431 __attribute__((unused))
432 static Bool port_exists(mach_port_t port)
434 OpenPort *i;
436 /* Check to see if this port is already open. */
437 i = allocated_ports;
438 while (i) {
439 if (i->port == port) {
440 return True;
442 i = i->next;
445 return False;
448 static OpenPort *info_for_port(mach_port_t port)
450 OpenPort *i;
451 if (!port) return NULL;
453 i = allocated_ports;
454 while (i) {
455 if (i->port == port) {
456 return i;
458 i = i->next;
461 return NULL;
465 // Give a port a name, without changing its refcount
466 // GrP fixme don't override name if it already has a specific one
467 __private_extern__ void assign_port_name(mach_port_t port, const HChar *name)
469 OpenPort *i;
470 if (!port) return;
471 vg_assert(name);
473 i = info_for_port(port);
474 vg_assert(i);
476 if (i->name) VG_(free)(i->name);
477 i->name =
478 VG_(malloc)("syswrap-darwin.mach-port-name",
479 VG_(strlen)(name) + PORT_STRLEN + 1);
480 VG_(sprintf)(i->name, name, port);
484 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
485 static const HChar *name_for_port(mach_port_t port)
487 static HChar buf[8 + PORT_STRLEN + 1];
488 OpenPort *i;
490 // hack
491 if (port == VG_(gettid)()) return "mach_thread_self()";
492 if (port == 0) return "NULL";
494 i = allocated_ports;
495 while (i) {
496 if (i->port == port) {
497 return i->name;
499 i = i->next;
502 VG_(sprintf)(buf, "NONPORT-%#x", port);
503 return buf;
506 /* Note the fact that a port was just deallocated. */
508 static
509 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
511 OpenPort *i = allocated_ports;
512 if (!port) return;
514 while(i) {
515 if(i->port == port) {
516 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
517 if (right & MACH_PORT_TYPE_SEND) {
518 // send rights are refcounted
519 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
520 i->send_count += delta;
521 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
522 else i->type &= ~MACH_PORT_TYPE_SEND;
524 right = right & ~MACH_PORT_TYPE_SEND;
525 if (right) {
526 // other rights are not refcounted
527 if (delta > 0) {
528 i->type |= right;
529 } else if (delta < 0) {
530 i->type &= ~right;
534 if (i->type != 0) return;
536 // Port has no rights left. Kill it.
537 // VG_(printf)("deleting port %p %s", i->port, i->name);
538 if(i->prev)
539 i->prev->next = i->next;
540 else
541 allocated_ports = i->next;
542 if(i->next)
543 i->next->prev = i->prev;
544 if(i->name)
545 VG_(free) (i->name);
546 VG_(free) (i);
547 allocated_port_count--;
548 return;
550 i = i->next;
553 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
556 static
557 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
559 switch (type) {
560 case MACH_MSG_TYPE_PORT_NAME:
561 // this task has no rights for the name
562 break;
563 case MACH_MSG_TYPE_PORT_RECEIVE:
564 // this task gets receive rights
565 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
566 break;
567 case MACH_MSG_TYPE_PORT_SEND:
568 // this task gets a send right
569 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
570 break;
571 case MACH_MSG_TYPE_PORT_SEND_ONCE:
572 // this task gets send-once rights
573 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
574 break;
575 default:
576 vg_assert(0);
577 break;
581 static
582 void record_port_dealloc(mach_port_t port)
584 // deletes 1 send or send-once right (port can't have both)
585 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1);
588 static
589 void record_port_destroy(mach_port_t port)
591 // deletes all rights to port
592 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
596 /* Note the fact that a Mach port was just allocated or transferred.
597 If the port is already known, increment its reference count. */
598 void record_named_port(ThreadId tid, mach_port_t port,
599 mach_port_right_t right, const HChar *name)
601 OpenPort *i;
602 if (!port) return;
604 /* Check to see if this port is already open. */
605 i = allocated_ports;
606 while (i) {
607 if (i->port == port) {
608 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
609 return;
611 i = i->next;
614 /* Not already one: allocate an OpenPort */
615 if (i == NULL) {
616 i = VG_(malloc)("syswrap-darwin.mach-port", sizeof(OpenPort));
618 i->prev = NULL;
619 i->next = allocated_ports;
620 if(allocated_ports) allocated_ports->prev = i;
621 allocated_ports = i;
622 allocated_port_count++;
624 i->port = port;
625 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
626 i->name = NULL;
627 if (right != -1) {
628 i->type = MACH_PORT_TYPE(right);
629 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
630 } else {
631 i->type = 0;
632 i->send_count = 0;
635 assign_port_name(port, name);
640 // Record opening of a nameless port.
641 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
643 record_named_port(tid, port, right, "unnamed-%p");
647 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
648 void VG_(show_open_ports)(void)
650 OpenPort *i;
652 VG_(message)(Vg_UserMsg,
653 "MACH PORTS: %d open at exit.\n", allocated_port_count);
655 for (i = allocated_ports; i; i = i->next) {
656 if (i->name) {
657 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s\n", i->port,
658 i->name);
659 } else {
660 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x\n", i->port);
663 if (i->where) {
664 VG_(pp_ExeContext)(i->where);
665 VG_(message)(Vg_UserMsg, "\n");
669 VG_(message)(Vg_UserMsg, "\n");
673 /* ---------------------------------------------------------------------
674 sync_mappings
675 ------------------------------------------------------------------ */
677 typedef
678 enum { CheckAlways=1, CheckEvery20, CheckNever }
679 CheckHowOften;
681 static const HChar* show_CheckHowOften ( CheckHowOften cho ) {
682 switch (cho) {
683 case CheckAlways: return "Always ";
684 case CheckEvery20: return "Every20";
685 case CheckNever: return "Never ";
686 default: vg_assert(0);
690 /* Statistics for one particular resync-call set of arguments,
691 as specified by key1, key2 and key3. */
692 typedef
693 struct {
694 CheckHowOften cho;
695 const HChar* key1;
696 const HChar* key2;
697 UWord key3;
698 ULong n_checks;
699 ULong n_mappings_added;
700 ULong n_mappings_removed;
702 SyncStats;
704 static Bool cmp_eqkeys_SyncStats ( SyncStats* ss1, SyncStats* ss2 ) {
705 return ss1->key3 == ss2->key3
706 && 0 == VG_(strcmp)(ss1->key1, ss2->key1)
707 && 0 == VG_(strcmp)(ss1->key2, ss2->key2);
710 /* The filter data. */
711 #define N_SYNCSTATS 1000
712 static Int syncstats_used = 0;
713 static SyncStats syncstats[N_SYNCSTATS];
715 /* Statistics overall, for the filter. */
716 static ULong n_syncsRequested = 0; // Total number requested
717 static ULong n_syncsPerformed = 0; // Number carried out (the rest skipped)
720 static
721 void update_syncstats ( CheckHowOften cho,
722 const HChar* key1, const HChar* key2,
723 UWord key3,
724 UInt n_mappings_added, UInt n_mappings_removed )
726 SyncStats dummy = { CheckAlways, key1, key2, key3, 0, 0, 0 };
727 Int i;
728 for (i = 0; i < syncstats_used; i++) {
729 if (cmp_eqkeys_SyncStats(&syncstats[i], &dummy))
730 break;
732 vg_assert(i >= 0 && i <= syncstats_used);
733 if (i == syncstats_used) {
734 // alloc new
735 vg_assert(syncstats_used < N_SYNCSTATS);
736 syncstats_used++;
737 syncstats[i] = dummy;
738 syncstats[i].cho = cho;
740 vg_assert(cmp_eqkeys_SyncStats(&syncstats[i], &dummy));
741 syncstats[i].n_checks++;
742 syncstats[i].n_mappings_added += (ULong)n_mappings_added;
743 syncstats[i].n_mappings_removed += (ULong)n_mappings_removed;
744 // reorder
745 static UInt reorder_ctr = 0;
746 if (i > 0 && 0 == (1 & reorder_ctr++)) {
747 SyncStats tmp = syncstats[i-1];
748 syncstats[i-1] = syncstats[i];
749 syncstats[i] = tmp;
754 static void maybe_show_syncstats ( void )
756 Int i;
758 // display
759 if (0 == (n_syncsRequested & 0xFF)) {
760 VG_(printf)("Resync filter: %'llu requested, %'llu performed (%llu%%)\n",
761 n_syncsRequested, n_syncsPerformed,
762 (100 * n_syncsPerformed) /
763 (n_syncsRequested == 0 ? 1 : n_syncsRequested));
764 for (i = 0; i < syncstats_used; i++) {
765 if (i >= 40) break; // just show the top 40
766 VG_(printf)(" [%3d] (%s) upd %6llu diff %4llu+,%3llu-"
767 " %s %s 0x%08llx\n",
768 i, show_CheckHowOften(syncstats[i].cho),
769 syncstats[i].n_checks,
770 syncstats[i].n_mappings_added,
771 syncstats[i].n_mappings_removed,
772 syncstats[i].key1, syncstats[i].key2,
773 (ULong)syncstats[i].key3);
775 if (i < syncstats_used) {
776 VG_(printf)(" and %d more entries not shown.\n", syncstats_used - i);
778 VG_(printf)("\n");
783 Bool ML_(sync_mappings)(const HChar* when, const HChar* where, UWord num)
785 // If VG(clo_resync_filter) == 0, the filter is disabled, and
786 // we must always honour the resync request.
788 // If VG(clo_resync_filter) == 1, the filter is enabled,
789 // so we try to avoid doing the sync if possible, but keep
790 // quiet.
792 // If VG(clo_resync_filter) == 2, the filter is enabled,
793 // so we try to avoid doing the sync if possible, and also
794 // periodically show stats, so that the filter can be updated.
795 // (by hand).
797 if (VG_(clo_resync_filter) >= 2)
798 maybe_show_syncstats();
800 n_syncsRequested++;
802 // Usually the number of segments added/removed in a single call is very
803 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
804 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
805 // because we can't do dynamic allocation within VG_(get_changed_segments),
806 // because it's in m_aspacemgr.
807 ChangedSeg* css = NULL;
808 Int css_size;
809 Int css_used;
810 Int i;
811 Bool ok;
813 // -------------- BEGIN resync-filter-kludge --------------
815 // Some kludges to try and avoid the worst case cost hit of doing
816 // zillions of resyncs (huge). The idea is that many of the most
817 // common resyncs never appear to cause a delta, so we just ignore
818 // them (CheckNever). Then, a bunch of them also happen a lot, but
819 // only very occasionally cause a delta. We resync after 20 of those
820 // (CheckEvery20). Finally, the rest form a long tail, so we always
821 // resync after those (CheckAlways).
823 // Assume this is kernel-version and word-size specific, so develop
824 // filters accordingly. This might be overly conservative --
825 // I don't know.
827 # define STREQ(_s1, _s2) (0 == VG_(strcmp)((_s1),(_s2)))
828 Bool when_in = STREQ(when, "in");
829 Bool when_after = STREQ(when, "after");
830 Bool where_mmr = STREQ(where, "mach_msg_receive");
831 Bool where_mmrU = STREQ(where, "mach_msg_receive-UNHANDLED");
832 Bool where_iuct = STREQ(where, "iokit_user_client_trap");
833 Bool where_MwcN = STREQ(where, "ML_(wqthread_continue_NORETURN)");
834 Bool where_woQR = STREQ(where, "workq_ops(QUEUE_REQTHREADS)");
835 Bool where_woQ2 = STREQ(where, "workq_ops(QUEUE_REQTHREADS2)");
836 Bool where_woTR = STREQ(where, "workq_ops(THREAD_RETURN)");
837 Bool where_ke64 = STREQ(where, "kevent64");
838 # undef STREQ
840 vg_assert(
841 1 >= ( (where_mmr ? 1 : 0) + (where_mmrU ? 1 : 0)
842 + (where_iuct ? 1 : 0) + (where_MwcN ? 1 : 0)
843 + (where_woQR ? 1 : 0) + (where_woQ2 ? 1 : 0)
844 + (where_woTR ? 1 : 0) + (where_ke64 ? 1 : 0)
846 // merely to stop gcc complaining of non-use in the case where
847 // there's no filter:
848 vg_assert(when_in == True || when_in == False);
849 vg_assert(when_after == True || when_after == False);
851 CheckHowOften check = CheckAlways;
853 # if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
854 /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
855 if (when_after && where_mmr) {
856 // "after mach_msg_receive <number>"
857 switch (num) {
858 case 0x00000000: // upd 12414 diff 36+,0-
859 check = CheckEvery20;
860 break;
861 default:
862 break;
865 else
866 if (when_after && where_mmrU) {
867 // "after mach_msg_receive-UNHANDLED <number>"
868 switch (num) {
869 case 0x00000000: // upd 16687 diff 73+,0-
870 case 0x00000001: // upd 5106 diff 89+,0-
871 case 0x00000002: // upd 1609 diff 1+,0-
872 case 0x00000003: // upd 1987 diff 6+,0-
873 // case 0x00000b95: // upd 2894 diff 57+,1- <==dangerous
874 case 0x000072d9: // upd 2616 diff 11+,0-
875 case 0x000072cb: // upd 2616 diff 9+,0-
876 case 0x000074d5: // upd 172 diff 0+,0-
877 check = CheckEvery20;
878 break;
879 default:
880 break;
883 else
884 if (when_in && where_MwcN && num == 0x00000000) {
885 // in ML_(wqthread_continue_NORETURN) 0x00000000
886 // upd 4346 diff 0+,0-
887 check = CheckEvery20;
889 else
890 if (when_after && where_woQR && num == 0x00000000) {
891 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
892 // upd 14434 diff 102+,0-
893 check = CheckEvery20;
895 /* if (when_after && where_woQ2 && num == 0x00000000) {
896 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
897 // upd XXXX diff XX+,0-
898 check = CheckEvery20;
899 } */
900 else
901 if (when_after && where_woTR && num == 0x00000000) {
902 // after workq_ops(THREAD_RETURN) 0x00000000
903 // upd 14434 diff 102+,0-
904 check = CheckEvery20;
906 else
907 if (when_after && where_ke64 && num == 0x00000000) {
908 // after kevent64 0x00000000
909 // upd 1736 diff 78+,0-
910 check = CheckEvery20;
912 /* ----------- END filter for 64-bit 10.9.x ----------- */
913 # endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
915 # if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
916 /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
917 if (when_after && where_mmr) {
918 // "after mach_msg_receive <number>"
919 switch (num) {
920 case 0x00000000: // upd 2380 diff 23+,0-
921 check = CheckEvery20;
922 break;
923 default:
924 break;
927 else
928 if (when_after && where_mmrU) {
929 // "after mach_msg_receive-UNHANDLED <number>"
930 switch (num) {
931 case 0x00000000: // upd 2370 diff 93+,1- <==dangerous
932 case 0x0000004f: // upd 212 diff 2+,0-
933 case 0x00000b95: // upd 9826 diff 163+,1- diff scale, dangerous
934 case 0x00000ba5: // upd 304 diff 0+,0-
935 case 0x0000157f: // upd 201 diff 2+,0-
936 case 0x0000157d: // upd 197 diff 1+,0-
937 case 0x0000333d: // upd 112 diff 0+,0-
938 case 0x0000333f: // upd 223 diff 10+,0-
939 case 0x000072cd: // upd 8286 diff 98+,0- diff scale
940 case 0x000072ae: // upd 193 diff 10+,0-
941 case 0x000072ec: // upd 319 diff 7+,0-
942 case 0x77303074: // upd 113 diff 3+,0-
943 case 0x10000000: // upd 314 diff 6+,0-
944 check = CheckEvery20;
945 break;
946 default:
947 break;
950 else
951 if (when_in && where_MwcN && num == 0x00000000) {
952 // in ML_(wqthread_continue_NORETURN) 0x00000000
953 // upd 1110 diff 37+,0-
954 check = CheckEvery20;
956 else
957 if (when_after && where_woQR && num == 0x00000000) {
958 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
959 // upd 1099 diff 37+,0-
960 check = CheckEvery20;
962 /* if (when_after && where_woQ2 && num == 0x00000000) {
963 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
964 // upd XXXX diff XX+,0-
965 check = CheckEvery20;
966 } */
967 else
968 if (when_after && where_woTR && num == 0x00000000) {
969 // after workq_ops(THREAD_RETURN) 0x00000000
970 // 1239 diff 53+,0-
971 check = CheckEvery20;
973 else
974 if (when_after && where_ke64 && num == 0x00000000) {
975 // after kevent64 0x00000000
976 // upd 1463 diff 15+,0-
977 check = CheckEvery20;
979 /* ----------- END filter for 64-bit 10.10.x ----------- */
980 # endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
982 /* Regardless of what the filter says, force a sync every 1 time in
983 1000, to stop things getting too far out of sync. */
985 static UInt ctr1k = 0;
986 ctr1k++;
987 if ((ctr1k % 1000) == 0)
988 check = CheckAlways;
991 /* If the filter is disabled, we must always check. */
992 if (VG_(clo_resync_filter) == 0)
993 check = CheckAlways;
995 switch (check) {
996 case CheckAlways:
997 break;
998 case CheckEvery20: {
999 // only resync once every 20th time
1000 static UInt ctr10 = 0;
1001 ctr10++;
1002 if ((ctr10 % 20) != 0) return False;
1003 break;
1005 case CheckNever:
1006 return False;
1007 default:
1008 vg_assert(0);
1011 // --------------- END resync-filter-kludge ---------------
1013 if (0 || VG_(clo_trace_syscalls)) {
1014 VG_(debugLog)(0, "syswrap-darwin",
1015 "sync_mappings (%s) (\"%s\", \"%s\", 0x%lx)\n",
1016 show_CheckHowOften(check), when, where, num);
1019 // 16 is enough for most cases, but small enough that overflow happens
1020 // occasionally and thus the overflow path gets some test coverage.
1021 css_size = 16;
1022 ok = False;
1023 while (!ok) {
1024 VG_(free)(css); // css is NULL on first iteration; that's ok.
1025 css = VG_(calloc)("sys_wrap.sync_mappings",
1026 css_size, sizeof(ChangedSeg));
1027 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
1028 css_size *= 2;
1031 UInt css_added = 0, css_removed = 0;
1033 // Now add/remove them.
1034 for (i = 0; i < css_used; i++) {
1035 ChangedSeg* cs = &css[i];
1036 if (cs->is_added) {
1037 css_added++;
1038 ML_(notify_core_and_tool_of_mmap)(
1039 cs->start, cs->end - cs->start + 1,
1040 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
1041 // should this call VG_(di_notify_mmap) also?
1042 } else {
1043 css_removed++;
1044 ML_(notify_core_and_tool_of_munmap)(
1045 cs->start, cs->end - cs->start + 1);
1047 if (VG_(clo_trace_syscalls)) {
1048 if (cs->is_added) {
1049 VG_(debugLog)(0, "syswrap-darwin",
1050 " added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
1051 cs->start, cs->end + 1, (UInt)cs->prot, where, when);
1052 } else {
1053 VG_(debugLog)(0, "syswrap-darwin",
1054 " removed region 0x%010lx..0x%010lx at %s (%s)\n",
1055 cs->start, cs->end + 1, where, when);
1060 VG_(free)(css);
1062 if (0)
1063 VG_(debugLog)(0, "syswrap-darwin", "SYNC: %d %s %s\n",
1064 css_used, when, where);
1066 // Update the stats, so we can derive the filter above.
1067 n_syncsPerformed++;
1068 update_syncstats(check, when, where, num, css_added, css_removed);
1070 return css_used > 0;
1073 /* ---------------------------------------------------------------------
1074 wrappers
1075 ------------------------------------------------------------------ */
1077 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
1078 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
1080 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
1081 #define POST_FN(name) vgSysWrap_darwin_##name##_after
1083 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
1084 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
1086 #if VG_WORDSIZE == 4
1087 // Combine two 32-bit values into a 64-bit value
1088 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
1089 # if defined(VGA_x86)
1090 # define LOHI64(lo,hi) ( ((ULong)(UInt)(lo)) | (((ULong)(UInt)(hi)) << 32) )
1091 # else
1092 # error unknown architecture
1093 # endif
1094 #endif
1096 // Retrieve the current Mach thread
1097 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1099 // Set the POST handler for a mach_msg derivative
1100 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1102 // Set or get values saved from Mach messages
1103 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
1104 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
1105 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
1107 /* ---------------------------------------------------------------------
1108 darwin ioctl wrapper
1109 ------------------------------------------------------------------ */
1111 PRE(ioctl)
1113 *flags |= SfMayBlock;
1115 /* Handle ioctls that don't take an arg first */
1116 switch (ARG2 /* request */) {
1117 case VKI_TIOCSCTTY:
1118 case VKI_TIOCEXCL:
1119 case VKI_TIOCSBRK:
1120 case VKI_TIOCCBRK:
1121 case VKI_TIOCPTYGRANT:
1122 case VKI_TIOCPTYUNLK:
1123 case VKI_DTRACEHIOC_REMOVE:
1124 case VKI_BIOCFLUSH:
1125 case VKI_BIOCPROMISC:
1126 PRINT("ioctl ( %lu, 0x%lx )", ARG1, ARG2);
1127 PRE_REG_READ2(long, "ioctl",
1128 unsigned int, fd, unsigned int, request);
1129 return;
1130 default:
1131 PRINT("ioctl ( %lu, 0x%lx, %#lx )", ARG1, ARG2, ARG3);
1132 PRE_REG_READ3(long, "ioctl",
1133 unsigned int, fd, unsigned int, request, unsigned long, arg);
1136 switch (ARG2 /* request */) {
1137 case VKI_TIOCGWINSZ:
1138 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
1139 break;
1140 case VKI_TIOCSWINSZ:
1141 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
1142 break;
1143 case VKI_TIOCMBIS:
1144 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
1145 break;
1146 case VKI_TIOCMBIC:
1147 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
1148 break;
1149 case VKI_TIOCMSET:
1150 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
1151 break;
1152 case VKI_TIOCMGET:
1153 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
1154 break;
1155 case VKI_TIOCGPGRP:
1156 /* Get process group ID for foreground processing group. */
1157 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1158 break;
1159 case VKI_TIOCSPGRP:
1160 /* Set a process group ID? */
1161 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1162 break;
1163 case VKI_FIONBIO:
1164 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
1165 break;
1166 case VKI_FIOASYNC:
1167 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
1168 break;
1169 case VKI_FIONREAD: /* identical to SIOCINQ */
1170 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1171 break;
1174 /* These all use struct ifreq AFAIK */
1175 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1176 case VKI_SIOCGIFFLAGS: /* get flags */
1177 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1178 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1179 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
1180 break;
1181 case VKI_SIOCGIFMTU: /* get MTU size */
1182 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1183 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1184 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
1185 break;
1186 case VKI_SIOCGIFADDR: /* get PA address */
1187 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1188 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1189 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
1190 break;
1191 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1192 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1193 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1194 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
1195 break;
1196 case VKI_SIOCGIFMETRIC: /* get metric */
1197 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1198 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1199 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
1200 break;
1201 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1202 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1203 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1204 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
1205 break;
1206 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1207 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1208 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1209 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
1210 break;
1211 case VKI_SIOCGIFCONF: /* get iface list */
1212 /* WAS:
1213 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1214 KERNEL_DO_SYSCALL(tid,RES);
1215 if (!VG_(is_kerror)(RES) && RES == 0)
1216 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1218 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1219 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
1220 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
1221 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1222 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
1223 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
1224 if ( ARG3 ) {
1225 // TODO len must be readable and writable
1226 // buf pointer only needs to be readable
1227 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1228 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1229 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1231 break;
1233 case VKI_SIOCSIFFLAGS: /* set flags */
1234 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1235 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1236 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1237 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1238 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1239 break;
1240 case VKI_SIOCSIFADDR: /* set PA address */
1241 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1242 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1243 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1244 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1245 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1246 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1247 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1248 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1249 break;
1250 case VKI_SIOCSIFMETRIC: /* set metric */
1251 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1252 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1253 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1254 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1255 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1256 break;
1257 case VKI_SIOCSIFMTU: /* set MTU size */
1258 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1259 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1260 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1261 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1262 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1263 break;
1264 /* Routing table calls. */
1265 #ifdef VKI_SIOCADDRT
1266 case VKI_SIOCADDRT: /* add routing table entry */
1267 case VKI_SIOCDELRT: /* delete routing table entry */
1268 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
1269 sizeof(struct vki_rtentry));
1270 break;
1271 #endif
1273 case VKI_SIOCGPGRP:
1274 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
1275 break;
1276 case VKI_SIOCSPGRP:
1277 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
1278 //tst->sys_flags &= ~SfMayBlock;
1279 break;
1281 case VKI_FIODTYPE:
1282 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1283 break;
1285 case VKI_DTRACEHIOC_ADDDOF:
1286 break;
1288 // ttycom.h
1289 case VKI_TIOCGETA:
1290 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
1291 break;
1292 case VKI_TIOCSETA:
1293 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
1294 break;
1295 case VKI_TIOCGETD:
1296 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
1297 break;
1298 case VKI_TIOCSETD:
1299 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
1300 break;
1301 case VKI_TIOCPTYGNAME:
1302 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
1303 break;
1305 // filio.h
1306 case VKI_FIOCLEX:
1307 break;
1308 case VKI_FIONCLEX:
1309 break;
1311 // net/bpf.h
1312 case VKI_BIOCSETF: /* set BPF filter */
1314 * struct bpf_program has a 32-bit count of instructions,
1315 * followed by a pointer to an array of those instructions.
1316 * In 64-bit mode, there's padding between those two elements.
1318 * So that we don't bogusly complain about the padding bytes,
1319 * we just report that we read bf_len and and bf_insns.
1321 * We then make sure that what bf_insns points to is valid.
1323 PRE_MEM_READ( "ioctl(BIOCSETF)",
1324 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_len,
1325 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_len) );
1326 PRE_MEM_READ( "ioctl(BIOCSETF)",
1327 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_insns,
1328 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_insns) );
1329 if ( ARG3 ) {
1330 /* bf_len * sizeof (*bf_insns) */
1331 struct vki_bpf_program *bp = (struct vki_bpf_program *)ARG3;
1332 if ( bp->bf_insns != NULL )
1333 PRE_MEM_READ( "ioctl(BIOCSETF) points to a struct bpf_program whose bf_insns member",
1334 (Addr)(bp->vki_bf_insns),
1335 bp->vki_bf_len * sizeof(*bp->vki_bf_insns) );
1337 break;
1338 case VKI_BIOCSETIF: /* set BPF interface */
1339 PRE_MEM_RASCIIZ( "ioctl(BIOCSETIF)",
1340 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1341 break;
1342 case VKI_BIOCSRTIMEOUT: /* set BPF timeout */
1344 * 64-bit struct timeval starts with a 64-bit "seconds since the
1345 * Epoch" value, followed by a 32-bit microseconds value. The
1346 * resulting structure is padded to a multiple of 8 bytes, so
1347 * there are 4 padding bytes at the end.
1349 * So that we don't bogusly complain about the padding bytes,
1350 * we just report that we read tv_sec and tv_usec.
1352 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1353 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_sec,
1354 sizeof(((struct vki_timeval *)ARG3)->vki_tv_sec) );
1355 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1356 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_usec,
1357 sizeof(((struct vki_timeval *)ARG3)->vki_tv_usec) );
1358 break;
1359 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1360 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1361 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list,
1362 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list) );
1363 if ( ARG3 ) {
1364 /* bfl_len * sizeof (*bfl_list) */
1365 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1366 if ( bdl->bfl_list != NULL )
1367 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1368 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len,
1369 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len) );
1370 PRE_MEM_WRITE( "ioctl(BIOCGDLTLIST) points to a struct bpf_dltlist whose bfl_list member",
1371 (Addr)(bdl->vki_bfl_list),
1372 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1374 break;
1376 default:
1377 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
1378 break;
1383 POST(ioctl)
1385 vg_assert(SUCCESS);
1386 switch (ARG2 /* request */) {
1387 case VKI_TIOCGWINSZ:
1388 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
1389 break;
1390 case VKI_TIOCSWINSZ:
1391 case VKI_TIOCMBIS:
1392 case VKI_TIOCMBIC:
1393 case VKI_TIOCMSET:
1394 break;
1395 case VKI_TIOCMGET:
1396 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
1397 break;
1398 case VKI_TIOCGPGRP:
1399 /* Get process group ID for foreground processing group. */
1400 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1401 break;
1402 case VKI_TIOCSPGRP:
1403 /* Set a process group ID? */
1404 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1405 break;
1406 case VKI_TIOCSCTTY:
1407 break;
1408 case VKI_FIONBIO:
1409 break;
1410 case VKI_FIOASYNC:
1411 break;
1412 case VKI_FIONREAD: /* identical to SIOCINQ */
1413 POST_MEM_WRITE( ARG3, sizeof(int) );
1414 break;
1416 /* These all use struct ifreq AFAIK */
1417 case VKI_SIOCGIFFLAGS: /* get flags */
1418 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1419 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1420 break;
1421 case VKI_SIOCGIFMTU: /* get MTU size */
1422 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1423 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1424 break;
1425 case VKI_SIOCGIFADDR: /* get PA address */
1426 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1427 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1428 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1429 POST_MEM_WRITE(
1430 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1431 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1432 break;
1433 case VKI_SIOCGIFMETRIC: /* get metric */
1434 POST_MEM_WRITE(
1435 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1436 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1437 break;
1438 case VKI_SIOCGIFCONF: /* get iface list */
1439 /* WAS:
1440 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1441 KERNEL_DO_SYSCALL(tid,RES);
1442 if (!VG_(is_kerror)(RES) && RES == 0)
1443 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1445 if (RES == 0 && ARG3 ) {
1446 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1447 if (ifc->vki_ifc_buf != NULL)
1448 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1450 break;
1452 case VKI_SIOCSIFFLAGS: /* set flags */
1453 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1454 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1455 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1456 case VKI_SIOCSIFMETRIC: /* set metric */
1457 case VKI_SIOCSIFADDR: /* set PA address */
1458 case VKI_SIOCSIFMTU: /* set MTU size */
1459 break;
1461 #ifdef VKI_SIOCADDRT
1462 /* Routing table calls. */
1463 case VKI_SIOCADDRT: /* add routing table entry */
1464 case VKI_SIOCDELRT: /* delete routing table entry */
1465 break;
1466 #endif
1468 case VKI_SIOCGPGRP:
1469 POST_MEM_WRITE(ARG3, sizeof(int));
1470 break;
1471 case VKI_SIOCSPGRP:
1472 break;
1474 case VKI_FIODTYPE:
1475 POST_MEM_WRITE( ARG3, sizeof(int) );
1476 break;
1478 case VKI_DTRACEHIOC_REMOVE:
1479 case VKI_DTRACEHIOC_ADDDOF:
1480 break;
1482 // ttycom.h
1483 case VKI_TIOCGETA:
1484 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1485 break;
1486 case VKI_TIOCSETA:
1487 break;
1488 case VKI_TIOCGETD:
1489 POST_MEM_WRITE( ARG3, sizeof(int) );
1490 break;
1491 case VKI_TIOCSETD:
1492 break;
1493 case VKI_TIOCPTYGNAME:
1494 POST_MEM_WRITE( ARG3, 128);
1495 break;
1496 case VKI_TIOCSBRK: /* set break bit */
1497 case VKI_TIOCCBRK: /* clear break bit */
1498 case VKI_TIOCPTYGRANT:
1499 case VKI_TIOCPTYUNLK:
1500 break;
1502 // bpf.h
1503 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1504 if (RES == 0 && ARG3 ) {
1505 /* bfl_len * sizeof (*bfl_list) */
1506 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1507 if ( bdl->vki_bfl_list != NULL )
1508 POST_MEM_WRITE( (Addr)(bdl->vki_bfl_list),
1509 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1511 break;
1513 default:
1514 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
1515 break;
1520 /* ---------------------------------------------------------------------
1521 darwin fcntl wrapper
1522 ------------------------------------------------------------------ */
1523 static const HChar *name_for_fcntl(UWord cmd) {
1524 #define F(n) case VKI_##n: return #n
1525 switch (cmd) {
1526 F(F_CHKCLEAN);
1527 F(F_RDAHEAD);
1528 F(F_NOCACHE);
1529 F(F_FULLFSYNC);
1530 F(F_FREEZE_FS);
1531 F(F_THAW_FS);
1532 F(F_GLOBAL_NOCACHE);
1533 F(F_PREALLOCATE);
1534 F(F_SETSIZE);
1535 F(F_RDADVISE);
1536 # if DARWIN_VERS < DARWIN_10_9
1537 F(F_READBOOTSTRAP);
1538 F(F_WRITEBOOTSTRAP);
1539 # endif
1540 F(F_LOG2PHYS);
1541 F(F_GETPATH);
1542 F(F_PATHPKG_CHECK);
1543 F(F_ADDSIGS);
1544 # if DARWIN_VERS >= DARWIN_10_9
1545 F(F_ADDFILESIGS);
1546 # endif
1547 # if DARWIN_VERS >= DARWIN_10_11
1548 F(F_ADDFILESIGS_FOR_DYLD_SIM);
1549 F(F_BARRIERFSYNC);
1550 F(F_ADDFILESIGS_RETURN);
1551 # endif
1552 default:
1553 return "UNKNOWN";
1555 #undef F
1558 PRE(fcntl)
1560 switch (ARG2) {
1561 // These ones ignore ARG3.
1562 case VKI_F_GETFD:
1563 case VKI_F_GETFL:
1564 case VKI_F_GETOWN:
1565 PRINT("fcntl ( %lu, %lu )", ARG1,ARG2);
1566 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1567 break;
1569 // These ones use ARG3 as "arg".
1570 case VKI_F_DUPFD:
1571 case VKI_F_SETFD:
1572 case VKI_F_SETFL:
1573 case VKI_F_SETOWN:
1574 PRINT("fcntl[ARG3=='arg'] ( %lu, %lu, %lu )", ARG1,ARG2,ARG3);
1575 PRE_REG_READ3(long, "fcntl",
1576 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1577 break;
1579 // These ones use ARG3 as "lock".
1580 case VKI_F_GETLK:
1581 case VKI_F_SETLK:
1582 case VKI_F_SETLKW:
1583 PRINT("fcntl[ARG3=='lock'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1584 PRE_REG_READ3(long, "fcntl",
1585 unsigned int, fd, unsigned int, cmd,
1586 struct flock64 *, lock);
1587 // GrP fixme mem read sizeof(flock64)
1588 if (ARG2 == VKI_F_SETLKW)
1589 *flags |= SfMayBlock;
1590 break;
1591 # if DARWIN_VERS >= DARWIN_10_10
1592 case VKI_F_SETLKWTIMEOUT:
1593 PRINT("fcntl[ARG3=='locktimeout'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1594 PRE_REG_READ3(long, "fcntl",
1595 unsigned int, fd, unsigned int, cmd,
1596 struct flocktimeout *, lock);
1597 *flags |= SfMayBlock;
1598 break;
1599 # endif
1601 // none
1602 case VKI_F_CHKCLEAN:
1603 case VKI_F_RDAHEAD:
1604 case VKI_F_NOCACHE:
1605 case VKI_F_FULLFSYNC:
1606 case VKI_F_FREEZE_FS:
1607 case VKI_F_THAW_FS:
1608 case VKI_F_GLOBAL_NOCACHE:
1609 PRINT("fcntl ( %lu, %s, %lu )", ARG1, name_for_fcntl(ARG1), ARG2);
1610 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1611 break;
1613 // struct fstore
1614 case VKI_F_PREALLOCATE:
1615 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1616 PRE_REG_READ3(long, "fcntl",
1617 unsigned int, fd, unsigned int, cmd,
1618 struct fstore *, fstore);
1620 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1621 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1622 fstore->fst_flags );
1623 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1624 fstore->fst_posmode );
1625 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1626 fstore->fst_offset );
1627 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1628 fstore->fst_length );
1629 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1630 fstore->fst_bytesalloc);
1632 break;
1634 // off_t
1635 case VKI_F_SETSIZE:
1636 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1637 PRE_REG_READ3(long, "fcntl",
1638 unsigned int, fd, unsigned int, cmd,
1639 vki_off_t *, offset);
1640 break;
1642 // struct radvisory
1643 case VKI_F_RDADVISE:
1644 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1645 PRE_REG_READ3(long, "fcntl",
1646 unsigned int, fd, unsigned int, cmd,
1647 struct vki_radvisory *, radvisory);
1649 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1650 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1651 radvisory->ra_offset );
1652 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1653 radvisory->ra_count );
1655 break;
1657 # if DARWIN_VERS < DARWIN_10_9
1658 // struct fbootstraptransfer
1659 case VKI_F_READBOOTSTRAP:
1660 case VKI_F_WRITEBOOTSTRAP:
1661 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1662 PRE_REG_READ3(long, "fcntl",
1663 unsigned int, fd, unsigned int, cmd,
1664 struct fbootstraptransfer *, bootstrap);
1665 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1666 ARG3, sizeof(struct vki_fbootstraptransfer) );
1667 break;
1668 # endif
1670 // struct log2phys (out)
1671 case VKI_F_LOG2PHYS:
1672 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1673 PRE_REG_READ3(long, "fcntl",
1674 unsigned int, fd, unsigned int, cmd,
1675 struct log2phys *, l2p);
1676 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1677 ARG3, sizeof(struct vki_log2phys) );
1678 break;
1680 // char[maxpathlen] (out)
1681 case VKI_F_GETPATH:
1682 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1683 PRE_REG_READ3(long, "fcntl",
1684 unsigned int, fd, unsigned int, cmd,
1685 char *, pathbuf);
1686 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1687 ARG3, VKI_MAXPATHLEN );
1688 break;
1690 // char[maxpathlen] (in)
1691 case VKI_F_PATHPKG_CHECK:
1692 PRINT("fcntl ( %lu, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1693 (HChar *)ARG3);
1694 PRE_REG_READ3(long, "fcntl",
1695 unsigned int, fd, unsigned int, cmd,
1696 char *, pathbuf);
1697 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1698 break;
1700 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1701 PRINT("fcntl ( %lu, %s )", ARG1, name_for_fcntl(ARG2));
1702 PRE_REG_READ3(long, "fcntl",
1703 unsigned int, fd, unsigned int, cmd,
1704 vki_fsignatures_t *, sigs);
1707 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1708 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1709 fsigs->fs_blob_start);
1710 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1711 fsigs->fs_blob_size);
1713 if (fsigs->fs_blob_start)
1714 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1715 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1717 break;
1719 case VKI_F_ADDFILESIGS: /* Add signature from same file (used by dyld for shared libs) */
1720 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1721 PRE_REG_READ3(long, "fcntl",
1722 unsigned int, fd, unsigned int, cmd,
1723 vki_fsignatures_t *, sigs);
1726 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1727 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1728 fsigs->fs_blob_start);
1729 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1730 fsigs->fs_blob_size);
1732 break;
1734 # if DARWIN_VERS >= DARWIN_10_11
1735 case VKI_F_ADDFILESIGS_FOR_DYLD_SIM: /* Add signature from same file, only if it is signed
1736 by Apple used by dyld for simulator */
1737 // FIXME: RK
1738 break;
1740 case VKI_F_BARRIERFSYNC: /* fsync + issue barrier to drive */
1741 // FIXME: RK
1742 break;
1744 case VKI_F_ADDFILESIGS_RETURN: /* Add signature from same file, return end offset in
1745 structure on success */
1746 // FIXME: RK
1747 break;
1748 # endif
1750 default:
1751 PRINT("fcntl ( %lu, %lu [??] )", ARG1, ARG2);
1752 log_decaying("UNKNOWN fcntl %lu!", ARG2);
1753 break;
1757 POST(fcntl)
1759 vg_assert(SUCCESS);
1760 switch (ARG2) {
1761 case VKI_F_DUPFD:
1762 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1763 VG_(close)(RES);
1764 SET_STATUS_Failure( VKI_EMFILE );
1765 } else {
1766 if (VG_(clo_track_fds))
1767 ML_(record_fd_open_named)(tid, RES);
1769 break;
1771 case VKI_F_GETFD:
1772 case VKI_F_GETFL:
1773 case VKI_F_GETOWN:
1774 case VKI_F_SETFD:
1775 case VKI_F_SETFL:
1776 case VKI_F_SETOWN:
1777 case VKI_F_GETLK:
1778 case VKI_F_SETLK:
1779 case VKI_F_SETLKW:
1780 # if DARWIN_VERS >= DARWIN_10_10
1781 case VKI_F_SETLKWTIMEOUT:
1782 break;
1783 # endif
1785 case VKI_F_PREALLOCATE:
1787 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1788 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1790 break;
1792 case VKI_F_LOG2PHYS:
1793 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1794 break;
1796 case VKI_F_GETPATH:
1797 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1798 PRINT("\"%s\"", (char*)ARG3);
1799 break;
1801 default:
1802 // DDD: ugh, missing lots of cases here, not nice
1803 break;
1807 /* ---------------------------------------------------------------------
1808 unix syscalls
1809 ------------------------------------------------------------------ */
1811 PRE(futimes)
1813 PRINT("futimes ( %ld, %#lx )", SARG1, ARG2);
1814 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1815 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1816 SET_STATUS_Failure( VKI_EBADF );
1817 } else if (ARG2 != 0) {
1818 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1819 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1823 PRE(semget)
1825 PRINT("semget ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1826 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1829 PRE(semop)
1831 *flags |= SfMayBlock;
1832 PRINT("semop ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
1833 PRE_REG_READ3(long, "semop",
1834 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1835 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1838 PRE(semctl)
1840 switch (ARG3) {
1841 case VKI_IPC_STAT:
1842 case VKI_IPC_SET:
1843 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1844 PRE_REG_READ4(long, "semctl",
1845 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1846 break;
1847 case VKI_GETALL:
1848 case VKI_SETALL:
1849 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1850 PRE_REG_READ4(long, "semctl",
1851 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1852 break;
1853 case VKI_SETVAL:
1854 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1855 PRE_REG_READ4(long, "semctl",
1856 int, semid, int, semnum, int, cmd, int, arg);
1857 break;
1858 default:
1859 PRINT("semctl ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1860 PRE_REG_READ3(long, "semctl",
1861 int, semid, int, semnum, int, cmd);
1862 break;
1864 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1866 POST(semctl)
1868 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1871 PRE(sem_open)
1873 if (ARG2 & VKI_O_CREAT) {
1874 // 4-arg version
1875 PRINT("sem_open ( %#lx(%s), %ld, %lu, %lu )",
1876 ARG1, (HChar*)ARG1, SARG2, ARG3, ARG4);
1877 PRE_REG_READ4(vki_sem_t *, "sem_open",
1878 const char *, name, int, oflag, vki_mode_t, mode,
1879 unsigned int, value);
1880 } else {
1881 // 2-arg version
1882 PRINT("sem_open ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
1883 PRE_REG_READ2(vki_sem_t *, "sem_open",
1884 const char *, name, int, oflag);
1886 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1888 /* Otherwise handle normally */
1889 *flags |= SfMayBlock;
1892 PRE(sem_close)
1894 PRINT("sem_close( %#lx )", ARG1);
1895 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1898 PRE(sem_unlink)
1900 PRINT("sem_unlink( %#lx(%s) )", ARG1, (HChar*)ARG1);
1901 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1902 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1905 PRE(sem_post)
1907 PRINT("sem_post( %#lx )", ARG1);
1908 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1909 *flags |= SfMayBlock;
1912 PRE(sem_destroy)
1914 PRINT("sem_destroy( %#lx )", ARG1);
1915 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1916 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1919 PRE(sem_init)
1921 PRINT("sem_init( %#lx, %ld, %lu )", ARG1, SARG2, ARG3);
1922 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1923 int, pshared, unsigned int, value);
1924 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1927 POST(sem_init)
1929 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1932 PRE(sem_wait)
1934 PRINT("sem_wait( %#lx )", ARG1);
1935 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1936 *flags |= SfMayBlock;
1939 PRE(sem_trywait)
1941 PRINT("sem_trywait( %#lx )", ARG1);
1942 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1943 *flags |= SfMayBlock;
1946 PRE(kqueue)
1948 PRINT("kqueue()");
1951 POST(kqueue)
1953 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1954 VG_(close)(RES);
1955 SET_STATUS_Failure( VKI_EMFILE );
1956 } else {
1957 if (VG_(clo_track_fds)) {
1958 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1963 PRE(fileport_makeport)
1965 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1966 ARG1, ARG2);
1969 PRE(guarded_open_np)
1971 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1972 ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1975 PRE(guarded_kqueue_np)
1977 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1978 ARG1, ARG2);
1981 POST(guarded_kqueue_np)
1983 if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1984 VG_(close)(RES);
1985 SET_STATUS_Failure( VKI_EMFILE );
1986 } else {
1987 if (VG_(clo_track_fds)) {
1988 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1993 PRE(guarded_close_np)
1995 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1996 ARG1, ARG2);
1999 PRE(change_fdguard_np)
2001 PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
2002 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2005 PRE(connectx)
2007 PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
2008 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2011 PRE(disconnectx)
2013 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
2014 ARG1, ARG2, ARG3);
2018 PRE(kevent)
2020 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2021 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2022 PRE_REG_READ6(int,"kevent", int,kq,
2023 const struct vki_kevent *,changelist, int,nchanges,
2024 struct vki_kevent *,eventlist, int,nevents,
2025 const struct vki_timespec *,timeout);
2027 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
2028 ARG2, ARG3 * sizeof(struct vki_kevent));
2029 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
2030 ARG4, ARG5 * sizeof(struct vki_kevent));
2031 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
2032 ARG6, sizeof(struct vki_timespec));
2034 *flags |= SfMayBlock;
2037 POST(kevent)
2039 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
2040 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
2044 PRE(kevent64)
2046 PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2047 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6);
2048 PRE_REG_READ6(int,"kevent64", int,kq,
2049 const struct vki_kevent64 *,changelist, int,nchanges,
2050 struct vki_kevent64 *,eventlist, int,nevents,
2051 const struct vki_timespec *,timeout);
2053 if (ARG3) PRE_MEM_READ ("kevent64(changelist)",
2054 ARG2, ARG3 * sizeof(struct vki_kevent64));
2055 if (ARG5) PRE_MEM_WRITE("kevent64(eventlist)",
2056 ARG4, ARG5 * sizeof(struct vki_kevent64));
2057 if (ARG6) PRE_MEM_READ ("kevent64(timeout)",
2058 ARG6, sizeof(struct vki_timespec));
2060 *flags |= SfMayBlock;
2063 POST(kevent64)
2065 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
2066 if (RES > 0) {
2067 ML_(sync_mappings)("after", "kevent64", 0);
2068 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
2073 Addr pthread_starter = 0;
2074 Addr wqthread_starter = 0;
2075 SizeT pthread_structsize = 0;
2077 PRE(bsdthread_register)
2079 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
2080 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
2081 void *,"wqthread", size_t,"pthsize");
2083 pthread_starter = ARG1;
2084 wqthread_starter = ARG2;
2085 pthread_structsize = ARG3;
2086 ARG1 = (Word)&pthread_hijack_asm;
2087 ARG2 = (Word)&wqthread_hijack_asm;
2090 PRE(workq_open)
2092 PRINT("workq_open()");
2093 PRE_REG_READ0(int, "workq_open");
2095 // This creates lots of threads and thread stacks under the covers,
2096 // but we ignore them all until some work item starts running on it.
2099 static const HChar *workqop_name(int op)
2101 switch (op) {
2102 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
2103 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
2104 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
2105 case VKI_WQOPS_THREAD_SETCONC: return "THREAD_SETCONC";
2106 case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
2107 case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
2108 case VKI_WQOPS_QUEUE_REQTHREADS2: return "QUEUE_REQTHREADS2";
2109 case VKI_WQOPS_THREAD_KEVENT_RETURN: return "THREAD_KEVENT_RETURN";
2110 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY: return "SET_EVENT_MANAGER_PRIORITY";
2111 case VKI_WQOPS_THREAD_WORKLOOP_RETURN: return "THREAD_WORKLOOP_RETURN";
2112 case VKI_WQOPS_SHOULD_NARROW: return "SHOULD_NARROW";
2113 default: return "?";
2118 PRE(workq_ops)
2120 PRINT("workq_ops( %ld(%s), %#lx, %ld )", SARG1, workqop_name(ARG1), ARG2,
2121 SARG3);
2122 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2123 int,"priority");
2125 switch (ARG1) {
2126 case VKI_WQOPS_QUEUE_ADD:
2127 case VKI_WQOPS_QUEUE_REMOVE:
2128 // GrP fixme need anything here?
2129 // GrP fixme may block?
2130 break;
2131 case VKI_WQOPS_THREAD_RETURN: {
2132 // The interesting case. The kernel will do one of two things:
2133 // 1. Return normally. We continue; libc proceeds to stop the thread.
2134 // V does nothing special here.
2135 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2136 // new work item, and never returns from workq_ops.
2137 // V handles this by longjmp() from wqthread_hijack back to the
2138 // scheduler, which continues at the new client SP/IP/state.
2139 // This works something like V's signal handling.
2140 // To the tool, this looks like workq_ops() sometimes returns
2141 // to a strange address.
2142 ThreadState *tst = VG_(get_ThreadState)(tid);
2143 tst->os_state.wq_jmpbuf_valid = True;
2144 *flags |= SfMayBlock; // GrP fixme true?
2145 break;
2147 case VKI_WQOPS_THREAD_SETCONC:
2148 // RK fixme need anything here?
2149 // RK fixme may block?
2150 break;
2151 case VKI_WQOPS_QUEUE_NEWSPISUPP:
2152 // JRS don't think we need to do anything here -- this just checks
2153 // whether some newer functionality is supported
2154 break;
2155 case VKI_WQOPS_QUEUE_REQTHREADS:
2156 case VKI_WQOPS_QUEUE_REQTHREADS2:
2157 // JRS uh, looks like it queues up a bunch of threads, or some such?
2158 *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
2159 break;
2160 case VKI_WQOPS_THREAD_KEVENT_RETURN:
2161 // RK fixme need anything here?
2162 // perhaps similar to VKI_WQOPS_THREAD_RETURN above?
2163 break;
2164 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY:
2165 // RK fixme this just sets scheduling priorities - don't think we need
2166 // to do anything here
2167 break;
2168 case VKI_WQOPS_THREAD_WORKLOOP_RETURN:
2169 case VKI_WQOPS_SHOULD_NARROW:
2170 // RK fixme need anything here?
2171 // RK fixme may block?
2172 break;
2173 default:
2174 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
2175 break;
2178 POST(workq_ops)
2180 ThreadState *tst = VG_(get_ThreadState)(tid);
2181 tst->os_state.wq_jmpbuf_valid = False;
2182 switch (ARG1) {
2183 case VKI_WQOPS_THREAD_RETURN:
2184 ML_(sync_mappings)("after", "workq_ops(THREAD_RETURN)", 0);
2185 break;
2186 case VKI_WQOPS_QUEUE_REQTHREADS:
2187 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2188 break;
2189 case VKI_WQOPS_QUEUE_REQTHREADS2:
2190 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS2)", 0);
2191 break;
2192 default:
2193 break;
2199 PRE(__mac_syscall)
2201 PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
2202 ARG1, (HChar*)ARG1, SARG2, ARG3);
2203 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
2204 int,"call", void *,"arg");
2206 // GrP fixme check call's arg?
2207 // GrP fixme check policy?
2211 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2212 More like syswrap-generic's sys_exit_group. */
2213 PRE(exit)
2215 ThreadId t;
2216 ThreadState* tst;
2218 PRINT("darwin exit( %ld )", SARG1);
2219 PRE_REG_READ1(void, "exit", int, status);
2221 tst = VG_(get_ThreadState)(tid);
2223 /* A little complex; find all the threads with the same threadgroup
2224 as this one (including this one), and mark them to exit */
2225 for (t = 1; t < VG_N_THREADS; t++) {
2226 if ( /* not alive */
2227 VG_(threads)[t].status == VgTs_Empty
2228 /* GrP fixme zombie? */
2230 continue;
2232 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
2233 VG_(threads)[t].os_state.exitcode = ARG1;
2235 if (t != tid)
2236 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
2239 /* We have to claim the syscall already succeeded. */
2240 SET_STATUS_Success(0);
2244 PRE(sigaction)
2246 PRINT("sigaction ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2247 PRE_REG_READ3(long, "sigaction",
2248 int, signum, vki_sigaction_toK_t *, act,
2249 vki_sigaction_fromK_t *, oldact);
2251 if (ARG2 != 0) {
2252 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
2253 PRE_MEM_READ( "sigaction(act->sa_handler)",
2254 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2255 PRE_MEM_READ( "sigaction(act->sa_mask)",
2256 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2257 PRE_MEM_READ( "sigaction(act->sa_flags)",
2258 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2260 if (ARG3 != 0)
2261 PRE_MEM_WRITE( "sigaction(oldact)",
2262 ARG3, sizeof(vki_sigaction_fromK_t));
2264 SET_STATUS_from_SysRes(
2265 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
2266 (vki_sigaction_fromK_t *)ARG3)
2269 POST(sigaction)
2271 vg_assert(SUCCESS);
2272 if (RES == 0 && ARG3 != 0)
2273 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
2277 PRE(__pthread_kill)
2279 PRINT("__pthread_kill ( %#lx, %ld )", ARG1, SARG2);
2280 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
2284 PRE(__pthread_sigmask)
2286 // arguments are identical to sigprocmask (how, sigset_t*, sigset_t*).
2287 UWord arg1;
2288 PRINT("__pthread_sigmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2289 PRE_REG_READ3(long, "__pthread_sigmask",
2290 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
2291 if (ARG2 != 0)
2292 PRE_MEM_READ( "__pthread_sigmask(set)", ARG2, sizeof(vki_sigset_t));
2293 if (ARG3 != 0)
2294 PRE_MEM_WRITE( "__pthread_sigmask(oldset)", ARG3, sizeof(vki_sigset_t));
2296 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
2297 value of 'how' is irrelevant, and it appears that Darwin's libc
2298 passes zero, which is not equal to any of
2299 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
2300 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
2301 value independently of the other args. Solution: in this case,
2302 simply pass a valid (but irrelevant) value for 'how'. */
2303 /* Also, in this case the new set is passed to the kernel by
2304 reference, not value, as in some other sigmask related Darwin
2305 syscalls. */
2306 arg1 = ARG1;
2307 if (ARG2 == 0 /* the new-set is NULL */
2308 && ARG1 != VKI_SIG_BLOCK
2309 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
2310 arg1 = VKI_SIG_SETMASK;
2312 SET_STATUS_from_SysRes(
2313 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
2314 (vki_sigset_t*)ARG3 )
2317 if (SUCCESS)
2318 *flags |= SfPollAfter;
2320 POST(__pthread_sigmask)
2322 vg_assert(SUCCESS);
2323 if (RES == 0 && ARG3 != 0)
2324 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2328 PRE(__pthread_canceled)
2330 *flags |= SfMayBlock; /* might kill this thread??? */
2331 /* I don't think so -- I think it just changes the cancellation
2332 state. But taking no chances. */
2333 PRINT("__pthread_canceled ( %#lx )", ARG1);
2334 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
2338 PRE(__pthread_markcancel)
2340 *flags |= SfMayBlock; /* might kill this thread??? */
2341 PRINT("__pthread_markcancel ( %#lx )", ARG1);
2342 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
2343 /* Just let it go through. No idea if this is correct. */
2347 PRE(__disable_threadsignal)
2349 vki_sigset_t set;
2350 PRINT("__disable_threadsignal(%ld, %ld, %ld)", SARG1, SARG2, SARG3);
2351 /* I don't think this really looks at its arguments. So don't
2352 bother to check them. */
2354 VG_(sigfillset)( &set );
2355 SET_STATUS_from_SysRes(
2356 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
2359 /* We don't expect that blocking all signals for this thread could
2360 cause any more to be delivered (how could it?), but just in case
2361 .. */
2362 if (SUCCESS)
2363 *flags |= SfPollAfter;
2367 PRE(__pthread_chdir)
2369 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2370 PRE_REG_READ1(long, "__pthread_chdir", const char *, path);
2371 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1 );
2376 PRE(__pthread_fchdir)
2378 PRINT("__pthread_fchdir ( %lu )", ARG1);
2379 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd);
2383 PRE(kdebug_trace)
2385 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2386 SARG1, SARG2, SARG3, SARG4, SARG5, SARG6);
2388 Don't check anything - some clients pass fewer arguments.
2389 PRE_REG_READ6(long, "kdebug_trace",
2390 int,"code", int,"arg1", int,"arg2",
2391 int,"arg3", int,"arg4", int,"arg5");
2396 PRE(seteuid)
2398 PRINT("seteuid(%lu)", ARG1);
2399 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
2403 PRE(setegid)
2405 PRINT("setegid(%lu)", ARG1);
2406 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
2409 PRE(settid)
2411 PRINT("settid(%lu, %lu)", ARG1, ARG2);
2412 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
2415 PRE(gettid)
2417 PRINT("gettid()");
2418 PRE_REG_READ0(long, gettid);
2421 /* XXX need to check whether we need POST operations for
2422 * waitevent, watchevent, modwatch -- jpeach
2424 PRE(watchevent)
2426 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
2427 PRE_REG_READ2(long, "watchevent",
2428 vki_eventreq *, "event", unsigned int, "eventmask");
2430 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
2431 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
2432 *flags |= SfMayBlock;
2435 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
2436 PRE(waitevent)
2438 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
2439 PRE_REG_READ2(long, "waitevent",
2440 vki_eventreq *, "event", struct timeval *, "timeout");
2441 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
2443 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
2444 PRE_timeval_READ("waitevent(timeout)", ARG2);
2447 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2448 *flags |= SfMayBlock;
2451 POST(waitevent)
2453 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
2456 PRE(modwatch)
2458 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
2459 PRE_REG_READ2(long, "modwatch",
2460 vki_eventreq *, "event", unsigned int, "eventmask");
2462 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
2463 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
2466 PRE(getxattr)
2468 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2469 ARG1, (HChar *)ARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2471 PRE_REG_READ6(vki_ssize_t, "getxattr",
2472 const char *, path, char *, name, void *, value,
2473 vki_size_t, size, uint32_t, position, int, options);
2474 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
2475 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2476 if (ARG3)
2477 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2480 POST(getxattr)
2482 vg_assert((vki_ssize_t)RES >= 0);
2483 if (ARG3)
2484 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2487 PRE(fgetxattr)
2489 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2490 SARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2492 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
2493 int, fd, char *, name, void *, value,
2494 vki_size_t, size, uint32_t, position, int, options);
2495 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2496 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2499 POST(fgetxattr)
2501 vg_assert((vki_ssize_t)RES >= 0);
2502 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2505 PRE(setxattr)
2507 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2508 ARG1, (HChar *)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2509 PRE_REG_READ6(int, "setxattr",
2510 const char *,"path", char *,"name", void *,"value",
2511 vki_size_t,"size", uint32_t,"position", int,"options" );
2513 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
2514 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
2515 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
2519 PRE(fsetxattr)
2521 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2522 SARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2523 PRE_REG_READ6(int, "fsetxattr",
2524 int,"fd", char *,"name", void *,"value",
2525 vki_size_t,"size", uint32_t,"position", int,"options" );
2527 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
2528 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
2532 PRE(removexattr)
2534 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2535 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, SARG3 );
2536 PRE_REG_READ3(int, "removexattr",
2537 const char*, "path", char*, "attrname", int, "options");
2538 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
2539 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2543 PRE(fremovexattr)
2545 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2546 SARG1, ARG2, (HChar*)ARG2, SARG3 );
2547 PRE_REG_READ3(int, "fremovexattr",
2548 int, "fd", char*, "attrname", int, "options");
2549 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2553 PRE(listxattr)
2555 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2556 ARG1, (HChar *)ARG1, ARG2, ARG3, SARG4 );
2557 PRE_REG_READ4 (long, "listxattr",
2558 const char *,"path", char *,"namebuf",
2559 vki_size_t,"size", int,"options" );
2561 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
2562 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
2563 *flags |= SfMayBlock;
2565 POST(listxattr)
2567 vg_assert(SUCCESS);
2568 vg_assert((vki_ssize_t)RES >= 0);
2569 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2573 PRE(flistxattr)
2575 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2576 SARG1, ARG2, ARG3, SARG4 );
2577 PRE_REG_READ4 (long, "flistxattr",
2578 int, "fd", char *,"namebuf",
2579 vki_size_t,"size", int,"options" );
2580 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2581 *flags |= SfMayBlock;
2583 POST(flistxattr)
2585 vg_assert(SUCCESS);
2586 vg_assert((vki_ssize_t)RES >= 0);
2587 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2591 PRE(shmat)
2593 UWord arg2tmp;
2594 PRINT("shmat ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
2595 PRE_REG_READ3(long, "shmat",
2596 int, shmid, const void *, shmaddr, int, shmflg);
2597 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2598 if (arg2tmp == 0)
2599 SET_STATUS_Failure( VKI_EINVAL );
2600 else
2601 ARG2 = arg2tmp; // used in POST
2603 POST(shmat)
2605 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2608 PRE(shmctl)
2610 PRINT("shmctl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
2611 PRE_REG_READ3(long, "shmctl",
2612 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2613 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2615 POST(shmctl)
2617 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2620 PRE(shmdt)
2622 PRINT("shmdt ( %#lx )",ARG1);
2623 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2624 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2625 SET_STATUS_Failure( VKI_EINVAL );
2627 POST(shmdt)
2629 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2632 PRE(shmget)
2634 PRINT("shmget ( %ld, %lu, %ld )", SARG1, ARG2, SARG3);
2635 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2638 PRE(shm_open)
2640 PRINT("shm_open(%#lx(%s), %ld, %lu)", ARG1, (HChar *)ARG1, SARG2, ARG3);
2641 PRE_REG_READ3(long, "shm_open",
2642 const char *,"name", int,"flags", vki_mode_t,"mode");
2644 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2646 *flags |= SfMayBlock;
2648 POST(shm_open)
2650 vg_assert(SUCCESS);
2651 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2652 VG_(close)(RES);
2653 SET_STATUS_Failure( VKI_EMFILE );
2654 } else {
2655 if (VG_(clo_track_fds))
2656 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
2660 PRE(shm_unlink)
2662 *flags |= SfMayBlock;
2663 PRINT("shm_unlink ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2664 PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2665 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2667 POST(shm_unlink)
2669 /* My reading of the man page suggests that a call may cause memory
2670 mappings to change: "if no references exist at the time of the
2671 call to shm_unlink(), the resources are reclaimed immediately".
2672 So we need to resync here, sigh. */
2673 ML_(sync_mappings)("after", "shm_unlink", 0);
2676 PRE(stat_extended)
2678 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2679 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2680 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2681 void *, fsacl, vki_size_t *, fsacl_size);
2682 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
2683 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2684 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2685 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2686 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2688 POST(stat_extended)
2690 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2691 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2692 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2693 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2697 PRE(lstat_extended)
2699 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2700 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2701 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2702 void *, fsacl, vki_size_t *, fsacl_size);
2703 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
2704 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2705 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2706 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2707 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2709 POST(lstat_extended)
2711 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2712 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2713 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2714 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2718 PRE(fstat_extended)
2720 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2721 SARG1, ARG2, ARG3, ARG4);
2722 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2723 void *, fsacl, vki_size_t *, fsacl_size);
2724 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2725 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2726 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2727 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2729 POST(fstat_extended)
2731 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2732 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2733 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2734 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2738 PRE(stat64_extended)
2740 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2741 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2742 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2743 void *, fsacl, vki_size_t *, fsacl_size);
2744 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
2745 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2746 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2747 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2748 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2750 POST(stat64_extended)
2752 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2753 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2754 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2755 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2759 PRE(lstat64_extended)
2761 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2762 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2763 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2764 void *, fsacl, vki_size_t *, fsacl_size);
2765 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2766 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2767 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2768 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2769 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2771 POST(lstat64_extended)
2773 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2774 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2775 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2776 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2780 PRE(fstat64_extended)
2782 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2783 SARG1, ARG2, ARG3, ARG4);
2784 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2785 void *, fsacl, vki_size_t *, fsacl_size);
2786 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2787 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2788 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2789 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2791 POST(fstat64_extended)
2793 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2794 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2795 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2796 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2800 PRE(fchmod_extended)
2802 /* DDD: Note: this is not really correct. Handling of
2803 chmod_extended is broken in the same way. */
2804 PRINT("fchmod_extended ( %lu, %lu, %lu, %lu, %#lx )",
2805 ARG1, ARG2, ARG3, ARG4, ARG5);
2806 PRE_REG_READ5(long, "fchmod_extended",
2807 unsigned int, fildes,
2808 uid_t, uid,
2809 gid_t, gid,
2810 vki_mode_t, mode,
2811 void* /*really,user_addr_t*/, xsecurity);
2812 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2813 is just way wrong. [The trouble is with the size, which depends on a
2814 non-trival kernel computation] */
2815 if (ARG5) {
2816 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2817 sizeof(struct vki_kauth_filesec) );
2821 PRE(chmod_extended)
2823 /* DDD: Note: this is not really correct. Handling of
2824 fchmod_extended is broken in the same way. */
2825 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2826 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2827 PRE_REG_READ5(long, "chmod_extended",
2828 unsigned int, fildes,
2829 uid_t, uid,
2830 gid_t, gid,
2831 vki_mode_t, mode,
2832 void* /*really,user_addr_t*/, xsecurity);
2833 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2834 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2835 is just way wrong. [The trouble is with the size, which depends on a
2836 non-trival kernel computation] */
2837 if (ARG5) {
2838 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2839 sizeof(struct vki_kauth_filesec) );
2843 PRE(open_extended)
2845 /* DDD: Note: this is not really correct. Handling of
2846 {,f}chmod_extended is broken in the same way. */
2847 PRINT("open_extended ( %#lx(%s), %ld, %lu, %lu, %lu, %#lx )",
2848 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2849 SARG2, ARG3, ARG4, ARG5, ARG6);
2850 PRE_REG_READ6(long, "open_extended",
2851 char*, path,
2852 int, flags,
2853 uid_t, uid,
2854 gid_t, gid,
2855 vki_mode_t, mode,
2856 void* /*really,user_addr_t*/, xsecurity);
2857 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2858 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2859 is just way wrong. [The trouble is with the size, which depends on a
2860 non-trival kernel computation] */
2861 if (ARG6)
2862 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2863 sizeof(struct vki_kauth_filesec) );
2866 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2867 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2868 // by one or more strings. Each accessx_descriptor contains a field,
2869 // 'ad_name_offset', which points to one of the strings (or it can contain
2870 // zero which means "reuse the string from the previous accessx_descriptor").
2872 // What's really ridiculous is that we are only given the size of the overall
2873 // buffer, not the number of accessx_descriptors, nor the number of strings.
2874 // The kernel determines the number of accessx_descriptors by walking through
2875 // them one by one, checking that the ad_name_offset points within the buffer,
2876 // past the current point (or that it's a zero, unless its the first
2877 // descriptor); if so, we assume that this really is an accessx_descriptor,
2878 // if not, we assume we've hit the strings section. Gah.
2880 // This affects us here because number of entries in the 'results' buffer is
2881 // determined by the number of accessx_descriptors. So we have to know that
2882 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2883 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2884 // computation after the syscall has succeeded, because the kernel will have
2885 // checked for all the zillion different ways this syscall can fail, and we'll
2886 // know we have a well-formed 'entries' buffer. This means we might miss some
2887 // uses of unaddressable memory but oh well.
2889 PRE(access_extended)
2891 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2892 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2893 // XXX: the accessx_descriptor struct contains padding, so this can cause
2894 // unnecessary undefined value errors. But you arguably shouldn't be
2895 // passing undefined values to the kernel anyway...
2896 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2897 vki_errno_t *, results, vki_uid_t *, uid);
2898 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2900 // XXX: as mentioned above, this check is too hard to do before the
2901 // syscall.
2902 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2904 POST(access_extended)
2906 // 'n_descs' is the number of descriptors we think are in the buffer. We
2907 // start with the maximum possible value, which occurs if we have the
2908 // shortest possible string section. The shortest string section allowed
2909 // consists of a single one-char string (plus the NUL char). Hence the
2910 // '2'.
2911 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2912 SizeT size = ARG2;
2913 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2914 Int i; // Current position in the descriptors section array.
2915 Int u; // Upper bound on the length of the descriptors array
2916 // (recomputed each time around the loop)
2917 vg_assert(n_descs > 0);
2919 // Step through the descriptors, lowering 'n_descs' until we know we've
2920 // reached the string section.
2921 for (i = 0; True; i++) {
2922 // If we're past our estimate, we must be one past the end of the
2923 // descriptors section (ie. at the start of the string section). Stop.
2924 if (i >= n_descs)
2925 break;
2927 // Get the array index for the string, but pretend momentarily that it
2928 // is actually another accessx_descriptor. That gives us an upper bound
2929 // on the length of the descriptors section. (Unless the index is zero,
2930 // in which case we have no new info.)
2931 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2932 if (u == 0) {
2933 vg_assert(i != 0);
2934 continue;
2937 // If the upper bound is below our current estimate, revise that
2938 // estimate downwards.
2939 if (u < n_descs)
2940 n_descs = u;
2943 // Sanity check.
2944 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2946 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2950 PRE(chflags)
2952 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (HChar *)ARG1, ARG2);
2953 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2954 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2956 // GrP fixme sanity-check flags value?
2959 PRE(fchflags)
2961 PRINT("fchflags ( %ld, %lu )", SARG1, ARG2);
2962 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2964 // GrP fixme sanity-check flags value?
2967 PRE(stat64)
2969 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
2970 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2971 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2972 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2974 POST(stat64)
2976 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2979 PRE(lstat64)
2981 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
2982 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2983 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2984 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2986 POST(lstat64)
2988 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2991 PRE(fstat64)
2993 PRINT("fstat64 ( %lu, %#lx )", ARG1,ARG2);
2994 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2995 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2997 POST(fstat64)
2999 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
3002 PRE(getfsstat)
3004 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3005 PRE_REG_READ3(int, "getfsstat",
3006 struct vki_statfs *, buf, int, bufsize, int, flags);
3007 if (ARG1) {
3008 // ARG2 is a BYTE SIZE
3009 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
3012 POST(getfsstat)
3014 if (ARG1) {
3015 // RES is a STRUCT COUNT
3016 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
3020 PRE(getfsstat64)
3022 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3023 PRE_REG_READ3(int, "getfsstat64",
3024 struct vki_statfs64 *, buf, int, bufsize, int, flags);
3025 if (ARG1) {
3026 // ARG2 is a BYTE SIZE
3027 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
3030 POST(getfsstat64)
3032 if (ARG1) {
3033 // RES is a STRUCT COUNT
3034 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
3038 PRE(mount)
3040 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
3041 // We are conservative and check everything, except the memory pointed to
3042 // by 'data'.
3043 *flags |= SfMayBlock;
3044 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
3045 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
3046 PRE_REG_READ4(long, "mount",
3047 const char *, type, const char *, dir,
3048 int, flags, void *, data);
3049 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
3050 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
3054 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
3055 void *attrBuf, SizeT attrBufSize,
3056 void (*fn)(ThreadId, void *attrData, SizeT size)
3059 typedef struct {
3060 uint32_t attrBit;
3061 int32_t attrSize;
3062 } attrspec;
3063 static const attrspec commonattr[] = {
3064 // This order is important.
3065 #if DARWIN_VERS >= DARWIN_10_6
3066 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
3067 #endif
3068 { ATTR_CMN_NAME, -1 },
3069 { ATTR_CMN_DEVID, sizeof(dev_t) },
3070 { ATTR_CMN_FSID, sizeof(fsid_t) },
3071 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
3072 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
3073 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
3074 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
3075 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
3076 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
3077 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
3078 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
3079 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
3080 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
3081 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
3082 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
3083 { ATTR_CMN_OWNERID, sizeof(uid_t) },
3084 { ATTR_CMN_GRPID, sizeof(gid_t) },
3085 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
3086 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
3087 { ATTR_CMN_NAMEDATTRLIST, -1 },
3088 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
3089 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
3090 { ATTR_CMN_EXTENDED_SECURITY, -1 },
3091 { ATTR_CMN_UUID, sizeof(guid_t) },
3092 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
3093 { ATTR_CMN_FILEID, sizeof(uint64_t) },
3094 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
3095 #if DARWIN_VERS >= DARWIN_10_6
3096 { ATTR_CMN_FULLPATH, -1 },
3097 #endif
3098 #if DARWIN_VERS >= DARWIN_10_8
3099 { ATTR_CMN_ADDEDTIME, -1 },
3100 #endif
3101 { 0, 0 }
3103 static const attrspec volattr[] = {
3104 // This order is important.
3105 { ATTR_VOL_INFO, 0 },
3106 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
3107 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
3108 { ATTR_VOL_SIZE, sizeof(off_t) },
3109 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
3110 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
3111 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
3112 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
3113 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
3114 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
3115 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
3116 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
3117 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
3118 { ATTR_VOL_MOUNTPOINT, -1 },
3119 { ATTR_VOL_NAME, -1 },
3120 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
3121 { ATTR_VOL_MOUNTEDDEVICE, -1 },
3122 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
3123 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
3124 #if DARWIN_VERS >= DARWIN_10_6
3125 { ATTR_VOL_UUID, sizeof(uuid_t) },
3126 #endif
3127 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
3128 { 0, 0 }
3130 static const attrspec dirattr[] = {
3131 // This order is important.
3132 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
3133 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
3134 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
3135 { 0, 0 }
3137 static const attrspec fileattr[] = {
3138 // This order is important.
3139 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
3140 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
3141 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
3142 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
3143 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
3144 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
3145 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
3146 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
3147 { ATTR_FILE_FORKLIST, -1 },
3148 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
3149 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
3150 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
3151 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
3152 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
3153 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
3154 { 0, 0 }
3156 static const attrspec forkattr[] = {
3157 // This order is important.
3158 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
3159 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
3160 { 0, 0 }
3163 static const attrspec *attrdefs[5] = {
3164 commonattr, volattr, dirattr, fileattr, forkattr
3166 attrgroup_t a[5];
3167 uint8_t *d, *dend;
3168 int g, i;
3170 vg_assert(attrList->bitmapcount == 5);
3171 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
3172 d = attrBuf;
3173 dend = d + attrBufSize;
3175 #if DARWIN_VERS >= DARWIN_10_6
3176 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3177 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
3178 // fixme range check this?
3179 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
3180 fn(tid, d, sizeof(attribute_set_t));
3181 VG_(memcpy)(a, d, sizeof(a));
3183 #endif
3185 for (g = 0; g < 5; g++) {
3186 for (i = 0; attrdefs[g][i].attrBit; i++) {
3187 uint32_t bit = attrdefs[g][i].attrBit;
3188 int32_t size = attrdefs[g][i].attrSize;
3190 if (a[g] & bit) {
3191 a[g] &= ~bit; // clear bit for error check later
3192 if (size == -1) {
3193 attrreference_t *ref = (attrreference_t *)d;
3194 size = MIN(sizeof(attrreference_t), dend - d);
3195 fn(tid, d, size);
3196 if (size >= sizeof(attrreference_t) &&
3197 d + ref->attr_dataoffset < dend)
3199 fn(tid, d + ref->attr_dataoffset,
3200 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
3202 d += size;
3204 else {
3205 size = MIN(size, dend - d);
3206 fn(tid, d, size);
3207 d += size;
3210 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
3211 if (d > dend) d = dend;
3215 // Known bits are cleared. Die if any bits are left.
3216 if (a[g] != 0) {
3217 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
3222 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3224 POST_MEM_WRITE((Addr)attrData, attrDataSize);
3227 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3229 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
3232 PRE(getattrlist)
3234 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3235 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3236 PRE_REG_READ5(int, "getattrlist",
3237 const char *,path, struct vki_attrlist *,attrList,
3238 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3239 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
3240 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3241 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
3244 POST(getattrlist)
3246 if (ARG4 > sizeof(vki_uint32_t)) {
3247 // attrBuf is uint32_t size followed by attr data
3248 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
3249 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
3250 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
3251 // *sizep is bytes required for return value, including *sizep
3252 } else {
3253 // *sizep is actual bytes returned, including *sizep
3255 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
3260 PRE(setattrlist)
3262 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3263 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3264 PRE_REG_READ5(int, "setattrlist",
3265 const char *,path, struct vki_attrlist *,attrList,
3266 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3267 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
3268 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3269 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
3273 PRE(getdirentriesattr)
3275 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %lu, %#lx, %#lx, %#lx, %lu)",
3276 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
3277 PRE_REG_READ8(int, "getdirentriesattr",
3278 int,fd, struct vki_attrlist *,attrList,
3279 void *,attrBuf, size_t,attrBufSize,
3280 unsigned int *,count, unsigned int *,basep,
3281 unsigned int *,newState, unsigned int,options);
3282 PRE_MEM_READ("getdirentriesattr(attrList)",
3283 ARG2, sizeof(struct vki_attrlist));
3284 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
3285 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3286 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3287 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
3288 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
3290 POST(getdirentriesattr)
3292 char *p, *end;
3293 unsigned int count;
3294 unsigned int i;
3296 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
3297 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
3298 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
3300 // return buffer is concatenation of variable-size structs
3301 count = *(unsigned int *)ARG5;
3302 p = (char *)ARG3;
3303 end = (char *)ARG3 + ARG4;
3304 for (i = 0; i < count; i++) {
3305 vg_assert(p < end); // failure is kernel bug or Valgrind bug
3306 p += *(unsigned int *)p;
3309 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
3311 PRINT("got %d records, %ld/%lu bytes\n",
3312 count, (Addr)p-(Addr)ARG3, ARG4);
3315 PRE(exchangedata)
3317 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3318 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3);
3319 PRE_REG_READ3(int, "exchangedata",
3320 char *, path1, char *, path2, unsigned long, options);
3321 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
3322 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
3325 PRE(fsctl)
3327 PRINT("fsctl ( %#lx(%s), %lu, %#lx, %lu )",
3328 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
3329 PRE_REG_READ4( long, "fsctl",
3330 char *,"path", unsigned int,"request",
3331 void *,"data", unsigned int,"options");
3333 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
3335 switch (ARG2) {
3336 case VKI_afpfsByteRangeLock2FSCTL: {
3337 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3338 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3339 pb->offset);
3340 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3341 pb->length);
3342 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3343 pb->unLockFlag);
3344 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3345 pb->startEndFlag);
3346 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3347 pb->fd);
3349 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3350 pb->retRangeStart);
3352 // GrP fixme check fd
3353 break;
3355 case VKI_FSIOC_SYNC_VOLUME:
3356 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
3357 break;
3359 default:
3360 // fsctl requests use ioctl encoding
3361 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3362 break;
3366 POST(fsctl)
3368 switch (ARG2) {
3369 case VKI_afpfsByteRangeLock2FSCTL: {
3370 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3371 POST_FIELD_WRITE(pb->retRangeStart);
3372 break;
3374 case VKI_FSIOC_SYNC_VOLUME:
3375 break;
3377 default:
3378 // fsctl requests use ioctl encoding
3379 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
3380 break;
3384 PRE(initgroups)
3386 PRINT("initgroups(%s, %#lx, %lu)", (HChar *)ARG1, ARG2, ARG3);
3387 PRE_REG_READ3(long, "initgroups",
3388 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
3389 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
3393 //--------- posix_spawn ---------//
3394 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3395 the simpler AIX equivalent (syswrap-aix5.c). */
3396 // Pre_read a char** argument.
3397 static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
3399 while (True) {
3400 Addr a_deref;
3401 Addr* a_p = (Addr*)a;
3402 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
3403 a_deref = *a_p;
3404 if (0 == a_deref)
3405 break;
3406 PRE_MEM_RASCIIZ( s2, a_deref );
3407 a += sizeof(char*);
3410 static SysRes simple_pre_exec_check ( const HChar* exe_name,
3411 Bool trace_this_child )
3413 Int fd, ret;
3414 SysRes res;
3415 Bool setuid_allowed;
3417 // Check it's readable
3418 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
3419 if (sr_isError(res)) {
3420 return res;
3422 fd = sr_Res(res);
3423 VG_(close)(fd);
3425 // Check we have execute permissions. We allow setuid executables
3426 // to be run only in the case when we are not simulating them, that
3427 // is, they to be run natively.
3428 setuid_allowed = trace_this_child ? False : True;
3429 ret = VG_(check_executable)(NULL/*&is_setuid*/,
3430 exe_name, setuid_allowed);
3431 if (0 != ret) {
3432 return VG_(mk_SysRes_Error)(ret);
3434 return VG_(mk_SysRes_Success)(0);
3436 PRE(posix_spawn)
3438 HChar* path = NULL; /* path to executable */
3439 HChar** envp = NULL;
3440 HChar** argv = NULL;
3441 HChar** arg2copy;
3442 HChar* launcher_basename = NULL;
3443 Int i, j, tot_args;
3444 SysRes res;
3445 Bool trace_this_child;
3447 /* args: pid_t* pid
3448 char* path
3449 posix_spawn_file_actions_t* file_actions
3450 char** argv
3451 char** envp
3453 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3454 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3456 /* Standard pre-syscall checks */
3458 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
3459 void*, file_actions, char**, argv, char**, envp );
3460 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
3461 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
3462 // DDD: check file_actions
3463 if (ARG4 != 0)
3464 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
3465 "posix_spawn(argv[i])" );
3466 if (ARG5 != 0)
3467 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
3468 "posix_spawn(envp[i])" );
3470 if (0)
3471 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3472 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3474 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3475 syswrap-generic.c. */
3477 /* Check that the name at least begins in client-accessible storage. */
3478 if (ARG2 == 0 /* obviously bogus */
3479 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
3480 SET_STATUS_Failure( VKI_EFAULT );
3481 return;
3484 // Decide whether or not we want to follow along
3485 { // Make 'child_argv' be a pointer to the child's arg vector
3486 // (skipping the exe name)
3487 const HChar** child_argv = (const HChar**)ARG4;
3488 if (child_argv && child_argv[0] == NULL)
3489 child_argv = NULL;
3490 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
3493 // Do the important checks: it is a file, is executable, permissions are
3494 // ok, etc. We allow setuid executables to run only in the case when
3495 // we are not simulating them, that is, they to be run natively.
3496 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
3497 if (sr_isError(res)) {
3498 SET_STATUS_Failure( sr_Err(res) );
3499 return;
3502 /* If we're tracing the child, and the launcher name looks bogus
3503 (possibly because launcher.c couldn't figure it out, see
3504 comments therein) then we have no option but to fail. */
3505 if (trace_this_child
3506 && (VG_(name_of_launcher) == NULL
3507 || VG_(name_of_launcher)[0] != '/')) {
3508 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
3509 return;
3512 /* Ok. So let's give it a try. */
3513 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
3515 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3516 So, we should not terminate gdbserver : this is still the parent
3517 running, which will terminate its gdbserver when exiting.
3518 If the child process is traced, it will start a fresh gdbserver
3519 after posix_spawn. */
3521 // Set up the child's exe path.
3523 if (trace_this_child) {
3525 // We want to exec the launcher. Get its pre-remembered path.
3526 path = VG_(name_of_launcher);
3527 // VG_(name_of_launcher) should have been acquired by m_main at
3528 // startup. The following two assertions should be assured by
3529 // the "If we're tracking the child .." test just above here.
3530 vg_assert(path);
3531 vg_assert(path[0] == '/');
3532 launcher_basename = path;
3534 } else {
3535 path = (HChar*)ARG2;
3538 // Set up the child's environment.
3540 // Remove the valgrind-specific stuff from the environment so the
3541 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3542 // This is done unconditionally, since if we are tracing the child,
3543 // the child valgrind will set up the appropriate client environment.
3544 // Nb: we make a copy of the environment before trying to mangle it
3545 // as it might be in read-only memory (this was bug #101881).
3547 // Then, if tracing the child, set VALGRIND_LIB for it.
3549 if (ARG5 == 0) {
3550 envp = NULL;
3551 } else {
3552 envp = VG_(env_clone)( (HChar**)ARG5 );
3553 vg_assert(envp);
3554 VG_(env_remove_valgrind_env_stuff)( envp, /* ro_strings */ False, NULL);
3557 if (trace_this_child) {
3558 // Set VALGRIND_LIB in ARG5 (the environment)
3559 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3562 // Set up the child's args. If not tracing it, they are
3563 // simply ARG4. Otherwise, they are
3565 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3567 // except that the first VG_(args_for_valgrind_noexecpass) args
3568 // are omitted.
3570 if (!trace_this_child) {
3571 argv = (HChar**)ARG4;
3572 } else {
3573 vg_assert( VG_(args_for_valgrind) );
3574 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3575 vg_assert( VG_(args_for_valgrind_noexecpass)
3576 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3577 /* how many args in total will there be? */
3578 // launcher basename
3579 tot_args = 1;
3580 // V's args
3581 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3582 tot_args -= VG_(args_for_valgrind_noexecpass);
3583 // name of client exe
3584 tot_args++;
3585 // args for client exe, skipping [0]
3586 arg2copy = (HChar**)ARG4;
3587 if (arg2copy && arg2copy[0]) {
3588 for (i = 1; arg2copy[i]; i++)
3589 tot_args++;
3591 // allocate
3592 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3593 (tot_args+1) * sizeof(HChar*) );
3594 // copy
3595 j = 0;
3596 argv[j++] = launcher_basename;
3597 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3598 if (i < VG_(args_for_valgrind_noexecpass))
3599 continue;
3600 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3602 argv[j++] = (HChar*)ARG2;
3603 if (arg2copy && arg2copy[0])
3604 for (i = 1; arg2copy[i]; i++)
3605 argv[j++] = arg2copy[i];
3606 argv[j++] = NULL;
3607 // check
3608 vg_assert(j == tot_args+1);
3611 /* DDD: sort out the signal state. What signal
3612 state does the child inherit from the parent? */
3614 if (0) {
3615 HChar **cpp;
3616 VG_(printf)("posix_spawn: %s\n", path);
3617 for (cpp = argv; cpp && *cpp; cpp++)
3618 VG_(printf)("argv: %s\n", *cpp);
3619 if (1)
3620 for (cpp = envp; cpp && *cpp; cpp++)
3621 VG_(printf)("env: %s\n", *cpp);
3624 /* Let the call go through as usual. However, we have to poke
3625 the altered arguments back into the argument slots. */
3626 ARG2 = (UWord)path;
3627 ARG4 = (UWord)argv;
3628 ARG5 = (UWord)envp;
3630 /* not to mention .. */
3631 *flags |= SfMayBlock;
3633 POST(posix_spawn)
3635 vg_assert(SUCCESS);
3636 if (ARG1 != 0) {
3637 POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3642 PRE(socket)
3644 PRINT("socket ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
3645 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3648 POST(socket)
3650 SysRes r;
3651 vg_assert(SUCCESS);
3652 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3653 SET_STATUS_from_SysRes(r);
3657 PRE(setsockopt)
3659 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3660 SARG1, SARG2, SARG3, ARG4, SARG5);
3661 PRE_REG_READ5(long, "setsockopt",
3662 int, s, int, level, int, optname,
3663 const void *, optval, vki_socklen_t, optlen);
3664 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3668 PRE(getsockopt)
3670 Addr optval_p = ARG4;
3671 Addr optlen_p = ARG5;
3672 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3673 SARG1, SARG2, SARG3, ARG4, ARG5);
3674 PRE_REG_READ5(long, "getsockopt",
3675 int, s, int, level, int, optname,
3676 void *, optval, vki_socklen_t *, optlen);
3677 /* int getsockopt(int socket, int level, int option_name,
3678 void *restrict option_value,
3679 socklen_t *restrict option_len); */
3680 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3681 if (optval_p != (Addr)NULL) {
3682 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3683 "socketcall.getsockopt(optval)",
3684 "socketcall.getsockopt(optlen)" );
3686 // DDD: #warning GrP fixme darwin-specific sockopts
3689 POST(getsockopt)
3691 Addr optval_p = ARG4;
3692 Addr optlen_p = ARG5;
3693 vg_assert(SUCCESS);
3694 if (optval_p != (Addr)NULL) {
3695 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3696 optval_p, optlen_p,
3697 "socketcall.getsockopt(optlen_out)" );
3698 // DDD: #warning GrP fixme darwin-specific sockopts
3703 PRE(connect)
3705 *flags |= SfMayBlock;
3706 PRINT("connect ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3707 PRE_REG_READ3(long, "connect",
3708 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3709 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3713 PRE(accept)
3715 *flags |= SfMayBlock;
3716 PRINT("accept ( %ld, %#lx, %#lx )", SARG1, ARG2, SARG3);
3717 PRE_REG_READ3(long, "accept",
3718 int, s, struct sockaddr *, addr, int *, addrlen);
3719 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3722 POST(accept)
3724 SysRes r;
3725 vg_assert(SUCCESS);
3726 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3727 ARG1,ARG2,ARG3);
3728 SET_STATUS_from_SysRes(r);
3731 PRE(mkfifo)
3733 *flags |= SfMayBlock;
3734 PRINT("mkfifo ( %#lx(%s), %lx )", ARG1, (HChar *)ARG1, ARG2);
3735 PRE_REG_READ2(long, "mkfifo", const char *, path, vki_mode_t, mode);
3736 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1 );
3739 POST(mkfifo)
3741 vg_assert(SUCCESS);
3742 if (!ML_(fd_allowed)(RES, "mkfifo", tid, True)) {
3743 VG_(close)(RES);
3744 SET_STATUS_Failure( VKI_EMFILE );
3745 } else {
3746 if (VG_(clo_track_fds))
3747 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3751 PRE(sendto)
3753 *flags |= SfMayBlock;
3754 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3755 SARG1, (HChar *)ARG2, SARG3, ARG4, ARG5, SARG6);
3756 PRE_REG_READ6(long, "sendto",
3757 int, s, const void *, msg, int, len,
3758 unsigned int, flags,
3759 const struct sockaddr *, to, int, tolen);
3760 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3763 PRE(sendfile)
3765 #if VG_WORDSIZE == 4
3766 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3767 SARG1, SARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, SARG7);
3769 PRE_REG_READ7(long, "sendfile",
3770 int, fromfd, int, tofd,
3771 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3772 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3773 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3774 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3775 #else
3776 PRINT("sendfile(%ld, %ld, %lu, %#lx, %#lx, %ld)",
3777 SARG1, SARG2, ARG3, ARG4, ARG5, SARG6);
3779 PRE_REG_READ6(long, "sendfile",
3780 int, fromfd, int, tofd,
3781 vki_uint64_t, offset,
3782 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3783 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3784 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3785 #endif
3787 *flags |= SfMayBlock;
3789 POST(sendfile)
3791 #if VG_WORDSIZE == 4
3792 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3793 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3794 #else
3795 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3796 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3797 #endif
3800 PRE(recvfrom)
3802 *flags |= SfMayBlock;
3803 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3804 SARG1, ARG2, SARG3, ARG4, ARG5, ARG6);
3805 PRE_REG_READ6(long, "recvfrom",
3806 int, s, void *, buf, int, len, unsigned int, flags,
3807 struct sockaddr *, from, int *, fromlen);
3808 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3811 POST(recvfrom)
3813 vg_assert(SUCCESS);
3814 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3815 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3819 PRE(sendmsg)
3821 *flags |= SfMayBlock;
3822 PRINT("sendmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3823 PRE_REG_READ3(long, "sendmsg",
3824 int, s, const struct msghdr *, msg, int, flags);
3825 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3829 PRE(recvmsg)
3831 *flags |= SfMayBlock;
3832 PRINT("recvmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3833 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3834 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3837 POST(recvmsg)
3839 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3843 PRE(shutdown)
3845 *flags |= SfMayBlock;
3846 PRINT("shutdown ( %ld, %ld )", SARG1, SARG2);
3847 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3851 PRE(bind)
3853 PRINT("bind ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3854 PRE_REG_READ3(long, "bind",
3855 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3856 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3860 PRE(listen)
3862 PRINT("listen ( %ld, %ld )", SARG1, SARG2);
3863 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3867 PRE(getsockname)
3869 PRINT("getsockname ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3870 PRE_REG_READ3(long, "getsockname",
3871 int, s, struct sockaddr *, name, int *, namelen);
3872 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3875 POST(getsockname)
3877 vg_assert(SUCCESS);
3878 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3879 ARG1,ARG2,ARG3);
3883 PRE(getpeername)
3885 PRINT("getpeername ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3886 PRE_REG_READ3(long, "getpeername",
3887 int, s, struct sockaddr *, name, int *, namelen);
3888 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3891 POST(getpeername)
3893 vg_assert(SUCCESS);
3894 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3895 ARG1,ARG2,ARG3);
3899 PRE(socketpair)
3901 PRINT("socketpair ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
3902 PRE_REG_READ4(long, "socketpair",
3903 int, d, int, type, int, protocol, int *, sv);
3904 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3907 POST(socketpair)
3909 vg_assert(SUCCESS);
3910 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3911 ARG1,ARG2,ARG3,ARG4);
3915 PRE(gethostuuid)
3917 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3918 PRE_REG_READ2(int,"gethostuuid",
3919 char *,"uuid_buf",
3920 const struct vki_timespec *,"timeout");
3922 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3923 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3925 *flags |= SfMayBlock;
3929 POST(gethostuuid)
3931 POST_MEM_WRITE(ARG1, 16);
3934 /* Darwin pipe() returns the two descriptors in two registers. */
3935 PRE(pipe)
3937 PRINT("pipe ( )");
3938 PRE_REG_READ0(int, "pipe");
3941 POST(pipe)
3943 Int p0, p1;
3944 vg_assert(SUCCESS);
3945 p0 = RES;
3946 p1 = RESHI;
3948 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3949 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3950 VG_(close)(p0);
3951 VG_(close)(p1);
3952 SET_STATUS_Failure( VKI_EMFILE );
3953 } else {
3954 if (VG_(clo_track_fds)) {
3955 ML_(record_fd_open_nameless)(tid, p0);
3956 ML_(record_fd_open_nameless)(tid, p1);
3962 PRE(getlogin)
3964 PRINT("getlogin ( %#lx, %lu )", ARG1, ARG2);
3965 PRE_REG_READ2(long, "getlogin",
3966 char *,"namebuf", unsigned int,"namelen");
3968 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3971 POST(getlogin)
3973 POST_MEM_WRITE(ARG1, ARG2);
3977 PRE(ptrace)
3979 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
3980 PRE_REG_READ4(long, "ptrace",
3981 int,"request", vki_pid_t,"pid",
3982 vki_caddr_t,"addr", int,"data");
3984 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3986 // GrP fixme anything needed?
3990 PRE(issetugid)
3992 PRINT("issetugid ( )");
3993 PRE_REG_READ0(long, "issetugid");
3997 PRE(getdtablesize)
3999 PRINT("getdtablesize ( )");
4000 PRE_REG_READ0(long, "getdtablesize");
4003 POST(getdtablesize)
4005 // Subtract Valgrind's fd range from client's dtable
4006 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
4009 PRE(lseek)
4011 PRINT("lseek ( %lu, %ld, %ld )", ARG1, SARG2, SARG3);
4012 PRE_REG_READ4(vki_off_t, "lseek",
4013 unsigned int,fd, int,offset_hi, int,offset_lo,
4014 unsigned int,whence);
4018 PRE(pathconf)
4020 PRINT("pathconf(%#lx(%s), %ld)", ARG1, (HChar *)ARG1, SARG2);
4021 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
4022 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
4026 PRE(fpathconf)
4028 PRINT("fpathconf(%ld, %ld)", SARG1, SARG2);
4029 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
4031 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
4032 SET_STATUS_Failure( VKI_EBADF );
4036 PRE(getdirentries)
4038 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", SARG1, ARG2, SARG3, ARG4);
4039 PRE_REG_READ4(int, "getdirentries",
4040 int, fd, char *, buf, int, nbytes, long *, basep);
4041 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
4042 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
4045 POST(getdirentries)
4047 POST_MEM_WRITE(ARG4, sizeof(long));
4048 // GrP fixme be specific about d_name?
4049 POST_MEM_WRITE(ARG2, RES);
4053 PRE(getdirentries64)
4055 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", SARG1, ARG2, ARG3, ARG4);
4056 PRE_REG_READ4(vki_ssize_t, "getdirentries",
4057 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
4058 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
4059 to valid memory and the kernel doesn't modify it. I can't
4060 determine the conditions under which that happens. But it
4061 causes Memcheck to complain, confusingly. So disable this check
4062 for the time being.
4064 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
4066 PRE_MEM_WRITE("getdirentries64(buf)", ARG2, ARG3);
4068 POST(getdirentries64)
4070 /* Disabled; see comments in the PRE wrapper.
4071 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
4073 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
4074 POST_MEM_WRITE(ARG2, RES);
4078 PRE(statfs64)
4080 PRINT("statfs64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
4081 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
4082 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4083 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4085 POST(statfs64)
4087 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4091 PRE(fstatfs64)
4093 PRINT("fstatfs64 ( %lu, %#lx )", ARG1, ARG2);
4094 PRE_REG_READ2(long, "fstatfs64",
4095 unsigned int, fd, struct statfs *, buf);
4096 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4098 POST(fstatfs64)
4100 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4103 PRE(csops)
4105 PRINT("csops ( %ld, %#lx, %#lx, %lu )", SARG1, ARG2, ARG3, ARG4);
4106 PRE_REG_READ4(int, "csops",
4107 vki_pid_t, pid, uint32_t, ops,
4108 void *, useraddr, vki_size_t, usersize);
4110 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
4112 // If the pid is ours, don't mark the program as KILL or HARD
4113 // Maybe we should keep track of this for later calls to STATUS
4114 if (!ARG1 || VG_(getpid)() == ARG1) {
4115 switch (ARG2) {
4116 case VKI_CS_OPS_MARKINVALID:
4117 case VKI_CS_OPS_MARKHARD:
4118 case VKI_CS_OPS_MARKKILL:
4119 SET_STATUS_Success(0);
4123 POST(csops)
4125 POST_MEM_WRITE( ARG3, ARG4 );
4128 PRE(auditon)
4130 PRINT("auditon ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
4131 PRE_REG_READ3(int,"auditon",
4132 int,"cmd", void*,"data", unsigned int,"length");
4134 switch (ARG1) {
4136 case VKI_A_SETPOLICY:
4137 case VKI_A_SETKMASK:
4138 case VKI_A_SETQCTRL:
4139 case VKI_A_SETCOND:
4140 case VKI_A_SETCLASS:
4141 case VKI_A_SETPMASK:
4142 case VKI_A_SETFSIZE:
4143 #if DARWIN_VERS >= DARWIN_10_6
4144 case VKI_A_SENDTRIGGER:
4145 #endif
4146 // kernel reads data..data+length
4147 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4148 break;
4150 case VKI_A_GETKMASK:
4151 case VKI_A_GETPOLICY:
4152 case VKI_A_GETQCTRL:
4153 case VKI_A_GETFSIZE:
4154 case VKI_A_GETCOND:
4155 // kernel writes data..data+length
4156 // GrP fixme be precise about what gets written
4157 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4158 break;
4161 case VKI_A_GETCLASS:
4162 case VKI_A_GETPINFO:
4163 case VKI_A_GETPINFO_ADDR:
4164 #if DARWIN_VERS >= DARWIN_10_6
4165 case VKI_A_GETSINFO_ADDR:
4166 #endif
4167 // kernel reads and writes data..data+length
4168 // GrP fixme be precise about what gets read and written
4169 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4170 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4171 break;
4173 case VKI_A_SETKAUDIT:
4174 case VKI_A_SETSTAT:
4175 case VKI_A_SETUMASK:
4176 case VKI_A_SETSMASK:
4177 case VKI_A_GETKAUDIT:
4178 case VKI_A_GETCWD:
4179 case VKI_A_GETCAR:
4180 case VKI_A_GETSTAT:
4181 // unimplemented on darwin
4182 break;
4184 default:
4185 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld\n", ARG1);
4186 break;
4189 POST(auditon)
4191 switch (ARG1) {
4193 case VKI_A_SETPOLICY:
4194 case VKI_A_SETKMASK:
4195 case VKI_A_SETQCTRL:
4196 case VKI_A_SETCOND:
4197 case VKI_A_SETCLASS:
4198 case VKI_A_SETPMASK:
4199 case VKI_A_SETFSIZE:
4200 #if DARWIN_VERS >= DARWIN_10_6
4201 case VKI_A_SENDTRIGGER:
4202 #endif
4203 // kernel reads data..data+length
4204 break;
4206 case VKI_A_GETKMASK:
4207 case VKI_A_GETPOLICY:
4208 case VKI_A_GETQCTRL:
4209 case VKI_A_GETFSIZE:
4210 case VKI_A_GETCOND:
4211 // kernel writes data..data+length
4212 // GrP fixme be precise about what gets written
4213 POST_MEM_WRITE(ARG2, ARG3);
4214 break;
4217 case VKI_A_GETCLASS:
4218 case VKI_A_GETPINFO:
4219 case VKI_A_GETPINFO_ADDR:
4220 #if DARWIN_VERS >= DARWIN_10_6
4221 case VKI_A_GETSINFO_ADDR:
4222 #endif
4223 // kernel reads and writes data..data+length
4224 // GrP fixme be precise about what gets read and written
4225 POST_MEM_WRITE(ARG2, ARG3);
4226 break;
4228 case VKI_A_SETKAUDIT:
4229 case VKI_A_SETSTAT:
4230 case VKI_A_SETUMASK:
4231 case VKI_A_SETSMASK:
4232 case VKI_A_GETKAUDIT:
4233 case VKI_A_GETCWD:
4234 case VKI_A_GETCAR:
4235 case VKI_A_GETSTAT:
4236 // unimplemented on darwin
4237 break;
4239 default:
4240 break;
4244 PRE(getaudit_addr)
4246 PRINT("getaudit_addr(%#lx, %ld)", ARG1, SARG2);
4247 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
4248 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
4250 POST(getaudit_addr)
4252 POST_MEM_WRITE(ARG1, ARG2);
4256 PRE(mmap)
4258 // SysRes r;
4259 if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
4261 #if VG_WORDSIZE == 4
4262 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %llu )",
4263 ARG1, ARG2, SARG3, SARG4, SARG5, LOHI64(ARG6, ARG7) );
4264 PRE_REG_READ7(Addr, "mmap",
4265 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4266 unsigned long,offset_hi, unsigned long,offset_lo);
4267 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4268 // V's mechanism for now
4269 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4270 // (Off64T)LOHI64(ARG6, ARG7) );
4271 #else
4272 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4273 ARG1, ARG2, SARG3, SARG4, SARG5, SARG6 );
4274 PRE_REG_READ6(long, "mmap",
4275 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4276 Off64T,offset);
4277 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4279 #endif
4281 // SET_STATUS_from_SysRes(r);
4284 POST(mmap)
4286 if (RES != -1) {
4287 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
4288 // Try to load symbols from the region
4289 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
4290 -1/*don't use_fd*/ );
4291 ML_(sync_mappings)("after", "mmap", 0);
4296 /* This function holds common elements of PRE(__sysctl) and
4297 PRE(sysctlbyname). */
4298 static void common_PRE_sysctl (
4299 /*IMPLICIT ARGS*/
4300 ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
4301 /*!IMPLICIT ARGS*/
4302 Bool is_kern_dot_userstack,
4303 UWord oldp, UWord oldlenp,
4304 UWord newp, UWord newlen )
4306 if (oldlenp) {
4307 // writes *oldlenp
4308 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4309 if (oldp) {
4310 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4311 PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4312 PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
4315 if (newp) {
4316 PRE_MEM_READ("sysctl(newp)", newp, newlen);
4319 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4320 // (executable path and arguments and environment
4322 if (is_kern_dot_userstack) {
4323 // Intercept sysctl(kern.usrstack). The kernel's reply
4324 // would be Valgrind's stack, not the client's stack.
4325 // GrP fixme kern_usrstack64 */
4326 if (newp || newlen) {
4327 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
4328 } else {
4329 Addr* t_oldp = (Addr*)oldp;
4330 size_t* t_oldlenp = (size_t*)oldlenp;
4331 if (t_oldlenp) {
4332 // According to some searches on the net, it looks like
4333 // USRSTACK gives the address of the byte following the
4334 // highest byte of the stack. As VG_(clstk_end) is the
4335 // address of the highest addressable byte, we add 1.
4336 Addr stack_end = VG_(clstk_end)+1;
4337 size_t oldlen = *t_oldlenp;
4338 // always return actual size
4339 *t_oldlenp = sizeof(Addr);
4340 if (t_oldp && oldlen >= sizeof(Addr)) {
4341 // oldp is big enough. copy value and return 0
4342 *t_oldp = stack_end;
4343 SET_STATUS_Success(0);
4344 } else {
4345 // oldp isn't big enough. copy as much as possible
4346 // and return ENOMEM
4347 if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
4348 SET_STATUS_Failure(VKI_ENOMEM);
4354 if (!SUCCESS && !FAILURE) {
4355 // Don't set SfPostOnFail if we've already handled it locally.
4356 *flags |= SfPostOnFail;
4361 PRE(__sysctl)
4363 UWord name = ARG1;
4364 UWord namelen = ARG2;
4365 UWord oldp = ARG3;
4366 UWord oldlenp = ARG4;
4367 UWord newp = ARG5;
4368 UWord newlen = ARG6;
4370 PRINT( "__sysctl ( %#lx, %lu, %#lx, %#lx, %#lx, %#lx )",
4371 name, namelen, oldp, oldlenp, newp, newlen );
4373 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
4374 void*, oldp, vki_size_t *, oldlenp,
4375 void*, newp, vki_size_t *, newlenp);
4377 PRE_MEM_READ("sysctl(name)", name, namelen); // reads name[0..namelen-1]
4379 if (VG_(clo_trace_syscalls)) {
4380 UInt i;
4381 Int* t_name = (Int*)name;
4382 VG_(printf)(" mib: [ ");
4383 for (i = 0; i < namelen; i++) {
4384 VG_(printf)("%d ", t_name[i]);
4386 VG_(printf)("]");
4389 Int vKI_KERN_USRSTACKXX
4390 = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64;
4391 Bool is_kern_dot_userstack
4392 = name && namelen == 2
4393 && ((Int*)name)[0] == VKI_CTL_KERN
4394 && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
4396 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
4397 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
4400 POST(__sysctl)
4402 UWord oldp = ARG3;
4403 UWord oldlenp = ARG4;
4405 if (SUCCESS || ERR == VKI_ENOMEM) {
4406 // sysctl can write truncated data and return VKI_ENOMEM
4407 if (oldlenp) {
4408 POST_MEM_WRITE(oldlenp, sizeof(size_t));
4410 if (oldp && oldlenp) {
4411 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
4417 PRE(sigpending)
4419 PRINT( "sigpending ( %#lx )", ARG1 );
4420 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
4421 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
4423 POST(sigpending)
4425 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
4429 PRE(sigprocmask)
4431 UWord arg1;
4432 PRINT("sigprocmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
4433 PRE_REG_READ3(long, "sigprocmask",
4434 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
4435 if (ARG2 != 0)
4436 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4437 if (ARG3 != 0)
4438 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
4440 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4441 value of 'how' is irrelevant, and it appears that Darwin's libc
4442 passes zero, which is not equal to any of
4443 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4444 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4445 value independently of the other args. Solution: in this case,
4446 simply pass a valid (but irrelevant) value for 'how'. */
4447 /* Also, in this case the new set is passed to the kernel by
4448 reference, not value, as in some other sigmask related Darwin
4449 syscalls. */
4450 arg1 = ARG1;
4451 if (ARG2 == 0 /* the new-set is NULL */
4452 && ARG1 != VKI_SIG_BLOCK
4453 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
4454 arg1 = VKI_SIG_SETMASK;
4456 SET_STATUS_from_SysRes(
4457 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
4458 (vki_sigset_t*)ARG3 )
4461 if (SUCCESS)
4462 *flags |= SfPollAfter;
4465 POST(sigprocmask)
4467 vg_assert(SUCCESS);
4468 if (RES == 0 && ARG3 != 0)
4469 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
4473 PRE(sigsuspend)
4475 /* Just hand this off to the kernel. Is that really correct? And
4476 shouldn't we at least set SfPollAfter? These questions apply to
4477 all the Linux versions too. */
4478 /* I think the first arg is the 32-bit signal mask (by value), and
4479 the other two args are ignored. */
4480 *flags |= SfMayBlock;
4481 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
4482 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
4486 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4487 and 32-bit wrappers are different.
4489 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4490 length in the usual way. I have seen values NULL, 0 passed in some
4491 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4492 basis that they don't do anything if the length is zero, so it's OK
4493 for the buffer pointer to be NULL in that case (meaning they don't
4494 complain).
4496 int proc_info(int32_t callnum, int32_t pid,
4497 uint32_t flavor, uint64_t arg,
4498 user_addr_t buffer, int32_t buffersize)
4500 PRE(proc_info)
4502 #if VG_WORDSIZE == 4
4503 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4504 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
4505 PRE_REG_READ7(int, "proc_info",
4506 int, callnum, int, pid, unsigned int, flavor,
4507 vki_uint32_t, arg_low32,
4508 vki_uint32_t, arg_high32,
4509 void*, buffer, int, buffersize);
4510 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
4511 #else
4512 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4513 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
4514 PRE_REG_READ6(int, "proc_info",
4515 int, callnum, int, pid, unsigned int, flavor,
4516 unsigned long long int, arg,
4517 void*, buffer, int, buffersize);
4518 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
4519 #endif
4522 POST(proc_info)
4524 #if VG_WORDSIZE == 4
4525 vg_assert(SUCCESS);
4527 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4528 if (ARG1 == 5 && ARG3 == 2 && LOHI64(ARG4,ARG5) == 0 )
4530 const HChar* new_name = (const HChar*) ARG6;
4531 if (new_name) { // Paranoia
4532 ThreadState* tst = VG_(get_ThreadState)(tid);
4533 SizeT new_len = VG_(strlen)(new_name);
4535 /* Don't bother reusing the memory. This is a rare event. */
4536 tst->thread_name =
4537 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4538 VG_(strcpy)(tst->thread_name, new_name);
4542 POST_MEM_WRITE(ARG6, ARG7);
4543 #else
4544 vg_assert(SUCCESS);
4546 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4547 if (ARG1 == 5 && ARG3 == 2 && ARG4 == 0 )
4549 const HChar* new_name = (const HChar*) ARG5;
4550 if (new_name) { // Paranoia
4551 ThreadState* tst = VG_(get_ThreadState)(tid);
4552 SizeT new_len = VG_(strlen)(new_name);
4554 /* Don't bother reusing the memory. This is a rare event. */
4555 tst->thread_name =
4556 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4557 VG_(strcpy)(tst->thread_name, new_name);
4561 POST_MEM_WRITE(ARG5, ARG6);
4562 #endif
4566 /* ---------------------------------------------------------------------
4567 aio_*
4568 ------------------------------------------------------------------ */
4570 // We must record the aiocbp for each aio_read() in a table so that when
4571 // aio_return() is called we can mark the memory written asynchronously by
4572 // aio_read() as having been written. We don't have to do this for
4573 // aio_write(). See bug 197227 for more details.
4574 static OSet* aiocbp_table = NULL;
4575 static Bool aio_init_done = False;
4577 static void aio_init(void)
4579 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
4580 aio_init_done = True;
4583 static Bool was_a_successful_aio_read = False;
4585 PRE(aio_return)
4587 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4588 // This assumes that the kernel looks at the struct pointer, but not the
4589 // contents of the struct.
4590 PRINT( "aio_return ( %#lx )", ARG1 );
4591 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
4593 if (!aio_init_done) aio_init();
4594 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
4596 POST(aio_return)
4598 // If we found the aiocbp in our own table it must have been an aio_read(),
4599 // so mark the buffer as written. If we didn't find it, it must have been
4600 // an aio_write() or a bogus aio_return() (eg. a second one on the same
4601 // aiocbp). Either way, the buffer won't have been written so we don't
4602 // have to mark the buffer as written.
4603 if (was_a_successful_aio_read) {
4604 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4605 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4606 was_a_successful_aio_read = False;
4610 PRE(aio_suspend)
4612 // This assumes that the kernel looks at the struct pointers in the list,
4613 // but not the contents of the structs.
4614 PRINT( "aio_suspend ( %#lx )", ARG1 );
4615 PRE_REG_READ3(long, "aio_suspend",
4616 const struct vki_aiocb *, aiocbp, int, nent,
4617 const struct vki_timespec *, timeout);
4618 if (ARG2 > 0)
4619 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
4620 if (ARG3)
4621 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
4624 PRE(aio_error)
4626 // This assumes that the kernel looks at the struct pointer, but not the
4627 // contents of the struct.
4628 PRINT( "aio_error ( %#lx )", ARG1 );
4629 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
4632 PRE(aio_read)
4634 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4636 PRINT( "aio_read ( %#lx )", ARG1 );
4637 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4638 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4640 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4641 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4642 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4643 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4644 } else {
4645 SET_STATUS_Failure( VKI_EBADF );
4647 } else {
4648 SET_STATUS_Failure( VKI_EINVAL );
4651 POST(aio_read)
4653 // We have to record the fact that there is an asynchronous read request
4654 // pending. When a successful aio_return() occurs for this aiocb, then we
4655 // will mark the memory as having been defined.
4656 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4657 if (!aio_init_done) aio_init();
4658 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4659 // should have caused the aio_read() to fail and we shouldn't have reached
4660 // here.
4661 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4664 PRE(aio_write)
4666 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4668 PRINT( "aio_write ( %#lx )", ARG1 );
4669 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4670 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4672 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4673 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4674 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4675 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4676 } else {
4677 SET_STATUS_Failure( VKI_EBADF );
4679 } else {
4680 SET_STATUS_Failure( VKI_EINVAL );
4684 /* ---------------------------------------------------------------------
4685 mach_msg: formatted messages
4686 ------------------------------------------------------------------ */
4688 static size_t desc_size(mach_msg_descriptor_t *desc)
4690 switch (desc->type.type) {
4691 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
4692 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
4693 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
4694 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
4695 default:
4696 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4697 return sizeof(desc->type); // guess
4702 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4703 const char *name)
4705 mach_msg_size_t i;
4706 mach_port_t *ports = (mach_port_t *)desc->address;
4707 for (i = 0; i < desc->count; i++) {
4708 assign_port_name(ports[i], name);
4713 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4715 mach_msg_body_t *body;
4716 mach_msg_size_t count, i;
4717 uint8_t *p;
4718 mach_msg_descriptor_t *desc;
4720 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4722 body = (mach_msg_body_t *)(mh+1);
4723 count = body->msgh_descriptor_count;
4724 p = (uint8_t *)(body+1);
4726 for (i = 0; i < count; i++) {
4727 desc = (mach_msg_descriptor_t *)p;
4728 p += desc_size(desc);
4730 switch (desc->type.type) {
4731 case MACH_MSG_PORT_DESCRIPTOR:
4732 // single port
4733 record_unnamed_port(tid, desc->port.name, -1);
4734 record_port_insert_rights(desc->port.name, desc->port.disposition);
4735 PRINT("got port %s;\n", name_for_port(desc->port.name));
4736 break;
4738 case MACH_MSG_OOL_DESCRIPTOR:
4739 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4740 // out-of-line memory - map it
4741 // GrP fixme how is VOLATILE different? do we care?
4742 // GrP fixme do other flags tell us anything? assume shared for now
4743 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4744 // GrP fixme protection
4745 if (desc->out_of_line.size > 0) {
4746 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4747 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4748 (Addr)desc->out_of_line.size);
4749 PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4750 (char*)desc->out_of_line.address+desc->out_of_line.size);
4752 ML_(notify_core_and_tool_of_mmap)(
4753 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4754 VKI_MAP_PRIVATE, -1, 0);
4756 // GrP fixme mark only un-rounded part as initialized
4757 break;
4759 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4760 // out-of-line array of ports - map it
4761 // GrP fixme see fixmes above
4762 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));
4764 if (desc->ool_ports.count > 0) {
4765 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4766 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4767 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4769 ML_(notify_core_and_tool_of_mmap)(
4770 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4771 VKI_MAP_PRIVATE, -1, 0);
4773 PRINT(":");
4774 for (i = 0; i < desc->ool_ports.count; i++) {
4775 record_unnamed_port(tid, ports[i], -1);
4776 record_port_insert_rights(ports[i], desc->port.disposition);
4777 PRINT(" %s", name_for_port(ports[i]));
4780 PRINT(";\n");
4781 break;
4783 default:
4784 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4785 break;
4791 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4793 #pragma pack(4)
4794 struct {
4795 mach_port_t name;
4796 mach_msg_size_t pad1;
4797 uint16_t pad2;
4798 uint8_t disposition;
4799 uint8_t type;
4800 } *desc = (void*)desc2;
4801 #pragma pack()
4803 PRE_FIELD_READ("msg->desc.port.name", desc->name);
4804 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4805 PRE_FIELD_READ("msg->desc.port.type", desc->type);
4809 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4811 #pragma pack(4)
4812 struct {
4813 Addr address;
4814 #if VG_WORDSIZE != 8
4815 mach_msg_size_t size;
4816 #endif
4817 uint8_t deallocate;
4818 uint8_t copy;
4819 uint8_t pad1;
4820 uint8_t type;
4821 #if VG_WORDSIZE == 8
4822 mach_msg_size_t size;
4823 #endif
4824 } *desc = (void*)desc2;
4825 #pragma pack()
4827 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4828 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4829 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4830 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4831 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4834 static void pre_oolports_desc_read(ThreadId tid,
4835 mach_msg_ool_ports_descriptor_t *desc2)
4837 #pragma pack(4)
4838 struct {
4839 Addr address;
4840 #if VG_WORDSIZE != 8
4841 mach_msg_size_t size;
4842 #endif
4843 uint8_t deallocate;
4844 uint8_t copy;
4845 uint8_t disposition;
4846 uint8_t type;
4847 #if VG_WORDSIZE == 8
4848 mach_msg_size_t size;
4849 #endif
4850 } *desc = (void*)desc2;
4851 #pragma pack()
4853 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4854 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4855 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4856 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4857 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4858 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4862 // Returns the size of the descriptor area
4863 // (mach_msg_body_t + any mach_msg_descriptor_t)
4864 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4866 mach_msg_body_t *body;
4867 mach_msg_size_t count, i;
4868 uint8_t *p;
4869 mach_msg_descriptor_t *desc;
4871 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4873 body = (mach_msg_body_t *)(mh+1);
4874 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4876 count = body->msgh_descriptor_count;
4877 p = (uint8_t *)(body+1);
4879 for (i = 0; i < count; i++) {
4880 desc = (mach_msg_descriptor_t *)p;
4881 p += desc_size(desc);
4883 switch (desc->type.type) {
4884 case MACH_MSG_PORT_DESCRIPTOR:
4885 // single port; no memory map effects
4886 pre_port_desc_read(tid, &desc->port);
4887 break;
4889 case MACH_MSG_OOL_DESCRIPTOR:
4890 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4891 // out-of-line memory - unmap it if it's marked dealloc
4892 // GrP fixme need to remap if message fails?
4893 // GrP fixme how is VOLATILE different? do we care?
4894 // GrP fixme struct is different for lp64
4895 pre_ool_desc_read(tid, &desc->out_of_line);
4897 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4898 vm_size_t size = desc->out_of_line.size;
4899 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4900 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4901 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4902 (Addr)desc->out_of_line.address + size);
4903 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4905 break;
4907 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4908 // out-of-line array of ports - unmap it if it's marked dealloc
4909 // GrP fixme need to remap if message fails?
4910 // GrP fixme struct different for lp64
4911 pre_oolports_desc_read(tid, &desc->ool_ports);
4913 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4914 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4915 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4916 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4917 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4918 (Addr)desc->ool_ports.address + size);
4919 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4921 break;
4922 default:
4923 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4924 break;
4928 return (size_t)((Addr)p - (Addr)body);
4932 /* ---------------------------------------------------------------------
4933 mach_msg: host-related messages
4934 ------------------------------------------------------------------ */
4937 POST(host_info)
4939 #pragma pack(4)
4940 typedef struct {
4941 mach_msg_header_t Head;
4942 NDR_record_t NDR;
4943 kern_return_t RetCode;
4944 mach_msg_type_number_t host_info_outCnt;
4945 integer_t host_info_out[14];
4946 } Reply;
4947 #pragma pack()
4949 Reply *reply = (Reply *)ARG1;
4951 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4954 PRE(host_info)
4956 #pragma pack(4)
4957 typedef struct {
4958 mach_msg_header_t Head;
4959 NDR_record_t NDR;
4960 host_flavor_t flavor;
4961 mach_msg_type_number_t host_info_outCnt;
4962 } Request;
4963 #pragma pack()
4965 Request *req = (Request *)ARG1;
4967 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4969 AFTER = POST_FN(host_info);
4973 POST(host_page_size)
4975 #pragma pack(4)
4976 typedef struct {
4977 mach_msg_header_t Head;
4978 NDR_record_t NDR;
4979 kern_return_t RetCode;
4980 vm_size_t out_page_size;
4981 } Reply;
4982 #pragma pack()
4984 Reply *reply = (Reply *)ARG1;
4986 if (!reply->RetCode) {
4987 PRINT("page size %llu", (ULong)reply->out_page_size);
4988 } else {
4989 PRINT("mig return %d", reply->RetCode);
4993 PRE(host_page_size)
4995 PRINT("host_page_size(mach_host_self(), ...)");
4997 AFTER = POST_FN(host_page_size);
5001 POST(host_get_io_master)
5003 #pragma pack(4)
5004 typedef struct {
5005 mach_msg_header_t Head;
5006 /* start of the kernel processed data */
5007 mach_msg_body_t msgh_body;
5008 mach_msg_port_descriptor_t io_master;
5009 /* end of the kernel processed data */
5010 } Reply;
5011 #pragma pack()
5013 Reply *reply = (Reply *)ARG1;
5015 assign_port_name(reply->io_master.name, "io_master-%p");
5016 PRINT("%s", name_for_port(reply->io_master.name));
5019 PRE(host_get_io_master)
5021 #pragma pack(4)
5022 typedef struct {
5023 mach_msg_header_t Head;
5024 } Request;
5025 #pragma pack()
5027 // Request *req = (Request *)ARG1;
5029 PRINT("host_get_io_master(mach_host_self())");
5031 AFTER = POST_FN(host_get_io_master);
5035 POST(host_get_clock_service)
5037 #pragma pack(4)
5038 typedef struct {
5039 mach_msg_header_t Head;
5040 /* start of the kernel processed data */
5041 mach_msg_body_t msgh_body;
5042 mach_msg_port_descriptor_t clock_serv;
5043 /* end of the kernel processed data */
5044 } Reply;
5045 #pragma pack()
5047 Reply *reply = (Reply *)ARG1;
5049 assign_port_name(reply->clock_serv.name, "clock-%p");
5050 PRINT("%s", name_for_port(reply->clock_serv.name));
5053 PRE(host_get_clock_service)
5055 #pragma pack(4)
5056 typedef struct {
5057 mach_msg_header_t Head;
5058 NDR_record_t NDR;
5059 clock_id_t clock_id;
5060 } Request;
5061 #pragma pack()
5063 Request *req = (Request *)ARG1;
5065 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
5067 AFTER = POST_FN(host_get_clock_service);
5071 PRE(host_request_notification)
5073 #pragma pack(4)
5074 typedef struct {
5075 mach_msg_header_t Head;
5076 /* start of the kernel processed data */
5077 mach_msg_body_t msgh_body;
5078 mach_msg_port_descriptor_t notify_port;
5079 /* end of the kernel processed data */
5080 NDR_record_t NDR;
5081 host_flavor_t notify_type;
5082 } Request;
5083 #pragma pack()
5085 Request *req = (Request *)ARG1;
5087 if (MACH_REMOTE == mach_task_self()) {
5088 if (req->notify_type == 0) {
5089 PRINT("host_request_notification(mach_host_self(), %s, %s)",
5090 "HOST_NOTIFY_CALENDAR_CHANGE",
5091 name_for_port(req->notify_port.name));
5092 } else {
5093 PRINT("host_request_notification(mach_host_self(), %d, %s)",
5094 req->notify_type,
5095 name_for_port(req->notify_port.name));
5097 } else {
5098 PRINT("host_request_notification(%s, %d, %s)",
5099 name_for_port(MACH_REMOTE),
5100 req->notify_type,
5101 name_for_port(req->notify_port.name));
5104 // GrP fixme only do this on success
5105 assign_port_name(req->notify_port.name, "host_notify-%p");
5109 PRE(host_create_mach_voucher)
5111 #pragma pack(4)
5112 typedef struct {
5113 mach_msg_header_t Head;
5114 NDR_record_t NDR;
5115 mach_msg_type_number_t recipesCnt;
5116 uint8_t recipes[5120];
5117 } Request;
5118 #pragma pack()
5120 Request *req = (Request *)ARG1;
5122 PRINT("host_create_mach_voucher(count %u)",
5123 req->recipesCnt);
5125 AFTER = POST_FN(host_create_mach_voucher);
5129 POST(host_create_mach_voucher)
5131 #pragma pack(4)
5132 typedef struct {
5133 mach_msg_header_t Head;
5134 /* start of the kernel processed data */
5135 mach_msg_body_t msgh_body;
5136 mach_msg_port_descriptor_t voucher;
5137 /* end of the kernel processed data */
5138 } Reply;
5139 #pragma pack()
5141 Reply *reply = (Reply *)ARG1;
5143 // RK fixme properly parse this return type
5144 PRINT("got voucher %#x ", reply->voucher.name);
5148 PRE(host_get_special_port)
5150 #pragma pack(4)
5151 typedef struct {
5152 mach_msg_header_t Head;
5153 NDR_record_t NDR;
5154 int node;
5155 int which;
5156 } Request;
5157 #pragma pack()
5159 Request *req = (Request *)ARG1;
5161 PRINT("host_get_special_port(node %d)", req->node);
5163 switch (req->which) {
5164 case HOST_PORT:
5165 PRINT("host_get_special_port(%s, HOST_PORT)",
5166 name_for_port(MACH_REMOTE));
5167 break;
5168 case HOST_PRIV_PORT:
5169 PRINT("host_get_special_port(%s, HOST_PRIV_PORT)",
5170 name_for_port(MACH_REMOTE));
5171 break;
5172 case HOST_IO_MASTER_PORT:
5173 PRINT("host_get_special_port(%s, HOST_IO_MASTER_PORT)",
5174 name_for_port(MACH_REMOTE));
5175 break;
5176 // Not provided by kernel
5177 case HOST_DYNAMIC_PAGER_PORT:
5178 PRINT("host_get_special_port(%s, HOST_DYNAMIC_PAGER_PORT)",
5179 name_for_port(MACH_REMOTE));
5180 break;
5181 case HOST_AUDIT_CONTROL_PORT:
5182 PRINT("host_get_special_port(%s, HOST_AUDIT_CONTROL_PORT)",
5183 name_for_port(MACH_REMOTE));
5184 break;
5185 case HOST_USER_NOTIFICATION_PORT:
5186 PRINT("host_get_special_port(%s, HOST_USER_NOTIFICATION_PORT)",
5187 name_for_port(MACH_REMOTE));
5188 break;
5189 // ...
5191 default:
5192 PRINT("host_get_special_port(%s, %d)",
5193 name_for_port(MACH_REMOTE), req->which);
5194 break;
5197 MACH_ARG(host_get_special_port.which) = req->which;
5199 AFTER = POST_FN(host_get_special_port);
5203 POST(host_get_special_port)
5205 #pragma pack(4)
5206 typedef struct {
5207 mach_msg_header_t Head;
5208 /* start of the kernel processed data */
5209 mach_msg_body_t msgh_body;
5210 mach_msg_port_descriptor_t port;
5211 /* end of the kernel processed data */
5212 } Reply;
5213 #pragma pack()
5215 Reply *reply = (Reply *)ARG1;
5217 PRINT("got port %#x ", reply->port.name);
5219 /* The required entry in the allocated_ports list (mapping) might
5220 not exist, due perhaps to broken syscall wrappers (mach__N etc).
5221 Create a minimal entry so that assign_port_name below doesn't
5222 cause an assertion. */
5223 if (!port_exists(reply->port.name)) {
5224 port_create_vanilla(reply->port.name);
5227 switch (MACH_ARG(host_get_special_port.which)) {
5228 case HOST_PORT:
5229 assign_port_name(reply->port.name, "port-%p");
5230 break;
5231 case HOST_PRIV_PORT:
5232 assign_port_name(reply->port.name, "priv-%p");
5233 break;
5234 case HOST_IO_MASTER_PORT:
5235 assign_port_name(reply->port.name, "io-master-%p");
5236 break;
5237 // Not provided by kernel
5238 case HOST_DYNAMIC_PAGER_PORT:
5239 assign_port_name(reply->port.name, "dynamic-pager-%p");
5240 break;
5241 case HOST_AUDIT_CONTROL_PORT:
5242 assign_port_name(reply->port.name, "audit-control-%p");
5243 break;
5244 case HOST_USER_NOTIFICATION_PORT:
5245 assign_port_name(reply->port.name, "user-notification-%p");
5246 break;
5247 // ...
5249 default:
5250 assign_port_name(reply->port.name, "special-%p");
5251 break;
5254 PRINT("%s", name_for_port(reply->port.name));
5257 /* ---------------------------------------------------------------------
5258 mach_msg: messages to a task
5259 ------------------------------------------------------------------ */
5261 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
5262 // these structs are derived. They obviously relate to the various
5263 // .def files in the xnu sources, and can also be found in some
5264 // form in /usr/include/mach/*.h, but not sure how these all
5265 // relate to each other.
5267 PRE(mach_port_set_context)
5269 #pragma pack(4)
5270 typedef struct {
5271 mach_msg_header_t Head;
5272 NDR_record_t NDR;
5273 mach_port_name_t name;
5274 mach_vm_address_t context;
5275 } Request;
5276 #pragma pack()
5278 Request *req = (Request *)ARG1;
5280 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
5281 name_for_port(MACH_REMOTE),
5282 name_for_port(req->name), req->context);
5284 AFTER = POST_FN(mach_port_set_context);
5287 POST(mach_port_set_context)
5289 #pragma pack(4)
5290 typedef struct {
5291 mach_msg_header_t Head;
5292 NDR_record_t NDR;
5293 kern_return_t RetCode;
5294 } Reply;
5295 #pragma pack()
5299 // JRS 2011-Aug-25 FIXME completely bogus
5300 PRE(task_get_exception_ports)
5302 #pragma pack(4)
5303 typedef struct {
5304 mach_msg_header_t Head;
5305 NDR_record_t NDR;
5306 exception_mask_t exception_mask;
5307 } Request;
5308 #pragma pack()
5310 PRINT("task_get_exception_ports(BOGUS)");
5311 AFTER = POST_FN(task_get_exception_ports);
5314 POST(task_get_exception_ports)
5316 #pragma pack(4)
5317 typedef struct {
5318 mach_msg_header_t Head;
5319 /* start of the kernel processed data */
5320 mach_msg_body_t msgh_body;
5321 mach_msg_port_descriptor_t old_handlers[32];
5322 /* end of the kernel processed data */
5323 NDR_record_t NDR;
5324 mach_msg_type_number_t masksCnt;
5325 exception_mask_t masks[32];
5326 exception_behavior_t old_behaviors[32];
5327 thread_state_flavor_t old_flavors[32];
5328 } Reply;
5329 #pragma pack()
5333 ///////////////////////////////////////////////////
5335 PRE(mach_port_type)
5337 #pragma pack(4)
5338 typedef struct {
5339 mach_msg_header_t Head;
5340 NDR_record_t NDR;
5341 mach_port_name_t name;
5342 } Request;
5343 #pragma pack()
5345 Request *req = (Request *)ARG1;
5347 PRINT("mach_port_type(%s, %s, ...)",
5348 name_for_port(MACH_REMOTE), name_for_port(req->name));
5350 AFTER = POST_FN(mach_port_type);
5353 POST(mach_port_type)
5358 PRE(mach_port_extract_member)
5360 #pragma pack(4)
5361 typedef struct {
5362 mach_msg_header_t Head;
5363 NDR_record_t NDR;
5364 mach_port_name_t name;
5365 mach_port_name_t pset;
5366 } Request;
5367 #pragma pack()
5369 Request *req = (Request *)ARG1;
5371 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5372 name_for_port(MACH_REMOTE),
5373 req->name, req->pset);
5375 AFTER = POST_FN(mach_port_extract_member);
5377 // GrP fixme port tracker?
5380 POST(mach_port_extract_member)
5382 #pragma pack(4)
5383 typedef struct {
5384 mach_msg_header_t Head;
5385 NDR_record_t NDR;
5386 kern_return_t RetCode;
5387 } Reply;
5388 #pragma pack()
5390 Reply *reply = (Reply *)ARG1;
5392 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
5396 PRE(mach_port_allocate)
5398 #pragma pack(4)
5399 typedef struct {
5400 mach_msg_header_t Head;
5401 NDR_record_t NDR;
5402 mach_port_right_t right;
5403 } Request;
5404 #pragma pack()
5406 Request *req = (Request *)ARG1;
5408 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
5410 MACH_ARG(mach_port_allocate.right) = req->right;
5412 AFTER = POST_FN(mach_port_allocate);
5415 POST(mach_port_allocate)
5417 #pragma pack(4)
5418 typedef struct {
5419 mach_msg_header_t Head;
5420 NDR_record_t NDR;
5421 kern_return_t RetCode;
5422 mach_port_name_t name;
5423 } Reply;
5424 #pragma pack()
5426 Reply *reply = (Reply *)ARG1;
5428 if (!reply->RetCode) {
5429 if (MACH_REMOTE == vg_task_port) {
5430 // GrP fixme port tracking is too imprecise
5431 // vg_assert(!port_exists(reply->name));
5432 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
5433 PRINT("got port 0x%x", reply->name);
5434 } else {
5435 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
5437 } else {
5438 PRINT("mig return %d", reply->RetCode);
5443 PRE(mach_port_deallocate)
5445 #pragma pack(4)
5446 typedef struct {
5447 mach_msg_header_t Head;
5448 NDR_record_t NDR;
5449 mach_port_name_t name;
5450 } Request;
5451 #pragma pack()
5453 Request *req = (Request *)ARG1;
5455 PRINT("mach_port_deallocate(%s, %s)",
5456 name_for_port(MACH_REMOTE),
5457 name_for_port(req->name));
5459 MACH_ARG(mach_port.port) = req->name;
5461 AFTER = POST_FN(mach_port_deallocate);
5463 // Must block to prevent race (other thread allocates and
5464 // notifies after we deallocate but before we notify)
5465 *flags &= ~SfMayBlock;
5468 POST(mach_port_deallocate)
5470 #pragma pack(4)
5471 typedef struct {
5472 mach_msg_header_t Head;
5473 NDR_record_t NDR;
5474 kern_return_t RetCode;
5475 } Reply;
5476 #pragma pack()
5478 Reply *reply = (Reply *)ARG1;
5480 if (!reply->RetCode) {
5481 if (MACH_REMOTE == vg_task_port) {
5482 // Must have cleared SfMayBlock in PRE to prevent race
5483 record_port_dealloc(MACH_ARG(mach_port.port));
5484 } else {
5485 VG_(printf)("UNKNOWN remote port dealloc\n");
5487 } else {
5488 PRINT("mig return %d", reply->RetCode);
5493 PRE(mach_port_get_refs)
5495 #pragma pack(4)
5496 typedef struct {
5497 mach_msg_header_t Head;
5498 NDR_record_t NDR;
5499 mach_port_name_t name;
5500 mach_port_right_t right;
5501 } Request;
5502 #pragma pack()
5504 Request *req = (Request *)ARG1;
5506 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5507 name_for_port(MACH_REMOTE),
5508 name_for_port(req->name), req->right);
5510 MACH_ARG(mach_port_mod_refs.port) = req->name;
5511 MACH_ARG(mach_port_mod_refs.right) = req->right;
5513 AFTER = POST_FN(mach_port_get_refs);
5516 POST(mach_port_get_refs)
5518 #pragma pack(4)
5519 typedef struct {
5520 mach_msg_header_t Head;
5521 NDR_record_t NDR;
5522 kern_return_t RetCode;
5523 mach_port_urefs_t refs;
5524 } Reply;
5525 #pragma pack()
5527 Reply *reply = (Reply *)ARG1;
5529 if (!reply->RetCode) {
5530 PRINT("got refs=%d", reply->refs);
5531 } else {
5532 PRINT("mig return %d", reply->RetCode);
5537 PRE(mach_port_mod_refs)
5539 #pragma pack(4)
5540 typedef struct {
5541 mach_msg_header_t Head;
5542 NDR_record_t NDR;
5543 mach_port_name_t name;
5544 mach_port_right_t right;
5545 mach_port_delta_t delta;
5546 } Request;
5547 #pragma pack()
5549 Request *req = (Request *)ARG1;
5551 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5552 name_for_port(MACH_REMOTE),
5553 name_for_port(req->name), req->right, req->delta);
5555 MACH_ARG(mach_port_mod_refs.port) = req->name;
5556 MACH_ARG(mach_port_mod_refs.right) = req->right;
5557 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
5559 AFTER = POST_FN(mach_port_mod_refs);
5561 // Must block to prevent race (other thread allocates and
5562 // notifies after we deallocate but before we notify)
5563 *flags &= ~SfMayBlock;
5566 POST(mach_port_mod_refs)
5568 #pragma pack(4)
5569 typedef struct {
5570 mach_msg_header_t Head;
5571 NDR_record_t NDR;
5572 kern_return_t RetCode;
5573 } Reply;
5574 #pragma pack()
5576 Reply *reply = (Reply *)ARG1;
5578 if (!reply->RetCode) {
5579 if (MACH_REMOTE == vg_task_port) {
5580 // Must have cleared SfMayBlock in PRE to prevent race
5581 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
5582 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
5583 MACH_ARG(mach_port_mod_refs.delta));
5584 } else {
5585 VG_(printf)("UNKNOWN remote port mod refs\n");
5587 } else {
5588 PRINT("mig return %d", reply->RetCode);
5593 PRE(mach_port_get_set_status)
5595 #pragma pack(4)
5596 typedef struct {
5597 mach_msg_header_t Head;
5598 NDR_record_t NDR;
5599 mach_port_name_t name;
5600 } Request;
5601 #pragma pack()
5603 Request *req = (Request *)ARG1;
5605 PRINT("mach_port_get_set_status(%s, %s)",
5606 name_for_port(MACH_REMOTE),
5607 name_for_port(req->name));
5609 AFTER = POST_FN(mach_port_get_set_status);
5612 POST(mach_port_get_set_status)
5614 #pragma pack(4)
5615 typedef struct {
5616 mach_msg_header_t Head;
5617 /* start of the kernel processed data */
5618 mach_msg_body_t msgh_body;
5619 mach_msg_ool_descriptor_t members;
5620 /* end of the kernel processed data */
5621 NDR_record_t NDR;
5622 mach_msg_type_number_t membersCnt;
5623 mach_msg_trailer_t trailer;
5624 } Reply;
5625 #pragma pack()
5627 // Reply *reply = (Reply *)ARG1;
5629 // GrP fixme nothing to do?
5633 PRE(mach_port_move_member)
5635 #pragma pack(4)
5636 typedef struct {
5637 mach_msg_header_t Head;
5638 NDR_record_t NDR;
5639 mach_port_name_t member;
5640 mach_port_name_t after;
5641 } Request;
5642 #pragma pack()
5644 Request *req = (Request *)ARG1;
5646 PRINT("mach_port_move_member(%s, %s, %s)",
5647 name_for_port(MACH_REMOTE),
5648 name_for_port(req->member),
5649 name_for_port(req->after));
5651 MACH_ARG(mach_port_move_member.member) = req->member;
5652 MACH_ARG(mach_port_move_member.after) = req->after;
5654 AFTER = POST_FN(mach_port_move_member);
5657 POST(mach_port_move_member)
5659 #pragma pack(4)
5660 typedef struct {
5661 mach_msg_header_t Head;
5662 NDR_record_t NDR;
5663 kern_return_t RetCode;
5664 mach_msg_trailer_t trailer;
5665 } Reply;
5666 #pragma pack()
5668 Reply *reply = (Reply *)ARG1;
5670 if (!reply->RetCode) {
5671 // fixme port set tracker?
5672 } else {
5673 PRINT("mig return %d", reply->RetCode);
5678 PRE(mach_port_destroy)
5680 #pragma pack(4)
5681 typedef struct {
5682 mach_msg_header_t Head;
5683 NDR_record_t NDR;
5684 mach_port_name_t name;
5685 } Request;
5686 #pragma pack()
5688 Request *req = (Request *)ARG1;
5690 PRINT("mach_port_destroy(%s, %s)",
5691 name_for_port(MACH_REMOTE),
5692 name_for_port(req->name));
5694 MACH_ARG(mach_port.port) = req->name;
5696 AFTER = POST_FN(mach_port_destroy);
5698 // Must block to prevent race (other thread allocates and
5699 // notifies after we deallocate but before we notify)
5700 *flags &= ~SfMayBlock;
5703 POST(mach_port_destroy)
5705 #pragma pack(4)
5706 typedef struct {
5707 mach_msg_header_t Head;
5708 NDR_record_t NDR;
5709 kern_return_t RetCode;
5710 } Reply;
5711 #pragma pack()
5713 Reply *reply = (Reply *)ARG1;
5715 if (!reply->RetCode) {
5716 if (MACH_REMOTE == vg_task_port) {
5717 // Must have cleared SfMayBlock in PRE to prevent race
5718 record_port_destroy(MACH_ARG(mach_port.port));
5719 } else {
5720 VG_(printf)("UNKNOWN remote port destroy\n");
5722 } else {
5723 PRINT("mig return %d", reply->RetCode);
5728 PRE(mach_port_request_notification)
5730 #pragma pack(4)
5731 typedef struct {
5732 mach_msg_header_t Head;
5733 /* start of the kernel processed data */
5734 mach_msg_body_t msgh_body;
5735 mach_msg_port_descriptor_t notify;
5736 /* end of the kernel processed data */
5737 NDR_record_t NDR;
5738 mach_port_name_t name;
5739 mach_msg_id_t msgid;
5740 mach_port_mscount_t sync;
5741 } Request;
5742 #pragma pack()
5744 Request *req = (Request *)ARG1;
5746 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5747 name_for_port(MACH_REMOTE),
5748 name_for_port(req->name), req->msgid, req->sync,
5749 req->notify.name, req->notify.disposition);
5751 AFTER = POST_FN(mach_port_request_notification);
5754 POST(mach_port_request_notification)
5756 // GrP fixme port tracker? not sure
5760 PRE(mach_port_insert_right)
5762 #pragma pack(4)
5763 typedef struct {
5764 mach_msg_header_t Head;
5765 /* start of the kernel processed data */
5766 mach_msg_body_t msgh_body;
5767 mach_msg_port_descriptor_t poly;
5768 /* end of the kernel processed data */
5769 NDR_record_t NDR;
5770 mach_port_name_t name;
5771 } Request;
5772 #pragma pack()
5774 Request *req = (Request *)ARG1;
5776 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5777 name_for_port(MACH_REMOTE),
5778 name_for_port(req->name), req->poly.name, req->poly.disposition);
5780 AFTER = POST_FN(mach_port_insert_right);
5782 if (MACH_REMOTE == mach_task_self()) {
5783 // GrP fixme import_complex_message handles everything?
5784 // what about export_complex_message for MOVE variants?
5785 } else {
5786 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5787 // GrP fixme also may remove rights from this task?
5790 // GrP fixme port tracker?
5793 POST(mach_port_insert_right)
5798 PRE(mach_port_extract_right)
5800 #pragma pack(4)
5801 typedef struct {
5802 mach_msg_header_t Head;
5803 NDR_record_t NDR;
5804 mach_port_name_t name;
5805 mach_msg_type_name_t msgt_name;
5806 } Request;
5807 #pragma pack()
5809 Request *req = (Request *)ARG1;
5811 PRINT("mach_port_extract_right(%s, %s, %d)",
5812 name_for_port(MACH_REMOTE),
5813 name_for_port(req->name), req->msgt_name);
5815 AFTER = POST_FN(mach_port_extract_right);
5817 // fixme port tracker?
5820 POST(mach_port_extract_right)
5822 // fixme import_complex_message handles the returned result, right?
5826 PRE(mach_port_get_attributes)
5828 #pragma pack(4)
5829 typedef struct {
5830 mach_msg_header_t Head;
5831 NDR_record_t NDR;
5832 mach_port_name_t name;
5833 mach_port_flavor_t flavor;
5834 mach_msg_type_number_t port_info_outCnt;
5835 } Request;
5836 #pragma pack()
5838 Request *req = (Request *)ARG1;
5840 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5841 name_for_port(MACH_REMOTE),
5842 name_for_port(req->name), req->flavor, req->port_info_outCnt);
5844 AFTER = POST_FN(mach_port_get_attributes);
5847 POST(mach_port_get_attributes)
5852 PRE(mach_port_set_attributes)
5854 #pragma pack(4)
5855 typedef struct {
5856 mach_msg_header_t Head;
5857 NDR_record_t NDR;
5858 mach_port_name_t name;
5859 mach_port_flavor_t flavor;
5860 mach_msg_type_number_t port_infoCnt;
5861 integer_t port_info[10];
5862 } Request;
5863 #pragma pack()
5865 Request *req = (Request *)ARG1;
5867 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5868 name_for_port(MACH_REMOTE),
5869 name_for_port(req->name), req->flavor, req->port_infoCnt);
5871 AFTER = POST_FN(mach_port_set_attributes);
5874 POST(mach_port_set_attributes)
5879 PRE(mach_port_insert_member)
5881 #pragma pack(4)
5882 typedef struct {
5883 mach_msg_header_t Head;
5884 NDR_record_t NDR;
5885 mach_port_name_t name;
5886 mach_port_name_t pset;
5887 } Request;
5888 #pragma pack()
5890 Request *req = (Request *)ARG1;
5892 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5893 name_for_port(MACH_REMOTE), req->name, req->pset);
5895 AFTER = POST_FN(mach_port_insert_member);
5897 // GrP fixme port tracker?
5900 POST(mach_port_insert_member)
5905 PRE(task_get_special_port)
5907 #pragma pack(4)
5908 typedef struct {
5909 mach_msg_header_t Head;
5910 NDR_record_t NDR;
5911 int which_port;
5912 } Request;
5913 #pragma pack()
5915 Request *req = (Request *)ARG1;
5917 switch (req->which_port) {
5918 case TASK_KERNEL_PORT:
5919 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5920 name_for_port(MACH_REMOTE));
5921 break;
5922 case TASK_HOST_PORT:
5923 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5924 name_for_port(MACH_REMOTE));
5925 break;
5926 case TASK_BOOTSTRAP_PORT:
5927 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5928 name_for_port(MACH_REMOTE));
5929 break;
5930 #if DARWIN_VERS < DARWIN_10_8
5931 /* These disappeared in 10.8 */
5932 case TASK_WIRED_LEDGER_PORT:
5933 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5934 name_for_port(MACH_REMOTE));
5935 break;
5936 case TASK_PAGED_LEDGER_PORT:
5937 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5938 name_for_port(MACH_REMOTE));
5939 break;
5940 #endif
5941 default:
5942 PRINT("task_get_special_port(%s, %d)",
5943 name_for_port(MACH_REMOTE), req->which_port);
5944 break;
5947 MACH_ARG(task_get_special_port.which_port) = req->which_port;
5949 AFTER = POST_FN(task_get_special_port);
5952 POST(task_get_special_port)
5954 #pragma pack(4)
5955 typedef struct {
5956 mach_msg_header_t Head;
5957 /* start of the kernel processed data */
5958 mach_msg_body_t msgh_body;
5959 mach_msg_port_descriptor_t special_port;
5960 /* end of the kernel processed data */
5961 } Reply;
5962 #pragma pack()
5964 Reply *reply = (Reply *)ARG1;
5966 PRINT("got port %#x ", reply->special_port.name);
5968 switch (MACH_ARG(task_get_special_port.which_port)) {
5969 case TASK_BOOTSTRAP_PORT:
5970 vg_bootstrap_port = reply->special_port.name;
5971 assign_port_name(reply->special_port.name, "bootstrap");
5972 break;
5973 case TASK_KERNEL_PORT:
5974 assign_port_name(reply->special_port.name, "kernel");
5975 break;
5976 case TASK_HOST_PORT:
5977 assign_port_name(reply->special_port.name, "host");
5978 break;
5979 #if DARWIN_VERS < DARWIN_10_8
5980 /* These disappeared in 10.8 */
5981 case TASK_WIRED_LEDGER_PORT:
5982 assign_port_name(reply->special_port.name, "wired-ledger");
5983 break;
5984 case TASK_PAGED_LEDGER_PORT:
5985 assign_port_name(reply->special_port.name, "paged-ledger");
5986 break;
5987 #endif
5988 default:
5989 assign_port_name(reply->special_port.name, "special-%p");
5990 break;
5993 PRINT("%s", name_for_port(reply->special_port.name));
5997 PRE(task_set_special_port)
5999 #pragma pack(4)
6000 typedef struct {
6001 mach_msg_header_t Head;
6002 /* start of the kernel processed data */
6003 mach_msg_body_t msgh_body;
6004 mach_msg_port_descriptor_t special_port;
6005 /* end of the kernel processed data */
6006 NDR_record_t NDR;
6007 int which_port;
6008 } Request;
6009 #pragma pack()
6011 Request *req = (Request *)ARG1;
6013 PRINT("got port %#x ", req->special_port.name);
6015 // MACH_ARG(task_set_special_port.which_port) = req->which_port;
6016 PRINT("%s", name_for_port(req->special_port.name));
6018 AFTER = POST_FN(task_set_special_port);
6021 POST(task_set_special_port)
6023 #pragma pack(4)
6024 typedef struct {
6025 mach_msg_header_t Head;
6026 NDR_record_t NDR;
6027 kern_return_t RetCode;
6028 } Reply;
6029 #pragma pack()
6031 Reply *reply = (Reply *)ARG1;
6032 if (!reply->RetCode) {
6033 } else {
6034 PRINT("mig return %d", reply->RetCode);
6039 PRE(semaphore_create)
6041 #pragma pack(4)
6042 typedef struct {
6043 mach_msg_header_t Head;
6044 NDR_record_t NDR;
6045 int policy;
6046 int value;
6047 } Request;
6048 #pragma pack()
6050 Request *req = (Request *)ARG1;
6052 PRINT("semaphore_create(%s, ..., %d, %d)",
6053 name_for_port(MACH_REMOTE), req->policy, req->value);
6055 AFTER = POST_FN(semaphore_create);
6058 POST(semaphore_create)
6060 #pragma pack(4)
6061 typedef struct {
6062 mach_msg_header_t Head;
6063 /* start of the kernel processed data */
6064 mach_msg_body_t msgh_body;
6065 mach_msg_port_descriptor_t semaphore;
6066 /* end of the kernel processed data */
6067 mach_msg_trailer_t trailer;
6068 } Reply;
6069 #pragma pack()
6071 Reply *reply = (Reply *)ARG1;
6073 assign_port_name(reply->semaphore.name, "semaphore-%p");
6074 PRINT("%s", name_for_port(reply->semaphore.name));
6078 PRE(semaphore_destroy)
6080 #pragma pack(4)
6081 typedef struct {
6082 mach_msg_header_t Head;
6083 /* start of the kernel processed data */
6084 mach_msg_body_t msgh_body;
6085 mach_msg_port_descriptor_t semaphore;
6086 /* end of the kernel processed data */
6087 mach_msg_trailer_t trailer;
6088 } Request;
6089 #pragma pack()
6091 Request *req = (Request *)ARG1;
6093 PRINT("semaphore_destroy(%s, %s)",
6094 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
6096 record_port_destroy(req->semaphore.name);
6098 AFTER = POST_FN(semaphore_destroy);
6101 POST(semaphore_destroy)
6103 #pragma pack(4)
6104 typedef struct {
6105 mach_msg_header_t Head;
6106 NDR_record_t NDR;
6107 kern_return_t RetCode;
6108 mach_msg_trailer_t trailer;
6109 } Reply;
6110 #pragma pack()
6112 Reply *reply = (Reply *)ARG1;
6113 if (!reply->RetCode) {
6114 } else {
6115 PRINT("mig return %d", reply->RetCode);
6119 PRE(task_policy_set)
6121 #pragma pack(4)
6122 typedef struct {
6123 mach_msg_header_t Head;
6124 NDR_record_t NDR;
6125 task_policy_flavor_t flavor;
6126 mach_msg_type_number_t policy_infoCnt;
6127 integer_t policy_info[16];
6128 } Request;
6129 #pragma pack()
6131 Request *req = (Request *)ARG1;
6133 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6135 AFTER = POST_FN(task_policy_set);
6138 POST(task_policy_set)
6140 #pragma pack(4)
6141 typedef struct {
6142 mach_msg_header_t Head;
6143 NDR_record_t NDR;
6144 kern_return_t RetCode;
6145 } Reply;
6146 #pragma pack()
6148 Reply *reply = (Reply *)ARG1;
6149 if (!reply->RetCode) {
6150 } else {
6151 PRINT("mig return %d", reply->RetCode);
6156 PRE(mach_ports_register)
6158 #pragma pack(4)
6159 typedef struct {
6160 mach_msg_header_t Head;
6161 /* start of the kernel processed data */
6162 mach_msg_body_t msgh_body;
6163 mach_msg_ool_ports_descriptor_t init_port_set;
6164 /* end of the kernel processed data */
6165 NDR_record_t NDR;
6166 mach_msg_type_number_t init_port_setCnt;
6167 } Request;
6168 #pragma pack()
6170 // Request *req = (Request *)ARG1;
6172 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE));
6174 AFTER = POST_FN(mach_ports_register);
6177 POST(mach_ports_register)
6179 #pragma pack(4)
6180 typedef struct {
6181 mach_msg_header_t Head;
6182 NDR_record_t NDR;
6183 kern_return_t RetCode;
6184 } Reply;
6185 #pragma pack()
6187 Reply *reply = (Reply *)ARG1;
6188 if (!reply->RetCode) {
6189 } else {
6190 PRINT("mig return %d", reply->RetCode);
6195 PRE(mach_ports_lookup)
6197 #pragma pack(4)
6198 typedef struct {
6199 mach_msg_header_t Head;
6200 } Request;
6201 #pragma pack()
6203 // Request *req = (Request *)ARG1;
6205 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
6207 AFTER = POST_FN(mach_ports_lookup);
6210 POST(mach_ports_lookup)
6212 #pragma pack(4)
6213 typedef struct {
6214 mach_msg_header_t Head;
6215 /* start of the kernel processed data */
6216 mach_msg_body_t msgh_body;
6217 mach_msg_ool_ports_descriptor_t init_port_set;
6218 /* end of the kernel processed data */
6219 NDR_record_t NDR;
6220 mach_msg_type_number_t init_port_setCnt;
6221 } Reply;
6222 #pragma pack()
6224 // Reply *reply = (Reply *)ARG1;
6228 PRE(task_info)
6230 #pragma pack(4)
6231 typedef struct {
6232 mach_msg_header_t Head;
6233 NDR_record_t NDR;
6234 task_flavor_t flavor;
6235 mach_msg_type_number_t task_info_outCnt;
6236 } Request;
6237 #pragma pack()
6239 Request *req = (Request *)ARG1;
6241 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6243 AFTER = POST_FN(task_info);
6246 POST(task_info)
6248 #pragma pack(4)
6249 typedef struct {
6250 mach_msg_header_t Head;
6251 NDR_record_t NDR;
6252 kern_return_t RetCode;
6253 mach_msg_type_number_t task_info_outCnt;
6254 integer_t task_info_out[52];
6255 } Reply;
6256 #pragma pack()
6258 Reply *reply = (Reply *)ARG1;
6259 if (!reply->RetCode) {
6260 } else {
6261 PRINT("mig return %d", reply->RetCode);
6266 PRE(task_set_info)
6268 #pragma pack(4)
6269 typedef struct {
6270 mach_msg_header_t Head;
6271 NDR_record_t NDR;
6272 task_flavor_t flavor;
6273 mach_msg_type_number_t task_info_inCnt;
6274 integer_t task_info_in[52];
6275 } Request;
6276 #pragma pack()
6278 Request *req = (Request *)ARG1;
6280 PRINT("task_set_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6282 AFTER = POST_FN(task_set_info);
6285 POST(task_set_info)
6287 #pragma pack(4)
6288 typedef struct {
6289 mach_msg_header_t Head;
6290 NDR_record_t NDR;
6291 kern_return_t RetCode;
6292 } Reply;
6293 #pragma pack()
6295 Reply *reply = (Reply *)ARG1;
6296 if (!reply->RetCode) {
6297 } else {
6298 PRINT("mig return %d", reply->RetCode);
6302 PRE(task_threads)
6304 #pragma pack(4)
6305 typedef struct {
6306 mach_msg_header_t Head;
6307 } Request;
6308 #pragma pack()
6310 // Request *req = (Request *)ARG1;
6312 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
6314 AFTER = POST_FN(task_threads);
6317 POST(task_threads)
6319 #pragma pack(4)
6320 typedef struct {
6321 mach_msg_header_t Head;
6322 /* start of the kernel processed data */
6323 mach_msg_body_t msgh_body;
6324 mach_msg_ool_ports_descriptor_t act_list;
6325 /* end of the kernel processed data */
6326 NDR_record_t NDR;
6327 mach_msg_type_number_t act_listCnt;
6328 mach_msg_trailer_t trailer;
6329 } Reply;
6330 #pragma pack()
6332 Reply *reply = (Reply *)ARG1;
6334 if (MACH_REMOTE == vg_task_port) {
6335 assign_port_names(&reply->act_list, "thread-%p");
6336 } else {
6337 assign_port_names(&reply->act_list, "remote-thread-%p");
6342 PRE(task_suspend)
6344 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
6346 if (MACH_REMOTE == vg_task_port) {
6347 // GrP fixme self-suspend
6348 vg_assert(0);
6349 } else {
6350 // suspend other - no problem
6353 AFTER = POST_FN(task_suspend);
6356 POST(task_suspend)
6361 PRE(task_resume)
6363 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
6365 if (MACH_REMOTE == vg_task_port) {
6366 // GrP fixme self-resume
6367 vg_assert(0);
6368 } else {
6369 // resume other - no problem
6372 AFTER = POST_FN(task_resume);
6375 POST(task_resume)
6380 PRE(vm_allocate)
6382 #pragma pack(4)
6383 typedef struct {
6384 mach_msg_header_t Head;
6385 NDR_record_t NDR;
6386 vm_address_t address;
6387 vm_size_t size;
6388 int flags;
6389 } Request;
6390 #pragma pack()
6392 Request *req = (Request *)ARG1;
6394 PRINT("vm_allocate (%s, at %#llx, size %llu, flags %#x)",
6395 name_for_port(MACH_REMOTE),
6396 (ULong)req->address, (ULong)req->size, req->flags);
6398 MACH_ARG(vm_allocate.size) = req->size;
6399 MACH_ARG(vm_allocate.flags) = req->flags;
6401 AFTER = POST_FN(vm_allocate);
6404 POST(vm_allocate)
6406 #pragma pack(4)
6407 typedef struct {
6408 mach_msg_header_t Head;
6409 NDR_record_t NDR;
6410 kern_return_t RetCode;
6411 vm_address_t address;
6412 mach_msg_trailer_t trailer;
6413 } Reply;
6414 #pragma pack()
6416 Reply *reply = (Reply *)ARG1;
6418 if (!reply->RetCode) {
6419 if (MACH_REMOTE == vg_task_port) {
6420 PRINT("allocated at %#llx", (ULong)reply->address);
6421 // requesting 0 bytes returns address 0 with no error
6422 if (MACH_ARG(vm_allocate.size)) {
6423 ML_(notify_core_and_tool_of_mmap)(
6424 reply->address, MACH_ARG(vm_allocate.size),
6425 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6427 } else {
6428 PRINT("allocated at %#llx in remote task %s",
6429 (ULong)reply->address,
6430 name_for_port(MACH_REMOTE));
6432 } else {
6433 PRINT("mig return %d", reply->RetCode);
6438 PRE(vm_deallocate)
6440 #pragma pack(4)
6441 typedef struct {
6442 mach_msg_header_t Head;
6443 NDR_record_t NDR;
6444 vm_address_t address;
6445 vm_size_t size;
6446 } Request;
6447 #pragma pack()
6449 Request *req = (Request *)ARG1;
6451 PRINT("vm_deallocate(%s, at %#llx, size %llu)",
6452 name_for_port(MACH_REMOTE),
6453 (ULong)req->address, (ULong)req->size);
6455 MACH_ARG(vm_deallocate.address) = req->address;
6456 MACH_ARG(vm_deallocate.size) = req->size;
6458 AFTER = POST_FN(vm_deallocate);
6460 // Must block to prevent race (other thread allocates and
6461 // notifies after we deallocate but before we notify)
6462 *flags &= ~SfMayBlock;
6465 POST(vm_deallocate)
6467 #pragma pack(4)
6468 typedef struct {
6469 mach_msg_header_t Head;
6470 NDR_record_t NDR;
6471 kern_return_t RetCode;
6472 mach_msg_trailer_t trailer;
6473 } Reply;
6474 #pragma pack()
6476 Reply *reply = (Reply *)ARG1;
6478 if (!reply->RetCode) {
6479 if (MACH_REMOTE == vg_task_port) {
6480 if (MACH_ARG(vm_deallocate.size)) {
6481 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
6482 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
6483 MACH_ARG(vm_deallocate.size));
6484 // Must have cleared SfMayBlock in PRE to prevent race
6485 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6488 } else {
6489 PRINT("mig return %d", reply->RetCode);
6494 PRE(vm_protect)
6496 #pragma pack(4)
6497 typedef struct {
6498 mach_msg_header_t Head;
6499 NDR_record_t NDR;
6500 vm_address_t address;
6501 vm_size_t size;
6502 boolean_t set_maximum;
6503 vm_prot_t new_protection;
6504 } Request;
6505 #pragma pack()
6507 Request *req = (Request *)ARG1;
6509 PRINT("vm_protect(%s, at %#llx, size %llu, set_max %d, prot %d)",
6510 name_for_port(MACH_REMOTE),
6511 (ULong)req->address, (ULong)req->size,
6512 req->set_maximum, req->new_protection);
6514 MACH_ARG(vm_protect.address) = req->address;
6515 MACH_ARG(vm_protect.size) = req->size;
6516 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
6517 MACH_ARG(vm_protect.new_protection) = req->new_protection;
6519 AFTER = POST_FN(vm_protect);
6522 POST(vm_protect)
6524 #pragma pack(4)
6525 typedef struct {
6526 mach_msg_header_t Head;
6527 NDR_record_t NDR;
6528 kern_return_t RetCode;
6529 mach_msg_trailer_t trailer;
6530 } Reply;
6531 #pragma pack()
6533 Reply *reply = (Reply *)ARG1;
6535 if (!reply->RetCode) {
6536 if (MACH_REMOTE == vg_task_port) {
6537 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
6538 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
6539 MACH_ARG(vm_protect.size));
6540 UInt prot = MACH_ARG(vm_protect.new_protection);
6541 if (MACH_ARG(vm_protect.set_maximum)) {
6542 // GrP fixme mprotect max
6543 VG_(printf)("UNKNOWN vm_protect set maximum");
6544 //VG_(mprotect_max_range)(start, end-start, prot);
6545 } else {
6546 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6547 VG_(di_notify_vm_protect)(start, end-start, prot);
6550 } else {
6551 PRINT("mig return %d", reply->RetCode);
6556 PRE(vm_inherit)
6558 #pragma pack(4)
6559 typedef struct {
6560 mach_msg_header_t Head;
6561 NDR_record_t NDR;
6562 vm_address_t address;
6563 vm_size_t size;
6564 vm_inherit_t new_inheritance;
6565 } Request;
6566 #pragma pack()
6568 Request *req = (Request *)ARG1;
6570 PRINT("vm_inherit(%s, at %#llx, size %llu, value %d)",
6571 name_for_port(MACH_REMOTE),
6572 (ULong)req->address, (ULong)req->size,
6573 req->new_inheritance);
6575 AFTER = POST_FN(vm_inherit);
6578 POST(vm_inherit)
6580 #pragma pack(4)
6581 typedef struct {
6582 mach_msg_header_t Head;
6583 NDR_record_t NDR;
6584 kern_return_t RetCode;
6585 mach_msg_trailer_t trailer;
6586 } Reply;
6587 #pragma pack()
6589 Reply *reply = (Reply *)ARG1;
6591 if (!reply->RetCode) {
6592 if (MACH_REMOTE == vg_task_port) {
6593 // GrP fixme do something?
6595 } else {
6596 PRINT("mig return %d", reply->RetCode);
6601 PRE(vm_read)
6603 #pragma pack(4)
6604 typedef struct {
6605 mach_msg_header_t Head;
6606 NDR_record_t NDR;
6607 vm_address_t address;
6608 vm_size_t size;
6609 } Request;
6610 #pragma pack()
6612 Request *req = (Request *)ARG1;
6614 PRINT("vm_read(from %s at %#llx size %llu)",
6615 name_for_port(MACH_REMOTE),
6616 (ULong)req->address, (ULong)req->size);
6618 MACH_ARG(vm_read.addr) = req->address;
6619 MACH_ARG(vm_read.size) = req->size;
6621 AFTER = POST_FN(vm_read);
6624 POST(vm_read)
6626 #pragma pack(4)
6627 typedef struct {
6628 mach_msg_header_t Head;
6629 /* start of the kernel processed data */
6630 mach_msg_body_t msgh_body;
6631 mach_msg_ool_descriptor_t data;
6632 /* end of the kernel processed data */
6633 NDR_record_t NDR;
6634 mach_msg_type_number_t dataCnt;
6635 } Reply;
6636 #pragma pack()
6638 // Reply *reply = (Reply *)ARG1;
6640 if (MACH_REMOTE == vg_task_port) {
6641 // vm_read from self
6642 // GrP fixme copy initialized state
6648 PRE(mach_vm_read)
6650 #pragma pack(4)
6651 typedef struct {
6652 mach_msg_header_t Head;
6653 NDR_record_t NDR;
6654 mach_vm_address_t address;
6655 mach_vm_size_t size;
6656 } Request;
6657 #pragma pack()
6659 Request *req = (Request *)ARG1;
6661 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6662 name_for_port(MACH_REMOTE), req->address, req->size);
6664 MACH_ARG(mach_vm_read.addr) = req->address;
6665 MACH_ARG(mach_vm_read.size) = req->size;
6667 AFTER = POST_FN(mach_vm_read);
6670 POST(mach_vm_read)
6672 #pragma pack(4)
6673 typedef struct {
6674 mach_msg_header_t Head;
6675 /* start of the kernel processed data */
6676 mach_msg_body_t msgh_body;
6677 mach_msg_ool_descriptor_t data;
6678 /* end of the kernel processed data */
6679 NDR_record_t NDR;
6680 mach_msg_type_number_t dataCnt;
6681 } Reply;
6682 #pragma pack()
6684 // Reply *reply = (Reply *)ARG1;
6686 if (MACH_REMOTE == vg_task_port) {
6687 // vm_read from self
6688 // GrP fixme copy initialized state
6693 PRE(vm_read_overwrite)
6695 #pragma pack(4)
6696 typedef struct {
6697 mach_msg_header_t Head;
6698 NDR_record_t NDR;
6699 vm_address_t address;
6700 vm_size_t size;
6701 vm_address_t data;
6702 } Request;
6703 #pragma pack()
6705 Request *req = (Request *)ARG1;
6707 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6708 name_for_port(MACH_REMOTE),
6709 (ULong)req->address, (ULong)req->size, (ULong)req->data);
6711 MACH_ARG(vm_read_overwrite.addr) = req->address;
6712 MACH_ARG(vm_read_overwrite.size) = req->size;
6713 MACH_ARG(vm_read_overwrite.data) = req->data;
6715 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
6717 AFTER = POST_FN(vm_read_overwrite);
6720 POST(vm_read_overwrite)
6722 #pragma pack(4)
6723 typedef struct {
6724 mach_msg_header_t Head;
6725 NDR_record_t NDR;
6726 kern_return_t RetCode;
6727 vm_size_t outsize;
6728 } Reply;
6729 #pragma pack()
6731 Reply *reply = (Reply *)ARG1;
6733 if (reply->RetCode) {
6734 PRINT("mig return %d", reply->RetCode);
6735 } else {
6736 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
6737 if (MACH_REMOTE == vg_task_port) {
6738 // vm_read_overwrite from self
6739 // GrP fixme copy initialized state
6740 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6741 } else {
6742 // vm_read_overwrite from remote
6743 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6749 PRE(vm_copy)
6751 #pragma pack(4)
6752 typedef struct {
6753 mach_msg_header_t Head;
6754 NDR_record_t NDR;
6755 vm_address_t source_address;
6756 vm_size_t size;
6757 vm_address_t dest_address;
6758 } Request;
6759 #pragma pack()
6761 Request *req = (Request *)ARG1;
6763 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6764 name_for_port(MACH_REMOTE),
6765 (ULong)req->source_address,
6766 (ULong)req->size, (ULong)req->dest_address);
6768 MACH_ARG(vm_copy.src) = req->source_address;
6769 MACH_ARG(vm_copy.dst) = req->dest_address;
6770 MACH_ARG(vm_copy.size) = req->size;
6772 AFTER = POST_FN(vm_copy);
6775 POST(vm_copy)
6777 #pragma pack(4)
6778 typedef struct {
6779 mach_msg_header_t Head;
6780 NDR_record_t NDR;
6781 kern_return_t RetCode;
6782 mach_msg_trailer_t trailer;
6783 } Reply;
6784 #pragma pack()
6786 Reply *reply = (Reply *)ARG1;
6788 if (!reply->RetCode) {
6789 if (MACH_REMOTE == vg_task_port) {
6790 // GrP fixme set dst's initialization equal to src's
6791 // and wipe any symbols or translations in dst
6793 } else {
6794 PRINT("mig return %d", reply->RetCode);
6799 PRE(vm_map)
6801 #pragma pack(4)
6802 typedef struct {
6803 mach_msg_header_t Head;
6804 /* start of the kernel processed data */
6805 mach_msg_body_t msgh_body;
6806 mach_msg_port_descriptor_t object;
6807 /* end of the kernel processed data */
6808 NDR_record_t NDR;
6809 vm_address_t address;
6810 vm_size_t size;
6811 vm_address_t mask;
6812 int flags;
6813 vm_offset_t offset;
6814 boolean_t copy;
6815 vm_prot_t cur_protection;
6816 vm_prot_t max_protection;
6817 vm_inherit_t inheritance;
6818 } Request;
6819 #pragma pack()
6821 Request *req = (Request *)ARG1;
6823 // GrP fixme check these
6824 PRINT("vm_map(in %s, at %#llx, size %llu, from %s ...)",
6825 name_for_port(MACH_REMOTE),
6826 (ULong)req->address, (ULong)req->size,
6827 name_for_port(req->object.name));
6829 MACH_ARG(vm_map.size) = req->size;
6830 MACH_ARG(vm_map.copy) = req->copy;
6831 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
6833 AFTER = POST_FN(vm_map);
6836 POST(vm_map)
6838 #pragma pack(4)
6839 typedef struct {
6840 mach_msg_header_t Head;
6841 NDR_record_t NDR;
6842 kern_return_t RetCode;
6843 vm_address_t address;
6844 mach_msg_trailer_t trailer;
6845 } Reply;
6846 #pragma pack()
6848 Reply *reply = (Reply *)ARG1;
6850 if (!reply->RetCode) {
6851 // GrP fixme check src and dest tasks
6852 PRINT("mapped at %#llx", (ULong)reply->address);
6853 // GrP fixme max prot
6854 ML_(notify_core_and_tool_of_mmap)(
6855 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
6856 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
6857 // GrP fixme VKI_MAP_PRIVATE if !copy?
6858 } else {
6859 PRINT("mig return %d", reply->RetCode);
6864 PRE(vm_remap)
6866 #pragma pack(4)
6867 typedef struct {
6868 mach_msg_header_t Head;
6869 /* start of the kernel processed data */
6870 mach_msg_body_t msgh_body;
6871 mach_msg_port_descriptor_t src_task;
6872 /* end of the kernel processed data */
6873 NDR_record_t NDR;
6874 vm_address_t target_address;
6875 vm_size_t size;
6876 vm_address_t mask;
6877 boolean_t anywhere;
6878 vm_address_t src_address;
6879 boolean_t copy;
6880 vm_inherit_t inheritance;
6881 } Request;
6882 #pragma pack()
6884 Request *req = (Request *)ARG1;
6886 // GrP fixme check src and dest tasks
6888 if (VG_(clo_trace_syscalls)) {
6889 mach_port_name_t source_task = req->src_task.name;
6890 if (source_task == mach_task_self()) {
6891 PRINT("vm_remap(mach_task_self(), "
6892 "to %#llx size %llu, from mach_task_self() at %#llx, ...)",
6893 (ULong)req->target_address,
6894 (ULong)req->size, (ULong)req->src_address);
6895 } else {
6896 PRINT("vm_remap(mach_task_self(), "
6897 "to %#llx size %llu, from task %u at %#llx, ...)",
6898 (ULong)req->target_address, (ULong)req->size,
6899 source_task, (ULong)req->src_address);
6903 // arg1 is task
6904 // vt->syscall_arg2 = req->target_address;
6905 MACH_ARG(vm_remap.size) = req->size;
6906 // vt->syscall_arg4 = req->copy;
6908 AFTER = POST_FN(vm_remap);
6911 POST(vm_remap)
6913 #pragma pack(4)
6914 typedef struct {
6915 mach_msg_header_t Head;
6916 NDR_record_t NDR;
6917 kern_return_t RetCode;
6918 vm_address_t target_address;
6919 vm_prot_t cur_protection;
6920 vm_prot_t max_protection;
6921 mach_msg_trailer_t trailer;
6922 } Reply;
6923 #pragma pack()
6925 Reply *reply = (Reply *)ARG1;
6927 if (!reply->RetCode) {
6928 // GrP fixme check src and dest tasks
6929 UInt prot = reply->cur_protection & reply->max_protection;
6930 // GrP fixme max prot
6931 PRINT("mapped at %#llx", (ULong)reply->target_address);
6932 ML_(notify_core_and_tool_of_mmap)(
6933 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
6934 prot, VKI_MAP_SHARED, -1, 0);
6935 // GrP fixme VKI_MAP_FIXED if !copy?
6936 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6937 } else {
6938 PRINT("mig return %d", reply->RetCode);
6943 PRE(mach_make_memory_entry_64)
6945 #pragma pack(4)
6946 typedef struct {
6947 mach_msg_header_t Head;
6948 /* start of the kernel processed data */
6949 mach_msg_body_t msgh_body;
6950 mach_msg_port_descriptor_t parent_entry;
6951 /* end of the kernel processed data */
6952 NDR_record_t NDR;
6953 memory_object_size_t size;
6954 memory_object_offset_t offset;
6955 vm_prot_t permission;
6956 } Request;
6957 #pragma pack()
6959 Request *req = (Request *)ARG1;
6961 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6962 name_for_port(MACH_REMOTE),
6963 req->size, req->offset, req->permission, req->parent_entry.type);
6965 AFTER = POST_FN(mach_make_memory_entry_64);
6968 POST(mach_make_memory_entry_64)
6970 #pragma pack(4)
6971 typedef struct {
6972 mach_msg_header_t Head;
6973 mach_msg_body_t msgh_body;
6974 mach_msg_port_descriptor_t object;
6975 NDR_record_t NDR;
6976 memory_object_size_t size;
6977 } Reply;
6978 #pragma pack()
6980 Reply *reply = (Reply *)ARG1;
6982 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6983 assign_port_name(reply->object.name, "memory-%p");
6984 PRINT("%s", name_for_port(reply->object.name));
6989 PRE(vm_purgable_control)
6991 #pragma pack(4)
6992 typedef struct {
6993 mach_msg_header_t Head;
6994 NDR_record_t NDR;
6995 vm_address_t address;
6996 vm_purgable_t control;
6997 int state;
6998 } Request;
6999 #pragma pack()
7001 Request *req = (Request *)ARG1;
7003 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
7004 name_for_port(MACH_REMOTE),
7005 (ULong)req->address, req->control, req->state);
7007 // GrP fixme verify address?
7009 AFTER = POST_FN(vm_purgable_control);
7012 POST(vm_purgable_control)
7014 #pragma pack(4)
7015 typedef struct {
7016 mach_msg_header_t Head;
7017 NDR_record_t NDR;
7018 kern_return_t RetCode;
7019 int state;
7020 } Reply;
7021 #pragma pack()
7023 Reply *reply = (Reply *)ARG1;
7025 if (!reply->RetCode) {
7026 } else {
7027 PRINT("mig return %d", reply->RetCode);
7032 PRE(mach_vm_purgable_control)
7034 #pragma pack(4)
7035 typedef struct {
7036 mach_msg_header_t Head;
7037 NDR_record_t NDR;
7038 mach_vm_address_t address;
7039 vm_purgable_t control;
7040 int state;
7041 } Request;
7042 #pragma pack()
7044 Request *req = (Request *)ARG1;
7046 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
7047 name_for_port(MACH_REMOTE),
7048 (ULong)req->address, req->control, req->state);
7050 // GrP fixme verify address?
7052 AFTER = POST_FN(mach_vm_purgable_control);
7055 POST(mach_vm_purgable_control)
7057 #pragma pack(4)
7058 typedef struct {
7059 mach_msg_header_t Head;
7060 NDR_record_t NDR;
7061 kern_return_t RetCode;
7062 int state;
7063 } Reply;
7064 #pragma pack()
7066 Reply *reply = (Reply *)ARG1;
7068 if (!reply->RetCode) {
7069 } else {
7070 PRINT("mig return %d", reply->RetCode);
7075 PRE(mach_vm_allocate)
7077 #pragma pack(4)
7078 typedef struct {
7079 mach_msg_header_t Head;
7080 NDR_record_t NDR;
7081 mach_vm_address_t address;
7082 mach_vm_size_t size;
7083 int flags;
7084 } Request;
7085 #pragma pack()
7087 Request *req = (Request *)ARG1;
7089 PRINT("mach_vm_allocate (%s, at 0x%llx, size %llu, flags 0x%x)",
7090 name_for_port(MACH_REMOTE),
7091 req->address, req->size, req->flags);
7093 MACH_ARG(mach_vm_allocate.size) = req->size;
7094 MACH_ARG(mach_vm_allocate.flags) = req->flags;
7096 AFTER = POST_FN(mach_vm_allocate);
7099 POST(mach_vm_allocate)
7101 #pragma pack(4)
7102 typedef struct {
7103 mach_msg_header_t Head;
7104 NDR_record_t NDR;
7105 kern_return_t RetCode;
7106 mach_vm_address_t address;
7107 mach_msg_trailer_t trailer;
7108 } Reply;
7109 #pragma pack()
7111 Reply *reply = (Reply *)ARG1;
7113 if (!reply->RetCode) {
7114 if (MACH_REMOTE == vg_task_port) {
7115 PRINT("allocated at 0x%llx", reply->address);
7116 // requesting 0 bytes returns address 0 with no error
7117 if (MACH_ARG(mach_vm_allocate.size)) {
7118 ML_(notify_core_and_tool_of_mmap)(
7119 reply->address, MACH_ARG(mach_vm_allocate.size),
7120 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
7122 } else {
7123 PRINT("allocated at 0x%llx in remote task %s", reply->address,
7124 name_for_port(MACH_REMOTE));
7126 } else {
7127 PRINT("mig return %d", reply->RetCode);
7132 PRE(mach_vm_deallocate)
7134 #pragma pack(4)
7135 typedef struct {
7136 mach_msg_header_t Head;
7137 NDR_record_t NDR;
7138 mach_vm_address_t address;
7139 mach_vm_size_t size;
7140 } Request;
7141 #pragma pack()
7143 Request *req = (Request *)ARG1;
7145 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %llu)",
7146 name_for_port(MACH_REMOTE),
7147 req->address, req->size);
7149 MACH_ARG(mach_vm_deallocate.address) = req->address;
7150 MACH_ARG(mach_vm_deallocate.size) = req->size;
7152 AFTER = POST_FN(mach_vm_deallocate);
7154 // Must block to prevent race (other thread allocates and
7155 // notifies after we deallocate but before we notify)
7156 *flags &= ~SfMayBlock;
7159 POST(mach_vm_deallocate)
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 if (MACH_REMOTE == vg_task_port) {
7174 if (MACH_ARG(mach_vm_deallocate.size)) {
7175 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
7176 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
7177 MACH_ARG(mach_vm_deallocate.size));
7178 // Must have cleared SfMayBlock in PRE to prevent race
7179 ML_(notify_core_and_tool_of_munmap)(start, end - start);
7182 } else {
7183 PRINT("mig return %d", reply->RetCode);
7188 PRE(mach_vm_protect)
7190 #pragma pack(4)
7191 typedef struct {
7192 mach_msg_header_t Head;
7193 NDR_record_t NDR;
7194 mach_vm_address_t address;
7195 mach_vm_size_t size;
7196 boolean_t set_maximum;
7197 vm_prot_t new_protection;
7198 } Request;
7199 #pragma pack()
7201 Request *req = (Request *)ARG1;
7203 PRINT("mach_vm_protect(%s, at 0x%llx, size %llu, set_max %d, prot %d)",
7204 name_for_port(MACH_REMOTE), req->address, req->size,
7205 req->set_maximum, req->new_protection);
7207 MACH_ARG(mach_vm_protect.address) = req->address;
7208 MACH_ARG(mach_vm_protect.size) = req->size;
7209 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
7210 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
7212 AFTER = POST_FN(mach_vm_protect);
7215 POST(mach_vm_protect)
7217 #pragma pack(4)
7218 typedef struct {
7219 mach_msg_header_t Head;
7220 NDR_record_t NDR;
7221 kern_return_t RetCode;
7222 mach_msg_trailer_t trailer;
7223 } Reply;
7224 #pragma pack()
7226 Reply *reply = (Reply *)ARG1;
7228 if (!reply->RetCode) {
7229 if (MACH_REMOTE == vg_task_port) {
7230 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
7231 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
7232 MACH_ARG(mach_vm_protect.size));
7233 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
7234 if (MACH_ARG(mach_vm_protect.set_maximum)) {
7235 // DDD: #warning GrP fixme mprotect max
7236 //VG_(mprotect_max_range)(start, end-start, prot);
7237 } else {
7238 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
7241 } else {
7242 PRINT("mig return %d", reply->RetCode);
7247 PRE(mach_vm_inherit)
7249 #pragma pack(4)
7250 typedef struct {
7251 mach_msg_header_t Head;
7252 NDR_record_t NDR;
7253 mach_vm_address_t address;
7254 mach_vm_size_t size;
7255 vm_inherit_t new_inheritance;
7256 } Request;
7257 #pragma pack()
7259 Request *req = (Request *)ARG1;
7261 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
7262 name_for_port(MACH_REMOTE),
7263 req->address, req->size, req->new_inheritance);
7265 AFTER = POST_FN(mach_vm_inherit);
7268 POST(mach_vm_inherit)
7270 #pragma pack(4)
7271 typedef struct {
7272 mach_msg_header_t Head;
7273 NDR_record_t NDR;
7274 kern_return_t RetCode;
7275 mach_msg_trailer_t trailer;
7276 } Reply;
7277 #pragma pack()
7279 Reply *reply = (Reply *)ARG1;
7281 if (!reply->RetCode) {
7282 // no V-visible side effects
7283 // GrP fixme except maybe fork/exec
7284 } else {
7285 PRINT("mig return %d", reply->RetCode);
7290 PRE(mach_vm_copy)
7292 #pragma pack(4)
7293 typedef struct {
7294 mach_msg_header_t Head;
7295 NDR_record_t NDR;
7296 mach_vm_address_t source_address;
7297 mach_vm_size_t size;
7298 mach_vm_address_t dest_address;
7299 } Request;
7300 #pragma pack()
7302 Request *req = (Request *)ARG1;
7304 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
7305 name_for_port(MACH_REMOTE),
7306 req->source_address, req->size, req->dest_address);
7308 // arg1 is task
7309 // vt->syscall_arg2 = req->source_address;
7310 // vt->syscall_arg3 = req->size;
7311 // vt->syscall_arg4 = req->dest_address;
7313 AFTER = POST_FN(mach_vm_copy);
7316 POST(mach_vm_copy)
7318 #pragma pack(4)
7319 typedef struct {
7320 mach_msg_header_t Head;
7321 NDR_record_t NDR;
7322 kern_return_t RetCode;
7323 mach_msg_trailer_t trailer;
7324 } Reply;
7325 #pragma pack()
7327 Reply *reply = (Reply *)ARG1;
7329 if (!reply->RetCode) {
7330 if (MACH_REMOTE == vg_task_port) {
7331 // GrP fixme set dest's initialization equal to src's
7332 // BUT vm_copy allocates no memory
7334 } else {
7335 PRINT("mig return %d", reply->RetCode);
7339 PRE(mach_vm_read_overwrite)
7341 #pragma pack(4)
7342 typedef struct {
7343 mach_msg_header_t Head;
7344 NDR_record_t NDR;
7345 mach_vm_address_t address;
7346 mach_vm_size_t size;
7347 mach_vm_address_t data;
7348 } Request;
7349 #pragma pack()
7351 Request *req = (Request *)ARG1;
7353 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
7354 name_for_port(MACH_REMOTE),
7355 req->address, req->size, req->data);
7357 AFTER = POST_FN(mach_vm_read_overwrite);
7360 POST(mach_vm_read_overwrite)
7362 #pragma pack(4)
7363 typedef struct {
7364 mach_msg_header_t Head;
7365 NDR_record_t NDR;
7366 kern_return_t RetCode;
7367 mach_vm_size_t outsize;
7368 } Reply;
7369 #pragma pack()
7371 Reply *reply = (Reply *)ARG1;
7373 if (!reply->RetCode) {
7374 if (MACH_REMOTE == vg_task_port) {
7375 // GrP fixme set dest's initialization equal to src's
7376 // BUT vm_copy allocates no memory
7378 } else {
7379 PRINT("mig return %d", reply->RetCode);
7383 PRE(mach_vm_map)
7385 #pragma pack(4)
7386 typedef struct {
7387 mach_msg_header_t Head;
7388 /* start of the kernel processed data */
7389 mach_msg_body_t msgh_body;
7390 mach_msg_port_descriptor_t object;
7391 /* end of the kernel processed data */
7392 NDR_record_t NDR;
7393 mach_vm_address_t address;
7394 mach_vm_size_t size;
7395 mach_vm_address_t mask;
7396 int flags;
7397 memory_object_offset_t offset;
7398 boolean_t copy;
7399 vm_prot_t cur_protection;
7400 vm_prot_t max_protection;
7401 vm_inherit_t inheritance;
7402 } Request;
7403 #pragma pack()
7405 Request *req = (Request *)ARG1;
7407 // GrP fixme check these
7408 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7409 name_for_port(req->Head.msgh_remote_port),
7410 name_for_port(req->object.name),
7411 req->address, req->size,
7412 req->cur_protection,
7413 req->max_protection);
7415 MACH_ARG(mach_vm_map.size) = req->size;
7416 MACH_ARG(mach_vm_map.copy) = req->copy;
7417 MACH_ARG(mach_vm_map.protection) =
7418 (req->cur_protection & req->max_protection);
7420 AFTER = POST_FN(mach_vm_map);
7423 POST(mach_vm_map)
7425 #pragma pack(4)
7426 typedef struct {
7427 mach_msg_header_t Head;
7428 NDR_record_t NDR;
7429 kern_return_t RetCode;
7430 mach_vm_address_t address;
7431 mach_msg_trailer_t trailer;
7432 } Reply;
7433 #pragma pack()
7435 Reply *reply = (Reply *)ARG1;
7437 if (!reply->RetCode) {
7438 // GrP fixme check src and dest tasks
7439 PRINT("mapped at 0x%llx", reply->address);
7440 # if 0
7441 // GrP fixme max prot
7442 ML_(notify_core_and_tool_of_mmap)(
7443 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
7444 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
7445 // GrP fixme VKI_MAP_PRIVATE if !copy?
7446 # else
7447 ML_(sync_mappings)("after", "mach_vm_map", 0);
7448 # endif
7449 } else {
7450 PRINT("mig return %d", reply->RetCode);
7455 PRE(mach_vm_remap)
7457 #pragma pack(4)
7458 typedef struct {
7459 mach_msg_header_t Head;
7460 /* start of the kernel processed data */
7461 mach_msg_body_t msgh_body;
7462 mach_msg_port_descriptor_t src_task;
7463 /* end of the kernel processed data */
7464 NDR_record_t NDR;
7465 mach_vm_address_t target_address;
7466 mach_vm_size_t size;
7467 mach_vm_offset_t mask;
7468 int flags;
7469 mach_vm_address_t src_address;
7470 boolean_t copy;
7471 vm_inherit_t inheritance;
7472 } Request;
7473 #pragma pack()
7475 Request *req = (Request *)ARG1;
7477 // GrP fixme check these
7478 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7479 name_for_port(MACH_REMOTE),
7480 req->target_address, req->size,
7481 name_for_port(req->src_task.name));
7483 MACH_ARG(mach_vm_remap.size) = req->size;
7484 MACH_ARG(mach_vm_remap.copy) = req->copy;
7486 AFTER = POST_FN(mach_vm_remap);
7489 POST(mach_vm_remap)
7491 #pragma pack(4)
7492 typedef struct {
7493 mach_msg_header_t Head;
7494 NDR_record_t NDR;
7495 kern_return_t RetCode;
7496 mach_vm_address_t target_address;
7497 vm_prot_t cur_protection;
7498 vm_prot_t max_protection;
7499 } Reply;
7500 #pragma pack()
7502 Reply *reply = (Reply *)ARG1;
7504 if (!reply->RetCode) {
7505 // GrP fixme check src and dest tasks
7506 PRINT("mapped at 0x%llx", reply->target_address);
7507 // GrP fixme max prot
7508 ML_(notify_core_and_tool_of_mmap)(
7509 reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
7510 reply->cur_protection, VKI_MAP_SHARED, -1, 0);
7511 // GrP fixme VKI_MAP_PRIVATE if !copy?
7512 } else {
7513 PRINT("mig return %d", reply->RetCode);
7518 PRE(mach_vm_region_recurse)
7520 #pragma pack(4)
7521 typedef struct {
7522 mach_msg_header_t Head;
7523 NDR_record_t NDR;
7524 mach_vm_address_t address;
7525 natural_t nesting_depth;
7526 mach_msg_type_number_t infoCnt;
7527 } Request;
7528 #pragma pack()
7530 Request *req = (Request *)ARG1;
7532 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7533 name_for_port(MACH_REMOTE),
7534 req->address, req->nesting_depth, req->infoCnt);
7536 AFTER = POST_FN(mach_vm_region_recurse);
7539 POST(mach_vm_region_recurse)
7541 #pragma pack(4)
7542 typedef struct {
7543 mach_msg_header_t Head;
7544 NDR_record_t NDR;
7545 kern_return_t RetCode;
7546 mach_vm_address_t address;
7547 mach_vm_size_t size;
7548 natural_t nesting_depth;
7549 mach_msg_type_number_t infoCnt;
7550 int info[19];
7551 } Reply;
7552 #pragma pack()
7554 Reply *reply = (Reply *)ARG1;
7556 if (!reply->RetCode) {
7557 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7558 reply->address, reply->size,
7559 reply->nesting_depth, reply->infoCnt);
7560 // GrP fixme mark info contents beyond infoCnt as bogus
7561 } else {
7562 PRINT("mig return %d", reply->RetCode);
7567 /* ---------------------------------------------------------------------
7568 mach_msg: messages to thread
7569 ------------------------------------------------------------------ */
7573 POST(thread_terminate)
7578 PRE(thread_terminate)
7580 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7581 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
7583 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
7585 AFTER = POST_FN(thread_terminate);
7587 if (self_terminate) {
7588 // Terminating this thread.
7589 // Copied from sys_exit.
7590 ThreadState *tst = VG_(get_ThreadState)(tid);
7591 tst->exitreason = VgSrc_ExitThread;
7592 tst->os_state.exitcode = 0; // GrP fixme anything better?
7593 // What we would like to do is:
7594 // SET_STATUS_Success(0);
7595 // but that doesn't work, because this is a MACH-class syscall,
7596 // and SET_STATUS_Success creates a UNIX-class syscall result.
7597 // Hence we have to laboriously construct the full SysRes "by hand"
7598 // and use that to set the syscall return status.
7599 #if defined(VGA_x86)
7600 SET_STATUS_from_SysRes(
7601 VG_(mk_SysRes_x86_darwin)(
7602 VG_DARWIN_SYSCALL_CLASS_MACH,
7603 False/*success*/, 0, 0
7606 #elif defined(VGA_amd64)
7607 SET_STATUS_from_SysRes(
7608 VG_(mk_SysRes_amd64_darwin)(
7609 VG_DARWIN_SYSCALL_CLASS_MACH,
7610 False/*success*/, 0, 0
7613 #else
7614 #error unknown architecture
7615 #endif
7616 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
7617 } else {
7618 // Terminating some other thread.
7619 // Do keep the scheduler lock while terminating any other thread.
7620 // Otherwise we might halt the other thread while it holds the lock,
7621 // which would deadlock the process.
7622 // GrP fixme good enough?
7623 // GrP fixme need to clean up other thread's valgrind data?
7628 POST(thread_create)
7633 PRE(thread_create)
7635 PRINT("thread_create(mach_task_self(), ...)");
7637 AFTER = POST_FN(thread_create);
7639 // GrP fixme
7640 VG_(core_panic)("thread_create() unimplemented");
7644 PRE(thread_create_running)
7646 #pragma pack(4)
7647 typedef struct {
7648 mach_msg_header_t Head;
7649 NDR_record_t NDR;
7650 thread_state_flavor_t flavor;
7651 mach_msg_type_number_t new_stateCnt;
7652 natural_t new_state[144];
7653 } Request;
7654 #pragma pack()
7656 Request *req;
7657 thread_state_t regs;
7658 ThreadState *new_thread;
7660 PRINT("thread_create_running(mach_task_self(), ...)");
7662 // The new thread will immediately begin execution,
7663 // so we need to hijack the register state here.
7665 req = (Request *)ARG1;
7666 regs = (thread_state_t)req->new_state;
7668 // Build virtual thread.
7669 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
7671 // Edit the thread state to send to the real kernel.
7672 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
7674 AFTER = POST_FN(thread_create_running);
7678 POST(thread_create_running)
7680 #pragma pack(4)
7681 typedef struct {
7682 mach_msg_header_t Head;
7683 /* start of the kernel processed data */
7684 mach_msg_body_t msgh_body;
7685 mach_msg_port_descriptor_t child_act;
7686 /* end of the kernel processed data */
7687 } Reply;
7688 #pragma pack()
7690 Reply *reply = (Reply *)ARG1;
7692 assign_port_name(reply->child_act.name, "thread-%p");
7693 PRINT("%s", name_for_port(reply->child_act.name));
7697 PRE(bsdthread_create)
7699 ThreadState *tst;
7701 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7702 ARG1, ARG2, ARG3, ARG4, ARG5);
7703 PRE_REG_READ5(pthread_t,"bsdthread_create",
7704 void *,"func", void *,"func_arg", void *,"stack",
7705 pthread_t,"thread", unsigned int,"flags");
7707 // The kernel will call V's pthread_hijack() to launch the thread.
7708 // Here we allocate the thread state and pass it to pthread_hijack()
7709 // via the func_arg parameter.
7711 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
7712 allocstack(tst->tid);
7714 tst->os_state.func_arg = (Addr)ARG2;
7715 ARG2 = (Word)tst;
7717 // Create a semaphore that pthread_hijack will signal once it starts
7718 // POST(bsdthread_create) needs to wait for the new memory map to appear
7719 semaphore_create(mach_task_self(), &tst->os_state.child_go,
7720 SYNC_POLICY_FIFO, 0);
7721 semaphore_create(mach_task_self(), &tst->os_state.child_done,
7722 SYNC_POLICY_FIFO, 0);
7725 POST(bsdthread_create)
7727 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7728 // We hold V's lock on the child's behalf.
7729 // If we return before letting pthread_hijack do its thing, V thinks
7730 // the new pthread struct is still unmapped when we return to libc,
7731 // causing false errors.
7733 ThreadState *tst = (ThreadState *)ARG2;
7734 semaphore_signal(tst->os_state.child_go);
7735 semaphore_wait(tst->os_state.child_done);
7736 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
7737 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
7739 // GrP fixme semaphore destroy needed when thread creation fails
7740 // GrP fixme probably other cleanup too
7741 // GrP fixme spinlocks might be good enough?
7743 // DDD: I'm not at all sure this is the right spot for this. It probably
7744 // should be in pthread_hijack instead, just before the call to
7745 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7746 // parent tid value there...
7747 vg_assert(VG_(owns_BigLock_LL)(tid));
7748 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
7752 PRE(bsdthread_terminate)
7754 ThreadState *tst;
7756 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7757 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
7758 PRE_REG_READ4(int,"bsdthread_terminate",
7759 void *,"freeaddr", size_t,"freesize",
7760 mach_port_t,"kport", mach_port_t,"joinsem");
7762 // Free memory and signal semaphore.
7763 // GrP fixme errors?
7764 if (ARG4) semaphore_signal((semaphore_t)ARG4);
7765 if (ARG1 && ARG2) {
7766 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
7767 # if DARWIN_VERS >= DARWIN_10_8
7768 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7769 the mig output. Work around it for the time being. */
7770 VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
7771 # else
7772 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
7773 # endif
7776 // Tell V to terminate the thread.
7777 // Copied from sys_exit.
7778 tst = VG_(get_ThreadState)(tid);
7779 tst->exitreason = VgSrc_ExitThread;
7780 tst->os_state.exitcode = 0; // GrP fixme anything better?
7781 SET_STATUS_Success(0);
7785 POST(thread_suspend)
7789 PRE(thread_suspend)
7791 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7792 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
7794 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
7796 AFTER = POST_FN(thread_suspend);
7798 if (self_suspend) {
7799 // Don't keep the scheduler lock while self-suspending.
7800 // Otherwise we might halt while still holding the lock,
7801 // which would deadlock the process.
7802 *flags |= SfMayBlock;
7803 } else {
7804 // Do keep the scheduler lock while suspending any other thread.
7805 // Otherwise we might halt the other thread while it holds the lock,
7806 // which would deadlock the process.
7807 *flags &= ~SfMayBlock;
7812 POST(thread_resume)
7816 PRE(thread_resume)
7818 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7819 Bool self_resume = (mh->msgh_request_port == MACH_THREAD);
7821 PRINT("thread_resume(%s)", name_for_port(mh->msgh_request_port));
7823 AFTER = POST_FN(thread_resume);
7825 if (self_resume) {
7826 // This doesn't make much sense. If we are resuming ourself, we can't
7827 // already be running. So I don't see how we can ever get here.
7828 vg_assert(0);
7829 } else {
7830 // Resuming some other thread. It might not yet come back to life
7831 // (if the suspend count is still above zero) so make sure we keep
7832 // holding the lock.
7833 *flags &= ~SfMayBlock;
7838 POST(thread_get_state)
7840 #pragma pack(4)
7841 typedef struct {
7842 mach_msg_header_t Head;
7843 NDR_record_t NDR;
7844 kern_return_t RetCode;
7845 mach_msg_type_number_t old_stateCnt;
7846 natural_t old_state[144];
7847 mach_msg_trailer_t trailer;
7848 } Reply;
7849 #pragma pack()
7851 Reply *reply = (Reply *)ARG1;
7852 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7853 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
7855 if (!reply->RetCode) {
7856 thread_state_from_vex((thread_state_t)reply->old_state,
7857 flavor, reply->old_stateCnt,
7858 &VG_(get_ThreadState)(tid)->arch.vex);
7859 } else {
7860 PRINT("mig return %d", reply->RetCode);
7864 PRE(thread_get_state)
7866 #pragma pack(4)
7867 typedef struct {
7868 mach_msg_header_t Head;
7869 NDR_record_t NDR;
7870 thread_state_flavor_t flavor;
7871 mach_msg_type_number_t old_stateCnt;
7872 } Request;
7873 #pragma pack()
7875 Request *req = (Request *)ARG1;
7876 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7878 // GrP fixme if (self) {
7879 PRINT("thread_get_state(%s, %d)",
7880 name_for_port(req->Head.msgh_request_port), req->flavor);
7881 /*} else {
7882 PRINT("thread_get_state(0x%x, %d)",
7883 req->Head.msgh_request_port, req->flavor);
7886 // Hack the thread state after making the real call.
7887 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
7888 MACH_ARG(thread_get_state.flavor) = req->flavor;
7890 AFTER = POST_FN(thread_get_state);
7894 PRE(thread_policy)
7896 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7897 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7899 // GrP fixme if (self) {
7900 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
7901 /*} else {
7902 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7905 AFTER = POST_FN(thread_policy);
7908 POST(thread_policy)
7913 PRE(thread_policy_set)
7915 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7917 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
7919 AFTER = POST_FN(thread_policy_set);
7922 POST(thread_policy_set)
7927 PRE(thread_info)
7929 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7931 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
7932 // GrP fixme does any thread info need to be hijacked?
7934 AFTER = POST_FN(thread_info);
7937 POST(thread_info)
7939 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7944 /* ---------------------------------------------------------------------
7945 mach_msg: messages to bootstrap port
7946 ------------------------------------------------------------------ */
7949 POST(bootstrap_register)
7951 #pragma pack(4)
7952 typedef struct {
7953 mach_msg_header_t Head;
7954 NDR_record_t NDR;
7955 kern_return_t RetCode;
7956 mach_msg_trailer_t trailer;
7957 } Reply;
7958 #pragma pack()
7960 Reply *reply = (Reply *)ARG1;
7962 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
7965 PRE(bootstrap_register)
7967 #pragma pack(4)
7968 typedef struct {
7969 mach_msg_header_t Head;
7970 /* start of the kernel processed data */
7971 mach_msg_body_t msgh_body;
7972 mach_msg_port_descriptor_t service_port;
7973 /* end of the kernel processed data */
7974 NDR_record_t NDR;
7975 name_t service_name;
7976 } Request;
7977 #pragma pack()
7979 Request *req = (Request *)ARG1;
7981 PRINT("bootstrap_register(port 0x%x, \"%s\")",
7982 req->service_port.name, req->service_name);
7984 /* The required entry in the allocated_ports list (mapping) might
7985 not exist, due perhaps to broken syscall wrappers (mach__N etc).
7986 Create a minimal entry so that assign_port_name below doesn't
7987 cause an assertion. */
7988 if (!port_exists(req->service_port.name)) {
7989 port_create_vanilla(req->service_port.name);
7992 assign_port_name(req->service_port.name, req->service_name);
7994 AFTER = POST_FN(bootstrap_register);
7998 POST(bootstrap_look_up)
8000 #pragma pack(4)
8001 typedef struct {
8002 mach_msg_header_t Head;
8003 /* start of the kernel processed data */
8004 mach_msg_body_t msgh_body;
8005 mach_msg_port_descriptor_t service_port;
8006 /* end of the kernel processed data */
8007 mach_msg_trailer_t trailer;
8008 } Reply;
8009 #pragma pack()
8011 Reply *reply = (Reply *)ARG1;
8013 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
8014 reply->service_port.name)
8016 assign_port_name(reply->service_port.name,
8017 MACH_ARG(bootstrap_look_up.service_name));
8018 PRINT("%s", name_for_port(reply->service_port.name));
8019 } else {
8020 PRINT("not found");
8022 VG_(free)(MACH_ARG(bootstrap_look_up.service_name));
8025 PRE(bootstrap_look_up)
8027 #pragma pack(4)
8028 typedef struct {
8029 mach_msg_header_t Head;
8030 NDR_record_t NDR;
8031 name_t service_name;
8032 } Request;
8033 #pragma pack()
8035 Request *req = (Request *)ARG1;
8037 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
8039 MACH_ARG(bootstrap_look_up.service_name) =
8040 VG_(strdup)("syswrap-darwin.bootstrap-name", req->service_name);
8042 AFTER = POST_FN(bootstrap_look_up);
8046 /* ---------------------------------------------------------------------
8047 mach_msg: receiver-specific handlers
8048 ------------------------------------------------------------------ */
8051 POST(mach_msg_receive)
8053 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8055 // GrP fixme don't know of anything interesting here currently
8056 // import_complex_message handles everything
8057 // PRINT("UNHANDLED reply %d", mh->msgh_id);
8059 // Assume the call may have mapped or unmapped memory
8060 ML_(sync_mappings)("after", "mach_msg_receive", mh->msgh_id);
8063 PRE(mach_msg_receive)
8065 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8067 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
8069 AFTER = POST_FN(mach_msg_receive);
8071 // no message sent, only listening for a reply
8072 // assume message may block
8073 *flags |= SfMayBlock;
8077 PRE(mach_msg_bootstrap)
8079 // message to bootstrap port
8081 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8083 switch (mh->msgh_id) {
8084 case 403:
8085 CALL_PRE(bootstrap_register);
8086 return;
8087 case 404:
8088 CALL_PRE(bootstrap_look_up);
8089 return;
8091 default:
8092 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
8093 mh->msgh_id, name_for_port(mh->msgh_request_port),
8094 mh->msgh_reply_port);
8095 return;
8100 PRE(mach_msg_host)
8102 // message to host self - check for host-level kernel calls
8104 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8106 switch (mh->msgh_id) {
8107 case 200:
8108 CALL_PRE(host_info);
8109 return;
8110 case 202:
8111 CALL_PRE(host_page_size);
8112 return;
8113 case 205:
8114 CALL_PRE(host_get_io_master);
8115 return;
8116 case 206:
8117 CALL_PRE(host_get_clock_service);
8118 return;
8119 case 217:
8120 CALL_PRE(host_request_notification);
8121 return;
8122 case 222:
8123 CALL_PRE(host_create_mach_voucher);
8124 return;
8126 case 412:
8127 CALL_PRE(host_get_special_port);
8128 return;
8130 default:
8131 // unknown message to host self
8132 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
8133 mh->msgh_id, name_for_port(mh->msgh_request_port),
8134 mh->msgh_reply_port);
8135 return;
8139 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
8140 // /usr/include/mach/mach_port.h et al (grep in /usr/include
8141 // for them)
8142 PRE(mach_msg_task)
8144 // message to a task port
8146 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8148 switch (mh->msgh_id) {
8149 case 3201:
8150 CALL_PRE(mach_port_type);
8151 return;
8152 case 3204:
8153 CALL_PRE(mach_port_allocate);
8154 return;
8155 case 3205:
8156 CALL_PRE(mach_port_destroy);
8157 return;
8158 case 3206:
8159 CALL_PRE(mach_port_deallocate);
8160 return;
8161 case 3207:
8162 CALL_PRE(mach_port_get_refs);
8163 return;
8164 case 3208:
8165 CALL_PRE(mach_port_mod_refs);
8166 return;
8167 case 3211:
8168 CALL_PRE(mach_port_get_set_status);
8169 return;
8170 case 3212:
8171 CALL_PRE(mach_port_move_member);
8172 return;
8173 case 3213:
8174 CALL_PRE(mach_port_request_notification);
8175 return;
8176 case 3214:
8177 CALL_PRE(mach_port_insert_right);
8178 return;
8179 case 3215:
8180 CALL_PRE(mach_port_extract_right);
8181 return;
8182 case 3217:
8183 CALL_PRE(mach_port_get_attributes);
8184 return;
8185 case 3218:
8186 CALL_PRE(mach_port_set_attributes);
8187 return;
8188 case 3226:
8189 CALL_PRE(mach_port_insert_member);
8190 return;
8191 case 3227:
8192 CALL_PRE(mach_port_extract_member);
8193 return;
8195 case 3229:
8196 CALL_PRE(mach_port_set_context);
8197 return;
8199 case 3402:
8200 CALL_PRE(task_threads);
8201 return;
8202 case 3403:
8203 CALL_PRE(mach_ports_register);
8204 return;
8205 case 3404:
8206 CALL_PRE(mach_ports_lookup);
8207 return;
8208 case 3405:
8209 CALL_PRE(task_info);
8210 return;
8211 case 3406:
8212 CALL_PRE(task_set_info);
8213 return;
8214 case 3407:
8215 CALL_PRE(task_suspend);
8216 return;
8217 case 3408:
8218 CALL_PRE(task_resume);
8219 return;
8220 case 3409:
8221 CALL_PRE(task_get_special_port);
8222 return;
8223 case 3410:
8224 CALL_PRE(task_set_special_port);
8225 return;
8226 case 3411:
8227 CALL_PRE(thread_create);
8228 return;
8229 case 3412:
8230 CALL_PRE(thread_create_running);
8231 return;
8233 case 3414:
8234 CALL_PRE(task_get_exception_ports);
8235 return;
8237 case 3418:
8238 CALL_PRE(semaphore_create);
8239 return;
8240 case 3419:
8241 CALL_PRE(semaphore_destroy);
8242 return;
8243 case 3420:
8244 CALL_PRE(task_policy_set);
8245 return;
8247 #if DARWIN_VERS >= DARWIN_10_12
8248 case 3444:
8249 CALL_PRE(task_register_dyld_image_infos);
8250 return;
8252 case 3447:
8253 CALL_PRE(task_register_dyld_shared_cache_image_info);
8254 return;
8255 #endif /* DARWIN_VERS >= DARWIN_10_12 */
8257 case 3801:
8258 CALL_PRE(vm_allocate);
8259 return;
8260 case 3802:
8261 CALL_PRE(vm_deallocate);
8262 return;
8263 case 3803:
8264 CALL_PRE(vm_protect);
8265 return;
8266 case 3804:
8267 CALL_PRE(vm_inherit);
8268 return;
8269 case 3805:
8270 CALL_PRE(vm_read);
8271 return;
8272 case 3808:
8273 CALL_PRE(vm_copy);
8274 return;
8275 case 3809:
8276 CALL_PRE(vm_read_overwrite);
8277 return;
8278 case 3812:
8279 CALL_PRE(vm_map);
8280 return;
8281 case 3814:
8282 CALL_PRE(vm_remap);
8283 return;
8284 case 3825:
8285 CALL_PRE(mach_make_memory_entry_64);
8286 return;
8287 case 3830:
8288 CALL_PRE(vm_purgable_control);
8289 return;
8291 case 4800:
8292 CALL_PRE(mach_vm_allocate);
8293 return;
8294 case 4801:
8295 CALL_PRE(mach_vm_deallocate);
8296 return;
8297 case 4802:
8298 CALL_PRE(mach_vm_protect);
8299 return;
8300 case 4803:
8301 CALL_PRE(mach_vm_inherit);
8302 return;
8303 case 4804:
8304 CALL_PRE(mach_vm_read);
8305 return;
8306 case 4807:
8307 CALL_PRE(mach_vm_copy);
8308 return;
8309 case 4808:
8310 CALL_PRE(mach_vm_read_overwrite);
8311 return;
8312 case 4811:
8313 CALL_PRE(mach_vm_map);
8314 return;
8315 case 4813:
8316 CALL_PRE(mach_vm_remap);
8317 return;
8318 case 4815:
8319 CALL_PRE(mach_vm_region_recurse);
8320 return;
8321 case 4817:
8322 CALL_PRE(mach_make_memory_entry_64);
8323 return;
8324 case 4818:
8325 CALL_PRE(mach_vm_purgable_control);
8326 return;
8328 default:
8329 // unknown message to task self
8330 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
8331 mh->msgh_id, name_for_port(mh->msgh_remote_port),
8332 mh->msgh_reply_port);
8333 return;
8338 PRE(mach_msg_thread)
8340 // message to local thread - check for thread-level kernel calls
8342 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8344 switch (mh->msgh_id) {
8345 case 3600:
8346 CALL_PRE(thread_terminate);
8347 return;
8348 case 3603:
8349 CALL_PRE(thread_get_state);
8350 return;
8351 case 3605:
8352 CALL_PRE(thread_suspend);
8353 return;
8354 case 3606:
8355 CALL_PRE(thread_resume);
8356 return;
8357 case 3612:
8358 CALL_PRE(thread_info);
8359 return;
8360 case 3616:
8361 CALL_PRE(thread_policy);
8362 return;
8363 case 3617:
8364 CALL_PRE(thread_policy_set);
8365 return;
8366 default:
8367 // unknown message to a thread
8368 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
8369 mh->msgh_id, name_for_port(mh->msgh_request_port),
8370 mh->msgh_reply_port);
8371 return;
8376 static int is_thread_port(mach_port_t port)
8378 if (port == 0) return False;
8380 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
8384 static int is_task_port(mach_port_t port)
8386 if (port == 0) return False;
8388 if (port == vg_task_port) return True;
8390 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
8394 /* ---------------------------------------------------------------------
8395 mach_msg: base handlers
8396 ------------------------------------------------------------------ */
8398 PRE(mach_msg)
8400 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8401 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8402 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8403 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
8404 // mach_port_t rcv_name = (mach_port_t)ARG5;
8405 size_t complex_header_size = 0;
8407 PRE_REG_READ7(long, "mach_msg",
8408 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
8409 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
8410 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
8411 mach_port_t,"notify");
8413 // Assume default POST handler until specified otherwise
8414 AFTER = NULL;
8416 // Assume call may block unless specified otherwise
8417 *flags |= SfMayBlock;
8419 if (option & MACH_SEND_MSG) {
8420 // Validate outgoing message header
8421 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8422 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
8423 // msgh_size not required, use parameter instead
8424 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8425 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
8426 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8427 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
8428 // msgh_reserved not required
8429 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8430 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
8432 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8433 // Validate typed message data and handle memory map changes.
8434 complex_header_size = export_complex_message(tid, mh);
8437 // GrP fixme handle sender-specified message trailer
8438 // (but is this only for too-secure processes?)
8439 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8440 # if DARWIN_VERS >= DARWIN_10_10
8441 if (mh->msgh_bits & MACH_SEND_TRAILER) {
8442 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8444 # else
8445 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
8446 # endif
8448 MACH_REMOTE = mh->msgh_remote_port;
8449 MACH_MSGH_ID = mh->msgh_id;
8452 if (option & MACH_RCV_MSG) {
8453 // Pre-validate receive buffer
8454 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
8457 // Call a PRE handler. The PRE handler may set an AFTER handler.
8459 if (!(option & MACH_SEND_MSG)) {
8460 // no message sent, receive only
8461 CALL_PRE(mach_msg_receive);
8462 return;
8464 else if (mh->msgh_request_port == vg_host_port) {
8465 // message sent to mach_host_self()
8466 CALL_PRE(mach_msg_host);
8467 return;
8469 else if (is_task_port(mh->msgh_request_port)) {
8470 // message sent to a task
8471 CALL_PRE(mach_msg_task);
8472 return;
8474 else if (mh->msgh_request_port == vg_bootstrap_port) {
8475 // message sent to bootstrap port
8476 CALL_PRE(mach_msg_bootstrap);
8477 return;
8479 else if (is_thread_port(mh->msgh_request_port)) {
8480 // message sent to one of this process's threads
8481 CALL_PRE(mach_msg_thread);
8482 return;
8484 else {
8485 // this is an attempt to optimize mapping sync
8486 // but there are always some cases hard to find
8487 #if 0
8488 Bool do_mapping_update = False;
8489 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8490 // which is obviously not true...
8491 switch (mh->msgh_id) {
8492 // com.apple.windowserver.active
8493 case 29008: // this one opens a port type 'a'
8495 // com.apple.windowserver.active 'a' port
8496 case 29000:
8497 case 29822:
8498 case 29820: // adds a vm mapping
8499 case 29809: // contains a ool mem
8500 case 29800: // opens a port type 'b'
8501 case 29873:
8502 case 29876: // adds a vm mapping
8504 // com.apple.windowserver.active 'b' port
8505 case 29624:
8506 case 29625:
8507 case 29506:
8508 case 29504:
8509 case 29509:
8510 case 29315:
8511 case 29236:
8512 case 29473:
8513 case 29268:
8514 case 29237: // contains a ool mem
8515 case 29360:
8516 case 29301:
8517 case 29287:
8518 case 29568:
8519 case 29570: // contains a ool mem
8520 case 29211:
8521 case 29569: // contains a ool mem
8522 case 29374:
8523 case 29246:
8524 case 29239:
8525 case 29272:
8526 if (mh->msgh_id == 29820 ||
8527 mh->msgh_id == 29876)
8528 do_mapping_update = True;
8530 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8531 mh->msgh_id, name_for_port(mh->msgh_request_port),
8532 mh->msgh_reply_port);
8533 break;
8535 // com.apple.FontServer
8536 case 13024:
8537 PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
8538 mh->msgh_id, name_for_port(mh->msgh_request_port),
8539 mh->msgh_reply_port);
8540 break;
8542 // com.apple.system.notification_center
8543 case 78945698:
8544 case 78945701:
8545 case 78945695: // contains a ool mem
8546 case 78945694:
8547 case 78945700:
8548 if (mh->msgh_id == 78945695)
8549 do_mapping_update = False;
8550 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8551 mh->msgh_id, name_for_port(mh->msgh_request_port),
8552 mh->msgh_reply_port);
8553 break;
8555 // com.apple.CoreServices.coreservicesd
8556 case 10000:
8557 case 10019:
8558 case 10002: // adds vm mappings
8559 case 10003: // adds vm mappings
8560 case 14007:
8561 case 13000:
8562 case 13001:
8563 case 13011:
8564 case 13016: // contains a ool mem
8565 if (mh->msgh_id == 10002||
8566 mh->msgh_id == 10003)
8567 do_mapping_update = True;
8568 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8569 mh->msgh_id, name_for_port(mh->msgh_request_port),
8570 mh->msgh_reply_port);
8571 break;
8573 // com.apple.system.logger
8574 case 118:
8575 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8576 mh->msgh_id, name_for_port(mh->msgh_request_port),
8577 mh->msgh_reply_port);
8578 break;
8580 // com.apple.coreservices.launchservicesd, and others
8581 case 1999646836: // might adds vm mapping
8582 if (mh->msgh_id == 1999646836)
8583 do_mapping_update = True;
8584 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8585 mh->msgh_id, name_for_port(mh->msgh_request_port),
8586 mh->msgh_reply_port);
8587 break;
8589 // com.apple.ocspd
8590 case 33012:
8591 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8592 mh->msgh_id, name_for_port(mh->msgh_request_port),
8593 mh->msgh_reply_port);
8595 default:
8596 // arbitrary message to arbitrary port
8597 do_mapping_update = True;
8598 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
8599 mh->msgh_id, name_for_port(mh->msgh_request_port),
8600 mh->msgh_reply_port);
8603 // this is an optimization, don't check mapping on known mach_msg
8604 if (do_mapping_update)
8605 AFTER = POST_FN(mach_msg_unhandled);
8606 else
8607 AFTER = POST_FN(mach_msg_unhandled_check);
8608 #else
8609 AFTER = POST_FN(mach_msg_unhandled);
8610 #endif
8612 // Assume the entire message body may be read.
8613 // GrP fixme generates false positives for unknown protocols
8615 PRE_MEM_READ("mach_msg(payload)",
8616 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8617 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8619 return;
8623 POST(mach_msg)
8625 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8626 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8628 if (option & MACH_RCV_MSG) {
8629 if (RES != 0) {
8630 // error during send or receive
8631 // GrP fixme need to clean up port rights?
8632 } else {
8633 mach_msg_trailer_t *mt =
8634 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
8636 // Assume the entire received message and trailer is initialized
8637 // GrP fixme would being more specific catch any bugs?
8638 POST_MEM_WRITE((Addr)mh,
8639 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
8641 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8642 // Update memory map for out-of-line message data
8643 import_complex_message(tid, mh);
8648 // Call handler chosen by PRE(mach_msg)
8649 if (AFTER) {
8650 (*AFTER)(tid, arrghs, status);
8655 POST(mach_msg_unhandled)
8657 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8658 ML_(sync_mappings)("after", "mach_msg_receive-UNHANDLED", mh->msgh_id);
8661 POST(mach_msg_unhandled_check)
8663 if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
8664 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
8668 /* ---------------------------------------------------------------------
8669 other Mach traps
8670 ------------------------------------------------------------------ */
8672 PRE(mach_reply_port)
8674 PRINT("mach_reply_port()");
8677 POST(mach_reply_port)
8679 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
8680 PRINT("reply port %s", name_for_port(RES));
8684 PRE(mach_thread_self)
8686 PRINT("mach_thread_self()");
8689 POST(mach_thread_self)
8691 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
8692 PRINT("thread %#lx", RES);
8696 PRE(mach_host_self)
8698 PRINT("mach_host_self()");
8701 POST(mach_host_self)
8703 vg_host_port = RES;
8704 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
8705 PRINT("host %#lx", RES);
8709 PRE(mach_task_self)
8711 PRINT("mach_task_self()");
8714 POST(mach_task_self)
8716 vg_task_port = RES;
8717 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
8718 PRINT("task %#lx", RES);
8722 PRE(syscall_thread_switch)
8724 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8725 name_for_port(ARG1), SARG2, SARG3);
8726 PRE_REG_READ3(long, "syscall_thread_switch",
8727 mach_port_t,"thread", int,"option", natural_t,"timeout");
8729 *flags |= SfMayBlock;
8733 PRE(semaphore_signal)
8735 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
8736 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8740 PRE(semaphore_signal_all)
8742 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
8743 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
8747 PRE(semaphore_signal_thread)
8749 PRINT("semaphore_signal_thread(%s, %s)",
8750 name_for_port(ARG1), name_for_port(ARG2));
8751 PRE_REG_READ2(long, "semaphore_signal_thread",
8752 semaphore_t,"semaphore", mach_port_t,"thread");
8756 PRE(semaphore_wait)
8758 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
8759 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8761 *flags |= SfMayBlock;
8765 PRE(semaphore_wait_signal)
8767 PRINT("semaphore_wait_signal(%s, %s)",
8768 name_for_port(ARG1), name_for_port(ARG2));
8769 PRE_REG_READ2(long, "semaphore_wait_signal",
8770 semaphore_t,"wait_semaphore",
8771 semaphore_t,"signal_semaphore");
8773 *flags |= SfMayBlock;
8777 PRE(semaphore_timedwait)
8779 PRINT("semaphore_timedwait(%s, %g seconds)",
8780 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
8781 PRE_REG_READ3(long, "semaphore_wait_signal",
8782 semaphore_t,"semaphore",
8783 int,"wait_time_hi",
8784 int,"wait_time_lo");
8786 *flags |= SfMayBlock;
8790 PRE(semaphore_timedwait_signal)
8792 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8793 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
8794 PRE_REG_READ4(long, "semaphore_wait_signal",
8795 semaphore_t,"wait_semaphore",
8796 semaphore_t,"signal_semaphore",
8797 int,"wait_time_hi",
8798 int,"wait_time_lo");
8800 *flags |= SfMayBlock;
8804 PRE(__semwait_signal)
8806 /* 10.5 args: int cond_sem, int mutex_sem,
8807 int timeout, int relative,
8808 time_t tv_sec, time_t tv_nsec */
8809 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8810 name_for_port(ARG1), name_for_port(ARG2), SARG3, SARG4, SARG5, SARG6);
8811 PRE_REG_READ6(long, "__semwait_signal",
8812 int,"cond_sem", int,"mutex_sem",
8813 int,"timeout", int,"relative",
8814 vki_time_t,"tv_sec", int,"tv_nsec");
8816 *flags |= SfMayBlock;
8818 // GrP provided this alternative version for 10.6, but NjN
8819 // reckons the 10.5 is is still correct for 10.6. So, retaining
8820 // Greg's version as a comment just in case we need it later.
8821 //PRE(__old_semwait_signal)
8823 // /* 10.5 args: int cond_sem, int mutex_sem,
8824 // int timeout, int relative,
8825 // const timespec *ts */
8826 // PRINT("__old_semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8827 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8828 // PRE_REG_READ5(int, "__old_semwait_signal",
8829 // int,cond_sem, int,mutex_sem,
8830 // int,timeout, int,relative,
8831 // const struct vki_timespec *,ts);
8833 // if (ARG5) PRE_MEM_READ ("__old_semwait_signal(ts)",
8834 // ARG5, sizeof(struct vki_timespec));
8836 // *flags |= SfMayBlock;
8840 PRE(task_for_pid)
8842 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), SARG2, ARG3);
8843 PRE_REG_READ3(long, "task_for_pid",
8844 mach_port_t,"target",
8845 vki_pid_t, "pid", mach_port_t *,"task");
8846 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
8849 POST(task_for_pid)
8851 mach_port_t task;
8853 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
8855 task = *(mach_port_t *)ARG3;
8856 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
8857 PRINT("task 0x%x", task);
8861 PRE(pid_for_task)
8863 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
8864 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
8865 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
8868 POST(pid_for_task)
8870 vki_pid_t pid;
8872 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
8874 pid = *(vki_pid_t *)ARG2;
8875 PRINT("pid %u", pid);
8879 PRE(mach_timebase_info)
8881 PRINT("mach_timebase_info(%#lx)", ARG1);
8882 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8883 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
8886 POST(mach_timebase_info)
8888 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
8892 PRE(mach_wait_until)
8894 #if VG_WORDSIZE == 8
8895 PRINT("mach_wait_until(%lu)", ARG1);
8896 PRE_REG_READ1(long, "mach_wait_until",
8897 unsigned long long,"deadline");
8898 #else
8899 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
8900 PRE_REG_READ2(long, "mach_wait_until",
8901 int,"deadline_hi", int,"deadline_lo");
8902 #endif
8903 *flags |= SfMayBlock;
8907 PRE(mk_timer_create)
8909 PRINT("mk_timer_create()");
8910 PRE_REG_READ0(long, "mk_timer_create");
8913 POST(mk_timer_create)
8915 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
8919 PRE(mk_timer_destroy)
8921 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
8922 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
8924 // Must block to prevent race (other thread allocates and
8925 // notifies after we deallocate but before we notify)
8926 *flags &= ~SfMayBlock;
8929 POST(mk_timer_destroy)
8931 // Must have cleared SfMayBlock in PRE to prevent race
8932 record_port_destroy(ARG1);
8936 PRE(mk_timer_arm)
8938 #if VG_WORDSIZE == 8
8939 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
8940 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
8941 unsigned long,"expire_time");
8942 #else
8943 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
8944 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
8945 int,"expire_time_hi", int,"expire_time_lo");
8946 #endif
8950 PRE(mk_timer_cancel)
8952 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
8953 PRE_REG_READ2(long, "mk_timer_cancel",
8954 mach_port_t,"name", Addr,"result_time");
8955 if (ARG2) {
8956 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
8960 POST(mk_timer_cancel)
8962 if (ARG2) {
8963 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
8968 PRE(iokit_user_client_trap)
8970 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
8971 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
8972 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
8973 mach_port_t,connect, unsigned int,index,
8974 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
8975 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
8977 // can't do anything else with this in general
8978 // might be able to use connect+index to choose something sometimes
8981 POST(iokit_user_client_trap)
8983 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
8987 PRE(swtch)
8989 PRINT("swtch ( )");
8990 PRE_REG_READ0(long, "swtch");
8992 *flags |= SfMayBlock;
8996 PRE(swtch_pri)
8998 PRINT("swtch_pri ( %ld )", SARG1);
8999 PRE_REG_READ1(long, "swtch_pri", int,"pri");
9001 *flags |= SfMayBlock;
9005 PRE(FAKE_SIGRETURN)
9007 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
9008 an explanation of what follows. */
9009 /* This handles the fake signal-return system call created by
9010 sigframe-x86-darwin.c. */
9011 /* See also comments just below on PRE(sigreturn). */
9013 PRINT("FAKE_SIGRETURN ( )");
9015 vg_assert(VG_(is_valid_tid)(tid));
9016 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9017 vg_assert(VG_(is_running_thread)(tid));
9019 /* Remove the signal frame from this thread's (guest) stack,
9020 in the process restoring the pre-signal guest state. */
9021 VG_(sigframe_destroy)(tid, True);
9023 /* Tell the driver not to update the guest state with the "result",
9024 and set a bogus result to keep it happy. */
9025 *flags |= SfNoWriteResult;
9026 SET_STATUS_Success(0);
9028 /* Check to see if any signals arose as a result of this. */
9029 *flags |= SfPollAfter;
9033 PRE(sigreturn)
9035 /* This is the "real" sigreturn. But because we construct all the
9036 signal frames ourselves (of course, in m_sigframe), this cannot
9037 happen as a result of normal signal delivery. I think it
9038 happens only when doing siglongjmp, in which case Darwin's Libc
9039 appears to use it for two different purposes: to mess with the
9040 per-thread sigaltstack flags (as per arg 2), or to restore the
9041 thread's state from a ucontext* (as per arg 1). */
9043 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
9045 vg_assert(VG_(is_valid_tid)(tid));
9046 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9047 vg_assert(VG_(is_running_thread)(tid));
9049 if (ARG2 == VKI_UC_SET_ALT_STACK) {
9050 /* This is confusing .. the darwin kernel sources imply there is
9051 a per-thread on-altstack/not-on-altstack flag, which is set
9052 by this flag. Just ignore it and claim success for the time
9053 being. */
9054 VG_(debugLog)(0, "syswrap-darwin",
9055 "WARNING: Ignoring sigreturn( ..., "
9056 "UC_SET_ALT_STACK );\n");
9057 SET_STATUS_Success(0);
9058 return;
9060 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
9061 /* Ditto */
9062 VG_(debugLog)(0, "syswrap-darwin",
9063 "WARNING: Ignoring sigreturn( ..., "
9064 "UC_RESET_ALT_STACK );\n");
9065 SET_STATUS_Success(0);
9066 return;
9069 /* Otherwise claim this isn't supported. (Could be
9070 catastrophic).
9072 What do we have to do if we do need to support it?
9074 1. Change the second argument of VG_(sigframe_destroy) from
9075 "Bool isRT" to "UInt sysno", so we can pass the syscall
9076 number, so it can distinguish this case from the
9077 __NR_DARWIN_FAKE_SIGRETURN case.
9079 2. In VG_(sigframe_destroy), look at sysno to distinguish the
9080 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
9081 For this case, restore the thread's CPU state (or at least
9082 the integer regs) from the ucontext in ARG1 (and do all the
9083 other "signal-returns" stuff too).
9085 3. For (2), how do we know where the ucontext is? One way is to
9086 temporarily copy ARG1 into this thread's guest_EBX (or any
9087 other int reg), and have VG_(sigframe_destroy) read
9088 guest_EBX. Why is it ok to trash guest_EBX (or any other int
9089 reg)? Because VG_(sigframe_destroy) is just about to
9090 overwrite all the regs anyway -- since the primary purpose of
9091 calling it is to restore the register state from the ucontext
9092 pointed to by ARG1.
9094 Hey, it's uggerly. But at least it's documented.
9096 /* But in the meantime ... */
9097 VG_(debugLog)(0, "syswrap-darwin",
9098 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
9099 VG_(debugLog)(0, "syswrap-darwin",
9100 "WARNING: Thread/program/Valgrind "
9101 "will likely segfault now.\n");
9102 VG_(debugLog)(0, "syswrap-darwin",
9103 "WARNING: Please file a bug report at "
9104 "http://www.valgrind.org.\n");
9105 SET_STATUS_Failure( VKI_ENOSYS );
9109 /* ---------------------------------------------------------------------
9110 machine-dependent traps
9111 ------------------------------------------------------------------ */
9113 #if defined(VGA_x86)
9114 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
9116 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
9117 return VG_(calloc)("syswrap-darwin.ldt", nbytes, 1);
9119 #endif
9121 PRE(thread_fast_set_cthread_self)
9123 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
9124 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
9126 #if defined(VGA_x86)
9127 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
9129 VexGuestX86SegDescr *ldt;
9130 ThreadState *tst = VG_(get_ThreadState)(tid);
9131 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
9132 if (!ldt) {
9133 ldt = alloc_zeroed_x86_LDT();
9134 tst->arch.vex.guest_LDT = (HWord)ldt;
9136 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
9137 ldt[6].LdtEnt.Bits.LimitLow = 1;
9138 ldt[6].LdtEnt.Bits.LimitHi = 0;
9139 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
9140 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
9141 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
9142 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
9143 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
9144 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
9145 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
9146 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
9148 tst->os_state.pthread = ARG1;
9149 tst->arch.vex.guest_GS = 0x37;
9151 // What we would like to do is:
9152 // SET_STATUS_Success(0x37);
9153 // but that doesn't work, because this is a MDEP-class syscall,
9154 // and SET_STATUS_Success creates a UNIX-class syscall result.
9155 // Hence we have to laboriously construct the full SysRes "by hand"
9156 // and use that to set the syscall return status.
9157 SET_STATUS_from_SysRes(
9158 VG_(mk_SysRes_x86_darwin)(
9159 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9160 False, 0, 0x37
9165 #elif defined(VGA_amd64)
9166 // GrP fixme bigger hack than x86
9168 ThreadState *tst = VG_(get_ThreadState)(tid);
9169 tst->os_state.pthread = ARG1;
9170 tst->arch.vex.guest_GS_CONST = ARG1;
9171 // SET_STATUS_Success(0x60);
9172 // see comments on x86 case just above
9173 SET_STATUS_from_SysRes(
9174 VG_(mk_SysRes_amd64_darwin)(
9175 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9176 False, 0, 0x60
9181 #else
9182 #error unknown architecture
9183 #endif
9187 /* ---------------------------------------------------------------------
9188 Added for OSX 10.6 (Snow Leopard)
9189 ------------------------------------------------------------------ */
9191 #if DARWIN_VERS >= DARWIN_10_6
9193 PRE(psynch_mutexwait)
9195 PRINT("psynch_mutexwait(BOGUS)");
9196 *flags |= SfMayBlock;
9198 POST(psynch_mutexwait)
9202 PRE(psynch_mutexdrop)
9204 PRINT("psynch_mutexdrop(BOGUS)");
9205 *flags |= SfMayBlock;
9207 POST(psynch_mutexdrop)
9211 PRE(psynch_cvbroad)
9213 PRINT("psynch_cvbroad(BOGUS)");
9215 POST(psynch_cvbroad)
9219 PRE(psynch_cvsignal)
9221 PRINT("psynch_cvsignal(BOGUS)");
9223 POST(psynch_cvsignal)
9227 PRE(psynch_cvwait)
9229 PRINT("psynch_cvwait(BOGUS)");
9230 *flags |= SfMayBlock;
9232 POST(psynch_cvwait)
9236 PRE(psynch_rw_rdlock)
9238 PRINT("psynch_rw_rdlock(BOGUS)");
9239 *flags |= SfMayBlock;
9241 POST(psynch_rw_rdlock)
9245 PRE(psynch_rw_wrlock)
9247 PRINT("psynch_rw_wrlock(BOGUS)");
9248 *flags |= SfMayBlock;
9250 POST(psynch_rw_wrlock)
9254 PRE(psynch_rw_unlock)
9256 PRINT("psynch_rw_unlock(BOGUS)");
9258 POST(psynch_rw_unlock)
9262 PRE(__thread_selfid)
9264 PRINT("__thread_selfid ()");
9265 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
9268 PRE(fsgetpath)
9270 #if VG_WORDSIZE == 4
9271 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
9272 ARG1, ARG2, ARG3,
9273 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
9274 LOHI64(ARG4, ARG5));
9275 PRE_REG_READ5(ssize_t, "fsgetpath",
9276 void*,"buf", size_t,"bufsize",
9277 fsid_t *,"fsid",
9278 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
9279 #else
9280 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
9281 ARG1, ARG2, ARG3,
9282 ((unsigned int *)ARG3)[0],
9283 ((unsigned int *)ARG3)[1], ARG4);
9284 PRE_REG_READ4(ssize_t, "fsgetpath",
9285 void*,"buf", size_t,"bufsize",
9286 fsid_t *,"fsid", uint64_t,"objid");
9287 #endif
9288 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
9289 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
9292 POST(fsgetpath)
9294 POST_MEM_WRITE(ARG1, RES);
9297 PRE(audit_session_self)
9299 PRINT("audit_session_self()");
9301 POST(audit_session_self)
9303 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
9304 PRINT("audit-session %#lx", RES);
9307 #endif /* DARWIN_VERS >= DARWIN_10_6 */
9310 /* ---------------------------------------------------------------------
9311 Added for OSX 10.7 (Lion)
9312 ------------------------------------------------------------------ */
9314 #if DARWIN_VERS >= DARWIN_10_7
9316 PRE(psynch_cvclrprepost)
9318 PRINT("psynch_cvclrprepost(BOGUS)");
9319 *flags |= SfMayBlock;
9321 POST(psynch_cvclrprepost)
9325 #endif /* DARWIN_VERS >= DARWIN_10_7 */
9328 /* ---------------------------------------------------------------------
9329 Added for OSX 10.8 (Mountain Lion)
9330 ------------------------------------------------------------------ */
9332 /* About munge tags, eg munge_wllww.
9334 Means the syscall takes 5 args. For a 64 bit process each arg
9335 occupies one 64-bit value and so the mapping to ARGn macros is
9336 direct. For a 32 bit process, this is more complex: 'w' denotes a
9337 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
9338 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
9339 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
9340 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
9341 in order to get sane values for the arguments in 32-bit
9342 processes. */
9344 static void munge_wwl(UWord* a1, UWord* a2, ULong* a3,
9345 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4)
9347 # if defined(VGA_x86)
9348 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4);
9349 # else
9350 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9351 # endif
9354 static void munge_wll(UWord* a1, ULong* a2, ULong* a3,
9355 UWord aRG1, UWord aRG2, UWord aRG3,
9356 UWord aRG4, UWord aRG5)
9358 # if defined(VGA_x86)
9359 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9360 # else
9361 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9362 # endif
9365 static void munge_wwlw(UWord* a1, UWord* a2, ULong* a3, UWord* a4,
9366 UWord aRG1, UWord aRG2, UWord aRG3,
9367 UWord aRG4, UWord aRG5)
9369 # if defined(VGA_x86)
9370 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4); *a4 = aRG5;
9371 # else
9372 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9373 # endif
9376 static void munge_wwwl(UWord* a1, UWord* a2, UWord* a3, ULong* a4,
9377 UWord aRG1, UWord aRG2, UWord aRG3,
9378 UWord aRG4, UWord aRG5)
9380 # if defined(VGA_x86)
9381 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = LOHI64(aRG4,aRG5);
9382 # else
9383 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9384 # endif
9387 static void munge_wllww(UWord* a1, ULong* a2, ULong* a3, UWord* a4, UWord* a5,
9388 UWord aRG1, UWord aRG2, UWord aRG3,
9389 UWord aRG4, UWord aRG5, UWord aRG6, UWord aRG7)
9391 # if defined(VGA_x86)
9392 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9393 *a4 = aRG6; *a5 = aRG7;
9394 # else
9395 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5;
9396 # endif
9399 static void munge_wwllww(UWord* a1, UWord* a2, ULong* a3,
9400 ULong* a4, UWord* a5, UWord* a6,
9401 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4,
9402 UWord aRG5, UWord aRG6, UWord aRG7, UWord aRG8)
9404 # if defined(VGA_x86)
9405 *a1 = aRG1; *a2 = aRG2;
9406 *a3 = LOHI64(aRG3,aRG4); *a4 = LOHI64(aRG5,aRG6);
9407 *a5 = aRG7; *a6 = aRG8;
9408 # else
9409 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5; *a6 = aRG6;
9410 # endif
9413 #if DARWIN_VERS >= DARWIN_10_8
9415 PRE(kernelrpc_mach_vm_allocate_trap)
9417 UWord a1; UWord a2; ULong a3; UWord a4;
9418 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9419 PRINT("kernelrpc_mach_vm_allocate_trap"
9420 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
9421 name_for_port(a1), *(void**)a2, a3, a4);
9422 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
9423 a2, sizeof(void*));
9425 POST(kernelrpc_mach_vm_allocate_trap)
9427 UWord a1; UWord a2; ULong a3; UWord a4;
9428 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9429 PRINT("address:%p size:%#llx", *(void**)a2, a3);
9430 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9431 POST_MEM_WRITE(a2, sizeof(void*));
9433 if (a1 == mach_task_self()) {
9434 # if 1
9435 ML_(sync_mappings)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
9436 # else
9437 /* This is nearly right, but not always -- sometimes the mapping
9438 appears to be r--, for some reason. Hence resync. */
9439 ML_(notify_core_and_tool_of_mmap)(
9440 *(UWord*)a2, a3,
9441 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9442 # endif
9446 PRE(kernelrpc_mach_vm_deallocate_trap)
9448 UWord a1; ULong a2; ULong a3;
9449 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9450 PRINT("kernelrpc_mach_vm_deallocate_trap"
9451 "(target:%#lx, address:%#llx, size:%#llx)", a1, a2, a3);
9453 POST(kernelrpc_mach_vm_deallocate_trap)
9455 UWord a1; ULong a2; ULong a3;
9456 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9457 // kernelrpc_mach_vm_deallocate_trap could be call with
9458 // address ==0 && size == 0,
9459 // we shall not notify any unmap then
9460 if (a3)
9461 ML_(notify_core_and_tool_of_munmap)(a2, a3);
9464 PRE(kernelrpc_mach_vm_protect_trap)
9466 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9467 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9468 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9469 PRINT("kernelrpc_mach_vm_protect_trap"
9470 "(task:%#lx, address:%#llx, size:%#llx,"
9471 " set_maximum:%#lx, new_prot:%#lx)", a1, a2, a3, a4, a5);
9473 POST(kernelrpc_mach_vm_protect_trap)
9475 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9476 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9477 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9478 if (/*a4 set_maximum == 0 && */a1 == mach_task_self()) {
9479 ML_(notify_core_and_tool_of_mprotect)((Addr)a2, (SizeT)a3, (Int)a5);
9480 VG_(di_notify_vm_protect)((Addr)a2, (SizeT)a3, (UInt)a5);
9484 PRE(kernelrpc_mach_port_allocate_trap)
9486 // munge_www -- no need to call helper
9487 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9488 ARG1, ARG2);
9489 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9490 ARG3, sizeof(mach_port_name_t));
9492 POST(kernelrpc_mach_port_allocate_trap)
9494 // munge_www -- no need to call helper
9495 POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
9496 PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
9497 record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
9500 PRE(kernelrpc_mach_port_destroy_trap)
9502 // munge_ww -- no need to call helper
9503 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
9504 record_port_destroy(ARG2);
9507 PRE(kernelrpc_mach_port_deallocate_trap)
9509 // munge_ww -- no need to call helper
9510 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9511 ARG1, ARG2);
9513 POST(kernelrpc_mach_port_deallocate_trap)
9515 // munge_ww -- no need to call helper
9518 PRE(kernelrpc_mach_port_mod_refs_trap)
9520 // munge_wwww -- no need to call helper
9521 PRINT("kernelrpc_mach_port_mod_refs_trap"
9522 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9523 ARG1, ARG2, ARG3, ARG4);
9526 PRE(kernelrpc_mach_port_move_member_trap)
9528 // munge_www -- no need to call helper
9529 PRINT("kernelrpc_mach_port_move_member_trap"
9530 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9531 ARG1, ARG2, ARG3);
9534 PRE(kernelrpc_mach_port_insert_right_trap)
9536 //munge_wwww -- no need to call helper
9537 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9538 "(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9541 PRE(kernelrpc_mach_port_insert_member_trap)
9543 // munge_www -- no need to call helper
9544 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9545 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9548 PRE(kernelrpc_mach_port_extract_member_trap)
9550 // munge_www -- no need to call helper
9551 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9552 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9555 PRE(iopolicysys)
9557 // munge_???
9558 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
9559 /* mem effects unknown */
9561 POST(iopolicysys)
9563 // munge_???
9566 PRE(process_policy)
9568 // munge_???
9569 PRINT("process_policy(FIXME)("
9570 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9571 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9572 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9573 /* mem effects unknown */
9575 POST(process_policy)
9577 // munge_???
9580 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9583 /* ---------------------------------------------------------------------
9584 Added for OSX 10.9 (Mavericks)
9585 ------------------------------------------------------------------ */
9587 #if DARWIN_VERS >= DARWIN_10_9
9589 PRE(kernelrpc_mach_vm_map_trap)
9591 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9592 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9593 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9594 PRINT("kernelrpc_mach_vm_map_trap"
9595 "(target:%#lx, address:%p, size:%#llx,"
9596 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9597 a1, *(void**)a2, a3, a4, a5, a6);
9598 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2, sizeof(void*));
9600 POST(kernelrpc_mach_vm_map_trap)
9602 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9603 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9604 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9605 PRINT("-> address:%p", *(void**)a2);
9606 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9607 POST_MEM_WRITE(a2, sizeof(void*));
9609 ML_(notify_core_and_tool_of_mmap)(
9610 *(mach_vm_address_t*)a2, a3,
9611 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9612 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9615 PRE(kernelrpc_mach_port_construct_trap)
9617 UWord a1; UWord a2; ULong a3; UWord a4;
9618 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9619 PRINT("kernelrpc_mach_port_construct_trap"
9620 "(target: %s, options: %#lx, content: %llx, name: %p)",
9621 name_for_port(a1), a2, a3, *(mach_port_name_t**)a4);
9622 PRE_MEM_WRITE("kernelrpc_mach_port_construct_trap(name)", a4,
9623 sizeof(mach_port_name_t*));
9625 POST(kernelrpc_mach_port_construct_trap)
9627 UWord a1; UWord a2; ULong a3; UWord a4;
9628 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9629 PRINT("-> name:%p", *(mach_port_name_t**)a4);
9630 if (ML_(safe_to_deref)((mach_port_name_t*)a4, sizeof(mach_port_name_t*))) {
9631 POST_MEM_WRITE(a4, sizeof(mach_port_name_t*));
9635 PRE(kernelrpc_mach_port_destruct_trap)
9637 UWord a1; UWord a2; UWord a3; ULong a4;
9638 munge_wwwl(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9639 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9640 "(%lx,%lx,%lx,%llx)", a1, a2, a3, a4);
9643 PRE(kernelrpc_mach_port_guard_trap)
9645 UWord a1; UWord a2; ULong a3; UWord a4;
9646 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9647 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9648 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9651 PRE(kernelrpc_mach_port_unguard_trap)
9653 // munge_wwl
9654 UWord a1; UWord a2; ULong a3;
9655 munge_wwl(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4);
9656 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9657 "(%lx,%lx,%llx)", a1, a2, a3);
9660 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9663 /* ---------------------------------------------------------------------
9664 Added for OSX 10.10 (Yosemite)
9665 ------------------------------------------------------------------ */
9667 #if DARWIN_VERS >= DARWIN_10_10
9669 PRE(necp_match_policy)
9671 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9672 // struct necp_aggregate_result *returned_result)
9673 PRINT("necp_match_policy(FIXME)(%lx,%lu, %lx)", ARG1, ARG2, ARG3);
9674 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
9675 size_t, parameters_size, struct necp_aggregate_result*,
9676 returned_result);
9677 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
9679 POST(necp_match_policy)
9681 POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
9684 PRE(sysctlbyname)
9686 UWord name = ARG1;
9687 UWord namelen = ARG2;
9688 UWord oldp = ARG3;
9689 UWord oldlenp = ARG4;
9690 UWord newp = ARG5;
9691 UWord newlen = ARG6; // FIXME: or newlenp ??
9693 PRINT( "sysctlbyname ( %#lx,%lu, %#lx,%#lx, %#lx,%lu )",
9694 name, namelen, oldp, oldlenp, newp, newlen );
9696 PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
9697 void*, oldp, vki_size_t *, oldlenp,
9698 void*, newp, vki_size_t *, newlenp); // <---<<
9700 // reads name[0..namelen-1]
9701 PRE_MEM_READ("sysctlbyname(name)", name, namelen);
9703 if (VG_(clo_trace_syscalls)) {
9704 UInt i;
9705 const HChar* t_name = (const HChar*)name;
9706 VG_(printf)(" name: ");
9707 for (i = 0; i < namelen; i++) {
9708 VG_(printf)("%c", t_name[i]);
9710 VG_(printf)(" ");
9713 Bool is_kern_dot_userstack
9714 = False;
9716 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
9717 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
9719 POST(sysctlbyname)
9721 UWord oldp = ARG3;
9722 UWord oldlenp = ARG4;
9724 if (SUCCESS || ERR == VKI_ENOMEM) {
9725 // sysctl can write truncated data and return VKI_ENOMEM
9726 if (oldlenp) {
9727 POST_MEM_WRITE(oldlenp, sizeof(size_t));
9729 if (oldp && oldlenp) {
9730 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
9735 PRE(getattrlistbulk)
9737 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9738 // void *attributeBuffer, size_t bufferSize,
9739 // uint64_t options);
9740 // Presumably the last arg is value-pair in the 32 bit case.
9741 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9742 SARG1, ARG2, ARG3, ARG4, ARG5);
9743 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
9744 void*, attributeBuffer, size_t, bufferSize,
9745 uint32_t, options_lo32);
9746 PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
9747 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
9749 POST(getattrlistbulk)
9751 // FIXME: this isn't right. It seems as if what is returned is a
9752 // set of variable-length records -- see complication in
9753 // POST(getattrlist). For now, just paint the entire result buffer
9754 // as defined. Sigh.
9755 vg_assert(SUCCESS);
9756 if (ARG3 && /* "at least one output element was written" */RES > 0)
9757 POST_MEM_WRITE(ARG3, ARG4);
9760 PRE(faccessat)
9762 PRINT("faccessat(FIXME)(fd:%ld, path:%#lx(%s), amode:%#lx, flag:%#lx)",
9763 ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
9764 PRE_REG_READ4(int, "faccessat",
9765 int, fd, user_addr_t, path, int, amode, int, flag);
9768 PRE(fstatat64)
9770 PRINT("fstatat64(FIXME)(fd:%ld, path:%#lx(%s), ub:%#lx, flag:%#lx)",
9771 ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
9772 PRE_REG_READ4(int, "fstatat64",
9773 int, fd, user_addr_t, path, user_addr_t, ub, int, flag);
9776 PRE(readlinkat)
9778 Word saved = SYSNO;
9780 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %ld )",
9781 SARG1, ARG2, (HChar*)ARG2, ARG3, SARG4);
9782 PRE_REG_READ4(long, "readlinkat",
9783 int, dfd, const char *, path, char *, buf, int, bufsiz);
9784 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
9785 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
9788 * Refer to coregrind/m_syswrap/syswrap-linux.c
9791 /* Normal case */
9792 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
9795 if (SUCCESS && RES > 0)
9796 POST_MEM_WRITE( ARG3, RES );
9799 PRE(bsdthread_ctl)
9801 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9802 // user_addr_t arg2, user_addr_t arg3)
9803 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9804 PRE_REG_READ4(int, "bsdthreadctl",
9805 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
9808 PRE(csrctl)
9810 PRINT("csrctl(op:%ld, useraddr:%#lx, usersize:%#lx) FIXME", ARG1, ARG2, ARG3);
9811 PRE_REG_READ3(int, "csrctl",
9812 uint32_t, op, user_addr_t, useraddr, user_addr_t, usersize);
9815 PRE(guarded_open_dprotected_np)
9817 PRINT("guarded_open_dprotected_np("
9818 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9819 "dpclass:%#lx, dpflags: %#lx) FIXME",
9820 ARG1, (HChar*)ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
9823 PRE(guarded_write_np)
9825 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9826 ARG1, ARG2, ARG3, (ULong)ARG4);
9829 PRE(guarded_pwrite_np)
9831 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9832 ARG1, ARG2, ARG3, (ULong)ARG4, (Long)ARG5);
9835 PRE(guarded_writev_np)
9837 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9838 ARG1, ARG2, ARG3, (ULong)ARG4);
9841 #endif /* DARWIN_VERS >= DARWIN_10_10 */
9844 /* ---------------------------------------------------------------------
9845 Added for OSX 10.11 (El Capitan)
9846 ------------------------------------------------------------------ */
9848 #if DARWIN_VERS >= DARWIN_10_11
9850 PRE(kevent_qos)
9852 PRINT("kevent_qos( %ld, %#lx, %ld, %#lx, %ld, %#lx, %ld, %ld )",
9853 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6, SARG7, ARG8);
9854 PRE_REG_READ8(int,"kevent_qos",
9855 int,kq,
9856 const struct vki_kevent_qos_s *,changelist,
9857 int,nchanges,
9858 struct vki_kevent_qos_s *,eventlist,
9859 int,nevents,
9860 void*,data_out,
9861 size_t*,data_available,
9862 unsigned int,flags);
9864 if (ARG3) PRE_MEM_READ ("kevent_qos(changelist)",
9865 ARG2, ARG3 * sizeof(struct vki_kevent_qos_s));
9866 if (ARG5) PRE_MEM_WRITE("kevent_qos(eventlist)",
9867 ARG4, ARG5 * sizeof(struct vki_kevent_qos_s));
9868 if (ARG7) PRE_MEM_WRITE("kevent_qos(data_out)",
9869 ARG6, ARG7 * sizeof(void*));
9871 *flags |= SfMayBlock;
9874 POST(kevent_qos)
9876 PRINT("kevent_qos ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent_qos_s));
9877 if (RES > 0) {
9878 ML_(sync_mappings)("after", "kevent_qos", 0);
9879 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent_qos_s));
9884 PRE(pselect)
9886 *flags |= SfMayBlock;
9887 PRINT("pselect ( %ld, %#lx, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
9888 ARG4, ARG5, ARG6);
9889 PRE_REG_READ5(long, "pselect",
9890 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
9891 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
9892 // XXX: this possibly understates how much memory is read.
9893 if (ARG2 != 0)
9894 PRE_MEM_READ( "pselect(readfds)",
9895 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
9896 if (ARG3 != 0)
9897 PRE_MEM_READ( "pselect(writefds)",
9898 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
9899 if (ARG4 != 0)
9900 PRE_MEM_READ( "pselect(exceptfds)",
9901 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
9902 if (ARG5 != 0)
9903 PRE_timeval_READ( "pselect(timeout)", ARG5 );
9904 if (ARG6 != 0)
9905 PRE_MEM_READ( "pselect(sigmask)", ARG6, sizeof(vki_sigset_t) );
9908 #endif /* DARWIN_VERS >= DARWIN_10_11 */
9911 /* ---------------------------------------------------------------------
9912 Added for macOS 10.12 (Sierra)
9913 ------------------------------------------------------------------ */
9915 #if DARWIN_VERS >= DARWIN_10_12
9917 PRE(getentropy)
9919 PRINT("getentropy(buffer:%#lx, size:%ld) FIXME", ARG1, ARG2);
9920 PRE_REG_READ2(int, "getentropy",
9921 void*, buffer, size_t, size);
9924 static const HChar *ulop_name(int op)
9926 switch (op) {
9927 case VKI_UL_UNFAIR_LOCK: return "UL_UNFAIR_LOCK";
9928 case VKI_UL_COMPARE_AND_WAIT: return "UL_COMPARE_AND_WAIT";
9929 default: return "??";
9933 PRE(ulock_wake)
9935 PRINT("ulock_wake(operation:%ld, addr:%#lx, wake_value:%ld) FIXME",
9936 ARG1, ARG2, ARG3);
9937 PRE_REG_READ3(int, "ulock_wake",
9938 uint32_t, operation, void*, addr, uint64_t, wake_value);
9941 PRE(ulock_wait)
9943 uint ul_opcode = ARG1 & VKI_UL_OPCODE_MASK;
9944 uint ul_flags = ARG1 & VKI_UL_FLAGS_MASK;
9946 switch (ul_opcode) {
9947 case VKI_UL_UNFAIR_LOCK:
9948 case VKI_UL_COMPARE_AND_WAIT: {
9949 const char* name = ulop_name(ul_opcode);
9950 PRINT("ulock_wait(operation:%s (flags: %#x), addr:%#lx, value:%ld, timeout:%ld)",
9951 name, ul_flags, ARG2, ARG3, ARG4);
9952 PRE_REG_READ4(int, "ulock_wait",
9953 uint32_t, operation, void*, addr, uint64_t, value, uint32_t, timeout);
9954 PRE_MEM_READ("ulock_wait(addr)", ARG2, 4 );
9955 break;
9958 default:
9959 PRINT("ulock_wait(operation:%ld (opcode: %u [??], flags: %#x), addr:%#lx, value:%ld, timeout:%ld)", ARG1, ul_opcode, ul_flags, ARG2, ARG3, ARG4);
9960 log_decaying("UNKNOWN ulock_wait %ld (opcode: %u [??], flags: %#x)!", ARG1, ul_opcode, ul_flags);
9961 break;
9965 PRE(host_create_mach_voucher_trap)
9967 // munge_wwww -- no need to call helper
9968 PRINT("host_create_mach_voucher_trap"
9969 "(host:%#lx, recipes:%#lx, recipes_size:%ld, voucher:%#lx) FIXME",
9970 ARG1, ARG2, ARG3, ARG4);
9973 PRE(task_register_dyld_image_infos)
9975 #pragma pack(4)
9976 typedef struct {
9977 mach_msg_header_t Head;
9978 /* start of the kernel processed data */
9979 mach_msg_body_t msgh_body;
9980 mach_msg_ool_descriptor_t dyld_images;
9981 /* end of the kernel processed data */
9982 NDR_record_t NDR;
9983 mach_msg_type_number_t dyld_imagesCnt;
9984 } Request;
9985 #pragma pack()
9987 // Request *req = (Request *)ARG1;
9989 PRINT("task_register_dyld_image_infos(%s)", name_for_port(MACH_REMOTE));
9991 AFTER = POST_FN(task_register_dyld_image_infos);
9994 POST(task_register_dyld_image_infos)
9996 #pragma pack(4)
9997 typedef struct {
9998 mach_msg_header_t Head;
9999 NDR_record_t NDR;
10000 kern_return_t RetCode;
10001 } Reply;
10002 #pragma pack()
10004 Reply *reply = (Reply *)ARG1;
10005 if (!reply->RetCode) {
10006 } else {
10007 PRINT("mig return %d", reply->RetCode);
10011 PRE(task_register_dyld_shared_cache_image_info)
10013 #pragma pack(4)
10014 typedef struct {
10015 mach_msg_header_t Head;
10016 NDR_record_t NDR;
10017 dyld_kernel_image_info_t dyld_cache_image;
10018 boolean_t no_cache;
10019 boolean_t private_cache;
10020 } Request;
10021 #pragma pack()
10023 // Request *req = (Request *)ARG1;
10025 PRINT("task_register_dyld_shared_cache_image_info(%s)",
10026 name_for_port(MACH_REMOTE));
10028 AFTER = POST_FN(task_register_dyld_shared_cache_image_info);
10031 POST(task_register_dyld_shared_cache_image_info)
10033 #pragma pack(4)
10034 typedef struct {
10035 mach_msg_header_t Head;
10036 NDR_record_t NDR;
10037 kern_return_t RetCode;
10038 } Reply;
10039 #pragma pack()
10041 Reply *reply = (Reply *)ARG1;
10042 if (!reply->RetCode) {
10043 } else {
10044 PRINT("mig return %d", reply->RetCode);
10048 PRE(mach_generate_activity_id)
10050 // munge_www -- no need to call helper
10051 PRINT("mach_generate_activity_id"
10052 "(target:%s, count:%ld)",
10053 name_for_port(ARG1), ARG2);
10054 PRE_REG_READ3(long, "mach_generate_activity_id",
10055 mach_port_name_t, target, int, count, uint64_t *, activity_id);
10056 if (ARG2 <= 0 || ARG2 > MACH_ACTIVITY_ID_COUNT_MAX) {
10057 SET_STATUS_Failure( VKI_EINVAL );
10059 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10060 PRE_MEM_WRITE( "mach_generate_activity_id(activity_id)", ARG3, sizeof(vki_uint64_t) );
10061 } else {
10062 SET_STATUS_Failure( VKI_EFAULT );
10066 POST(mach_generate_activity_id)
10068 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10069 POST_MEM_WRITE( ARG3, sizeof(vki_uint64_t) );
10070 PRINT("-> activity_id:%#llx", *(uint64_t*)ARG3);
10074 #endif /* DARWIN_VERS >= DARWIN_10_12 */
10077 /* ---------------------------------------------------------------------
10078 syscall tables
10079 ------------------------------------------------------------------ */
10081 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
10083 #define MACX_(sysno, name) \
10084 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10086 #define MACXY(sysno, name) \
10087 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10089 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
10092 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
10093 unfortunately misused for Mach too, causing assertion failures
10094 // _____ : unimplemented in valgrind
10095 GEN : handlers are in syswrap-generic.c
10096 MAC : handlers are in this file
10097 X_ : PRE handler only
10098 XY : PRE and POST handlers
10100 const SyscallTableEntry ML_(syscall_table)[] = {
10101 // _____(__NR_syscall), // 0
10102 MACX_(__NR_exit, exit),
10103 GENX_(__NR_fork, sys_fork),
10104 GENXY(__NR_read, sys_read),
10105 GENX_(__NR_write, sys_write),
10106 GENXY(__NR_open, sys_open),
10107 GENXY(__NR_close, sys_close),
10108 GENXY(__NR_wait4, sys_wait4),
10109 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
10110 GENX_(__NR_link, sys_link),
10111 GENX_(__NR_unlink, sys_unlink),
10112 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
10113 GENX_(__NR_chdir, sys_chdir),
10114 GENX_(__NR_fchdir, sys_fchdir),
10115 GENX_(__NR_mknod, sys_mknod),
10116 GENX_(__NR_chmod, sys_chmod),
10117 GENX_(__NR_chown, sys_chown),
10118 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
10119 MACXY(__NR_getfsstat, getfsstat),
10120 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
10121 GENX_(__NR_getpid, sys_getpid), // 20
10122 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
10123 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
10124 GENX_(__NR_setuid, sys_setuid),
10125 GENX_(__NR_getuid, sys_getuid),
10126 GENX_(__NR_geteuid, sys_geteuid),
10127 MACX_(__NR_ptrace, ptrace),
10128 MACXY(__NR_recvmsg, recvmsg),
10129 MACX_(__NR_sendmsg, sendmsg),
10130 MACXY(__NR_recvfrom, recvfrom),
10131 MACXY(__NR_accept, accept),
10132 MACXY(__NR_getpeername, getpeername),
10133 MACXY(__NR_getsockname, getsockname),
10134 GENX_(__NR_access, sys_access),
10135 MACX_(__NR_chflags, chflags),
10136 MACX_(__NR_fchflags, fchflags),
10137 GENX_(__NR_sync, sys_sync),
10138 GENX_(__NR_kill, sys_kill),
10139 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
10140 GENX_(__NR_getppid, sys_getppid),
10141 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
10142 GENXY(__NR_dup, sys_dup),
10143 MACXY(__NR_pipe, pipe),
10144 GENX_(__NR_getegid, sys_getegid),
10145 #if DARWIN_VERS >= DARWIN_10_7
10146 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
10147 #else
10148 // _____(__NR_profil),
10149 #endif
10150 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
10151 MACXY(__NR_sigaction, sigaction),
10152 GENX_(__NR_getgid, sys_getgid),
10153 MACXY(__NR_sigprocmask, sigprocmask),
10154 MACXY(__NR_getlogin, getlogin),
10155 // _____(__NR_setlogin),
10156 // _____(__NR_acct),
10157 MACXY(__NR_sigpending, sigpending),
10158 GENXY(__NR_sigaltstack, sys_sigaltstack),
10159 MACXY(__NR_ioctl, ioctl),
10160 // _____(__NR_reboot),
10161 // _____(__NR_revoke),
10162 GENX_(__NR_symlink, sys_symlink), // 57
10163 GENX_(__NR_readlink, sys_readlink),
10164 GENX_(__NR_execve, sys_execve),
10165 GENX_(__NR_umask, sys_umask), // 60
10166 GENX_(__NR_chroot, sys_chroot),
10167 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
10168 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
10169 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
10170 GENX_(__NR_msync, sys_msync),
10171 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
10172 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
10173 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
10174 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
10175 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
10176 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
10177 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
10178 GENXY(__NR_munmap, sys_munmap),
10179 GENXY(__NR_mprotect, sys_mprotect),
10180 GENX_(__NR_madvise, sys_madvise),
10181 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
10182 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
10183 GENXY(__NR_mincore, sys_mincore),
10184 GENXY(__NR_getgroups, sys_getgroups),
10185 // _____(__NR_setgroups), // 80
10186 GENX_(__NR_getpgrp, sys_getpgrp),
10187 GENX_(__NR_setpgid, sys_setpgid),
10188 GENXY(__NR_setitimer, sys_setitimer),
10189 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
10190 // _____(__NR_swapon),
10191 GENXY(__NR_getitimer, sys_getitimer),
10192 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
10193 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
10194 MACXY(__NR_getdtablesize, getdtablesize),
10195 GENXY(__NR_dup2, sys_dup2),
10196 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
10197 MACXY(__NR_fcntl, fcntl),
10198 GENX_(__NR_select, sys_select),
10199 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
10200 GENX_(__NR_fsync, sys_fsync),
10201 GENX_(__NR_setpriority, sys_setpriority),
10202 MACXY(__NR_socket, socket),
10203 MACX_(__NR_connect, connect),
10204 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
10205 GENX_(__NR_getpriority, sys_getpriority), // 100
10206 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
10207 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
10208 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
10209 MACX_(__NR_bind, bind),
10210 MACX_(__NR_setsockopt, setsockopt),
10211 MACX_(__NR_listen, listen),
10212 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
10213 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
10214 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
10215 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
10216 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
10217 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
10218 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
10219 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
10220 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
10221 GENXY(__NR_gettimeofday, sys_gettimeofday),
10222 GENXY(__NR_getrusage, sys_getrusage),
10223 MACXY(__NR_getsockopt, getsockopt),
10224 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
10225 GENXY(__NR_readv, sys_readv), // 120
10226 GENX_(__NR_writev, sys_writev),
10227 // _____(__NR_settimeofday),
10228 GENX_(__NR_fchown, sys_fchown),
10229 GENX_(__NR_fchmod, sys_fchmod),
10230 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
10231 // _____(__NR_setreuid),
10232 // _____(__NR_setregid),
10233 GENX_(__NR_rename, sys_rename),
10234 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
10235 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
10236 GENX_(__NR_flock, sys_flock),
10237 MACXY(__NR_mkfifo, mkfifo),
10238 MACX_(__NR_sendto, sendto),
10239 MACX_(__NR_shutdown, shutdown),
10240 MACXY(__NR_socketpair, socketpair),
10241 GENX_(__NR_mkdir, sys_mkdir),
10242 GENX_(__NR_rmdir, sys_rmdir),
10243 GENX_(__NR_utimes, sys_utimes),
10244 MACX_(__NR_futimes, futimes),
10245 // _____(__NR_adjtime), // 140
10246 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
10247 MACXY(__NR_gethostuuid, gethostuuid),
10248 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
10249 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
10250 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
10251 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
10252 GENX_(__NR_setsid, sys_setsid),
10253 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
10254 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
10255 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
10256 // _____(__NR_getpgid),
10257 // _____(__NR_setprivexec),
10258 GENXY(__NR_pread, sys_pread64),
10259 GENX_(__NR_pwrite, sys_pwrite64),
10260 // _____(__NR_nfssvc),
10261 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
10262 GENXY(__NR_statfs, sys_statfs),
10263 GENXY(__NR_fstatfs, sys_fstatfs),
10264 // _____(__NR_unmount),
10265 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
10266 // _____(__NR_getfh),
10267 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
10268 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
10269 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
10270 // _____(__NR_quotactl),
10271 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
10272 MACX_(__NR_mount, mount),
10273 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
10274 MACXY(__NR_csops, csops), // code-signing ops
10275 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
10276 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
10277 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
10278 // _____(__NR_waitid),
10279 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
10280 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
10281 // _____(__NR_add_profil),
10282 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
10283 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
10284 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
10285 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
10286 GENX_(__NR_setgid, sys_setgid),
10287 MACX_(__NR_setegid, setegid),
10288 MACX_(__NR_seteuid, seteuid),
10289 MACX_(__NR_sigreturn, sigreturn),
10290 // _____(__NR_chud),
10291 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
10292 #if DARWIN_VERS >= DARWIN_10_6
10293 // _____(__NR_fdatasync),
10294 #else
10295 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
10296 #endif
10297 GENXY(__NR_stat, sys_newstat),
10298 GENXY(__NR_fstat, sys_newfstat),
10299 GENXY(__NR_lstat, sys_newlstat),
10300 MACX_(__NR_pathconf, pathconf),
10301 MACX_(__NR_fpathconf, fpathconf),
10302 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
10303 GENXY(__NR_getrlimit, sys_getrlimit),
10304 GENX_(__NR_setrlimit, sys_setrlimit),
10305 MACXY(__NR_getdirentries, getdirentries),
10306 MACXY(__NR_mmap, mmap),
10307 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
10308 MACX_(__NR_lseek, lseek),
10309 GENX_(__NR_truncate, sys_truncate64), // 200
10310 GENX_(__NR_ftruncate, sys_ftruncate64),
10311 MACXY(__NR___sysctl, __sysctl),
10312 GENX_(__NR_mlock, sys_mlock),
10313 GENX_(__NR_munlock, sys_munlock),
10314 // _____(__NR_undelete),
10315 // _____(__NR_ATsocket),
10316 // _____(__NR_ATgetmsg),
10317 // _____(__NR_ATputmsg),
10318 // _____(__NR_ATPsndreq),
10319 // _____(__NR_ATPsndrsp),
10320 // _____(__NR_ATPgetreq),
10321 // _____(__NR_ATPgetrsp),
10322 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
10323 #if DARWIN_VERS >= DARWIN_10_6
10324 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
10325 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
10326 #else
10327 // _____(__NR_kqueue_from_portset_np),
10328 // _____(__NR_kqueue_portset_np),
10329 #endif
10330 // _____(__NR_mkcomplex),
10331 // _____(__NR_statv),
10332 // _____(__NR_lstatv),
10333 // _____(__NR_fstatv),
10334 MACXY(__NR_getattrlist, getattrlist), // 220
10335 MACX_(__NR_setattrlist, setattrlist),
10336 MACXY(__NR_getdirentriesattr, getdirentriesattr),
10337 MACX_(__NR_exchangedata, exchangedata),
10338 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
10339 // _____(__NR_searchfs),
10340 GENX_(__NR_delete, sys_unlink),
10341 // _____(__NR_copyfile),
10342 #if DARWIN_VERS >= DARWIN_10_6
10343 // _____(__NR_fgetattrlist),
10344 // _____(__NR_fsetattrlist),
10345 #else
10346 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
10347 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
10348 #endif
10349 GENXY(__NR_poll, sys_poll),
10350 MACX_(__NR_watchevent, watchevent),
10351 MACXY(__NR_waitevent, waitevent),
10352 MACX_(__NR_modwatch, modwatch),
10353 MACXY(__NR_getxattr, getxattr),
10354 MACXY(__NR_fgetxattr, fgetxattr),
10355 MACX_(__NR_setxattr, setxattr),
10356 MACX_(__NR_fsetxattr, fsetxattr),
10357 MACX_(__NR_removexattr, removexattr),
10358 MACX_(__NR_fremovexattr, fremovexattr),
10359 MACXY(__NR_listxattr, listxattr), // 240
10360 MACXY(__NR_flistxattr, flistxattr),
10361 MACXY(__NR_fsctl, fsctl),
10362 MACX_(__NR_initgroups, initgroups),
10363 MACXY(__NR_posix_spawn, posix_spawn),
10364 #if DARWIN_VERS >= DARWIN_10_6
10365 // _____(__NR_ffsctl),
10366 #else
10367 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
10368 #endif
10369 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
10370 // _____(__NR_nfsclnt),
10371 // _____(__NR_fhopen),
10372 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
10373 // _____(__NR_minherit),
10374 // _____(__NR_semsys),
10375 // _____(__NR_msgsys),
10376 // _____(__NR_shmsys),
10377 MACXY(__NR_semctl, semctl),
10378 MACX_(__NR_semget, semget),
10379 MACX_(__NR_semop, semop),
10380 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
10381 // _____(__NR_msgctl),
10382 // _____(__NR_msgget),
10383 // _____(__NR_msgsnd), // 260
10384 // _____(__NR_msgrcv),
10385 MACXY(__NR_shmat, shmat),
10386 MACXY(__NR_shmctl, shmctl),
10387 MACXY(__NR_shmdt, shmdt),
10388 MACX_(__NR_shmget, shmget),
10389 MACXY(__NR_shm_open, shm_open),
10390 MACXY(__NR_shm_unlink, shm_unlink),
10391 MACX_(__NR_sem_open, sem_open),
10392 MACX_(__NR_sem_close, sem_close),
10393 MACX_(__NR_sem_unlink, sem_unlink),
10394 MACX_(__NR_sem_wait, sem_wait),
10395 MACX_(__NR_sem_trywait, sem_trywait),
10396 MACX_(__NR_sem_post, sem_post),
10397 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
10398 // has become sysctlbyname. See below.
10399 MACXY(__NR_sem_init, sem_init),
10400 MACX_(__NR_sem_destroy, sem_destroy),
10401 MACX_(__NR_open_extended, open_extended), // 277
10402 // _____(__NR_umask_extended),
10403 MACXY(__NR_stat_extended, stat_extended),
10404 MACXY(__NR_lstat_extended, lstat_extended), // 280
10405 MACXY(__NR_fstat_extended, fstat_extended),
10406 MACX_(__NR_chmod_extended, chmod_extended),
10407 MACX_(__NR_fchmod_extended,fchmod_extended),
10408 MACXY(__NR_access_extended,access_extended),
10409 MACX_(__NR_settid, settid),
10410 #if DARWIN_VERS >= DARWIN_10_8
10411 MACX_(__NR_gettid, gettid), // 286
10412 #endif
10413 // _____(__NR_setsgroups),
10414 // _____(__NR_getsgroups),
10415 // _____(__NR_setwgroups),
10416 // _____(__NR_getwgroups),
10417 // _____(__NR_mkfifo_extended),
10418 // _____(__NR_mkdir_extended),
10419 // _____(__NR_identitysvc),
10420 // _____(__NR_shared_region_check_np),
10421 // _____(__NR_shared_region_map_np),
10422 #if DARWIN_VERS >= DARWIN_10_6
10423 // _____(__NR_vm_pressure_monitor),
10424 // _____(__NR_psynch_rw_longrdlock),
10425 // _____(__NR_psynch_rw_yieldwrlock),
10426 // _____(__NR_psynch_rw_downgrade),
10427 // _____(__NR_psynch_rw_upgrade),
10428 MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
10429 MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
10430 MACXY(__NR_psynch_cvbroad, psynch_cvbroad), // 303
10431 MACXY(__NR_psynch_cvsignal, psynch_cvsignal), // 304
10432 MACXY(__NR_psynch_cvwait, psynch_cvwait), // 305
10433 MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
10434 MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
10435 MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
10436 // _____(__NR_psynch_rw_unlock2),
10437 #else
10438 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
10439 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
10440 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
10441 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
10442 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
10443 // _____(__NR___pthread_mutex_destroy),
10444 // _____(__NR___pthread_mutex_init),
10445 // _____(__NR___pthread_mutex_lock),
10446 // _____(__NR___pthread_mutex_trylock),
10447 // _____(__NR___pthread_mutex_unlock),
10448 // _____(__NR___pthread_cond_init),
10449 // _____(__NR___pthread_cond_destroy),
10450 // _____(__NR___pthread_cond_broadcast),
10451 // _____(__NR___pthread_cond_signal),
10452 #endif
10453 // _____(__NR_getsid),
10454 // _____(__NR_settid_with_pid),
10455 #if DARWIN_VERS >= DARWIN_10_7
10456 MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
10457 #else
10458 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // old __pthread_cond_timedwait
10459 #endif
10460 // _____(__NR_aio_fsync),
10461 MACXY(__NR_aio_return, aio_return),
10462 MACX_(__NR_aio_suspend, aio_suspend),
10463 // _____(__NR_aio_cancel),
10464 MACX_(__NR_aio_error, aio_error),
10465 MACXY(__NR_aio_read, aio_read),
10466 MACX_(__NR_aio_write, aio_write),
10467 // _____(__NR_lio_listio), // 320
10468 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
10470 #if DARWIN_VERS >= DARWIN_10_8
10471 MACXY(__NR_iopolicysys, iopolicysys),
10472 MACXY(__NR_process_policy, process_policy),
10473 #else
10474 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
10475 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
10476 #endif
10477 // _____(__NR_mlockall),
10478 // _____(__NR_munlockall),
10479 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
10480 MACX_(__NR_issetugid, issetugid),
10481 MACX_(__NR___pthread_kill, __pthread_kill),
10482 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
10483 // _____(__NR___sigwait),
10484 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
10485 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
10486 MACX_(__NR___pthread_canceled, __pthread_canceled),
10487 MACX_(__NR___semwait_signal, __semwait_signal),
10488 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
10489 MACXY(__NR_proc_info, proc_info), // 336
10490 MACXY(__NR_sendfile, sendfile),
10491 MACXY(__NR_stat64, stat64),
10492 MACXY(__NR_fstat64, fstat64),
10493 MACXY(__NR_lstat64, lstat64), // 340
10494 MACXY(__NR_stat64_extended, stat64_extended),
10495 MACXY(__NR_lstat64_extended, lstat64_extended),
10496 MACXY(__NR_fstat64_extended, fstat64_extended),
10497 MACXY(__NR_getdirentries64, getdirentries64),
10498 MACXY(__NR_statfs64, statfs64),
10499 MACXY(__NR_fstatfs64, fstatfs64),
10500 MACXY(__NR_getfsstat64, getfsstat64),
10501 MACX_(__NR___pthread_chdir, __pthread_chdir),
10502 MACX_(__NR___pthread_fchdir, __pthread_fchdir),
10503 // _____(__NR_audit),
10504 MACXY(__NR_auditon, auditon),
10505 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
10506 // _____(__NR_getauid),
10507 // _____(__NR_setauid),
10508 // _____(__NR_getaudit),
10509 // _____(__NR_setaudit),
10510 MACXY(__NR_getaudit_addr, getaudit_addr),
10511 // _____(__NR_setaudit_addr),
10512 // _____(__NR_auditctl),
10513 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
10514 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
10515 MACXY(__NR_kqueue, kqueue),
10516 MACXY(__NR_kevent, kevent),
10517 GENX_(__NR_lchown, sys_lchown),
10518 // _____(__NR_stack_snapshot),
10519 MACX_(__NR_bsdthread_register, bsdthread_register),
10520 MACX_(__NR_workq_open, workq_open),
10521 MACXY(__NR_workq_ops, workq_ops),
10522 #if DARWIN_VERS >= DARWIN_10_6
10523 MACXY(__NR_kevent64, kevent64),
10524 #else
10525 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
10526 #endif
10527 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // old semwait_signal
10528 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // old semwait_signal_nocancel
10529 #if DARWIN_VERS >= DARWIN_10_6
10530 MACX_(__NR___thread_selfid, __thread_selfid),
10531 #else
10532 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
10533 #endif
10534 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
10535 #if DARWIN_VERS < DARWIN_10_11
10536 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
10537 #endif
10538 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
10539 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
10540 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
10541 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
10542 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
10543 // _____(__NR___mac_execve), // 380
10544 MACX_(__NR___mac_syscall, __mac_syscall),
10545 // _____(__NR___mac_get_file),
10546 // _____(__NR___mac_set_file),
10547 // _____(__NR___mac_get_link),
10548 // _____(__NR___mac_set_link),
10549 // _____(__NR___mac_get_proc),
10550 // _____(__NR___mac_set_proc),
10551 // _____(__NR___mac_get_fd),
10552 // _____(__NR___mac_set_fd),
10553 // _____(__NR___mac_get_pid),
10554 // _____(__NR___mac_get_lcid),
10555 // _____(__NR___mac_get_lctx),
10556 // _____(__NR___mac_set_lctx),
10557 // _____(__NR_setlcid),
10558 // _____(__NR_getlcid),
10559 // GrP fixme need any special nocancel handling?
10560 GENXY(__NR_read_nocancel, sys_read),
10561 GENX_(__NR_write_nocancel, sys_write),
10562 GENXY(__NR_open_nocancel, sys_open),
10563 GENXY(__NR_close_nocancel, sys_close),
10564 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
10565 MACXY(__NR_recvmsg_nocancel, recvmsg),
10566 MACX_(__NR_sendmsg_nocancel, sendmsg),
10567 MACXY(__NR_recvfrom_nocancel, recvfrom),
10568 MACXY(__NR_accept_nocancel, accept),
10569 GENX_(__NR_msync_nocancel, sys_msync),
10570 MACXY(__NR_fcntl_nocancel, fcntl),
10571 GENX_(__NR_select_nocancel, sys_select),
10572 GENX_(__NR_fsync_nocancel, sys_fsync),
10573 MACX_(__NR_connect_nocancel, connect),
10574 MACX_(__NR_sigsuspend_nocancel, sigsuspend),
10575 GENXY(__NR_readv_nocancel, sys_readv),
10576 GENX_(__NR_writev_nocancel, sys_writev),
10577 MACX_(__NR_sendto_nocancel, sendto),
10578 GENXY(__NR_pread_nocancel, sys_pread64),
10579 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
10580 // _____(__NR_waitid_nocancel),
10581 GENXY(__NR_poll_nocancel, sys_poll),
10582 // _____(__NR_msgsnd_nocancel),
10583 // _____(__NR_msgrcv_nocancel),
10584 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
10585 // _____(__NR_aio_suspend_nocancel),
10586 // _____(__NR___sigwait_nocancel),
10587 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
10588 // _____(__NR___mac_mount),
10589 // _____(__NR___mac_get_mount),
10590 // _____(__NR___mac_getfsstat),
10591 #if DARWIN_VERS >= DARWIN_10_6
10592 MACXY(__NR_fsgetpath, fsgetpath),
10593 MACXY(__NR_audit_session_self, audit_session_self),
10594 // _____(__NR_audit_session_join),
10595 #endif
10596 #if DARWIN_VERS >= DARWIN_10_9
10597 MACX_(__NR_fileport_makeport, fileport_makeport),
10598 // _____(__NR_fileport_makefd), // 431
10599 // _____(__NR_audit_session_port), // 432
10600 // _____(__NR_pid_suspend), // 433
10601 // _____(__NR_pid_resume), // 434
10602 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(435)), // ???
10603 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(436)), // ???
10604 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(437)), // ???
10605 // _____(__NR_shared_region_map_and_slide_np), // 438
10606 // _____(__NR_kas_info), // 439
10607 // _____(__NR_memorystatus_control), // 440
10608 MACX_(__NR_guarded_open_np, guarded_open_np),
10609 MACX_(__NR_guarded_close_np, guarded_close_np),
10610 MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
10611 MACX_(__NR_change_fdguard_np, change_fdguard_np),
10612 MACX_(__NR_connectx, connectx),
10613 MACX_(__NR_disconnectx, disconnectx),
10614 #endif
10615 #if DARWIN_VERS >= DARWIN_10_10
10616 MACXY(__NR_sysctlbyname, sysctlbyname), // 274
10617 MACXY(__NR_necp_match_policy, necp_match_policy), // 460
10618 MACXY(__NR_getattrlistbulk, getattrlistbulk), // 461
10619 MACX_(__NR_faccessat, faccessat), // 466
10620 MACX_(__NR_fstatat64, fstatat64), // 470
10621 MACX_(__NR_readlinkat, readlinkat), // 473
10622 MACX_(__NR_bsdthread_ctl, bsdthread_ctl), // 478
10623 MACX_(__NR_csrctl, csrctl), // 483
10624 MACX_(__NR_guarded_open_dprotected_np, guarded_open_dprotected_np), // 484
10625 MACX_(__NR_guarded_write_np, guarded_write_np), // 485
10626 MACX_(__NR_guarded_pwrite_np, guarded_pwrite_np), // 486
10627 MACX_(__NR_guarded_writev_np, guarded_writev_np), // 487
10628 // _____(__NR___mremap_encrypted), // 489
10629 #endif
10630 #if DARWIN_VERS >= DARWIN_10_11
10631 // _____(__NR_kdebug_trace_string), // 178
10632 MACXY(__NR_kevent_qos, kevent_qos), // 374
10633 MACX_(__NR_pselect, pselect), // 394
10634 // _____(__NR_netagent_trigger), // 490
10635 // _____(__NR_stack_snapshot_with_config), // 491
10636 // _____(__NR_microstackshot), // 492
10637 // _____(__NR_grab_pgo_data), // 493
10638 // _____(__NR_persona), // 494
10639 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(495)), // ???
10640 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(496)), // ???
10641 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(497)), // ???
10642 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(498)), // ???
10643 // _____(__NR_work_interval_ctl), // 499
10644 #endif
10645 #if DARWIN_VERS >= DARWIN_10_12
10646 // _____(__NR_kdebug_typefilter), // 177
10647 // _____(__NR_clonefileat), // 462
10648 // _____(__NR_renameatx_np), // 488
10649 MACX_(__NR_getentropy, getentropy), // 500
10650 // _____(__NR_necp_open), // 501
10651 // _____(__NR_necp_client_action), // 502
10652 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(503)), // ???
10653 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(504)), // ???
10654 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(505)), // ???
10655 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(506)), // ???
10656 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(507)), // ???
10657 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(508)), // ???
10658 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(509)), // ???
10659 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(510)), // ???
10660 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(511)), // ???
10661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(512)), // ???
10662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(513)), // ???
10663 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(514)), // ???
10664 MACX_(__NR_ulock_wait, ulock_wait), // 515
10665 MACX_(__NR_ulock_wake, ulock_wake), // 516
10666 // _____(__NR_fclonefileat), // 517
10667 // _____(__NR_fs_snapshot), // 518
10668 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(519)), // ???
10669 // _____(__NR_terminate_with_payload), // 520
10670 // _____(__NR_abort_with_payload), // 521
10671 #endif
10672 #if DARWIN_VERS >= DARWIN_10_13
10673 // _____(__NR_thread_selfcounts), // 186
10674 // _____(__NR_kevent_id, // 375
10675 // _____(__NR_necp_session_open), // 522
10676 // _____(__NR_necp_session_action), // 523
10677 // _____(__NR_setattrlistat), // 524
10678 // _____(__NR_net_qos_guideline), // 525
10679 // _____(__NR_fmount), // 526
10680 // _____(__NR_ntp_adjtime), // 527
10681 // _____(__NR_ntp_gettime), // 528
10682 // _____(__NR_os_fault_with_payload), // 529
10683 #endif
10684 // _____(__NR_MAXSYSCALL)
10685 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
10689 // Mach traps use negative syscall numbers.
10690 // Use ML_(mach_trap_table)[-mach_trap_number] .
10691 // cf xnu sources osfmk/kern/syscall_sw.c
10693 const SyscallTableEntry ML_(mach_trap_table)[] = {
10694 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
10695 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
10696 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
10697 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
10698 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
10699 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
10700 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
10701 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
10702 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
10703 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
10705 # if DARWIN_VERS >= DARWIN_10_8
10706 MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
10707 # else
10708 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
10709 # endif
10711 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
10713 # if DARWIN_VERS >= DARWIN_10_8
10714 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
10715 # else
10716 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
10717 # endif
10719 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
10721 # if DARWIN_VERS >= DARWIN_10_8
10722 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
10723 # endif
10725 # if DARWIN_VERS >= DARWIN_10_9
10726 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
10727 # endif
10729 # if DARWIN_VERS < DARWIN_10_8
10730 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
10731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
10732 # endif
10734 # if DARWIN_VERS >= DARWIN_10_8
10735 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
10736 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
10737 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
10738 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
10739 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
10740 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
10741 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
10742 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
10743 # else
10744 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
10745 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
10746 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
10747 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
10748 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
10749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
10750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
10751 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
10752 # endif
10754 # if DARWIN_VERS >= DARWIN_10_9
10755 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
10756 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
10757 # else
10758 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
10759 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
10760 # endif
10762 MACXY(__NR_mach_reply_port, mach_reply_port),
10763 MACXY(__NR_thread_self_trap, mach_thread_self),
10764 MACXY(__NR_task_self_trap, mach_task_self),
10765 MACXY(__NR_host_self_trap, mach_host_self),
10766 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
10767 MACXY(__NR_mach_msg_trap, mach_msg),
10768 // _____(__NR_mach_msg_overwrite_trap),
10769 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
10770 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
10771 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
10772 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
10773 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
10774 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
10775 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
10776 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
10778 # if DARWIN_VERS >= DARWIN_10_9
10779 MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
10780 MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
10781 # else
10782 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
10783 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
10784 # endif
10786 # if DARWIN_VERS >= DARWIN_10_12
10787 MACXY(__NR_mach_generate_activity_id, mach_generate_activity_id),
10788 # elif DARWIN_VERS >= DARWIN_10_10
10789 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10790 # elif defined(VGA_x86) || DARWIN_VERS == DARWIN_10_9
10791 // _____(__NR_map_fd),
10792 # else
10793 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10794 # endif
10796 // _____(__NR_task_name_for_pid),
10797 MACXY(__NR_task_for_pid, task_for_pid),
10798 MACXY(__NR_pid_for_task, pid_for_task),
10799 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
10800 #if defined(VGA_x86)
10801 // _____(__NR_macx_swapon),
10802 // _____(__NR_macx_swapoff),
10803 #else
10804 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
10805 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
10806 #endif
10807 #if DARWIN_VERS >= DARWIN_10_13
10808 // _____(__NR_thread_get_special_reply_port, // 50
10809 #else
10810 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10811 #endif /* DARWIN_VERS >= DARWIN_10_13 */
10812 #if defined(VGA_x86)
10813 // _____(__NR_macx_triggers),
10814 // _____(__NR_macx_backing_store_suspend),
10815 // _____(__NR_macx_backing_store_recovery),
10816 #else
10817 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
10818 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
10819 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
10820 #endif
10821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
10822 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
10823 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
10824 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
10825 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
10826 MACX_(__NR_swtch_pri, swtch_pri),
10827 MACX_(__NR_swtch, swtch), // -60
10828 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
10829 // _____(__NR_clock_sleep_trap),
10830 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
10831 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
10832 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
10833 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
10834 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
10835 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
10836 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
10837 #if DARWIN_VERS >= DARWIN_10_12
10838 MACX_(__NR_host_create_mach_voucher_trap, host_create_mach_voucher_trap),
10839 #else
10840 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
10841 #endif
10842 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
10843 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
10844 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
10845 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
10846 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
10847 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
10848 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
10849 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
10850 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
10851 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
10852 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
10853 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
10854 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
10855 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
10856 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
10857 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
10858 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
10859 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
10860 MACXY(__NR_mach_timebase_info, mach_timebase_info),
10861 MACX_(__NR_mach_wait_until, mach_wait_until),
10862 MACXY(__NR_mk_timer_create, mk_timer_create),
10863 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
10864 MACX_(__NR_mk_timer_arm, mk_timer_arm),
10865 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
10866 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
10867 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
10868 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
10869 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
10870 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
10871 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
10875 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
10876 // calling convention instead of the syscall convention.
10877 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
10879 #if defined(VGA_x86)
10880 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10881 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10883 #elif defined(VGA_amd64)
10884 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10885 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10887 #else
10888 #error unknown architecture
10889 #endif
10891 const UInt ML_(syscall_table_size) =
10892 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
10894 const UInt ML_(mach_trap_table_size) =
10895 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
10897 const UInt ML_(mdep_trap_table_size) =
10898 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
10900 #endif // defined(VGO_darwin)
10902 /*--------------------------------------------------------------------*/
10903 /*--- end ---*/
10904 /*--------------------------------------------------------------------*/