FreeBSD: add file descriptor tracking for _umtx_op
[valgrind.git] / coregrind / m_syswrap / syswrap-darwin.c
blob6b0f5914950141535a0088c38e9a2a1ebd01f69d
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 // Retrieve the current Mach thread
1087 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1089 // Set the POST handler for a mach_msg derivative
1090 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1092 // Set or get values saved from Mach messages
1093 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
1094 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
1095 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
1097 /* ---------------------------------------------------------------------
1098 darwin ioctl wrapper
1099 ------------------------------------------------------------------ */
1101 PRE(ioctl)
1103 *flags |= SfMayBlock;
1105 /* Handle ioctls that don't take an arg first */
1106 switch (ARG2 /* request */) {
1107 case VKI_TIOCSCTTY:
1108 case VKI_TIOCEXCL:
1109 case VKI_TIOCSBRK:
1110 case VKI_TIOCCBRK:
1111 case VKI_TIOCPTYGRANT:
1112 case VKI_TIOCPTYUNLK:
1113 case VKI_DTRACEHIOC_REMOVE:
1114 case VKI_BIOCFLUSH:
1115 case VKI_BIOCPROMISC:
1116 PRINT("ioctl ( %lu, 0x%lx )", ARG1, ARG2);
1117 PRE_REG_READ2(long, "ioctl",
1118 unsigned int, fd, unsigned int, request);
1119 return;
1120 default:
1121 PRINT("ioctl ( %lu, 0x%lx, %#lx )", ARG1, ARG2, ARG3);
1122 PRE_REG_READ3(long, "ioctl",
1123 unsigned int, fd, unsigned int, request, unsigned long, arg);
1126 switch (ARG2 /* request */) {
1127 case VKI_TIOCGWINSZ:
1128 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
1129 break;
1130 case VKI_TIOCSWINSZ:
1131 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
1132 break;
1133 case VKI_TIOCMBIS:
1134 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
1135 break;
1136 case VKI_TIOCMBIC:
1137 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
1138 break;
1139 case VKI_TIOCMSET:
1140 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
1141 break;
1142 case VKI_TIOCMGET:
1143 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
1144 break;
1145 case VKI_TIOCGPGRP:
1146 /* Get process group ID for foreground processing group. */
1147 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1148 break;
1149 case VKI_TIOCSPGRP:
1150 /* Set a process group ID? */
1151 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1152 break;
1153 case VKI_FIONBIO:
1154 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
1155 break;
1156 case VKI_FIOASYNC:
1157 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
1158 break;
1159 case VKI_FIONREAD: /* identical to SIOCINQ */
1160 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1161 break;
1164 /* These all use struct ifreq AFAIK */
1165 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1166 case VKI_SIOCGIFFLAGS: /* get flags */
1167 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1168 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1169 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
1170 break;
1171 case VKI_SIOCGIFMTU: /* get MTU size */
1172 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1173 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1174 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
1175 break;
1176 case VKI_SIOCGIFADDR: /* get PA address */
1177 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1178 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1179 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
1180 break;
1181 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1182 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1183 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1184 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
1185 break;
1186 case VKI_SIOCGIFMETRIC: /* get metric */
1187 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1188 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1189 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
1190 break;
1191 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1192 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1193 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1194 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
1195 break;
1196 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1197 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1198 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1199 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
1200 break;
1201 case VKI_SIOCGIFCONF: /* get iface list */
1202 /* WAS:
1203 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1204 KERNEL_DO_SYSCALL(tid,RES);
1205 if (!VG_(is_kerror)(RES) && RES == 0)
1206 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1208 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1209 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
1210 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
1211 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1212 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
1213 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
1214 if ( ARG3 ) {
1215 // TODO len must be readable and writable
1216 // buf pointer only needs to be readable
1217 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1218 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1219 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1221 break;
1223 case VKI_SIOCSIFFLAGS: /* set flags */
1224 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1225 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1226 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1227 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1228 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1229 break;
1230 case VKI_SIOCSIFADDR: /* set PA address */
1231 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1232 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1233 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1234 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1235 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1236 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1237 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1238 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1239 break;
1240 case VKI_SIOCSIFMETRIC: /* set metric */
1241 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1242 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1243 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1244 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1245 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1246 break;
1247 case VKI_SIOCSIFMTU: /* set MTU size */
1248 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1249 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1250 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1251 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1252 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1253 break;
1254 /* Routing table calls. */
1255 #ifdef VKI_SIOCADDRT
1256 case VKI_SIOCADDRT: /* add routing table entry */
1257 case VKI_SIOCDELRT: /* delete routing table entry */
1258 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
1259 sizeof(struct vki_rtentry));
1260 break;
1261 #endif
1263 case VKI_SIOCGPGRP:
1264 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
1265 break;
1266 case VKI_SIOCSPGRP:
1267 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
1268 //tst->sys_flags &= ~SfMayBlock;
1269 break;
1271 case VKI_FIODTYPE:
1272 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1273 break;
1275 case VKI_DTRACEHIOC_ADDDOF:
1276 break;
1278 // ttycom.h
1279 case VKI_TIOCGETA:
1280 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
1281 break;
1282 case VKI_TIOCSETA:
1283 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
1284 break;
1285 case VKI_TIOCGETD:
1286 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
1287 break;
1288 case VKI_TIOCSETD:
1289 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
1290 break;
1291 case VKI_TIOCPTYGNAME:
1292 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
1293 break;
1295 // filio.h
1296 case VKI_FIOCLEX:
1297 break;
1298 case VKI_FIONCLEX:
1299 break;
1301 // net/bpf.h
1302 case VKI_BIOCSETF: /* set BPF filter */
1304 * struct bpf_program has a 32-bit count of instructions,
1305 * followed by a pointer to an array of those instructions.
1306 * In 64-bit mode, there's padding between those two elements.
1308 * So that we don't bogusly complain about the padding bytes,
1309 * we just report that we read bf_len and and bf_insns.
1311 * We then make sure that what bf_insns points to is valid.
1313 PRE_MEM_READ( "ioctl(BIOCSETF)",
1314 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_len,
1315 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_len) );
1316 PRE_MEM_READ( "ioctl(BIOCSETF)",
1317 (Addr)&((struct vki_bpf_program *)ARG3)->vki_bf_insns,
1318 sizeof(((struct vki_bpf_program *)ARG3)->vki_bf_insns) );
1319 if ( ARG3 ) {
1320 /* bf_len * sizeof (*bf_insns) */
1321 struct vki_bpf_program *bp = (struct vki_bpf_program *)ARG3;
1322 if ( bp->bf_insns != NULL )
1323 PRE_MEM_READ( "ioctl(BIOCSETF) points to a struct bpf_program whose bf_insns member",
1324 (Addr)(bp->vki_bf_insns),
1325 bp->vki_bf_len * sizeof(*bp->vki_bf_insns) );
1327 break;
1328 case VKI_BIOCSETIF: /* set BPF interface */
1329 PRE_MEM_RASCIIZ( "ioctl(BIOCSETIF)",
1330 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1331 break;
1332 case VKI_BIOCSRTIMEOUT: /* set BPF timeout */
1334 * 64-bit struct timeval starts with a 64-bit "seconds since the
1335 * Epoch" value, followed by a 32-bit microseconds value. The
1336 * resulting structure is padded to a multiple of 8 bytes, so
1337 * there are 4 padding bytes at the end.
1339 * So that we don't bogusly complain about the padding bytes,
1340 * we just report that we read tv_sec and tv_usec.
1342 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1343 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_sec,
1344 sizeof(((struct vki_timeval *)ARG3)->vki_tv_sec) );
1345 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1346 (Addr)&((struct vki_timeval *)ARG3)->vki_tv_usec,
1347 sizeof(((struct vki_timeval *)ARG3)->vki_tv_usec) );
1348 break;
1349 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1350 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1351 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list,
1352 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_list) );
1353 if ( ARG3 ) {
1354 /* bfl_len * sizeof (*bfl_list) */
1355 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1356 if ( bdl->bfl_list != NULL )
1357 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1358 (Addr)&((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len,
1359 sizeof(((struct vki_bpf_dltlist *)ARG3)->vki_bfl_len) );
1360 PRE_MEM_WRITE( "ioctl(BIOCGDLTLIST) points to a struct bpf_dltlist whose bfl_list member",
1361 (Addr)(bdl->vki_bfl_list),
1362 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1364 break;
1366 default:
1367 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
1368 break;
1373 POST(ioctl)
1375 vg_assert(SUCCESS);
1376 switch (ARG2 /* request */) {
1377 case VKI_TIOCGWINSZ:
1378 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
1379 break;
1380 case VKI_TIOCSWINSZ:
1381 case VKI_TIOCMBIS:
1382 case VKI_TIOCMBIC:
1383 case VKI_TIOCMSET:
1384 break;
1385 case VKI_TIOCMGET:
1386 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
1387 break;
1388 case VKI_TIOCGPGRP:
1389 /* Get process group ID for foreground processing group. */
1390 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1391 break;
1392 case VKI_TIOCSPGRP:
1393 /* Set a process group ID? */
1394 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1395 break;
1396 case VKI_TIOCSCTTY:
1397 break;
1398 case VKI_FIONBIO:
1399 break;
1400 case VKI_FIOASYNC:
1401 break;
1402 case VKI_FIONREAD: /* identical to SIOCINQ */
1403 POST_MEM_WRITE( ARG3, sizeof(int) );
1404 break;
1406 /* These all use struct ifreq AFAIK */
1407 case VKI_SIOCGIFFLAGS: /* get flags */
1408 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1409 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1410 break;
1411 case VKI_SIOCGIFMTU: /* get MTU size */
1412 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1413 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1414 break;
1415 case VKI_SIOCGIFADDR: /* get PA address */
1416 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1417 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1418 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1419 POST_MEM_WRITE(
1420 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1421 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1422 break;
1423 case VKI_SIOCGIFMETRIC: /* get metric */
1424 POST_MEM_WRITE(
1425 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1426 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1427 break;
1428 case VKI_SIOCGIFCONF: /* get iface list */
1429 /* WAS:
1430 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1431 KERNEL_DO_SYSCALL(tid,RES);
1432 if (!VG_(is_kerror)(RES) && RES == 0)
1433 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1435 if (RES == 0 && ARG3 ) {
1436 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1437 if (ifc->vki_ifc_buf != NULL)
1438 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1440 break;
1442 case VKI_SIOCSIFFLAGS: /* set flags */
1443 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1444 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1445 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1446 case VKI_SIOCSIFMETRIC: /* set metric */
1447 case VKI_SIOCSIFADDR: /* set PA address */
1448 case VKI_SIOCSIFMTU: /* set MTU size */
1449 break;
1451 #ifdef VKI_SIOCADDRT
1452 /* Routing table calls. */
1453 case VKI_SIOCADDRT: /* add routing table entry */
1454 case VKI_SIOCDELRT: /* delete routing table entry */
1455 break;
1456 #endif
1458 case VKI_SIOCGPGRP:
1459 POST_MEM_WRITE(ARG3, sizeof(int));
1460 break;
1461 case VKI_SIOCSPGRP:
1462 break;
1464 case VKI_FIODTYPE:
1465 POST_MEM_WRITE( ARG3, sizeof(int) );
1466 break;
1468 case VKI_DTRACEHIOC_REMOVE:
1469 case VKI_DTRACEHIOC_ADDDOF:
1470 break;
1472 // ttycom.h
1473 case VKI_TIOCGETA:
1474 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1475 break;
1476 case VKI_TIOCSETA:
1477 break;
1478 case VKI_TIOCGETD:
1479 POST_MEM_WRITE( ARG3, sizeof(int) );
1480 break;
1481 case VKI_TIOCSETD:
1482 break;
1483 case VKI_TIOCPTYGNAME:
1484 POST_MEM_WRITE( ARG3, 128);
1485 break;
1486 case VKI_TIOCSBRK: /* set break bit */
1487 case VKI_TIOCCBRK: /* clear break bit */
1488 case VKI_TIOCPTYGRANT:
1489 case VKI_TIOCPTYUNLK:
1490 break;
1492 // bpf.h
1493 case VKI_BIOCGDLTLIST: /* get list of BPF DLTs */
1494 if (RES == 0 && ARG3 ) {
1495 /* bfl_len * sizeof (*bfl_list) */
1496 struct vki_bpf_dltlist *bdl = (struct vki_bpf_dltlist *)ARG3;
1497 if ( bdl->vki_bfl_list != NULL )
1498 POST_MEM_WRITE( (Addr)(bdl->vki_bfl_list),
1499 bdl->bfl_len * sizeof(*bdl->vki_bfl_list) );
1501 break;
1503 default:
1504 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
1505 break;
1510 /* ---------------------------------------------------------------------
1511 darwin fcntl wrapper
1512 ------------------------------------------------------------------ */
1513 static const HChar *name_for_fcntl(UWord cmd) {
1514 #define F(n) case VKI_##n: return #n
1515 switch (cmd) {
1516 F(F_CHKCLEAN);
1517 F(F_RDAHEAD);
1518 F(F_NOCACHE);
1519 F(F_FULLFSYNC);
1520 F(F_FREEZE_FS);
1521 F(F_THAW_FS);
1522 F(F_GLOBAL_NOCACHE);
1523 F(F_PREALLOCATE);
1524 F(F_SETSIZE);
1525 F(F_RDADVISE);
1526 # if DARWIN_VERS < DARWIN_10_9
1527 F(F_READBOOTSTRAP);
1528 F(F_WRITEBOOTSTRAP);
1529 # endif
1530 F(F_LOG2PHYS);
1531 F(F_GETPATH);
1532 F(F_PATHPKG_CHECK);
1533 F(F_ADDSIGS);
1534 # if DARWIN_VERS >= DARWIN_10_9
1535 F(F_ADDFILESIGS);
1536 # endif
1537 # if DARWIN_VERS >= DARWIN_10_11
1538 F(F_ADDFILESIGS_FOR_DYLD_SIM);
1539 F(F_BARRIERFSYNC);
1540 F(F_ADDFILESIGS_RETURN);
1541 # endif
1542 default:
1543 return "UNKNOWN";
1545 #undef F
1548 PRE(fcntl)
1550 switch (ARG2) {
1551 // These ones ignore ARG3.
1552 case VKI_F_GETFD:
1553 case VKI_F_GETFL:
1554 case VKI_F_GETOWN:
1555 PRINT("fcntl ( %lu, %lu )", ARG1,ARG2);
1556 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1557 break;
1559 // These ones use ARG3 as "arg".
1560 case VKI_F_DUPFD:
1561 case VKI_F_SETFD:
1562 case VKI_F_SETFL:
1563 case VKI_F_SETOWN:
1564 PRINT("fcntl[ARG3=='arg'] ( %lu, %lu, %lu )", ARG1,ARG2,ARG3);
1565 PRE_REG_READ3(long, "fcntl",
1566 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1567 break;
1569 // These ones use ARG3 as "lock".
1570 case VKI_F_GETLK:
1571 case VKI_F_SETLK:
1572 case VKI_F_SETLKW:
1573 PRINT("fcntl[ARG3=='lock'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1574 PRE_REG_READ3(long, "fcntl",
1575 unsigned int, fd, unsigned int, cmd,
1576 struct flock64 *, lock);
1577 // GrP fixme mem read sizeof(flock64)
1578 if (ARG2 == VKI_F_SETLKW)
1579 *flags |= SfMayBlock;
1580 break;
1581 # if DARWIN_VERS >= DARWIN_10_10
1582 case VKI_F_SETLKWTIMEOUT:
1583 PRINT("fcntl[ARG3=='locktimeout'] ( %lu, %lu, %#lx )", ARG1,ARG2,ARG3);
1584 PRE_REG_READ3(long, "fcntl",
1585 unsigned int, fd, unsigned int, cmd,
1586 struct flocktimeout *, lock);
1587 *flags |= SfMayBlock;
1588 break;
1589 # endif
1591 // none
1592 case VKI_F_CHKCLEAN:
1593 case VKI_F_RDAHEAD:
1594 case VKI_F_NOCACHE:
1595 case VKI_F_FULLFSYNC:
1596 case VKI_F_FREEZE_FS:
1597 case VKI_F_THAW_FS:
1598 case VKI_F_GLOBAL_NOCACHE:
1599 PRINT("fcntl ( %lu, %s, %lu )", ARG1, name_for_fcntl(ARG1), ARG2);
1600 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1601 break;
1603 // struct fstore
1604 case VKI_F_PREALLOCATE:
1605 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1606 PRE_REG_READ3(long, "fcntl",
1607 unsigned int, fd, unsigned int, cmd,
1608 struct fstore *, fstore);
1610 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1611 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1612 fstore->fst_flags );
1613 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1614 fstore->fst_posmode );
1615 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1616 fstore->fst_offset );
1617 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1618 fstore->fst_length );
1619 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1620 fstore->fst_bytesalloc);
1622 break;
1624 // off_t
1625 case VKI_F_SETSIZE:
1626 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1627 PRE_REG_READ3(long, "fcntl",
1628 unsigned int, fd, unsigned int, cmd,
1629 vki_off_t *, offset);
1630 break;
1632 // struct radvisory
1633 case VKI_F_RDADVISE:
1634 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1635 PRE_REG_READ3(long, "fcntl",
1636 unsigned int, fd, unsigned int, cmd,
1637 struct vki_radvisory *, radvisory);
1639 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3;
1640 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1641 radvisory->ra_offset );
1642 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1643 radvisory->ra_count );
1645 break;
1647 # if DARWIN_VERS < DARWIN_10_9
1648 // struct fbootstraptransfer
1649 case VKI_F_READBOOTSTRAP:
1650 case VKI_F_WRITEBOOTSTRAP:
1651 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1652 PRE_REG_READ3(long, "fcntl",
1653 unsigned int, fd, unsigned int, cmd,
1654 struct fbootstraptransfer *, bootstrap);
1655 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1656 ARG3, sizeof(struct vki_fbootstraptransfer) );
1657 break;
1658 # endif
1660 // struct log2phys (out)
1661 case VKI_F_LOG2PHYS:
1662 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1663 PRE_REG_READ3(long, "fcntl",
1664 unsigned int, fd, unsigned int, cmd,
1665 struct log2phys *, l2p);
1666 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1667 ARG3, sizeof(struct vki_log2phys) );
1668 break;
1670 // char[maxpathlen] (out)
1671 case VKI_F_GETPATH:
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 char *, pathbuf);
1676 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1677 ARG3, VKI_MAXPATHLEN );
1678 break;
1680 // char[maxpathlen] (in)
1681 case VKI_F_PATHPKG_CHECK:
1682 PRINT("fcntl ( %lu, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1683 (HChar *)ARG3);
1684 PRE_REG_READ3(long, "fcntl",
1685 unsigned int, fd, unsigned int, cmd,
1686 char *, pathbuf);
1687 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1688 break;
1690 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */
1691 PRINT("fcntl ( %lu, %s )", ARG1, name_for_fcntl(ARG2));
1692 PRE_REG_READ3(long, "fcntl",
1693 unsigned int, fd, unsigned int, cmd,
1694 vki_fsignatures_t *, sigs);
1697 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1698 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1699 fsigs->fs_blob_start);
1700 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1701 fsigs->fs_blob_size);
1703 if (fsigs->fs_blob_start)
1704 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1705 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size);
1707 break;
1709 case VKI_F_ADDFILESIGS: /* Add signature from same file (used by dyld for shared libs) */
1710 PRINT("fcntl ( %lu, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1711 PRE_REG_READ3(long, "fcntl",
1712 unsigned int, fd, unsigned int, cmd,
1713 vki_fsignatures_t *, sigs);
1716 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3;
1717 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1718 fsigs->fs_blob_start);
1719 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1720 fsigs->fs_blob_size);
1722 break;
1724 # if DARWIN_VERS >= DARWIN_10_11
1725 case VKI_F_ADDFILESIGS_FOR_DYLD_SIM: /* Add signature from same file, only if it is signed
1726 by Apple used by dyld for simulator */
1727 // FIXME: RK
1728 break;
1730 case VKI_F_BARRIERFSYNC: /* fsync + issue barrier to drive */
1731 // FIXME: RK
1732 break;
1734 case VKI_F_ADDFILESIGS_RETURN: /* Add signature from same file, return end offset in
1735 structure on success */
1736 // FIXME: RK
1737 break;
1738 # endif
1740 default:
1741 PRINT("fcntl ( %lu, %lu [??] )", ARG1, ARG2);
1742 log_decaying("UNKNOWN fcntl %lu!", ARG2);
1743 break;
1747 POST(fcntl)
1749 vg_assert(SUCCESS);
1750 switch (ARG2) {
1751 case VKI_F_DUPFD:
1752 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1753 VG_(close)(RES);
1754 SET_STATUS_Failure( VKI_EMFILE );
1755 } else {
1756 if (VG_(clo_track_fds))
1757 ML_(record_fd_open_named)(tid, RES);
1759 break;
1761 case VKI_F_GETFD:
1762 case VKI_F_GETFL:
1763 case VKI_F_GETOWN:
1764 case VKI_F_SETFD:
1765 case VKI_F_SETFL:
1766 case VKI_F_SETOWN:
1767 case VKI_F_GETLK:
1768 case VKI_F_SETLK:
1769 case VKI_F_SETLKW:
1770 # if DARWIN_VERS >= DARWIN_10_10
1771 case VKI_F_SETLKWTIMEOUT:
1772 break;
1773 # endif
1775 case VKI_F_PREALLOCATE:
1777 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1778 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1780 break;
1782 case VKI_F_LOG2PHYS:
1783 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1784 break;
1786 case VKI_F_GETPATH:
1787 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1788 PRINT("\"%s\"", (char*)ARG3);
1789 break;
1791 default:
1792 // DDD: ugh, missing lots of cases here, not nice
1793 break;
1797 /* ---------------------------------------------------------------------
1798 unix syscalls
1799 ------------------------------------------------------------------ */
1801 PRE(futimes)
1803 PRINT("futimes ( %ld, %#lx )", SARG1, ARG2);
1804 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp);
1805 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) {
1806 SET_STATUS_Failure( VKI_EBADF );
1807 } else if (ARG2 != 0) {
1808 PRE_timeval_READ( "futimes(tvp[0])", ARG2 );
1809 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) );
1813 PRE(semget)
1815 PRINT("semget ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1816 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1819 PRE(semop)
1821 *flags |= SfMayBlock;
1822 PRINT("semop ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
1823 PRE_REG_READ3(long, "semop",
1824 int, semid, struct sembuf *, sops, vki_size_t, nsoops);
1825 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
1828 PRE(semctl)
1830 switch (ARG3) {
1831 case VKI_IPC_STAT:
1832 case VKI_IPC_SET:
1833 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1834 PRE_REG_READ4(long, "semctl",
1835 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1836 break;
1837 case VKI_GETALL:
1838 case VKI_SETALL:
1839 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1840 PRE_REG_READ4(long, "semctl",
1841 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1842 break;
1843 case VKI_SETVAL:
1844 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
1845 PRE_REG_READ4(long, "semctl",
1846 int, semid, int, semnum, int, cmd, int, arg);
1847 break;
1848 default:
1849 PRINT("semctl ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
1850 PRE_REG_READ3(long, "semctl",
1851 int, semid, int, semnum, int, cmd);
1852 break;
1854 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1856 POST(semctl)
1858 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1861 PRE(sem_open)
1863 if (ARG2 & VKI_O_CREAT) {
1864 // 4-arg version
1865 PRINT("sem_open ( %#lx(%s), %ld, %lu, %lu )",
1866 ARG1, (HChar*)ARG1, SARG2, ARG3, ARG4);
1867 PRE_REG_READ4(vki_sem_t *, "sem_open",
1868 const char *, name, int, oflag, vki_mode_t, mode,
1869 unsigned int, value);
1870 } else {
1871 // 2-arg version
1872 PRINT("sem_open ( %#lx(%s), %ld )", ARG1, (HChar*)ARG1, SARG2);
1873 PRE_REG_READ2(vki_sem_t *, "sem_open",
1874 const char *, name, int, oflag);
1876 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1878 /* Otherwise handle normally */
1879 *flags |= SfMayBlock;
1882 PRE(sem_close)
1884 PRINT("sem_close( %#lx )", ARG1);
1885 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1888 PRE(sem_unlink)
1890 PRINT("sem_unlink( %#lx(%s) )", ARG1, (HChar*)ARG1);
1891 PRE_REG_READ1(int, "sem_unlink", const char *, name);
1892 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 );
1895 PRE(sem_post)
1897 PRINT("sem_post( %#lx )", ARG1);
1898 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1899 *flags |= SfMayBlock;
1902 PRE(sem_destroy)
1904 PRINT("sem_destroy( %#lx )", ARG1);
1905 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem);
1906 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t));
1909 PRE(sem_init)
1911 PRINT("sem_init( %#lx, %ld, %lu )", ARG1, SARG2, ARG3);
1912 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem,
1913 int, pshared, unsigned int, value);
1914 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t));
1917 POST(sem_init)
1919 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1922 PRE(sem_wait)
1924 PRINT("sem_wait( %#lx )", ARG1);
1925 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1926 *flags |= SfMayBlock;
1929 PRE(sem_trywait)
1931 PRINT("sem_trywait( %#lx )", ARG1);
1932 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1933 *flags |= SfMayBlock;
1936 PRE(kqueue)
1938 PRINT("kqueue()");
1941 POST(kqueue)
1943 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1944 VG_(close)(RES);
1945 SET_STATUS_Failure( VKI_EMFILE );
1946 } else {
1947 if (VG_(clo_track_fds)) {
1948 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1953 PRE(fileport_makeport)
1955 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1956 ARG1, ARG2);
1959 PRE(guarded_open_np)
1961 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1962 ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1965 PRE(guarded_kqueue_np)
1967 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1968 ARG1, ARG2);
1971 POST(guarded_kqueue_np)
1973 if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1974 VG_(close)(RES);
1975 SET_STATUS_Failure( VKI_EMFILE );
1976 } else {
1977 if (VG_(clo_track_fds)) {
1978 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1983 PRE(guarded_close_np)
1985 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1986 ARG1, ARG2);
1989 PRE(change_fdguard_np)
1991 PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
1992 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
1995 PRE(connectx)
1997 PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
1998 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
2001 PRE(disconnectx)
2003 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
2004 ARG1, ARG2, ARG3);
2008 PRE(kevent)
2010 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2011 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2012 PRE_REG_READ6(int,"kevent", int,kq,
2013 const struct vki_kevent *,changelist, int,nchanges,
2014 struct vki_kevent *,eventlist, int,nevents,
2015 const struct vki_timespec *,timeout);
2017 if (ARG3) PRE_MEM_READ ("kevent(changelist)",
2018 ARG2, ARG3 * sizeof(struct vki_kevent));
2019 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)",
2020 ARG4, ARG5 * sizeof(struct vki_kevent));
2021 if (ARG6) PRE_MEM_READ ("kevent(timeout)",
2022 ARG6, sizeof(struct vki_timespec));
2024 *flags |= SfMayBlock;
2027 POST(kevent)
2029 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent));
2030 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent));
2034 PRE(kevent64)
2036 PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2037 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6);
2038 PRE_REG_READ6(int,"kevent64", int,kq,
2039 const struct vki_kevent64 *,changelist, int,nchanges,
2040 struct vki_kevent64 *,eventlist, int,nevents,
2041 const struct vki_timespec *,timeout);
2043 if (ARG3) PRE_MEM_READ ("kevent64(changelist)",
2044 ARG2, ARG3 * sizeof(struct vki_kevent64));
2045 if (ARG5) PRE_MEM_WRITE("kevent64(eventlist)",
2046 ARG4, ARG5 * sizeof(struct vki_kevent64));
2047 if (ARG6) PRE_MEM_READ ("kevent64(timeout)",
2048 ARG6, sizeof(struct vki_timespec));
2050 *flags |= SfMayBlock;
2053 POST(kevent64)
2055 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
2056 if (RES > 0) {
2057 ML_(sync_mappings)("after", "kevent64", 0);
2058 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
2063 Addr pthread_starter = 0;
2064 Addr wqthread_starter = 0;
2065 SizeT pthread_structsize = 0;
2066 SizeT pthread_tsd_offset = 0;
2068 PRE(bsdthread_register)
2070 #if DARWIN_VERS >= DARWIN_10_12
2071 PRINT("bsdthread_register( %#lx, %#lx, %lu, %#lx, %#lx, %#lx, %#lx )",
2072 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
2073 PRE_REG_READ7(int,"__bsdthread_register", void *,"threadstart",
2074 void *,"wqthread", size_t,"pthsize",
2075 void *,"stack_addr_hint", void *,"targetconc_ptr",
2076 uint32_t,"dispatchqueue_offset", uint32_t,"tsd_offset");
2077 #else
2078 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3);
2079 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
2080 void *,"wqthread", size_t,"pthsize");
2081 #endif
2083 pthread_starter = ARG1;
2084 wqthread_starter = ARG2;
2085 pthread_structsize = ARG3;
2086 #if DARWIN_VERS >= DARWIN_10_12
2087 typedef struct {
2088 uint64_t version;
2089 uint64_t dispatch_queue_offset;
2090 uint64_t main_qos;
2091 uint32_t tsd_offset;
2092 uint32_t return_to_kernel_offset;
2093 uint32_t mach_thread_self_offset;
2094 } __attribute__ ((packed)) _pthread_registration_data;
2096 pthread_tsd_offset = ((_pthread_registration_data*) ARG4)->tsd_offset;
2097 #endif
2098 ARG1 = (Word)&pthread_hijack_asm;
2099 ARG2 = (Word)&wqthread_hijack_asm;
2102 PRE(workq_open)
2104 PRINT("workq_open()");
2105 PRE_REG_READ0(int, "workq_open");
2107 // This creates lots of threads and thread stacks under the covers,
2108 // but we ignore them all until some work item starts running on it.
2111 static const HChar *workqop_name(int op)
2113 switch (op) {
2114 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
2115 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
2116 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
2117 case VKI_WQOPS_THREAD_SETCONC: return "THREAD_SETCONC";
2118 case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
2119 case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
2120 case VKI_WQOPS_QUEUE_REQTHREADS2: return "QUEUE_REQTHREADS2";
2121 case VKI_WQOPS_THREAD_KEVENT_RETURN: return "THREAD_KEVENT_RETURN";
2122 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY: return "SET_EVENT_MANAGER_PRIORITY";
2123 case VKI_WQOPS_THREAD_WORKLOOP_RETURN: return "THREAD_WORKLOOP_RETURN";
2124 case VKI_WQOPS_SHOULD_NARROW: return "SHOULD_NARROW";
2125 default: return "?";
2130 PRE(workq_ops)
2132 PRINT("workq_ops( %ld(%s), %#lx, %ld )", SARG1, workqop_name(ARG1), ARG2,
2133 SARG3);
2134 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2135 int,"priority");
2137 switch (ARG1) {
2138 case VKI_WQOPS_QUEUE_ADD:
2139 case VKI_WQOPS_QUEUE_REMOVE:
2140 // GrP fixme need anything here?
2141 // GrP fixme may block?
2142 break;
2143 case VKI_WQOPS_THREAD_RETURN: {
2144 // The interesting case. The kernel will do one of two things:
2145 // 1. Return normally. We continue; libc proceeds to stop the thread.
2146 // V does nothing special here.
2147 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2148 // new work item, and never returns from workq_ops.
2149 // V handles this by longjmp() from wqthread_hijack back to the
2150 // scheduler, which continues at the new client SP/IP/state.
2151 // This works something like V's signal handling.
2152 // To the tool, this looks like workq_ops() sometimes returns
2153 // to a strange address.
2154 ThreadState *tst = VG_(get_ThreadState)(tid);
2155 tst->os_state.wq_jmpbuf_valid = True;
2156 *flags |= SfMayBlock; // GrP fixme true?
2157 break;
2159 case VKI_WQOPS_THREAD_SETCONC:
2160 // RK fixme need anything here?
2161 // RK fixme may block?
2162 break;
2163 case VKI_WQOPS_QUEUE_NEWSPISUPP:
2164 // JRS don't think we need to do anything here -- this just checks
2165 // whether some newer functionality is supported
2166 break;
2167 case VKI_WQOPS_QUEUE_REQTHREADS:
2168 case VKI_WQOPS_QUEUE_REQTHREADS2:
2169 // JRS uh, looks like it queues up a bunch of threads, or some such?
2170 *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
2171 break;
2172 case VKI_WQOPS_THREAD_KEVENT_RETURN:
2173 // RK fixme need anything here?
2174 // perhaps similar to VKI_WQOPS_THREAD_RETURN above?
2175 break;
2176 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY:
2177 // RK fixme this just sets scheduling priorities - don't think we need
2178 // to do anything here
2179 break;
2180 case VKI_WQOPS_THREAD_WORKLOOP_RETURN:
2181 case VKI_WQOPS_SHOULD_NARROW:
2182 // RK fixme need anything here?
2183 // RK fixme may block?
2184 break;
2185 default:
2186 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
2187 break;
2190 POST(workq_ops)
2192 ThreadState *tst = VG_(get_ThreadState)(tid);
2193 tst->os_state.wq_jmpbuf_valid = False;
2194 switch (ARG1) {
2195 case VKI_WQOPS_THREAD_RETURN:
2196 ML_(sync_mappings)("after", "workq_ops(THREAD_RETURN)", 0);
2197 break;
2198 case VKI_WQOPS_QUEUE_REQTHREADS:
2199 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2200 break;
2201 case VKI_WQOPS_QUEUE_REQTHREADS2:
2202 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS2)", 0);
2203 break;
2204 default:
2205 break;
2211 PRE(__mac_syscall)
2213 PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
2214 ARG1, (HChar*)ARG1, SARG2, ARG3);
2215 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
2216 int,"call", void *,"arg");
2218 // GrP fixme check call's arg?
2219 // GrP fixme check policy?
2223 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2224 More like syswrap-generic's sys_exit_group. */
2225 PRE(exit)
2227 ThreadId t;
2229 PRINT("darwin exit( %ld )", SARG1);
2230 PRE_REG_READ1(void, "exit", int, status);
2232 /* A little complex; find all the threads with the same threadgroup
2233 as this one (including this one), and mark them to exit */
2234 for (t = 1; t < VG_N_THREADS; t++) {
2235 if ( /* not alive */
2236 VG_(threads)[t].status == VgTs_Empty
2237 /* GrP fixme zombie? */
2239 continue;
2241 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
2242 VG_(threads)[t].os_state.exitcode = ARG1;
2244 if (t != tid)
2245 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
2248 /* We have to claim the syscall already succeeded. */
2249 SET_STATUS_Success(0);
2253 PRE(sigaction)
2255 PRINT("sigaction ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2256 PRE_REG_READ3(long, "sigaction",
2257 int, signum, vki_sigaction_toK_t *, act,
2258 vki_sigaction_fromK_t *, oldact);
2260 if (ARG2 != 0) {
2261 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
2262 PRE_MEM_READ( "sigaction(act->sa_handler)",
2263 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2264 PRE_MEM_READ( "sigaction(act->sa_mask)",
2265 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2266 PRE_MEM_READ( "sigaction(act->sa_flags)",
2267 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2269 if (ARG3 != 0)
2270 PRE_MEM_WRITE( "sigaction(oldact)",
2271 ARG3, sizeof(vki_sigaction_fromK_t));
2273 SET_STATUS_from_SysRes(
2274 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
2275 (vki_sigaction_fromK_t *)ARG3)
2278 POST(sigaction)
2280 vg_assert(SUCCESS);
2281 if (RES == 0 && ARG3 != 0)
2282 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
2286 PRE(__pthread_kill)
2288 PRINT("__pthread_kill ( %#lx, %ld )", ARG1, SARG2);
2289 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
2293 PRE(__pthread_sigmask)
2295 // arguments are identical to sigprocmask (how, sigset_t*, sigset_t*).
2296 UWord arg1;
2297 PRINT("__pthread_sigmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
2298 PRE_REG_READ3(long, "__pthread_sigmask",
2299 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
2300 if (ARG2 != 0)
2301 PRE_MEM_READ( "__pthread_sigmask(set)", ARG2, sizeof(vki_sigset_t));
2302 if (ARG3 != 0)
2303 PRE_MEM_WRITE( "__pthread_sigmask(oldset)", ARG3, sizeof(vki_sigset_t));
2305 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
2306 value of 'how' is irrelevant, and it appears that Darwin's libc
2307 passes zero, which is not equal to any of
2308 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
2309 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
2310 value independently of the other args. Solution: in this case,
2311 simply pass a valid (but irrelevant) value for 'how'. */
2312 /* Also, in this case the new set is passed to the kernel by
2313 reference, not value, as in some other sigmask related Darwin
2314 syscalls. */
2315 arg1 = ARG1;
2316 if (ARG2 == 0 /* the new-set is NULL */
2317 && ARG1 != VKI_SIG_BLOCK
2318 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
2319 arg1 = VKI_SIG_SETMASK;
2321 SET_STATUS_from_SysRes(
2322 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
2323 (vki_sigset_t*)ARG3 )
2326 if (SUCCESS)
2327 *flags |= SfPollAfter;
2329 POST(__pthread_sigmask)
2331 vg_assert(SUCCESS);
2332 if (RES == 0 && ARG3 != 0)
2333 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2337 // SYS___sigwait 330
2338 // int sigwait(const sigset_t * __restrict, int * __restrict) __DARWIN_ALIAS_C(sigwait);
2339 PRE(__sigwait)
2341 *flags |= SfMayBlock;
2342 PRINT("sys_sigwait ( %#" FMT_REGWORD "x, %#" FMT_REGWORD "x )",
2343 ARG1,ARG2);
2344 PRE_REG_READ2(int, "sigwait",
2345 const vki_sigset_t *, set, int *, sig);
2346 if (ARG1 != 0) {
2347 PRE_MEM_READ( "sigwait(set)", ARG1, sizeof(vki_sigset_t));
2349 if (ARG2 != 0) {
2350 PRE_MEM_WRITE( "sigwait(sig)", ARG2, sizeof(int));
2354 POST(__sigwait)
2356 if (ARG2 != 0) {
2357 POST_MEM_WRITE( ARG2, sizeof(int));
2361 PRE(__pthread_canceled)
2363 *flags |= SfMayBlock; /* might kill this thread??? */
2364 /* I don't think so -- I think it just changes the cancellation
2365 state. But taking no chances. */
2366 PRINT("__pthread_canceled ( %#lx )", ARG1);
2367 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
2371 PRE(__pthread_markcancel)
2373 *flags |= SfMayBlock; /* might kill this thread??? */
2374 PRINT("__pthread_markcancel ( %#lx )", ARG1);
2375 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
2376 /* Just let it go through. No idea if this is correct. */
2380 PRE(__disable_threadsignal)
2382 vki_sigset_t set;
2383 PRINT("__disable_threadsignal(%ld, %ld, %ld)", SARG1, SARG2, SARG3);
2384 /* I don't think this really looks at its arguments. So don't
2385 bother to check them. */
2387 VG_(sigfillset)( &set );
2388 SET_STATUS_from_SysRes(
2389 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
2392 /* We don't expect that blocking all signals for this thread could
2393 cause any more to be delivered (how could it?), but just in case
2394 .. */
2395 if (SUCCESS)
2396 *flags |= SfPollAfter;
2400 PRE(__pthread_chdir)
2402 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2403 PRE_REG_READ1(long, "__pthread_chdir", const char *, path);
2404 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1 );
2409 PRE(__pthread_fchdir)
2411 PRINT("__pthread_fchdir ( %lu )", ARG1);
2412 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd);
2416 PRE(kdebug_trace)
2418 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2419 SARG1, SARG2, SARG3, SARG4, SARG5, SARG6);
2421 Don't check anything - some clients pass fewer arguments.
2422 PRE_REG_READ6(long, "kdebug_trace",
2423 int,"code", int,"arg1", int,"arg2",
2424 int,"arg3", int,"arg4", int,"arg5");
2429 PRE(seteuid)
2431 PRINT("seteuid(%lu)", ARG1);
2432 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
2436 PRE(setegid)
2438 PRINT("setegid(%lu)", ARG1);
2439 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
2442 PRE(settid)
2444 PRINT("settid(%lu, %lu)", ARG1, ARG2);
2445 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
2448 PRE(gettid)
2450 PRINT("gettid()");
2451 PRE_REG_READ0(long, gettid);
2454 /* XXX need to check whether we need POST operations for
2455 * waitevent, watchevent, modwatch -- jpeach
2457 PRE(watchevent)
2459 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
2460 PRE_REG_READ2(long, "watchevent",
2461 vki_eventreq *, "event", unsigned int, "eventmask");
2463 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
2464 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
2465 *flags |= SfMayBlock;
2468 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
2469 PRE(waitevent)
2471 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
2472 PRE_REG_READ2(long, "waitevent",
2473 vki_eventreq *, "event", struct timeval *, "timeout");
2474 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
2476 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
2477 PRE_timeval_READ("waitevent(timeout)", ARG2);
2480 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2481 *flags |= SfMayBlock;
2484 POST(waitevent)
2486 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
2489 PRE(modwatch)
2491 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
2492 PRE_REG_READ2(long, "modwatch",
2493 vki_eventreq *, "event", unsigned int, "eventmask");
2495 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
2496 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
2499 PRE(getxattr)
2501 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2502 ARG1, (HChar *)ARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2504 PRE_REG_READ6(vki_ssize_t, "getxattr",
2505 const char *, path, char *, name, void *, value,
2506 vki_size_t, size, uint32_t, position, int, options);
2507 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
2508 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2509 if (ARG3)
2510 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2513 POST(getxattr)
2515 vg_assert((vki_ssize_t)RES >= 0);
2516 if (ARG3)
2517 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2520 PRE(fgetxattr)
2522 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2523 SARG1, ARG2, (HChar *)ARG2, ARG3, ARG4, ARG5, SARG6);
2525 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
2526 int, fd, char *, name, void *, value,
2527 vki_size_t, size, uint32_t, position, int, options);
2528 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2529 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2532 POST(fgetxattr)
2534 vg_assert((vki_ssize_t)RES >= 0);
2535 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2538 PRE(setxattr)
2540 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2541 ARG1, (HChar *)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2542 PRE_REG_READ6(int, "setxattr",
2543 const char *,"path", char *,"name", void *,"value",
2544 vki_size_t,"size", uint32_t,"position", int,"options" );
2546 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
2547 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
2548 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
2552 PRE(fsetxattr)
2554 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2555 SARG1, ARG2, (HChar*)ARG2, ARG3, ARG4, ARG5, SARG6 );
2556 PRE_REG_READ6(int, "fsetxattr",
2557 int,"fd", char *,"name", void *,"value",
2558 vki_size_t,"size", uint32_t,"position", int,"options" );
2560 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
2561 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
2565 PRE(removexattr)
2567 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2568 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, SARG3 );
2569 PRE_REG_READ3(int, "removexattr",
2570 const char*, "path", char*, "attrname", int, "options");
2571 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
2572 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2576 PRE(fremovexattr)
2578 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2579 SARG1, ARG2, (HChar*)ARG2, SARG3 );
2580 PRE_REG_READ3(int, "fremovexattr",
2581 int, "fd", char*, "attrname", int, "options");
2582 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2586 PRE(listxattr)
2588 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2589 ARG1, (HChar *)ARG1, ARG2, ARG3, SARG4 );
2590 PRE_REG_READ4 (long, "listxattr",
2591 const char *,"path", char *,"namebuf",
2592 vki_size_t,"size", int,"options" );
2594 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
2595 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
2596 *flags |= SfMayBlock;
2598 POST(listxattr)
2600 vg_assert(SUCCESS);
2601 vg_assert((vki_ssize_t)RES >= 0);
2602 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2606 PRE(flistxattr)
2608 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2609 SARG1, ARG2, ARG3, SARG4 );
2610 PRE_REG_READ4 (long, "flistxattr",
2611 int, "fd", char *,"namebuf",
2612 vki_size_t,"size", int,"options" );
2613 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2614 *flags |= SfMayBlock;
2616 POST(flistxattr)
2618 vg_assert(SUCCESS);
2619 vg_assert((vki_ssize_t)RES >= 0);
2620 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2624 PRE(shmat)
2626 UWord arg2tmp;
2627 PRINT("shmat ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
2628 PRE_REG_READ3(long, "shmat",
2629 int, shmid, const void *, shmaddr, int, shmflg);
2630 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2631 if (arg2tmp == 0)
2632 SET_STATUS_Failure( VKI_EINVAL );
2633 else
2634 ARG2 = arg2tmp; // used in POST
2636 POST(shmat)
2638 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2641 PRE(shmctl)
2643 PRINT("shmctl ( %ld, %ld, %#lx )", SARG1, SARG2, ARG3);
2644 PRE_REG_READ3(long, "shmctl",
2645 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2646 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2648 POST(shmctl)
2650 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2653 PRE(shmdt)
2655 PRINT("shmdt ( %#lx )",ARG1);
2656 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2657 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2658 SET_STATUS_Failure( VKI_EINVAL );
2660 POST(shmdt)
2662 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2665 PRE(shmget)
2667 PRINT("shmget ( %ld, %lu, %ld )", SARG1, ARG2, SARG3);
2668 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2671 PRE(shm_open)
2673 PRINT("shm_open(%#lx(%s), %ld, %lu)", ARG1, (HChar *)ARG1, SARG2, ARG3);
2674 PRE_REG_READ3(long, "shm_open",
2675 const char *,"name", int,"flags", vki_mode_t,"mode");
2677 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2679 *flags |= SfMayBlock;
2681 POST(shm_open)
2683 vg_assert(SUCCESS);
2684 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2685 VG_(close)(RES);
2686 SET_STATUS_Failure( VKI_EMFILE );
2687 } else {
2688 if (VG_(clo_track_fds))
2689 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
2693 PRE(shm_unlink)
2695 *flags |= SfMayBlock;
2696 PRINT("shm_unlink ( %#lx(%s) )", ARG1, (HChar*)ARG1);
2697 PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2698 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2700 POST(shm_unlink)
2702 /* My reading of the man page suggests that a call may cause memory
2703 mappings to change: "if no references exist at the time of the
2704 call to shm_unlink(), the resources are reclaimed immediately".
2705 So we need to resync here, sigh. */
2706 ML_(sync_mappings)("after", "shm_unlink", 0);
2709 PRE(stat_extended)
2711 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2712 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2713 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2714 void *, fsacl, vki_size_t *, fsacl_size);
2715 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
2716 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2717 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2718 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2719 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2721 POST(stat_extended)
2723 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2724 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2725 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2726 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2730 PRE(lstat_extended)
2732 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2733 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2734 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2735 void *, fsacl, vki_size_t *, fsacl_size);
2736 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
2737 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2738 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2739 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2740 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2742 POST(lstat_extended)
2744 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2745 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2746 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2747 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2751 PRE(fstat_extended)
2753 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2754 SARG1, ARG2, ARG3, ARG4);
2755 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2756 void *, fsacl, vki_size_t *, fsacl_size);
2757 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2758 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2759 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2760 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2762 POST(fstat_extended)
2764 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2765 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2766 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2767 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2771 PRE(stat64_extended)
2773 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2774 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2775 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2776 void *, fsacl, vki_size_t *, fsacl_size);
2777 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
2778 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2779 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2780 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2781 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2783 POST(stat64_extended)
2785 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2786 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2787 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2788 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2792 PRE(lstat64_extended)
2794 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2795 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2796 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2797 void *, fsacl, vki_size_t *, fsacl_size);
2798 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2799 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2800 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2801 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2802 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2804 POST(lstat64_extended)
2806 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2807 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2808 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2809 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2813 PRE(fstat64_extended)
2815 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2816 SARG1, ARG2, ARG3, ARG4);
2817 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2818 void *, fsacl, vki_size_t *, fsacl_size);
2819 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2820 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2821 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2822 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2824 POST(fstat64_extended)
2826 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2827 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2828 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2829 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2833 PRE(fchmod_extended)
2835 /* DDD: Note: this is not really correct. Handling of
2836 chmod_extended is broken in the same way. */
2837 PRINT("fchmod_extended ( %lu, %lu, %lu, %lu, %#lx )",
2838 ARG1, ARG2, ARG3, ARG4, ARG5);
2839 PRE_REG_READ5(long, "fchmod_extended",
2840 unsigned int, fildes,
2841 uid_t, uid,
2842 gid_t, gid,
2843 vki_mode_t, mode,
2844 void* /*really,user_addr_t*/, xsecurity);
2845 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2846 is just way wrong. [The trouble is with the size, which depends on a
2847 non-trival kernel computation] */
2848 if (ARG5) {
2849 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2850 sizeof(struct vki_kauth_filesec) );
2854 PRE(chmod_extended)
2856 /* DDD: Note: this is not really correct. Handling of
2857 fchmod_extended is broken in the same way. */
2858 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2859 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2860 PRE_REG_READ5(long, "chmod_extended",
2861 unsigned int, fildes,
2862 uid_t, uid,
2863 gid_t, gid,
2864 vki_mode_t, mode,
2865 void* /*really,user_addr_t*/, xsecurity);
2866 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2867 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2868 is just way wrong. [The trouble is with the size, which depends on a
2869 non-trival kernel computation] */
2870 if (ARG5) {
2871 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2872 sizeof(struct vki_kauth_filesec) );
2876 PRE(open_extended)
2878 /* DDD: Note: this is not really correct. Handling of
2879 {,f}chmod_extended is broken in the same way. */
2880 PRINT("open_extended ( %#lx(%s), %ld, %lu, %lu, %lu, %#lx )",
2881 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2882 SARG2, ARG3, ARG4, ARG5, ARG6);
2883 PRE_REG_READ6(long, "open_extended",
2884 char*, path,
2885 int, flags,
2886 uid_t, uid,
2887 gid_t, gid,
2888 vki_mode_t, mode,
2889 void* /*really,user_addr_t*/, xsecurity);
2890 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2891 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2892 is just way wrong. [The trouble is with the size, which depends on a
2893 non-trival kernel computation] */
2894 if (ARG6)
2895 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2896 sizeof(struct vki_kauth_filesec) );
2899 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2900 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2901 // by one or more strings. Each accessx_descriptor contains a field,
2902 // 'ad_name_offset', which points to one of the strings (or it can contain
2903 // zero which means "reuse the string from the previous accessx_descriptor").
2905 // What's really ridiculous is that we are only given the size of the overall
2906 // buffer, not the number of accessx_descriptors, nor the number of strings.
2907 // The kernel determines the number of accessx_descriptors by walking through
2908 // them one by one, checking that the ad_name_offset points within the buffer,
2909 // past the current point (or that it's a zero, unless its the first
2910 // descriptor); if so, we assume that this really is an accessx_descriptor,
2911 // if not, we assume we've hit the strings section. Gah.
2913 // This affects us here because number of entries in the 'results' buffer is
2914 // determined by the number of accessx_descriptors. So we have to know that
2915 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2916 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2917 // computation after the syscall has succeeded, because the kernel will have
2918 // checked for all the zillion different ways this syscall can fail, and we'll
2919 // know we have a well-formed 'entries' buffer. This means we might miss some
2920 // uses of unaddressable memory but oh well.
2922 PRE(access_extended)
2924 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2925 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
2926 // XXX: the accessx_descriptor struct contains padding, so this can cause
2927 // unnecessary undefined value errors. But you arguably shouldn't be
2928 // passing undefined values to the kernel anyway...
2929 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2930 vki_errno_t *, results, vki_uid_t *, uid);
2931 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2933 // XXX: as mentioned above, this check is too hard to do before the
2934 // syscall.
2935 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2937 POST(access_extended)
2939 // 'n_descs' is the number of descriptors we think are in the buffer. We
2940 // start with the maximum possible value, which occurs if we have the
2941 // shortest possible string section. The shortest string section allowed
2942 // consists of a single one-char string (plus the NUL char). Hence the
2943 // '2'.
2944 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2945 SizeT size = ARG2;
2946 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2947 Int i; // Current position in the descriptors section array.
2948 Int u; // Upper bound on the length of the descriptors array
2949 // (recomputed each time around the loop)
2950 vg_assert(n_descs > 0);
2952 // Step through the descriptors, lowering 'n_descs' until we know we've
2953 // reached the string section.
2954 for (i = 0; True; i++) {
2955 // If we're past our estimate, we must be one past the end of the
2956 // descriptors section (ie. at the start of the string section). Stop.
2957 if (i >= n_descs)
2958 break;
2960 // Get the array index for the string, but pretend momentarily that it
2961 // is actually another accessx_descriptor. That gives us an upper bound
2962 // on the length of the descriptors section. (Unless the index is zero,
2963 // in which case we have no new info.)
2964 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2965 if (u == 0) {
2966 vg_assert(i != 0);
2967 continue;
2970 // If the upper bound is below our current estimate, revise that
2971 // estimate downwards.
2972 if (u < n_descs)
2973 n_descs = u;
2976 // Sanity check.
2977 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2979 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2983 PRE(chflags)
2985 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (HChar *)ARG1, ARG2);
2986 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2987 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2989 // GrP fixme sanity-check flags value?
2992 PRE(fchflags)
2994 PRINT("fchflags ( %ld, %lu )", SARG1, ARG2);
2995 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2997 // GrP fixme sanity-check flags value?
3000 PRE(stat64)
3002 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
3003 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
3004 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
3005 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
3007 POST(stat64)
3009 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
3012 PRE(lstat64)
3014 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
3015 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
3016 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
3017 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
3019 POST(lstat64)
3021 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
3024 PRE(fstat64)
3026 PRINT("fstat64 ( %lu, %#lx )", ARG1,ARG2);
3027 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
3028 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
3030 POST(fstat64)
3032 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
3035 PRE(getfsstat)
3037 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3038 PRE_REG_READ3(int, "getfsstat",
3039 struct vki_statfs *, buf, int, bufsize, int, flags);
3040 if (ARG1) {
3041 // ARG2 is a BYTE SIZE
3042 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
3045 POST(getfsstat)
3047 if (ARG1) {
3048 // RES is a STRUCT COUNT
3049 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
3053 PRE(getfsstat64)
3055 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, SARG2, SARG3);
3056 PRE_REG_READ3(int, "getfsstat64",
3057 struct vki_statfs64 *, buf, int, bufsize, int, flags);
3058 if (ARG1) {
3059 // ARG2 is a BYTE SIZE
3060 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
3063 POST(getfsstat64)
3065 if (ARG1) {
3066 // RES is a STRUCT COUNT
3067 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
3071 PRE(mount)
3073 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
3074 // We are conservative and check everything, except the memory pointed to
3075 // by 'data'.
3076 *flags |= SfMayBlock;
3077 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
3078 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3, ARG4);
3079 PRE_REG_READ4(long, "mount",
3080 const char *, type, const char *, dir,
3081 int, flags, void *, data);
3082 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
3083 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
3087 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
3088 void *attrBuf, SizeT attrBufSize,
3089 void (*fn)(ThreadId, void *attrData, SizeT size)
3092 typedef struct {
3093 uint32_t attrBit;
3094 int32_t attrSize;
3095 } attrspec;
3096 static const attrspec commonattr[] = {
3097 // This order is important.
3098 #if DARWIN_VERS >= DARWIN_10_6
3099 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
3100 #endif
3101 { ATTR_CMN_NAME, -1 },
3102 { ATTR_CMN_DEVID, sizeof(dev_t) },
3103 { ATTR_CMN_FSID, sizeof(fsid_t) },
3104 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
3105 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
3106 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
3107 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
3108 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
3109 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
3110 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
3111 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
3112 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
3113 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
3114 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
3115 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
3116 { ATTR_CMN_OWNERID, sizeof(uid_t) },
3117 { ATTR_CMN_GRPID, sizeof(gid_t) },
3118 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
3119 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
3120 { ATTR_CMN_NAMEDATTRLIST, -1 },
3121 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
3122 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
3123 { ATTR_CMN_EXTENDED_SECURITY, -1 },
3124 { ATTR_CMN_UUID, sizeof(guid_t) },
3125 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
3126 { ATTR_CMN_FILEID, sizeof(uint64_t) },
3127 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
3128 #if DARWIN_VERS >= DARWIN_10_6
3129 { ATTR_CMN_FULLPATH, -1 },
3130 #endif
3131 #if DARWIN_VERS >= DARWIN_10_8
3132 { ATTR_CMN_ADDEDTIME, -1 },
3133 #endif
3134 { 0, 0 }
3136 static const attrspec volattr[] = {
3137 // This order is important.
3138 { ATTR_VOL_INFO, 0 },
3139 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
3140 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
3141 { ATTR_VOL_SIZE, sizeof(off_t) },
3142 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
3143 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
3144 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
3145 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
3146 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
3147 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
3148 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
3149 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
3150 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
3151 { ATTR_VOL_MOUNTPOINT, -1 },
3152 { ATTR_VOL_NAME, -1 },
3153 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
3154 { ATTR_VOL_MOUNTEDDEVICE, -1 },
3155 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
3156 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
3157 #if DARWIN_VERS >= DARWIN_10_6
3158 { ATTR_VOL_UUID, sizeof(uuid_t) },
3159 #endif
3160 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
3161 { 0, 0 }
3163 static const attrspec dirattr[] = {
3164 // This order is important.
3165 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
3166 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
3167 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
3168 { 0, 0 }
3170 static const attrspec fileattr[] = {
3171 // This order is important.
3172 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
3173 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
3174 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
3175 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
3176 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
3177 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
3178 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
3179 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
3180 { ATTR_FILE_FORKLIST, -1 },
3181 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
3182 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
3183 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
3184 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
3185 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
3186 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
3187 { 0, 0 }
3189 static const attrspec forkattr[] = {
3190 // This order is important.
3191 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
3192 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
3193 { 0, 0 }
3196 static const attrspec *attrdefs[5] = {
3197 commonattr, volattr, dirattr, fileattr, forkattr
3199 attrgroup_t a[5];
3200 uint8_t *d, *dend;
3201 int g, i;
3203 vg_assert(attrList->bitmapcount == 5);
3204 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
3205 d = attrBuf;
3206 dend = d + attrBufSize;
3208 #if DARWIN_VERS >= DARWIN_10_6
3209 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3210 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
3211 // fixme range check this?
3212 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
3213 fn(tid, d, sizeof(attribute_set_t));
3214 VG_(memcpy)(a, d, sizeof(a));
3216 #endif
3218 for (g = 0; g < 5; g++) {
3219 for (i = 0; attrdefs[g][i].attrBit; i++) {
3220 uint32_t bit = attrdefs[g][i].attrBit;
3221 int32_t size = attrdefs[g][i].attrSize;
3223 if (a[g] & bit) {
3224 a[g] &= ~bit; // clear bit for error check later
3225 if (size == -1) {
3226 attrreference_t *ref = (attrreference_t *)d;
3227 size = MIN(sizeof(attrreference_t), dend - d);
3228 fn(tid, d, size);
3229 if (size >= sizeof(attrreference_t) &&
3230 d + ref->attr_dataoffset < dend)
3232 fn(tid, d + ref->attr_dataoffset,
3233 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
3235 d += size;
3237 else {
3238 size = MIN(size, dend - d);
3239 fn(tid, d, size);
3240 d += size;
3243 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
3244 if (d > dend) d = dend;
3248 // Known bits are cleared. Die if any bits are left.
3249 if (a[g] != 0) {
3250 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
3255 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3257 POST_MEM_WRITE((Addr)attrData, attrDataSize);
3260 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3262 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
3265 PRE(getattrlist)
3267 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3268 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3269 PRE_REG_READ5(int, "getattrlist",
3270 const char *,path, struct vki_attrlist *,attrList,
3271 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3272 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
3273 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3274 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
3277 POST(getattrlist)
3279 if (ARG4 > sizeof(vki_uint32_t)) {
3280 // attrBuf is uint32_t size followed by attr data
3281 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
3282 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
3283 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
3284 // *sizep is bytes required for return value, including *sizep
3285 } else {
3286 // *sizep is actual bytes returned, including *sizep
3288 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
3293 PRE(setattrlist)
3295 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3296 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4, ARG5);
3297 PRE_REG_READ5(int, "setattrlist",
3298 const char *,path, struct vki_attrlist *,attrList,
3299 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3300 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
3301 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3302 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
3306 PRE(getdirentriesattr)
3308 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %lu, %#lx, %#lx, %#lx, %lu)",
3309 SARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
3310 PRE_REG_READ8(int, "getdirentriesattr",
3311 int,fd, struct vki_attrlist *,attrList,
3312 void *,attrBuf, size_t,attrBufSize,
3313 unsigned int *,count, unsigned int *,basep,
3314 unsigned int *,newState, unsigned int,options);
3315 PRE_MEM_READ("getdirentriesattr(attrList)",
3316 ARG2, sizeof(struct vki_attrlist));
3317 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
3318 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3319 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3320 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
3321 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
3323 POST(getdirentriesattr)
3325 char *p, *end;
3326 unsigned int count;
3327 unsigned int i;
3329 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
3330 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
3331 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
3333 // return buffer is concatenation of variable-size structs
3334 count = *(unsigned int *)ARG5;
3335 p = (char *)ARG3;
3336 end = (char *)ARG3 + ARG4;
3337 for (i = 0; i < count; i++) {
3338 vg_assert(p < end); // failure is kernel bug or Valgrind bug
3339 p += *(unsigned int *)p;
3342 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
3344 PRINT("got %d records, %ld/%lu bytes\n",
3345 count, (Addr)p-(Addr)ARG3, ARG4);
3348 PRE(exchangedata)
3350 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3351 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3);
3352 PRE_REG_READ3(int, "exchangedata",
3353 char *, path1, char *, path2, unsigned long, options);
3354 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
3355 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
3358 PRE(fsctl)
3360 PRINT("fsctl ( %#lx(%s), %lu, %#lx, %lu )",
3361 ARG1, (HChar *)ARG1, ARG2, ARG3, ARG4);
3362 PRE_REG_READ4( long, "fsctl",
3363 char *,"path", unsigned int,"request",
3364 void *,"data", unsigned int,"options");
3366 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
3368 switch (ARG2) {
3369 case VKI_afpfsByteRangeLock2FSCTL: {
3370 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3371 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3372 pb->offset);
3373 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3374 pb->length);
3375 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3376 pb->unLockFlag);
3377 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3378 pb->startEndFlag);
3379 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3380 pb->fd);
3382 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3383 pb->retRangeStart);
3385 // GrP fixme check fd
3386 break;
3388 case VKI_FSIOC_SYNC_VOLUME:
3389 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
3390 break;
3392 default:
3393 // fsctl requests use ioctl encoding
3394 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3395 break;
3399 POST(fsctl)
3401 switch (ARG2) {
3402 case VKI_afpfsByteRangeLock2FSCTL: {
3403 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3404 POST_FIELD_WRITE(pb->retRangeStart);
3405 break;
3407 case VKI_FSIOC_SYNC_VOLUME:
3408 break;
3410 default:
3411 // fsctl requests use ioctl encoding
3412 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
3413 break;
3417 PRE(initgroups)
3419 PRINT("initgroups(%s, %#lx, %lu)", (HChar *)ARG1, ARG2, ARG3);
3420 PRE_REG_READ3(long, "initgroups",
3421 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
3422 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
3426 //--------- posix_spawn ---------//
3427 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3428 the simpler AIX equivalent (syswrap-aix5.c). */
3429 // Pre_read a char** argument.
3430 static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
3432 while (True) {
3433 Addr a_deref;
3434 Addr* a_p = (Addr*)a;
3435 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
3436 a_deref = *a_p;
3437 if (0 == a_deref)
3438 break;
3439 PRE_MEM_RASCIIZ( s2, a_deref );
3440 a += sizeof(char*);
3443 static SysRes simple_pre_exec_check ( const HChar* exe_name,
3444 Bool trace_this_child )
3446 Int fd, ret;
3447 SysRes res;
3448 Bool setuid_allowed;
3450 // Check it's readable
3451 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
3452 if (sr_isError(res)) {
3453 return res;
3455 fd = sr_Res(res);
3456 VG_(close)(fd);
3458 // Check we have execute permissions. We allow setuid executables
3459 // to be run only in the case when we are not simulating them, that
3460 // is, they to be run natively.
3461 setuid_allowed = trace_this_child ? False : True;
3462 ret = VG_(check_executable)(NULL/*&is_setuid*/,
3463 exe_name, setuid_allowed);
3464 if (0 != ret) {
3465 return VG_(mk_SysRes_Error)(ret);
3467 return VG_(mk_SysRes_Success)(0);
3469 PRE(posix_spawn)
3471 HChar* path = NULL; /* path to executable */
3472 HChar** envp = NULL;
3473 HChar** argv = NULL;
3474 HChar** arg2copy;
3475 HChar* launcher_basename = NULL;
3476 Int i, j, tot_args;
3477 SysRes res;
3478 Bool trace_this_child;
3480 /* args: pid_t* pid
3481 char* path
3482 posix_spawn_file_actions_t* file_actions
3483 char** argv
3484 char** envp
3486 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3487 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3489 /* Standard pre-syscall checks */
3491 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
3492 void*, file_actions, char**, argv, char**, envp );
3493 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
3494 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
3495 // DDD: check file_actions
3496 if (ARG4 != 0)
3497 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
3498 "posix_spawn(argv[i])" );
3499 if (ARG5 != 0)
3500 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
3501 "posix_spawn(envp[i])" );
3503 if (0)
3504 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3505 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3507 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3508 syswrap-generic.c. */
3510 /* Check that the name at least begins in client-accessible storage. */
3511 if (ARG2 == 0 /* obviously bogus */
3512 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
3513 SET_STATUS_Failure( VKI_EFAULT );
3514 return;
3517 // Decide whether or not we want to follow along
3518 { // Make 'child_argv' be a pointer to the child's arg vector
3519 // (skipping the exe name)
3520 const HChar** child_argv = (const HChar**)ARG4;
3521 if (child_argv && child_argv[0] == NULL)
3522 child_argv = NULL;
3523 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
3526 // Do the important checks: it is a file, is executable, permissions are
3527 // ok, etc. We allow setuid executables to run only in the case when
3528 // we are not simulating them, that is, they to be run natively.
3529 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
3530 if (sr_isError(res)) {
3531 SET_STATUS_Failure( sr_Err(res) );
3532 return;
3535 /* If we're tracing the child, and the launcher name looks bogus
3536 (possibly because launcher.c couldn't figure it out, see
3537 comments therein) then we have no option but to fail. */
3538 if (trace_this_child
3539 && (VG_(name_of_launcher) == NULL
3540 || VG_(name_of_launcher)[0] != '/')) {
3541 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
3542 return;
3545 /* Ok. So let's give it a try. */
3546 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
3548 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3549 So, we should not terminate gdbserver : this is still the parent
3550 running, which will terminate its gdbserver when exiting.
3551 If the child process is traced, it will start a fresh gdbserver
3552 after posix_spawn. */
3554 // Set up the child's exe path.
3556 if (trace_this_child) {
3558 // We want to exec the launcher. Get its pre-remembered path.
3559 path = VG_(name_of_launcher);
3560 // VG_(name_of_launcher) should have been acquired by m_main at
3561 // startup. The following two assertions should be assured by
3562 // the "If we're tracking the child .." test just above here.
3563 vg_assert(path);
3564 vg_assert(path[0] == '/');
3565 launcher_basename = path;
3567 } else {
3568 path = (HChar*)ARG2;
3571 // Set up the child's environment.
3573 // Remove the valgrind-specific stuff from the environment so the
3574 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3575 // This is done unconditionally, since if we are tracing the child,
3576 // the child valgrind will set up the appropriate client environment.
3577 // Nb: we make a copy of the environment before trying to mangle it
3578 // as it might be in read-only memory (this was bug #101881).
3580 // Then, if tracing the child, set VALGRIND_LIB for it.
3582 if (ARG5 == 0) {
3583 envp = NULL;
3584 } else {
3585 envp = VG_(env_clone)( (HChar**)ARG5 );
3586 vg_assert(envp);
3587 VG_(env_remove_valgrind_env_stuff)( envp, /* ro_strings */ False, NULL);
3590 if (trace_this_child) {
3591 // Set VALGRIND_LIB in ARG5 (the environment)
3592 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3595 // Set up the child's args. If not tracing it, they are
3596 // simply ARG4. Otherwise, they are
3598 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3600 // except that the first VG_(args_for_valgrind_noexecpass) args
3601 // are omitted.
3603 if (!trace_this_child) {
3604 argv = (HChar**)ARG4;
3605 } else {
3606 vg_assert( VG_(args_for_valgrind) );
3607 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3608 vg_assert( VG_(args_for_valgrind_noexecpass)
3609 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3610 /* how many args in total will there be? */
3611 // launcher basename
3612 tot_args = 1;
3613 // V's args
3614 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3615 tot_args -= VG_(args_for_valgrind_noexecpass);
3616 // name of client exe
3617 tot_args++;
3618 // args for client exe, skipping [0]
3619 arg2copy = (HChar**)ARG4;
3620 if (arg2copy && arg2copy[0]) {
3621 for (i = 1; arg2copy[i]; i++)
3622 tot_args++;
3624 // allocate
3625 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3626 (tot_args+1) * sizeof(HChar*) );
3627 // copy
3628 j = 0;
3629 argv[j++] = launcher_basename;
3630 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3631 if (i < VG_(args_for_valgrind_noexecpass))
3632 continue;
3633 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3635 argv[j++] = (HChar*)ARG2;
3636 if (arg2copy && arg2copy[0])
3637 for (i = 1; arg2copy[i]; i++)
3638 argv[j++] = arg2copy[i];
3639 argv[j++] = NULL;
3640 // check
3641 vg_assert(j == tot_args+1);
3644 /* DDD: sort out the signal state. What signal
3645 state does the child inherit from the parent? */
3647 if (0) {
3648 HChar **cpp;
3649 VG_(printf)("posix_spawn: %s\n", path);
3650 for (cpp = argv; cpp && *cpp; cpp++)
3651 VG_(printf)("argv: %s\n", *cpp);
3652 if (1)
3653 for (cpp = envp; cpp && *cpp; cpp++)
3654 VG_(printf)("env: %s\n", *cpp);
3657 /* Let the call go through as usual. However, we have to poke
3658 the altered arguments back into the argument slots. */
3659 ARG2 = (UWord)path;
3660 ARG4 = (UWord)argv;
3661 ARG5 = (UWord)envp;
3663 /* not to mention .. */
3664 *flags |= SfMayBlock;
3666 POST(posix_spawn)
3668 vg_assert(SUCCESS);
3669 if (ARG1 != 0) {
3670 POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3675 PRE(socket)
3677 PRINT("socket ( %ld, %ld, %ld )", SARG1, SARG2, SARG3);
3678 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3681 POST(socket)
3683 SysRes r;
3684 vg_assert(SUCCESS);
3685 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3686 SET_STATUS_from_SysRes(r);
3690 PRE(setsockopt)
3692 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3693 SARG1, SARG2, SARG3, ARG4, SARG5);
3694 PRE_REG_READ5(long, "setsockopt",
3695 int, s, int, level, int, optname,
3696 const void *, optval, vki_socklen_t, optlen);
3697 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3701 PRE(getsockopt)
3703 Addr optval_p = ARG4;
3704 Addr optlen_p = ARG5;
3705 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3706 SARG1, SARG2, SARG3, ARG4, ARG5);
3707 PRE_REG_READ5(long, "getsockopt",
3708 int, s, int, level, int, optname,
3709 void *, optval, vki_socklen_t *, optlen);
3710 /* int getsockopt(int socket, int level, int option_name,
3711 void *restrict option_value,
3712 socklen_t *restrict option_len); */
3713 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3714 if (optval_p != (Addr)NULL) {
3715 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3716 "socketcall.getsockopt(optval)",
3717 "socketcall.getsockopt(optlen)" );
3719 // DDD: #warning GrP fixme darwin-specific sockopts
3722 POST(getsockopt)
3724 Addr optval_p = ARG4;
3725 Addr optlen_p = ARG5;
3726 vg_assert(SUCCESS);
3727 if (optval_p != (Addr)NULL) {
3728 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3729 optval_p, optlen_p,
3730 "socketcall.getsockopt(optlen_out)" );
3731 // DDD: #warning GrP fixme darwin-specific sockopts
3736 PRE(connect)
3738 *flags |= SfMayBlock;
3739 PRINT("connect ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3740 PRE_REG_READ3(long, "connect",
3741 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3742 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3746 PRE(accept)
3748 *flags |= SfMayBlock;
3749 PRINT("accept ( %ld, %#lx, %#lx )", SARG1, ARG2, SARG3);
3750 PRE_REG_READ3(long, "accept",
3751 int, s, struct sockaddr *, addr, int *, addrlen);
3752 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3755 POST(accept)
3757 SysRes r;
3758 vg_assert(SUCCESS);
3759 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3760 ARG1,ARG2,ARG3);
3761 SET_STATUS_from_SysRes(r);
3764 PRE(mkfifo)
3766 *flags |= SfMayBlock;
3767 PRINT("mkfifo ( %#lx(%s), %lx )", ARG1, (HChar *)ARG1, ARG2);
3768 PRE_REG_READ2(long, "mkfifo", const char *, path, vki_mode_t, mode);
3769 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1 );
3772 POST(mkfifo)
3774 vg_assert(SUCCESS);
3775 if (!ML_(fd_allowed)(RES, "mkfifo", tid, True)) {
3776 VG_(close)(RES);
3777 SET_STATUS_Failure( VKI_EMFILE );
3778 } else {
3779 if (VG_(clo_track_fds))
3780 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3784 PRE(sendto)
3786 *flags |= SfMayBlock;
3787 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3788 SARG1, (HChar *)ARG2, SARG3, ARG4, ARG5, SARG6);
3789 PRE_REG_READ6(long, "sendto",
3790 int, s, const void *, msg, int, len,
3791 unsigned int, flags,
3792 const struct sockaddr *, to, int, tolen);
3793 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3796 PRE(sendfile)
3798 #if VG_WORDSIZE == 4
3799 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3800 SARG1, SARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, SARG7);
3802 PRE_REG_READ7(long, "sendfile",
3803 int, fromfd, int, tofd,
3804 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3805 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3806 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3807 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3808 #else
3809 PRINT("sendfile(%ld, %ld, %lu, %#lx, %#lx, %ld)",
3810 SARG1, SARG2, ARG3, ARG4, ARG5, SARG6);
3812 PRE_REG_READ6(long, "sendfile",
3813 int, fromfd, int, tofd,
3814 vki_uint64_t, offset,
3815 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3816 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3817 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3818 #endif
3820 *flags |= SfMayBlock;
3822 POST(sendfile)
3824 #if VG_WORDSIZE == 4
3825 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3826 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3827 #else
3828 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3829 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3830 #endif
3833 PRE(recvfrom)
3835 *flags |= SfMayBlock;
3836 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3837 SARG1, ARG2, SARG3, ARG4, ARG5, ARG6);
3838 PRE_REG_READ6(long, "recvfrom",
3839 int, s, void *, buf, int, len, unsigned int, flags,
3840 struct sockaddr *, from, int *, fromlen);
3841 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3844 POST(recvfrom)
3846 vg_assert(SUCCESS);
3847 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3848 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3852 PRE(sendmsg)
3854 *flags |= SfMayBlock;
3855 PRINT("sendmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3856 PRE_REG_READ3(long, "sendmsg",
3857 int, s, const struct msghdr *, msg, int, flags);
3858 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3862 PRE(recvmsg)
3864 *flags |= SfMayBlock;
3865 PRINT("recvmsg ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3866 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3867 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3870 POST(recvmsg)
3872 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3876 PRE(shutdown)
3878 *flags |= SfMayBlock;
3879 PRINT("shutdown ( %ld, %ld )", SARG1, SARG2);
3880 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3884 PRE(bind)
3886 PRINT("bind ( %ld, %#lx, %ld )", SARG1, ARG2, SARG3);
3887 PRE_REG_READ3(long, "bind",
3888 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3889 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3893 PRE(listen)
3895 PRINT("listen ( %ld, %ld )", SARG1, SARG2);
3896 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3900 PRE(getsockname)
3902 PRINT("getsockname ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3903 PRE_REG_READ3(long, "getsockname",
3904 int, s, struct sockaddr *, name, int *, namelen);
3905 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3908 POST(getsockname)
3910 vg_assert(SUCCESS);
3911 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3912 ARG1,ARG2,ARG3);
3916 PRE(getpeername)
3918 PRINT("getpeername ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
3919 PRE_REG_READ3(long, "getpeername",
3920 int, s, struct sockaddr *, name, int *, namelen);
3921 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3924 POST(getpeername)
3926 vg_assert(SUCCESS);
3927 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3928 ARG1,ARG2,ARG3);
3932 PRE(socketpair)
3934 PRINT("socketpair ( %ld, %ld, %ld, %#lx )", SARG1, SARG2, SARG3, ARG4);
3935 PRE_REG_READ4(long, "socketpair",
3936 int, d, int, type, int, protocol, int *, sv);
3937 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3940 POST(socketpair)
3942 vg_assert(SUCCESS);
3943 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3944 ARG1,ARG2,ARG3,ARG4);
3948 PRE(gethostuuid)
3950 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3951 PRE_REG_READ2(int,"gethostuuid",
3952 char *,"uuid_buf",
3953 const struct vki_timespec *,"timeout");
3955 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3956 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3958 *flags |= SfMayBlock;
3962 POST(gethostuuid)
3964 POST_MEM_WRITE(ARG1, 16);
3967 /* Darwin pipe() returns the two descriptors in two registers. */
3968 PRE(pipe)
3970 PRINT("pipe ( )");
3971 PRE_REG_READ0(int, "pipe");
3974 POST(pipe)
3976 Int p0, p1;
3977 vg_assert(SUCCESS);
3978 p0 = RES;
3979 p1 = RESHI;
3981 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3982 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3983 VG_(close)(p0);
3984 VG_(close)(p1);
3985 SET_STATUS_Failure( VKI_EMFILE );
3986 } else {
3987 if (VG_(clo_track_fds)) {
3988 ML_(record_fd_open_nameless)(tid, p0);
3989 ML_(record_fd_open_nameless)(tid, p1);
3995 PRE(getlogin)
3997 PRINT("getlogin ( %#lx, %lu )", ARG1, ARG2);
3998 PRE_REG_READ2(long, "getlogin",
3999 char *,"namebuf", unsigned int,"namelen");
4001 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
4004 POST(getlogin)
4006 POST_MEM_WRITE(ARG1, ARG2);
4010 PRE(ptrace)
4012 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", SARG1, SARG2, ARG3, SARG4);
4013 PRE_REG_READ4(long, "ptrace",
4014 int,"request", vki_pid_t,"pid",
4015 vki_caddr_t,"addr", int,"data");
4017 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
4019 // GrP fixme anything needed?
4023 PRE(issetugid)
4025 PRINT("issetugid ( )");
4026 PRE_REG_READ0(long, "issetugid");
4030 PRE(getdtablesize)
4032 PRINT("getdtablesize ( )");
4033 PRE_REG_READ0(long, "getdtablesize");
4036 POST(getdtablesize)
4038 // Subtract Valgrind's fd range from client's dtable
4039 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
4042 PRE(lseek)
4044 PRINT("lseek ( %lu, %ld, %ld )", ARG1, SARG2, SARG3);
4045 PRE_REG_READ4(vki_off_t, "lseek",
4046 unsigned int,fd, int,offset_hi, int,offset_lo,
4047 unsigned int,whence);
4051 PRE(pathconf)
4053 PRINT("pathconf(%#lx(%s), %ld)", ARG1, (HChar *)ARG1, SARG2);
4054 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
4055 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
4059 PRE(fpathconf)
4061 PRINT("fpathconf(%ld, %ld)", SARG1, SARG2);
4062 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
4064 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
4065 SET_STATUS_Failure( VKI_EBADF );
4069 PRE(getdirentries)
4071 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", SARG1, ARG2, SARG3, ARG4);
4072 PRE_REG_READ4(int, "getdirentries",
4073 int, fd, char *, buf, int, nbytes, long *, basep);
4074 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
4075 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
4078 POST(getdirentries)
4080 POST_MEM_WRITE(ARG4, sizeof(long));
4081 // GrP fixme be specific about d_name?
4082 POST_MEM_WRITE(ARG2, RES);
4086 PRE(getdirentries64)
4088 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", SARG1, ARG2, ARG3, ARG4);
4089 PRE_REG_READ4(vki_ssize_t, "getdirentries",
4090 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
4091 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
4092 to valid memory and the kernel doesn't modify it. I can't
4093 determine the conditions under which that happens. But it
4094 causes Memcheck to complain, confusingly. So disable this check
4095 for the time being.
4097 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
4099 PRE_MEM_WRITE("getdirentries64(buf)", ARG2, ARG3);
4101 POST(getdirentries64)
4103 /* Disabled; see comments in the PRE wrapper.
4104 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
4106 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
4107 POST_MEM_WRITE(ARG2, RES);
4111 PRE(statfs64)
4113 PRINT("statfs64 ( %#lx(%s), %#lx )", ARG1, (HChar *)ARG1, ARG2);
4114 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
4115 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
4116 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4118 POST(statfs64)
4120 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4124 PRE(fstatfs64)
4126 PRINT("fstatfs64 ( %lu, %#lx )", ARG1, ARG2);
4127 PRE_REG_READ2(long, "fstatfs64",
4128 unsigned int, fd, struct statfs *, buf);
4129 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
4131 POST(fstatfs64)
4133 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
4136 PRE(csops)
4138 PRINT("csops ( %ld, %#lx, %#lx, %lu )", SARG1, ARG2, ARG3, ARG4);
4139 PRE_REG_READ4(int, "csops",
4140 vki_pid_t, pid, uint32_t, ops,
4141 void *, useraddr, vki_size_t, usersize);
4143 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
4145 // If the pid is ours, don't mark the program as KILL or HARD
4146 // Maybe we should keep track of this for later calls to STATUS
4147 if (!ARG1 || VG_(getpid)() == ARG1) {
4148 switch (ARG2) {
4149 case VKI_CS_OPS_MARKINVALID:
4150 case VKI_CS_OPS_MARKHARD:
4151 case VKI_CS_OPS_MARKKILL:
4152 SET_STATUS_Success(0);
4156 POST(csops)
4158 POST_MEM_WRITE( ARG3, ARG4 );
4161 PRE(auditon)
4163 PRINT("auditon ( %ld, %#lx, %lu )", SARG1, ARG2, ARG3);
4164 PRE_REG_READ3(int,"auditon",
4165 int,"cmd", void*,"data", unsigned int,"length");
4167 switch (ARG1) {
4169 case VKI_A_SETPOLICY:
4170 case VKI_A_SETKMASK:
4171 case VKI_A_SETQCTRL:
4172 case VKI_A_SETCOND:
4173 case VKI_A_SETCLASS:
4174 case VKI_A_SETPMASK:
4175 case VKI_A_SETFSIZE:
4176 #if DARWIN_VERS >= DARWIN_10_6
4177 case VKI_A_SENDTRIGGER:
4178 #endif
4179 // kernel reads data..data+length
4180 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4181 break;
4183 case VKI_A_GETKMASK:
4184 case VKI_A_GETPOLICY:
4185 case VKI_A_GETQCTRL:
4186 case VKI_A_GETFSIZE:
4187 case VKI_A_GETCOND:
4188 // kernel writes data..data+length
4189 // GrP fixme be precise about what gets written
4190 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4191 break;
4194 case VKI_A_GETCLASS:
4195 case VKI_A_GETPINFO:
4196 case VKI_A_GETPINFO_ADDR:
4197 #if DARWIN_VERS >= DARWIN_10_6
4198 case VKI_A_GETSINFO_ADDR:
4199 #endif
4200 // kernel reads and writes data..data+length
4201 // GrP fixme be precise about what gets read and written
4202 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4203 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4204 break;
4206 case VKI_A_SETKAUDIT:
4207 case VKI_A_SETSTAT:
4208 case VKI_A_SETUMASK:
4209 case VKI_A_SETSMASK:
4210 case VKI_A_GETKAUDIT:
4211 case VKI_A_GETCWD:
4212 case VKI_A_GETCAR:
4213 case VKI_A_GETSTAT:
4214 // unimplemented on darwin
4215 break;
4217 default:
4218 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld\n", ARG1);
4219 break;
4222 POST(auditon)
4224 switch (ARG1) {
4226 case VKI_A_SETPOLICY:
4227 case VKI_A_SETKMASK:
4228 case VKI_A_SETQCTRL:
4229 case VKI_A_SETCOND:
4230 case VKI_A_SETCLASS:
4231 case VKI_A_SETPMASK:
4232 case VKI_A_SETFSIZE:
4233 #if DARWIN_VERS >= DARWIN_10_6
4234 case VKI_A_SENDTRIGGER:
4235 #endif
4236 // kernel reads data..data+length
4237 break;
4239 case VKI_A_GETKMASK:
4240 case VKI_A_GETPOLICY:
4241 case VKI_A_GETQCTRL:
4242 case VKI_A_GETFSIZE:
4243 case VKI_A_GETCOND:
4244 // kernel writes data..data+length
4245 // GrP fixme be precise about what gets written
4246 POST_MEM_WRITE(ARG2, ARG3);
4247 break;
4250 case VKI_A_GETCLASS:
4251 case VKI_A_GETPINFO:
4252 case VKI_A_GETPINFO_ADDR:
4253 #if DARWIN_VERS >= DARWIN_10_6
4254 case VKI_A_GETSINFO_ADDR:
4255 #endif
4256 // kernel reads and writes data..data+length
4257 // GrP fixme be precise about what gets read and written
4258 POST_MEM_WRITE(ARG2, ARG3);
4259 break;
4261 case VKI_A_SETKAUDIT:
4262 case VKI_A_SETSTAT:
4263 case VKI_A_SETUMASK:
4264 case VKI_A_SETSMASK:
4265 case VKI_A_GETKAUDIT:
4266 case VKI_A_GETCWD:
4267 case VKI_A_GETCAR:
4268 case VKI_A_GETSTAT:
4269 // unimplemented on darwin
4270 break;
4272 default:
4273 break;
4277 PRE(getaudit_addr)
4279 PRINT("getaudit_addr(%#lx, %ld)", ARG1, SARG2);
4280 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
4281 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
4283 POST(getaudit_addr)
4285 POST_MEM_WRITE(ARG1, ARG2);
4289 PRE(mmap)
4291 // SysRes r;
4292 if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
4294 #if VG_WORDSIZE == 4
4295 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %llu )",
4296 ARG1, ARG2, SARG3, SARG4, SARG5, LOHI64(ARG6, ARG7) );
4297 PRE_REG_READ7(Addr, "mmap",
4298 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4299 unsigned long,offset_hi, unsigned long,offset_lo);
4300 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4301 // V's mechanism for now
4302 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4303 // (Off64T)LOHI64(ARG6, ARG7) );
4304 #else
4305 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4306 ARG1, ARG2, SARG3, SARG4, SARG5, SARG6 );
4307 PRE_REG_READ6(long, "mmap",
4308 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4309 Off64T,offset);
4310 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4312 #endif
4314 // SET_STATUS_from_SysRes(r);
4317 POST(mmap)
4319 if (RES != -1) {
4320 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
4321 // Try to load symbols from the region
4322 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
4323 -1/*don't use_fd*/ );
4324 ML_(sync_mappings)("after", "mmap", 0);
4329 /* This function holds common elements of PRE(__sysctl) and
4330 PRE(sysctlbyname). */
4331 static void common_PRE_sysctl (
4332 /*IMPLICIT ARGS*/
4333 ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
4334 /*!IMPLICIT ARGS*/
4335 Bool is_kern_dot_userstack,
4336 UWord oldp, UWord oldlenp,
4337 UWord newp, UWord newlen )
4339 if (oldlenp) {
4340 // writes *oldlenp
4341 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4342 if (oldp) {
4343 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4344 PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4345 PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
4348 if (newp) {
4349 PRE_MEM_READ("sysctl(newp)", newp, newlen);
4352 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4353 // (executable path and arguments and environment
4355 if (is_kern_dot_userstack) {
4356 // Intercept sysctl(kern.usrstack). The kernel's reply
4357 // would be Valgrind's stack, not the client's stack.
4358 // GrP fixme kern_usrstack64 */
4359 if (newp || newlen) {
4360 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
4361 } else {
4362 Addr* t_oldp = (Addr*)oldp;
4363 size_t* t_oldlenp = (size_t*)oldlenp;
4364 if (t_oldlenp) {
4365 // According to some searches on the net, it looks like
4366 // USRSTACK gives the address of the byte following the
4367 // highest byte of the stack. As VG_(clstk_end) is the
4368 // address of the highest addressable byte, we add 1.
4369 Addr stack_end = VG_(clstk_end)+1;
4370 size_t oldlen = *t_oldlenp;
4371 // always return actual size
4372 *t_oldlenp = sizeof(Addr);
4373 if (t_oldp && oldlen >= sizeof(Addr)) {
4374 // oldp is big enough. copy value and return 0
4375 *t_oldp = stack_end;
4376 SET_STATUS_Success(0);
4377 } else {
4378 // oldp isn't big enough. copy as much as possible
4379 // and return ENOMEM
4380 if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
4381 SET_STATUS_Failure(VKI_ENOMEM);
4387 if (!SUCCESS && !FAILURE) {
4388 // Don't set SfPostOnFail if we've already handled it locally.
4389 *flags |= SfPostOnFail;
4394 PRE(__sysctl)
4396 UWord name = ARG1;
4397 UWord namelen = ARG2;
4398 UWord oldp = ARG3;
4399 UWord oldlenp = ARG4;
4400 UWord newp = ARG5;
4401 UWord newlen = ARG6;
4403 PRINT( "__sysctl ( %#lx, %lu, %#lx, %#lx, %#lx, %#lx )",
4404 name, namelen, oldp, oldlenp, newp, newlen );
4406 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
4407 void*, oldp, vki_size_t *, oldlenp,
4408 void*, newp, vki_size_t *, newlenp);
4410 PRE_MEM_READ("sysctl(name)", name, namelen); // reads name[0..namelen-1]
4412 if (VG_(clo_trace_syscalls)) {
4413 UInt i;
4414 Int* t_name = (Int*)name;
4415 VG_(printf)(" mib: [ ");
4416 for (i = 0; i < namelen; i++) {
4417 VG_(printf)("%d ", t_name[i]);
4419 VG_(printf)("]");
4422 Int vKI_KERN_USRSTACKXX
4423 = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64;
4424 Bool is_kern_dot_userstack
4425 = name && namelen == 2
4426 && ((Int*)name)[0] == VKI_CTL_KERN
4427 && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
4429 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
4430 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
4433 POST(__sysctl)
4435 UWord oldp = ARG3;
4436 UWord oldlenp = ARG4;
4438 if (SUCCESS || ERR == VKI_ENOMEM) {
4439 // sysctl can write truncated data and return VKI_ENOMEM
4440 if (oldlenp) {
4441 POST_MEM_WRITE(oldlenp, sizeof(size_t));
4443 if (oldp && oldlenp) {
4444 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
4450 PRE(sigpending)
4452 PRINT( "sigpending ( %#lx )", ARG1 );
4453 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
4454 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
4456 POST(sigpending)
4458 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
4462 PRE(sigprocmask)
4464 UWord arg1;
4465 PRINT("sigprocmask ( %ld, %#lx, %#lx )", SARG1, ARG2, ARG3);
4466 PRE_REG_READ3(long, "sigprocmask",
4467 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
4468 if (ARG2 != 0)
4469 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4470 if (ARG3 != 0)
4471 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
4473 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4474 value of 'how' is irrelevant, and it appears that Darwin's libc
4475 passes zero, which is not equal to any of
4476 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4477 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4478 value independently of the other args. Solution: in this case,
4479 simply pass a valid (but irrelevant) value for 'how'. */
4480 /* Also, in this case the new set is passed to the kernel by
4481 reference, not value, as in some other sigmask related Darwin
4482 syscalls. */
4483 arg1 = ARG1;
4484 if (ARG2 == 0 /* the new-set is NULL */
4485 && ARG1 != VKI_SIG_BLOCK
4486 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
4487 arg1 = VKI_SIG_SETMASK;
4489 SET_STATUS_from_SysRes(
4490 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
4491 (vki_sigset_t*)ARG3 )
4494 if (SUCCESS)
4495 *flags |= SfPollAfter;
4498 POST(sigprocmask)
4500 vg_assert(SUCCESS);
4501 if (RES == 0 && ARG3 != 0)
4502 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
4506 PRE(sigsuspend)
4508 /* Just hand this off to the kernel. Is that really correct? And
4509 shouldn't we at least set SfPollAfter? These questions apply to
4510 all the Linux versions too. */
4511 /* I think the first arg is the 32-bit signal mask (by value), and
4512 the other two args are ignored. */
4513 *flags |= SfMayBlock;
4514 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
4515 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
4519 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4520 and 32-bit wrappers are different.
4522 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4523 length in the usual way. I have seen values NULL, 0 passed in some
4524 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4525 basis that they don't do anything if the length is zero, so it's OK
4526 for the buffer pointer to be NULL in that case (meaning they don't
4527 complain).
4529 int proc_info(int32_t callnum, int32_t pid,
4530 uint32_t flavor, uint64_t arg,
4531 user_addr_t buffer, int32_t buffersize)
4533 PRE(proc_info)
4535 #if VG_WORDSIZE == 4
4536 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4537 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
4538 PRE_REG_READ7(int, "proc_info",
4539 int, callnum, int, pid, unsigned int, flavor,
4540 vki_uint32_t, arg_low32,
4541 vki_uint32_t, arg_high32,
4542 void*, buffer, int, buffersize);
4543 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
4544 #else
4545 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4546 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
4547 PRE_REG_READ6(int, "proc_info",
4548 int, callnum, int, pid, unsigned int, flavor,
4549 unsigned long long int, arg,
4550 void*, buffer, int, buffersize);
4551 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
4552 #endif
4555 POST(proc_info)
4557 #if VG_WORDSIZE == 4
4558 vg_assert(SUCCESS);
4560 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4561 if (ARG1 == 5 && ARG3 == 2 && LOHI64(ARG4,ARG5) == 0 )
4563 const HChar* new_name = (const HChar*) ARG6;
4564 if (new_name) { // Paranoia
4565 ThreadState* tst = VG_(get_ThreadState)(tid);
4566 SizeT new_len = VG_(strlen)(new_name);
4568 /* Don't bother reusing the memory. This is a rare event. */
4569 tst->thread_name =
4570 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4571 VG_(strcpy)(tst->thread_name, new_name);
4575 POST_MEM_WRITE(ARG6, ARG7);
4576 #else
4577 vg_assert(SUCCESS);
4579 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4580 if (ARG1 == 5 && ARG3 == 2 && ARG4 == 0 )
4582 const HChar* new_name = (const HChar*) ARG5;
4583 if (new_name) { // Paranoia
4584 ThreadState* tst = VG_(get_ThreadState)(tid);
4585 SizeT new_len = VG_(strlen)(new_name);
4587 /* Don't bother reusing the memory. This is a rare event. */
4588 tst->thread_name =
4589 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4590 VG_(strcpy)(tst->thread_name, new_name);
4594 POST_MEM_WRITE(ARG5, ARG6);
4595 #endif
4599 /* ---------------------------------------------------------------------
4600 aio_*
4601 ------------------------------------------------------------------ */
4603 // We must record the aiocbp for each aio_read() in a table so that when
4604 // aio_return() is called we can mark the memory written asynchronously by
4605 // aio_read() as having been written. We don't have to do this for
4606 // aio_write(). See bug 197227 for more details.
4607 static OSet* aiocbp_table = NULL;
4608 static Bool aio_init_done = False;
4610 static void aio_init(void)
4612 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
4613 aio_init_done = True;
4616 PRE(aio_return)
4618 // This assumes that the kernel looks at the struct pointer, but not the
4619 // contents of the struct.
4620 PRINT( "aio_return ( %#lx )", ARG1 );
4621 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
4622 if (ML_(safe_to_deref)((struct vki_aiocb *)ARG1, sizeof(struct vki_aiocb))) {
4623 SET_STATUS_from_SysRes(VG_(do_syscall1)(SYSNO, ARG1));
4624 if (SUCCESS && RES >= 0) {
4625 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4626 if (!aio_init_done) {
4627 aio_init();
4629 if (VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp)) {
4630 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4633 } else {
4634 SET_STATUS_Failure(VKI_EINVAL);
4639 PRE(aio_suspend)
4641 // This assumes that the kernel looks at the struct pointers in the list,
4642 // but not the contents of the structs.
4643 PRINT( "aio_suspend ( %#lx )", ARG1 );
4644 PRE_REG_READ3(long, "aio_suspend",
4645 const struct vki_aiocb * const *, aiocbp, int, nent,
4646 const struct vki_timespec *, timeout);
4647 if (ARG2 > 0) {
4648 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
4650 if (ARG3) {
4651 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
4655 PRE(aio_error)
4657 // This assumes that the kernel looks at the struct pointer, but not the
4658 // contents of the struct.
4659 PRINT( "aio_error ( %#lx )", ARG1 );
4660 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
4663 PRE(aio_read)
4665 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4667 PRINT( "aio_read ( %#lx )", ARG1 );
4668 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4669 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4671 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4672 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4673 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4674 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4675 } else {
4676 SET_STATUS_Failure( VKI_EBADF );
4678 } else {
4679 SET_STATUS_Failure( VKI_EINVAL );
4682 POST(aio_read)
4684 // We have to record the fact that there is an asynchronous read request
4685 // pending. When a successful aio_return() occurs for this aiocb, then we
4686 // will mark the memory as having been defined.
4687 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4688 if (!aio_init_done) aio_init();
4689 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4690 // should have caused the aio_read() to fail and we shouldn't have reached
4691 // here.
4692 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4695 PRE(aio_write)
4697 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4699 PRINT( "aio_write ( %#lx )", ARG1 );
4700 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4701 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4703 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4704 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4705 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4706 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4707 } else {
4708 SET_STATUS_Failure( VKI_EBADF );
4710 } else {
4711 SET_STATUS_Failure( VKI_EINVAL );
4715 /* ---------------------------------------------------------------------
4716 mach_msg: formatted messages
4717 ------------------------------------------------------------------ */
4719 static size_t desc_size(mach_msg_descriptor_t *desc)
4721 switch (desc->type.type) {
4722 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
4723 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
4724 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
4725 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
4726 default:
4727 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4728 return sizeof(desc->type); // guess
4733 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4734 const char *name)
4736 mach_msg_size_t i;
4737 mach_port_t *ports = (mach_port_t *)desc->address;
4738 for (i = 0; i < desc->count; i++) {
4739 assign_port_name(ports[i], name);
4744 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4746 mach_msg_body_t *body;
4747 mach_msg_size_t count, i;
4748 uint8_t *p;
4749 mach_msg_descriptor_t *desc;
4751 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4753 body = (mach_msg_body_t *)(mh+1);
4754 count = body->msgh_descriptor_count;
4755 p = (uint8_t *)(body+1);
4757 for (i = 0; i < count; i++) {
4758 desc = (mach_msg_descriptor_t *)p;
4759 p += desc_size(desc);
4761 switch (desc->type.type) {
4762 case MACH_MSG_PORT_DESCRIPTOR:
4763 // single port
4764 record_unnamed_port(tid, desc->port.name, -1);
4765 record_port_insert_rights(desc->port.name, desc->port.disposition);
4766 PRINT("got port %s;\n", name_for_port(desc->port.name));
4767 break;
4769 case MACH_MSG_OOL_DESCRIPTOR:
4770 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4771 // out-of-line memory - map it
4772 // GrP fixme how is VOLATILE different? do we care?
4773 // GrP fixme do other flags tell us anything? assume shared for now
4774 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4775 // GrP fixme protection
4776 if (desc->out_of_line.size > 0) {
4777 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4778 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4779 (Addr)desc->out_of_line.size);
4780 PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4781 (char*)desc->out_of_line.address+desc->out_of_line.size);
4783 ML_(notify_core_and_tool_of_mmap)(
4784 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4785 VKI_MAP_PRIVATE, -1, 0);
4787 // GrP fixme mark only un-rounded part as initialized
4788 break;
4790 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4791 // out-of-line array of ports - map it
4792 // GrP fixme see fixmes above
4793 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));
4795 if (desc->ool_ports.count > 0) {
4796 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4797 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4798 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4800 ML_(notify_core_and_tool_of_mmap)(
4801 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4802 VKI_MAP_PRIVATE, -1, 0);
4804 PRINT(":");
4805 for (i = 0; i < desc->ool_ports.count; i++) {
4806 record_unnamed_port(tid, ports[i], -1);
4807 record_port_insert_rights(ports[i], desc->port.disposition);
4808 PRINT(" %s", name_for_port(ports[i]));
4811 PRINT(";\n");
4812 break;
4814 default:
4815 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4816 break;
4822 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4824 #pragma pack(4)
4825 struct {
4826 mach_port_t name;
4827 mach_msg_size_t pad1;
4828 uint16_t pad2;
4829 uint8_t disposition;
4830 uint8_t type;
4831 } *desc = (void*)desc2;
4832 #pragma pack()
4834 PRE_FIELD_READ("msg->desc.port.name", desc->name);
4835 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4836 PRE_FIELD_READ("msg->desc.port.type", desc->type);
4840 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4842 #pragma pack(4)
4843 struct {
4844 Addr address;
4845 #if VG_WORDSIZE != 8
4846 mach_msg_size_t size;
4847 #endif
4848 uint8_t deallocate;
4849 uint8_t copy;
4850 uint8_t pad1;
4851 uint8_t type;
4852 #if VG_WORDSIZE == 8
4853 mach_msg_size_t size;
4854 #endif
4855 } *desc = (void*)desc2;
4856 #pragma pack()
4858 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4859 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4860 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4861 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4862 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4865 static void pre_oolports_desc_read(ThreadId tid,
4866 mach_msg_ool_ports_descriptor_t *desc2)
4868 #pragma pack(4)
4869 struct {
4870 Addr address;
4871 #if VG_WORDSIZE != 8
4872 mach_msg_size_t size;
4873 #endif
4874 uint8_t deallocate;
4875 uint8_t copy;
4876 uint8_t disposition;
4877 uint8_t type;
4878 #if VG_WORDSIZE == 8
4879 mach_msg_size_t size;
4880 #endif
4881 } *desc = (void*)desc2;
4882 #pragma pack()
4884 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4885 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4886 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4887 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4888 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4889 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4893 // Returns the size of the descriptor area
4894 // (mach_msg_body_t + any mach_msg_descriptor_t)
4895 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4897 mach_msg_body_t *body;
4898 mach_msg_size_t count, i;
4899 uint8_t *p;
4900 mach_msg_descriptor_t *desc;
4902 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4904 body = (mach_msg_body_t *)(mh+1);
4905 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4907 count = body->msgh_descriptor_count;
4908 p = (uint8_t *)(body+1);
4910 for (i = 0; i < count; i++) {
4911 desc = (mach_msg_descriptor_t *)p;
4912 p += desc_size(desc);
4914 switch (desc->type.type) {
4915 case MACH_MSG_PORT_DESCRIPTOR:
4916 // single port; no memory map effects
4917 pre_port_desc_read(tid, &desc->port);
4918 break;
4920 case MACH_MSG_OOL_DESCRIPTOR:
4921 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4922 // out-of-line memory - unmap it if it's marked dealloc
4923 // GrP fixme need to remap if message fails?
4924 // GrP fixme how is VOLATILE different? do we care?
4925 // GrP fixme struct is different for lp64
4926 pre_ool_desc_read(tid, &desc->out_of_line);
4928 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4929 vm_size_t size = desc->out_of_line.size;
4930 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4931 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4932 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4933 (Addr)desc->out_of_line.address + size);
4934 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4936 break;
4938 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4939 // out-of-line array of ports - unmap it if it's marked dealloc
4940 // GrP fixme need to remap if message fails?
4941 // GrP fixme struct different for lp64
4942 pre_oolports_desc_read(tid, &desc->ool_ports);
4944 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4945 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4946 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4947 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4948 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4949 (Addr)desc->ool_ports.address + size);
4950 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4952 break;
4953 default:
4954 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4955 break;
4959 return (size_t)((Addr)p - (Addr)body);
4963 /* ---------------------------------------------------------------------
4964 mach_msg: host-related messages
4965 ------------------------------------------------------------------ */
4968 POST(host_info)
4970 #pragma pack(4)
4971 typedef struct {
4972 mach_msg_header_t Head;
4973 NDR_record_t NDR;
4974 kern_return_t RetCode;
4975 mach_msg_type_number_t host_info_outCnt;
4976 integer_t host_info_out[14];
4977 } Reply;
4978 #pragma pack()
4980 Reply *reply = (Reply *)ARG1;
4982 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4985 PRE(host_info)
4987 #pragma pack(4)
4988 typedef struct {
4989 mach_msg_header_t Head;
4990 NDR_record_t NDR;
4991 host_flavor_t flavor;
4992 mach_msg_type_number_t host_info_outCnt;
4993 } Request;
4994 #pragma pack()
4996 Request *req = (Request *)ARG1;
4998 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
5000 AFTER = POST_FN(host_info);
5004 POST(host_page_size)
5006 #pragma pack(4)
5007 typedef struct {
5008 mach_msg_header_t Head;
5009 NDR_record_t NDR;
5010 kern_return_t RetCode;
5011 vm_size_t out_page_size;
5012 } Reply;
5013 #pragma pack()
5015 Reply *reply = (Reply *)ARG1;
5017 if (!reply->RetCode) {
5018 PRINT("page size %llu", (ULong)reply->out_page_size);
5019 } else {
5020 PRINT("mig return %d", reply->RetCode);
5024 PRE(host_page_size)
5026 PRINT("host_page_size(mach_host_self(), ...)");
5028 AFTER = POST_FN(host_page_size);
5032 POST(host_get_io_master)
5034 #pragma pack(4)
5035 typedef struct {
5036 mach_msg_header_t Head;
5037 /* start of the kernel processed data */
5038 mach_msg_body_t msgh_body;
5039 mach_msg_port_descriptor_t io_master;
5040 /* end of the kernel processed data */
5041 } Reply;
5042 #pragma pack()
5044 Reply *reply = (Reply *)ARG1;
5046 assign_port_name(reply->io_master.name, "io_master-%p");
5047 PRINT("%s", name_for_port(reply->io_master.name));
5050 PRE(host_get_io_master)
5052 //#pragma pack(4)
5053 // typedef struct {
5054 // mach_msg_header_t Head;
5055 // } Request;
5056 //#pragma pack()
5058 // Request *req = (Request *)ARG1;
5060 PRINT("host_get_io_master(mach_host_self())");
5062 AFTER = POST_FN(host_get_io_master);
5066 POST(host_get_clock_service)
5068 #pragma pack(4)
5069 typedef struct {
5070 mach_msg_header_t Head;
5071 /* start of the kernel processed data */
5072 mach_msg_body_t msgh_body;
5073 mach_msg_port_descriptor_t clock_serv;
5074 /* end of the kernel processed data */
5075 } Reply;
5076 #pragma pack()
5078 Reply *reply = (Reply *)ARG1;
5080 assign_port_name(reply->clock_serv.name, "clock-%p");
5081 PRINT("%s", name_for_port(reply->clock_serv.name));
5084 PRE(host_get_clock_service)
5086 #pragma pack(4)
5087 typedef struct {
5088 mach_msg_header_t Head;
5089 NDR_record_t NDR;
5090 clock_id_t clock_id;
5091 } Request;
5092 #pragma pack()
5094 Request *req = (Request *)ARG1;
5096 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
5098 AFTER = POST_FN(host_get_clock_service);
5102 PRE(host_request_notification)
5104 #pragma pack(4)
5105 typedef struct {
5106 mach_msg_header_t Head;
5107 /* start of the kernel processed data */
5108 mach_msg_body_t msgh_body;
5109 mach_msg_port_descriptor_t notify_port;
5110 /* end of the kernel processed data */
5111 NDR_record_t NDR;
5112 host_flavor_t notify_type;
5113 } Request;
5114 #pragma pack()
5116 Request *req = (Request *)ARG1;
5118 if (MACH_REMOTE == mach_task_self()) {
5119 if (req->notify_type == 0) {
5120 PRINT("host_request_notification(mach_host_self(), %s, %s)",
5121 "HOST_NOTIFY_CALENDAR_CHANGE",
5122 name_for_port(req->notify_port.name));
5123 } else {
5124 PRINT("host_request_notification(mach_host_self(), %d, %s)",
5125 req->notify_type,
5126 name_for_port(req->notify_port.name));
5128 } else {
5129 PRINT("host_request_notification(%s, %d, %s)",
5130 name_for_port(MACH_REMOTE),
5131 req->notify_type,
5132 name_for_port(req->notify_port.name));
5135 // GrP fixme only do this on success
5136 assign_port_name(req->notify_port.name, "host_notify-%p");
5140 PRE(host_create_mach_voucher)
5142 #pragma pack(4)
5143 typedef struct {
5144 mach_msg_header_t Head;
5145 NDR_record_t NDR;
5146 mach_msg_type_number_t recipesCnt;
5147 uint8_t recipes[5120];
5148 } Request;
5149 #pragma pack()
5151 Request *req = (Request *)ARG1;
5153 PRINT("host_create_mach_voucher(count %u)",
5154 req->recipesCnt);
5156 AFTER = POST_FN(host_create_mach_voucher);
5160 POST(host_create_mach_voucher)
5162 #pragma pack(4)
5163 typedef struct {
5164 mach_msg_header_t Head;
5165 /* start of the kernel processed data */
5166 mach_msg_body_t msgh_body;
5167 mach_msg_port_descriptor_t voucher;
5168 /* end of the kernel processed data */
5169 } Reply;
5170 #pragma pack()
5172 Reply *reply = (Reply *)ARG1;
5174 // RK fixme properly parse this return type
5175 PRINT("got voucher %#x ", reply->voucher.name);
5179 PRE(host_get_special_port)
5181 #pragma pack(4)
5182 typedef struct {
5183 mach_msg_header_t Head;
5184 NDR_record_t NDR;
5185 int node;
5186 int which;
5187 } Request;
5188 #pragma pack()
5190 Request *req = (Request *)ARG1;
5192 PRINT("host_get_special_port(node %d)", req->node);
5194 switch (req->which) {
5195 case HOST_PORT:
5196 PRINT("host_get_special_port(%s, HOST_PORT)",
5197 name_for_port(MACH_REMOTE));
5198 break;
5199 case HOST_PRIV_PORT:
5200 PRINT("host_get_special_port(%s, HOST_PRIV_PORT)",
5201 name_for_port(MACH_REMOTE));
5202 break;
5203 case HOST_IO_MASTER_PORT:
5204 PRINT("host_get_special_port(%s, HOST_IO_MASTER_PORT)",
5205 name_for_port(MACH_REMOTE));
5206 break;
5207 // Not provided by kernel
5208 case HOST_DYNAMIC_PAGER_PORT:
5209 PRINT("host_get_special_port(%s, HOST_DYNAMIC_PAGER_PORT)",
5210 name_for_port(MACH_REMOTE));
5211 break;
5212 case HOST_AUDIT_CONTROL_PORT:
5213 PRINT("host_get_special_port(%s, HOST_AUDIT_CONTROL_PORT)",
5214 name_for_port(MACH_REMOTE));
5215 break;
5216 case HOST_USER_NOTIFICATION_PORT:
5217 PRINT("host_get_special_port(%s, HOST_USER_NOTIFICATION_PORT)",
5218 name_for_port(MACH_REMOTE));
5219 break;
5220 // ...
5222 default:
5223 PRINT("host_get_special_port(%s, %d)",
5224 name_for_port(MACH_REMOTE), req->which);
5225 break;
5228 MACH_ARG(host_get_special_port.which) = req->which;
5230 AFTER = POST_FN(host_get_special_port);
5234 POST(host_get_special_port)
5236 #pragma pack(4)
5237 typedef struct {
5238 mach_msg_header_t Head;
5239 /* start of the kernel processed data */
5240 mach_msg_body_t msgh_body;
5241 mach_msg_port_descriptor_t port;
5242 /* end of the kernel processed data */
5243 } Reply;
5244 #pragma pack()
5246 Reply *reply = (Reply *)ARG1;
5248 PRINT("got port %#x ", reply->port.name);
5250 /* The required entry in the allocated_ports list (mapping) might
5251 not exist, due perhaps to broken syscall wrappers (mach__N etc).
5252 Create a minimal entry so that assign_port_name below doesn't
5253 cause an assertion. */
5254 if (!port_exists(reply->port.name)) {
5255 port_create_vanilla(reply->port.name);
5258 switch (MACH_ARG(host_get_special_port.which)) {
5259 case HOST_PORT:
5260 assign_port_name(reply->port.name, "port-%p");
5261 break;
5262 case HOST_PRIV_PORT:
5263 assign_port_name(reply->port.name, "priv-%p");
5264 break;
5265 case HOST_IO_MASTER_PORT:
5266 assign_port_name(reply->port.name, "io-master-%p");
5267 break;
5268 // Not provided by kernel
5269 case HOST_DYNAMIC_PAGER_PORT:
5270 assign_port_name(reply->port.name, "dynamic-pager-%p");
5271 break;
5272 case HOST_AUDIT_CONTROL_PORT:
5273 assign_port_name(reply->port.name, "audit-control-%p");
5274 break;
5275 case HOST_USER_NOTIFICATION_PORT:
5276 assign_port_name(reply->port.name, "user-notification-%p");
5277 break;
5278 // ...
5280 default:
5281 assign_port_name(reply->port.name, "special-%p");
5282 break;
5285 PRINT("%s", name_for_port(reply->port.name));
5288 /* ---------------------------------------------------------------------
5289 mach_msg: messages to a task
5290 ------------------------------------------------------------------ */
5292 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
5293 // these structs are derived. They obviously relate to the various
5294 // .def files in the xnu sources, and can also be found in some
5295 // form in /usr/include/mach/*.h, but not sure how these all
5296 // relate to each other.
5298 PRE(mach_port_set_context)
5300 #pragma pack(4)
5301 typedef struct {
5302 mach_msg_header_t Head;
5303 NDR_record_t NDR;
5304 mach_port_name_t name;
5305 mach_vm_address_t context;
5306 } Request;
5307 #pragma pack()
5309 Request *req = (Request *)ARG1;
5311 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
5312 name_for_port(MACH_REMOTE),
5313 name_for_port(req->name), req->context);
5315 AFTER = POST_FN(mach_port_set_context);
5318 POST(mach_port_set_context)
5320 //#pragma pack(4)
5321 // typedef struct {
5322 // mach_msg_header_t Head;
5323 // NDR_record_t NDR;
5324 // kern_return_t RetCode;
5325 // } Reply;
5326 //#pragma pack()
5330 // JRS 2011-Aug-25 FIXME completely bogus
5331 PRE(task_get_exception_ports)
5333 //#pragma pack(4)
5334 // typedef struct {
5335 // mach_msg_header_t Head;
5336 // NDR_record_t NDR;
5337 // exception_mask_t exception_mask;
5338 // } Request;
5339 //#pragma pack()
5341 PRINT("task_get_exception_ports(BOGUS)");
5342 AFTER = POST_FN(task_get_exception_ports);
5345 POST(task_get_exception_ports)
5347 //#pragma pack(4)
5348 // typedef struct {
5349 // mach_msg_header_t Head;
5350 // /* start of the kernel processed data */
5351 // mach_msg_body_t msgh_body;
5352 // mach_msg_port_descriptor_t old_handlers[32];
5353 // /* end of the kernel processed data */
5354 // NDR_record_t NDR;
5355 // mach_msg_type_number_t masksCnt;
5356 // exception_mask_t masks[32];
5357 // exception_behavior_t old_behaviors[32];
5358 // thread_state_flavor_t old_flavors[32];
5359 // } Reply;
5360 //#pragma pack()
5364 ///////////////////////////////////////////////////
5366 PRE(mach_port_type)
5368 #pragma pack(4)
5369 typedef struct {
5370 mach_msg_header_t Head;
5371 NDR_record_t NDR;
5372 mach_port_name_t name;
5373 } Request;
5374 #pragma pack()
5376 Request *req = (Request *)ARG1;
5378 PRINT("mach_port_type(%s, %s, ...)",
5379 name_for_port(MACH_REMOTE), name_for_port(req->name));
5381 AFTER = POST_FN(mach_port_type);
5384 POST(mach_port_type)
5389 PRE(mach_port_extract_member)
5391 #pragma pack(4)
5392 typedef struct {
5393 mach_msg_header_t Head;
5394 NDR_record_t NDR;
5395 mach_port_name_t name;
5396 mach_port_name_t pset;
5397 } Request;
5398 #pragma pack()
5400 Request *req = (Request *)ARG1;
5402 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5403 name_for_port(MACH_REMOTE),
5404 req->name, req->pset);
5406 AFTER = POST_FN(mach_port_extract_member);
5408 // GrP fixme port tracker?
5411 POST(mach_port_extract_member)
5413 #pragma pack(4)
5414 typedef struct {
5415 mach_msg_header_t Head;
5416 NDR_record_t NDR;
5417 kern_return_t RetCode;
5418 } Reply;
5419 #pragma pack()
5421 Reply *reply = (Reply *)ARG1;
5423 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
5427 PRE(mach_port_allocate)
5429 #pragma pack(4)
5430 typedef struct {
5431 mach_msg_header_t Head;
5432 NDR_record_t NDR;
5433 mach_port_right_t right;
5434 } Request;
5435 #pragma pack()
5437 Request *req = (Request *)ARG1;
5439 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
5441 MACH_ARG(mach_port_allocate.right) = req->right;
5443 AFTER = POST_FN(mach_port_allocate);
5446 POST(mach_port_allocate)
5448 #pragma pack(4)
5449 typedef struct {
5450 mach_msg_header_t Head;
5451 NDR_record_t NDR;
5452 kern_return_t RetCode;
5453 mach_port_name_t name;
5454 } Reply;
5455 #pragma pack()
5457 Reply *reply = (Reply *)ARG1;
5459 if (!reply->RetCode) {
5460 if (MACH_REMOTE == vg_task_port) {
5461 // GrP fixme port tracking is too imprecise
5462 // vg_assert(!port_exists(reply->name));
5463 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
5464 PRINT("got port 0x%x", reply->name);
5465 } else {
5466 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
5468 } else {
5469 PRINT("mig return %d", reply->RetCode);
5474 PRE(mach_port_deallocate)
5476 #pragma pack(4)
5477 typedef struct {
5478 mach_msg_header_t Head;
5479 NDR_record_t NDR;
5480 mach_port_name_t name;
5481 } Request;
5482 #pragma pack()
5484 Request *req = (Request *)ARG1;
5486 PRINT("mach_port_deallocate(%s, %s)",
5487 name_for_port(MACH_REMOTE),
5488 name_for_port(req->name));
5490 MACH_ARG(mach_port.port) = req->name;
5492 AFTER = POST_FN(mach_port_deallocate);
5494 // Must block to prevent race (other thread allocates and
5495 // notifies after we deallocate but before we notify)
5496 *flags &= ~SfMayBlock;
5499 POST(mach_port_deallocate)
5501 #pragma pack(4)
5502 typedef struct {
5503 mach_msg_header_t Head;
5504 NDR_record_t NDR;
5505 kern_return_t RetCode;
5506 } Reply;
5507 #pragma pack()
5509 Reply *reply = (Reply *)ARG1;
5511 if (!reply->RetCode) {
5512 if (MACH_REMOTE == vg_task_port) {
5513 // Must have cleared SfMayBlock in PRE to prevent race
5514 record_port_dealloc(MACH_ARG(mach_port.port));
5515 } else {
5516 VG_(printf)("UNKNOWN remote port dealloc\n");
5518 } else {
5519 PRINT("mig return %d", reply->RetCode);
5524 PRE(mach_port_get_refs)
5526 #pragma pack(4)
5527 typedef struct {
5528 mach_msg_header_t Head;
5529 NDR_record_t NDR;
5530 mach_port_name_t name;
5531 mach_port_right_t right;
5532 } Request;
5533 #pragma pack()
5535 Request *req = (Request *)ARG1;
5537 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5538 name_for_port(MACH_REMOTE),
5539 name_for_port(req->name), req->right);
5541 MACH_ARG(mach_port_mod_refs.port) = req->name;
5542 MACH_ARG(mach_port_mod_refs.right) = req->right;
5544 AFTER = POST_FN(mach_port_get_refs);
5547 POST(mach_port_get_refs)
5549 #pragma pack(4)
5550 typedef struct {
5551 mach_msg_header_t Head;
5552 NDR_record_t NDR;
5553 kern_return_t RetCode;
5554 mach_port_urefs_t refs;
5555 } Reply;
5556 #pragma pack()
5558 Reply *reply = (Reply *)ARG1;
5560 if (!reply->RetCode) {
5561 PRINT("got refs=%d", reply->refs);
5562 } else {
5563 PRINT("mig return %d", reply->RetCode);
5568 PRE(mach_port_mod_refs)
5570 #pragma pack(4)
5571 typedef struct {
5572 mach_msg_header_t Head;
5573 NDR_record_t NDR;
5574 mach_port_name_t name;
5575 mach_port_right_t right;
5576 mach_port_delta_t delta;
5577 } Request;
5578 #pragma pack()
5580 Request *req = (Request *)ARG1;
5582 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5583 name_for_port(MACH_REMOTE),
5584 name_for_port(req->name), req->right, req->delta);
5586 MACH_ARG(mach_port_mod_refs.port) = req->name;
5587 MACH_ARG(mach_port_mod_refs.right) = req->right;
5588 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
5590 AFTER = POST_FN(mach_port_mod_refs);
5592 // Must block to prevent race (other thread allocates and
5593 // notifies after we deallocate but before we notify)
5594 *flags &= ~SfMayBlock;
5597 POST(mach_port_mod_refs)
5599 #pragma pack(4)
5600 typedef struct {
5601 mach_msg_header_t Head;
5602 NDR_record_t NDR;
5603 kern_return_t RetCode;
5604 } Reply;
5605 #pragma pack()
5607 Reply *reply = (Reply *)ARG1;
5609 if (!reply->RetCode) {
5610 if (MACH_REMOTE == vg_task_port) {
5611 // Must have cleared SfMayBlock in PRE to prevent race
5612 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
5613 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
5614 MACH_ARG(mach_port_mod_refs.delta));
5615 } else {
5616 VG_(printf)("UNKNOWN remote port mod refs\n");
5618 } else {
5619 PRINT("mig return %d", reply->RetCode);
5624 PRE(mach_port_get_set_status)
5626 #pragma pack(4)
5627 typedef struct {
5628 mach_msg_header_t Head;
5629 NDR_record_t NDR;
5630 mach_port_name_t name;
5631 } Request;
5632 #pragma pack()
5634 Request *req = (Request *)ARG1;
5636 PRINT("mach_port_get_set_status(%s, %s)",
5637 name_for_port(MACH_REMOTE),
5638 name_for_port(req->name));
5640 AFTER = POST_FN(mach_port_get_set_status);
5643 POST(mach_port_get_set_status)
5645 //#pragma pack(4)
5646 // typedef struct {
5647 // mach_msg_header_t Head;
5648 // /* start of the kernel processed data */
5649 // mach_msg_body_t msgh_body;
5650 // mach_msg_ool_descriptor_t members;
5651 // /* end of the kernel processed data */
5652 // NDR_record_t NDR;
5653 // mach_msg_type_number_t membersCnt;
5654 // mach_msg_trailer_t trailer;
5655 // } Reply;
5656 //#pragma pack()
5658 // Reply *reply = (Reply *)ARG1;
5660 // GrP fixme nothing to do?
5664 PRE(mach_port_move_member)
5666 #pragma pack(4)
5667 typedef struct {
5668 mach_msg_header_t Head;
5669 NDR_record_t NDR;
5670 mach_port_name_t member;
5671 mach_port_name_t after;
5672 } Request;
5673 #pragma pack()
5675 Request *req = (Request *)ARG1;
5677 PRINT("mach_port_move_member(%s, %s, %s)",
5678 name_for_port(MACH_REMOTE),
5679 name_for_port(req->member),
5680 name_for_port(req->after));
5682 MACH_ARG(mach_port_move_member.member) = req->member;
5683 MACH_ARG(mach_port_move_member.after) = req->after;
5685 AFTER = POST_FN(mach_port_move_member);
5688 POST(mach_port_move_member)
5690 #pragma pack(4)
5691 typedef struct {
5692 mach_msg_header_t Head;
5693 NDR_record_t NDR;
5694 kern_return_t RetCode;
5695 mach_msg_trailer_t trailer;
5696 } Reply;
5697 #pragma pack()
5699 Reply *reply = (Reply *)ARG1;
5701 if (!reply->RetCode) {
5702 // fixme port set tracker?
5703 } else {
5704 PRINT("mig return %d", reply->RetCode);
5709 PRE(mach_port_destroy)
5711 #pragma pack(4)
5712 typedef struct {
5713 mach_msg_header_t Head;
5714 NDR_record_t NDR;
5715 mach_port_name_t name;
5716 } Request;
5717 #pragma pack()
5719 Request *req = (Request *)ARG1;
5721 PRINT("mach_port_destroy(%s, %s)",
5722 name_for_port(MACH_REMOTE),
5723 name_for_port(req->name));
5725 MACH_ARG(mach_port.port) = req->name;
5727 AFTER = POST_FN(mach_port_destroy);
5729 // Must block to prevent race (other thread allocates and
5730 // notifies after we deallocate but before we notify)
5731 *flags &= ~SfMayBlock;
5734 POST(mach_port_destroy)
5736 #pragma pack(4)
5737 typedef struct {
5738 mach_msg_header_t Head;
5739 NDR_record_t NDR;
5740 kern_return_t RetCode;
5741 } Reply;
5742 #pragma pack()
5744 Reply *reply = (Reply *)ARG1;
5746 if (!reply->RetCode) {
5747 if (MACH_REMOTE == vg_task_port) {
5748 // Must have cleared SfMayBlock in PRE to prevent race
5749 record_port_destroy(MACH_ARG(mach_port.port));
5750 } else {
5751 VG_(printf)("UNKNOWN remote port destroy\n");
5753 } else {
5754 PRINT("mig return %d", reply->RetCode);
5759 PRE(mach_port_request_notification)
5761 #pragma pack(4)
5762 typedef struct {
5763 mach_msg_header_t Head;
5764 /* start of the kernel processed data */
5765 mach_msg_body_t msgh_body;
5766 mach_msg_port_descriptor_t notify;
5767 /* end of the kernel processed data */
5768 NDR_record_t NDR;
5769 mach_port_name_t name;
5770 mach_msg_id_t msgid;
5771 mach_port_mscount_t sync;
5772 } Request;
5773 #pragma pack()
5775 Request *req = (Request *)ARG1;
5777 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5778 name_for_port(MACH_REMOTE),
5779 name_for_port(req->name), req->msgid, req->sync,
5780 req->notify.name, req->notify.disposition);
5782 AFTER = POST_FN(mach_port_request_notification);
5785 POST(mach_port_request_notification)
5787 // GrP fixme port tracker? not sure
5791 PRE(mach_port_insert_right)
5793 #pragma pack(4)
5794 typedef struct {
5795 mach_msg_header_t Head;
5796 /* start of the kernel processed data */
5797 mach_msg_body_t msgh_body;
5798 mach_msg_port_descriptor_t poly;
5799 /* end of the kernel processed data */
5800 NDR_record_t NDR;
5801 mach_port_name_t name;
5802 } Request;
5803 #pragma pack()
5805 Request *req = (Request *)ARG1;
5807 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5808 name_for_port(MACH_REMOTE),
5809 name_for_port(req->name), req->poly.name, req->poly.disposition);
5811 AFTER = POST_FN(mach_port_insert_right);
5813 if (MACH_REMOTE == mach_task_self()) {
5814 // GrP fixme import_complex_message handles everything?
5815 // what about export_complex_message for MOVE variants?
5816 } else {
5817 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5818 // GrP fixme also may remove rights from this task?
5821 // GrP fixme port tracker?
5824 POST(mach_port_insert_right)
5829 PRE(mach_port_extract_right)
5831 #pragma pack(4)
5832 typedef struct {
5833 mach_msg_header_t Head;
5834 NDR_record_t NDR;
5835 mach_port_name_t name;
5836 mach_msg_type_name_t msgt_name;
5837 } Request;
5838 #pragma pack()
5840 Request *req = (Request *)ARG1;
5842 PRINT("mach_port_extract_right(%s, %s, %d)",
5843 name_for_port(MACH_REMOTE),
5844 name_for_port(req->name), req->msgt_name);
5846 AFTER = POST_FN(mach_port_extract_right);
5848 // fixme port tracker?
5851 POST(mach_port_extract_right)
5853 // fixme import_complex_message handles the returned result, right?
5857 PRE(mach_port_get_attributes)
5859 #pragma pack(4)
5860 typedef struct {
5861 mach_msg_header_t Head;
5862 NDR_record_t NDR;
5863 mach_port_name_t name;
5864 mach_port_flavor_t flavor;
5865 mach_msg_type_number_t port_info_outCnt;
5866 } Request;
5867 #pragma pack()
5869 Request *req = (Request *)ARG1;
5871 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5872 name_for_port(MACH_REMOTE),
5873 name_for_port(req->name), req->flavor, req->port_info_outCnt);
5875 AFTER = POST_FN(mach_port_get_attributes);
5878 POST(mach_port_get_attributes)
5883 PRE(mach_port_set_attributes)
5885 #pragma pack(4)
5886 typedef struct {
5887 mach_msg_header_t Head;
5888 NDR_record_t NDR;
5889 mach_port_name_t name;
5890 mach_port_flavor_t flavor;
5891 mach_msg_type_number_t port_infoCnt;
5892 integer_t port_info[10];
5893 } Request;
5894 #pragma pack()
5896 Request *req = (Request *)ARG1;
5898 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5899 name_for_port(MACH_REMOTE),
5900 name_for_port(req->name), req->flavor, req->port_infoCnt);
5902 AFTER = POST_FN(mach_port_set_attributes);
5905 POST(mach_port_set_attributes)
5910 PRE(mach_port_insert_member)
5912 #pragma pack(4)
5913 typedef struct {
5914 mach_msg_header_t Head;
5915 NDR_record_t NDR;
5916 mach_port_name_t name;
5917 mach_port_name_t pset;
5918 } Request;
5919 #pragma pack()
5921 Request *req = (Request *)ARG1;
5923 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5924 name_for_port(MACH_REMOTE), req->name, req->pset);
5926 AFTER = POST_FN(mach_port_insert_member);
5928 // GrP fixme port tracker?
5931 POST(mach_port_insert_member)
5936 PRE(task_get_special_port)
5938 #pragma pack(4)
5939 typedef struct {
5940 mach_msg_header_t Head;
5941 NDR_record_t NDR;
5942 int which_port;
5943 } Request;
5944 #pragma pack()
5946 Request *req = (Request *)ARG1;
5948 switch (req->which_port) {
5949 case TASK_KERNEL_PORT:
5950 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5951 name_for_port(MACH_REMOTE));
5952 break;
5953 case TASK_HOST_PORT:
5954 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5955 name_for_port(MACH_REMOTE));
5956 break;
5957 case TASK_BOOTSTRAP_PORT:
5958 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5959 name_for_port(MACH_REMOTE));
5960 break;
5961 #if DARWIN_VERS < DARWIN_10_8
5962 /* These disappeared in 10.8 */
5963 case TASK_WIRED_LEDGER_PORT:
5964 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5965 name_for_port(MACH_REMOTE));
5966 break;
5967 case TASK_PAGED_LEDGER_PORT:
5968 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5969 name_for_port(MACH_REMOTE));
5970 break;
5971 #endif
5972 default:
5973 PRINT("task_get_special_port(%s, %d)",
5974 name_for_port(MACH_REMOTE), req->which_port);
5975 break;
5978 MACH_ARG(task_get_special_port.which_port) = req->which_port;
5980 AFTER = POST_FN(task_get_special_port);
5983 POST(task_get_special_port)
5985 #pragma pack(4)
5986 typedef struct {
5987 mach_msg_header_t Head;
5988 /* start of the kernel processed data */
5989 mach_msg_body_t msgh_body;
5990 mach_msg_port_descriptor_t special_port;
5991 /* end of the kernel processed data */
5992 } Reply;
5993 #pragma pack()
5995 Reply *reply = (Reply *)ARG1;
5997 PRINT("got port %#x ", reply->special_port.name);
5999 switch (MACH_ARG(task_get_special_port.which_port)) {
6000 case TASK_BOOTSTRAP_PORT:
6001 vg_bootstrap_port = reply->special_port.name;
6002 assign_port_name(reply->special_port.name, "bootstrap");
6003 break;
6004 case TASK_KERNEL_PORT:
6005 assign_port_name(reply->special_port.name, "kernel");
6006 break;
6007 case TASK_HOST_PORT:
6008 assign_port_name(reply->special_port.name, "host");
6009 break;
6010 #if DARWIN_VERS < DARWIN_10_8
6011 /* These disappeared in 10.8 */
6012 case TASK_WIRED_LEDGER_PORT:
6013 assign_port_name(reply->special_port.name, "wired-ledger");
6014 break;
6015 case TASK_PAGED_LEDGER_PORT:
6016 assign_port_name(reply->special_port.name, "paged-ledger");
6017 break;
6018 #endif
6019 default:
6020 assign_port_name(reply->special_port.name, "special-%p");
6021 break;
6024 PRINT("%s", name_for_port(reply->special_port.name));
6028 PRE(task_set_special_port)
6030 #pragma pack(4)
6031 typedef struct {
6032 mach_msg_header_t Head;
6033 /* start of the kernel processed data */
6034 mach_msg_body_t msgh_body;
6035 mach_msg_port_descriptor_t special_port;
6036 /* end of the kernel processed data */
6037 NDR_record_t NDR;
6038 int which_port;
6039 } Request;
6040 #pragma pack()
6042 Request *req = (Request *)ARG1;
6044 PRINT("got port %#x ", req->special_port.name);
6046 // MACH_ARG(task_set_special_port.which_port) = req->which_port;
6047 PRINT("%s", name_for_port(req->special_port.name));
6049 AFTER = POST_FN(task_set_special_port);
6052 POST(task_set_special_port)
6054 #pragma pack(4)
6055 typedef struct {
6056 mach_msg_header_t Head;
6057 NDR_record_t NDR;
6058 kern_return_t RetCode;
6059 } Reply;
6060 #pragma pack()
6062 Reply *reply = (Reply *)ARG1;
6063 if (!reply->RetCode) {
6064 } else {
6065 PRINT("mig return %d", reply->RetCode);
6070 PRE(semaphore_create)
6072 #pragma pack(4)
6073 typedef struct {
6074 mach_msg_header_t Head;
6075 NDR_record_t NDR;
6076 int policy;
6077 int value;
6078 } Request;
6079 #pragma pack()
6081 Request *req = (Request *)ARG1;
6083 PRINT("semaphore_create(%s, ..., %d, %d)",
6084 name_for_port(MACH_REMOTE), req->policy, req->value);
6086 AFTER = POST_FN(semaphore_create);
6089 POST(semaphore_create)
6091 #pragma pack(4)
6092 typedef struct {
6093 mach_msg_header_t Head;
6094 /* start of the kernel processed data */
6095 mach_msg_body_t msgh_body;
6096 mach_msg_port_descriptor_t semaphore;
6097 /* end of the kernel processed data */
6098 mach_msg_trailer_t trailer;
6099 } Reply;
6100 #pragma pack()
6102 Reply *reply = (Reply *)ARG1;
6104 assign_port_name(reply->semaphore.name, "semaphore-%p");
6105 PRINT("%s", name_for_port(reply->semaphore.name));
6109 PRE(semaphore_destroy)
6111 #pragma pack(4)
6112 typedef struct {
6113 mach_msg_header_t Head;
6114 /* start of the kernel processed data */
6115 mach_msg_body_t msgh_body;
6116 mach_msg_port_descriptor_t semaphore;
6117 /* end of the kernel processed data */
6118 mach_msg_trailer_t trailer;
6119 } Request;
6120 #pragma pack()
6122 Request *req = (Request *)ARG1;
6124 PRINT("semaphore_destroy(%s, %s)",
6125 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
6127 record_port_destroy(req->semaphore.name);
6129 AFTER = POST_FN(semaphore_destroy);
6132 POST(semaphore_destroy)
6134 #pragma pack(4)
6135 typedef struct {
6136 mach_msg_header_t Head;
6137 NDR_record_t NDR;
6138 kern_return_t RetCode;
6139 mach_msg_trailer_t trailer;
6140 } Reply;
6141 #pragma pack()
6143 Reply *reply = (Reply *)ARG1;
6144 if (!reply->RetCode) {
6145 } else {
6146 PRINT("mig return %d", reply->RetCode);
6150 PRE(task_policy_set)
6152 #pragma pack(4)
6153 typedef struct {
6154 mach_msg_header_t Head;
6155 NDR_record_t NDR;
6156 task_policy_flavor_t flavor;
6157 mach_msg_type_number_t policy_infoCnt;
6158 integer_t policy_info[16];
6159 } Request;
6160 #pragma pack()
6162 Request *req = (Request *)ARG1;
6164 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6166 AFTER = POST_FN(task_policy_set);
6169 POST(task_policy_set)
6171 #pragma pack(4)
6172 typedef struct {
6173 mach_msg_header_t Head;
6174 NDR_record_t NDR;
6175 kern_return_t RetCode;
6176 } Reply;
6177 #pragma pack()
6179 Reply *reply = (Reply *)ARG1;
6180 if (!reply->RetCode) {
6181 } else {
6182 PRINT("mig return %d", reply->RetCode);
6187 PRE(mach_ports_register)
6189 //#pragma pack(4)
6190 // typedef struct {
6191 // mach_msg_header_t Head;
6192 // /* start of the kernel processed data */
6193 // mach_msg_body_t msgh_body;
6194 // mach_msg_ool_ports_descriptor_t init_port_set;
6195 // /* end of the kernel processed data */
6196 // NDR_record_t NDR;
6197 // mach_msg_type_number_t init_port_setCnt;
6198 // } Request;
6199 //#pragma pack()
6201 // Request *req = (Request *)ARG1;
6203 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE));
6205 AFTER = POST_FN(mach_ports_register);
6208 POST(mach_ports_register)
6210 #pragma pack(4)
6211 typedef struct {
6212 mach_msg_header_t Head;
6213 NDR_record_t NDR;
6214 kern_return_t RetCode;
6215 } Reply;
6216 #pragma pack()
6218 Reply *reply = (Reply *)ARG1;
6219 if (!reply->RetCode) {
6220 } else {
6221 PRINT("mig return %d", reply->RetCode);
6226 PRE(mach_ports_lookup)
6228 //#pragma pack(4)
6229 // typedef struct {
6230 // mach_msg_header_t Head;
6231 // } Request;
6232 //#pragma pack()
6234 // Request *req = (Request *)ARG1;
6236 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
6238 AFTER = POST_FN(mach_ports_lookup);
6241 POST(mach_ports_lookup)
6243 //#pragma pack(4)
6244 // typedef struct {
6245 // mach_msg_header_t Head;
6246 // /* start of the kernel processed data */
6247 // mach_msg_body_t msgh_body;
6248 // mach_msg_ool_ports_descriptor_t init_port_set;
6249 // /* end of the kernel processed data */
6250 // NDR_record_t NDR;
6251 // mach_msg_type_number_t init_port_setCnt;
6252 // } Reply;
6253 //#pragma pack()
6255 // Reply *reply = (Reply *)ARG1;
6259 PRE(task_info)
6261 #pragma pack(4)
6262 typedef struct {
6263 mach_msg_header_t Head;
6264 NDR_record_t NDR;
6265 task_flavor_t flavor;
6266 mach_msg_type_number_t task_info_outCnt;
6267 } Request;
6268 #pragma pack()
6270 Request *req = (Request *)ARG1;
6272 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6274 AFTER = POST_FN(task_info);
6277 POST(task_info)
6279 #pragma pack(4)
6280 typedef struct {
6281 mach_msg_header_t Head;
6282 NDR_record_t NDR;
6283 kern_return_t RetCode;
6284 mach_msg_type_number_t task_info_outCnt;
6285 integer_t task_info_out[52];
6286 } Reply;
6287 #pragma pack()
6289 Reply *reply = (Reply *)ARG1;
6290 if (!reply->RetCode) {
6291 } else {
6292 PRINT("mig return %d", reply->RetCode);
6297 PRE(task_set_info)
6299 #pragma pack(4)
6300 typedef struct {
6301 mach_msg_header_t Head;
6302 NDR_record_t NDR;
6303 task_flavor_t flavor;
6304 mach_msg_type_number_t task_info_inCnt;
6305 integer_t task_info_in[52];
6306 } Request;
6307 #pragma pack()
6309 Request *req = (Request *)ARG1;
6311 PRINT("task_set_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
6313 AFTER = POST_FN(task_set_info);
6316 POST(task_set_info)
6318 #pragma pack(4)
6319 typedef struct {
6320 mach_msg_header_t Head;
6321 NDR_record_t NDR;
6322 kern_return_t RetCode;
6323 } Reply;
6324 #pragma pack()
6326 Reply *reply = (Reply *)ARG1;
6327 if (!reply->RetCode) {
6328 } else {
6329 PRINT("mig return %d", reply->RetCode);
6333 PRE(task_threads)
6335 //#pragma pack(4)
6336 // typedef struct {
6337 // mach_msg_header_t Head;
6338 // } Request;
6339 //#pragma pack()
6341 // Request *req = (Request *)ARG1;
6343 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
6345 AFTER = POST_FN(task_threads);
6348 POST(task_threads)
6350 #pragma pack(4)
6351 typedef struct {
6352 mach_msg_header_t Head;
6353 /* start of the kernel processed data */
6354 mach_msg_body_t msgh_body;
6355 mach_msg_ool_ports_descriptor_t act_list;
6356 /* end of the kernel processed data */
6357 NDR_record_t NDR;
6358 mach_msg_type_number_t act_listCnt;
6359 mach_msg_trailer_t trailer;
6360 } Reply;
6361 #pragma pack()
6363 Reply *reply = (Reply *)ARG1;
6365 if (MACH_REMOTE == vg_task_port) {
6366 assign_port_names(&reply->act_list, "thread-%p");
6367 } else {
6368 assign_port_names(&reply->act_list, "remote-thread-%p");
6373 PRE(task_suspend)
6375 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
6377 if (MACH_REMOTE == vg_task_port) {
6378 // GrP fixme self-suspend
6379 vg_assert(0);
6380 } else {
6381 // suspend other - no problem
6384 AFTER = POST_FN(task_suspend);
6387 POST(task_suspend)
6392 PRE(task_resume)
6394 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
6396 if (MACH_REMOTE == vg_task_port) {
6397 // GrP fixme self-resume
6398 vg_assert(0);
6399 } else {
6400 // resume other - no problem
6403 AFTER = POST_FN(task_resume);
6406 POST(task_resume)
6411 PRE(vm_allocate)
6413 #pragma pack(4)
6414 typedef struct {
6415 mach_msg_header_t Head;
6416 NDR_record_t NDR;
6417 vm_address_t address;
6418 vm_size_t size;
6419 int flags;
6420 } Request;
6421 #pragma pack()
6423 Request *req = (Request *)ARG1;
6425 PRINT("vm_allocate (%s, at %#llx, size %llu, flags %#x)",
6426 name_for_port(MACH_REMOTE),
6427 (ULong)req->address, (ULong)req->size, req->flags);
6429 MACH_ARG(vm_allocate.size) = req->size;
6430 MACH_ARG(vm_allocate.flags) = req->flags;
6432 AFTER = POST_FN(vm_allocate);
6435 POST(vm_allocate)
6437 #pragma pack(4)
6438 typedef struct {
6439 mach_msg_header_t Head;
6440 NDR_record_t NDR;
6441 kern_return_t RetCode;
6442 vm_address_t address;
6443 mach_msg_trailer_t trailer;
6444 } Reply;
6445 #pragma pack()
6447 Reply *reply = (Reply *)ARG1;
6449 if (!reply->RetCode) {
6450 if (MACH_REMOTE == vg_task_port) {
6451 PRINT("allocated at %#llx", (ULong)reply->address);
6452 // requesting 0 bytes returns address 0 with no error
6453 if (MACH_ARG(vm_allocate.size)) {
6454 ML_(notify_core_and_tool_of_mmap)(
6455 reply->address, MACH_ARG(vm_allocate.size),
6456 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6458 } else {
6459 PRINT("allocated at %#llx in remote task %s",
6460 (ULong)reply->address,
6461 name_for_port(MACH_REMOTE));
6463 } else {
6464 PRINT("mig return %d", reply->RetCode);
6469 PRE(vm_deallocate)
6471 #pragma pack(4)
6472 typedef struct {
6473 mach_msg_header_t Head;
6474 NDR_record_t NDR;
6475 vm_address_t address;
6476 vm_size_t size;
6477 } Request;
6478 #pragma pack()
6480 Request *req = (Request *)ARG1;
6482 PRINT("vm_deallocate(%s, at %#llx, size %llu)",
6483 name_for_port(MACH_REMOTE),
6484 (ULong)req->address, (ULong)req->size);
6486 MACH_ARG(vm_deallocate.address) = req->address;
6487 MACH_ARG(vm_deallocate.size) = req->size;
6489 AFTER = POST_FN(vm_deallocate);
6491 // Must block to prevent race (other thread allocates and
6492 // notifies after we deallocate but before we notify)
6493 *flags &= ~SfMayBlock;
6496 POST(vm_deallocate)
6498 #pragma pack(4)
6499 typedef struct {
6500 mach_msg_header_t Head;
6501 NDR_record_t NDR;
6502 kern_return_t RetCode;
6503 mach_msg_trailer_t trailer;
6504 } Reply;
6505 #pragma pack()
6507 Reply *reply = (Reply *)ARG1;
6509 if (!reply->RetCode) {
6510 if (MACH_REMOTE == vg_task_port) {
6511 if (MACH_ARG(vm_deallocate.size)) {
6512 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
6513 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
6514 MACH_ARG(vm_deallocate.size));
6515 // Must have cleared SfMayBlock in PRE to prevent race
6516 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6519 } else {
6520 PRINT("mig return %d", reply->RetCode);
6525 PRE(vm_protect)
6527 #pragma pack(4)
6528 typedef struct {
6529 mach_msg_header_t Head;
6530 NDR_record_t NDR;
6531 vm_address_t address;
6532 vm_size_t size;
6533 boolean_t set_maximum;
6534 vm_prot_t new_protection;
6535 } Request;
6536 #pragma pack()
6538 Request *req = (Request *)ARG1;
6540 PRINT("vm_protect(%s, at %#llx, size %llu, set_max %d, prot %d)",
6541 name_for_port(MACH_REMOTE),
6542 (ULong)req->address, (ULong)req->size,
6543 req->set_maximum, req->new_protection);
6545 MACH_ARG(vm_protect.address) = req->address;
6546 MACH_ARG(vm_protect.size) = req->size;
6547 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
6548 MACH_ARG(vm_protect.new_protection) = req->new_protection;
6550 AFTER = POST_FN(vm_protect);
6553 POST(vm_protect)
6555 #pragma pack(4)
6556 typedef struct {
6557 mach_msg_header_t Head;
6558 NDR_record_t NDR;
6559 kern_return_t RetCode;
6560 mach_msg_trailer_t trailer;
6561 } Reply;
6562 #pragma pack()
6564 Reply *reply = (Reply *)ARG1;
6566 if (!reply->RetCode) {
6567 if (MACH_REMOTE == vg_task_port) {
6568 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
6569 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
6570 MACH_ARG(vm_protect.size));
6571 UInt prot = MACH_ARG(vm_protect.new_protection);
6572 if (MACH_ARG(vm_protect.set_maximum)) {
6573 // GrP fixme mprotect max
6574 VG_(printf)("UNKNOWN vm_protect set maximum");
6575 //VG_(mprotect_max_range)(start, end-start, prot);
6576 } else {
6577 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6578 VG_(di_notify_vm_protect)(start, end-start, prot);
6581 } else {
6582 PRINT("mig return %d", reply->RetCode);
6587 PRE(vm_inherit)
6589 #pragma pack(4)
6590 typedef struct {
6591 mach_msg_header_t Head;
6592 NDR_record_t NDR;
6593 vm_address_t address;
6594 vm_size_t size;
6595 vm_inherit_t new_inheritance;
6596 } Request;
6597 #pragma pack()
6599 Request *req = (Request *)ARG1;
6601 PRINT("vm_inherit(%s, at %#llx, size %llu, value %d)",
6602 name_for_port(MACH_REMOTE),
6603 (ULong)req->address, (ULong)req->size,
6604 req->new_inheritance);
6606 AFTER = POST_FN(vm_inherit);
6609 POST(vm_inherit)
6611 #pragma pack(4)
6612 typedef struct {
6613 mach_msg_header_t Head;
6614 NDR_record_t NDR;
6615 kern_return_t RetCode;
6616 mach_msg_trailer_t trailer;
6617 } Reply;
6618 #pragma pack()
6620 Reply *reply = (Reply *)ARG1;
6622 if (!reply->RetCode) {
6623 if (MACH_REMOTE == vg_task_port) {
6624 // GrP fixme do something?
6626 } else {
6627 PRINT("mig return %d", reply->RetCode);
6632 PRE(vm_read)
6634 #pragma pack(4)
6635 typedef struct {
6636 mach_msg_header_t Head;
6637 NDR_record_t NDR;
6638 vm_address_t address;
6639 vm_size_t size;
6640 } Request;
6641 #pragma pack()
6643 Request *req = (Request *)ARG1;
6645 PRINT("vm_read(from %s at %#llx size %llu)",
6646 name_for_port(MACH_REMOTE),
6647 (ULong)req->address, (ULong)req->size);
6649 MACH_ARG(vm_read.addr) = req->address;
6650 MACH_ARG(vm_read.size) = req->size;
6652 AFTER = POST_FN(vm_read);
6655 POST(vm_read)
6657 //#pragma pack(4)
6658 // typedef struct {
6659 // mach_msg_header_t Head;
6660 // /* start of the kernel processed data */
6661 // mach_msg_body_t msgh_body;
6662 // mach_msg_ool_descriptor_t data;
6663 // /* end of the kernel processed data */
6664 // NDR_record_t NDR;
6665 // mach_msg_type_number_t dataCnt;
6666 // } Reply;
6667 //#pragma pack()
6669 // Reply *reply = (Reply *)ARG1;
6671 if (MACH_REMOTE == vg_task_port) {
6672 // vm_read from self
6673 // GrP fixme copy initialized state
6679 PRE(mach_vm_read)
6681 #pragma pack(4)
6682 typedef struct {
6683 mach_msg_header_t Head;
6684 NDR_record_t NDR;
6685 mach_vm_address_t address;
6686 mach_vm_size_t size;
6687 } Request;
6688 #pragma pack()
6690 Request *req = (Request *)ARG1;
6692 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6693 name_for_port(MACH_REMOTE), req->address, req->size);
6695 MACH_ARG(mach_vm_read.addr) = req->address;
6696 MACH_ARG(mach_vm_read.size) = req->size;
6698 AFTER = POST_FN(mach_vm_read);
6701 POST(mach_vm_read)
6703 //#pragma pack(4)
6704 // typedef struct {
6705 // mach_msg_header_t Head;
6706 // /* start of the kernel processed data */
6707 // mach_msg_body_t msgh_body;
6708 // mach_msg_ool_descriptor_t data;
6709 // /* end of the kernel processed data */
6710 // NDR_record_t NDR;
6711 // mach_msg_type_number_t dataCnt;
6712 // } Reply;
6713 //#pragma pack()
6715 // Reply *reply = (Reply *)ARG1;
6717 if (MACH_REMOTE == vg_task_port) {
6718 // vm_read from self
6719 // GrP fixme copy initialized state
6724 PRE(vm_read_overwrite)
6726 #pragma pack(4)
6727 typedef struct {
6728 mach_msg_header_t Head;
6729 NDR_record_t NDR;
6730 vm_address_t address;
6731 vm_size_t size;
6732 vm_address_t data;
6733 } Request;
6734 #pragma pack()
6736 Request *req = (Request *)ARG1;
6738 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6739 name_for_port(MACH_REMOTE),
6740 (ULong)req->address, (ULong)req->size, (ULong)req->data);
6742 MACH_ARG(vm_read_overwrite.addr) = req->address;
6743 MACH_ARG(vm_read_overwrite.size) = req->size;
6744 MACH_ARG(vm_read_overwrite.data) = req->data;
6746 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
6748 AFTER = POST_FN(vm_read_overwrite);
6751 POST(vm_read_overwrite)
6753 #pragma pack(4)
6754 typedef struct {
6755 mach_msg_header_t Head;
6756 NDR_record_t NDR;
6757 kern_return_t RetCode;
6758 vm_size_t outsize;
6759 } Reply;
6760 #pragma pack()
6762 Reply *reply = (Reply *)ARG1;
6764 if (reply->RetCode) {
6765 PRINT("mig return %d", reply->RetCode);
6766 } else {
6767 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
6768 if (MACH_REMOTE == vg_task_port) {
6769 // vm_read_overwrite from self
6770 // GrP fixme copy initialized state
6771 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6772 } else {
6773 // vm_read_overwrite from remote
6774 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6780 PRE(vm_copy)
6782 #pragma pack(4)
6783 typedef struct {
6784 mach_msg_header_t Head;
6785 NDR_record_t NDR;
6786 vm_address_t source_address;
6787 vm_size_t size;
6788 vm_address_t dest_address;
6789 } Request;
6790 #pragma pack()
6792 Request *req = (Request *)ARG1;
6794 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6795 name_for_port(MACH_REMOTE),
6796 (ULong)req->source_address,
6797 (ULong)req->size, (ULong)req->dest_address);
6799 MACH_ARG(vm_copy.src) = req->source_address;
6800 MACH_ARG(vm_copy.dst) = req->dest_address;
6801 MACH_ARG(vm_copy.size) = req->size;
6803 AFTER = POST_FN(vm_copy);
6806 POST(vm_copy)
6808 #pragma pack(4)
6809 typedef struct {
6810 mach_msg_header_t Head;
6811 NDR_record_t NDR;
6812 kern_return_t RetCode;
6813 mach_msg_trailer_t trailer;
6814 } Reply;
6815 #pragma pack()
6817 Reply *reply = (Reply *)ARG1;
6819 if (!reply->RetCode) {
6820 if (MACH_REMOTE == vg_task_port) {
6821 // GrP fixme set dst's initialization equal to src's
6822 // and wipe any symbols or translations in dst
6824 } else {
6825 PRINT("mig return %d", reply->RetCode);
6830 PRE(vm_map)
6832 #pragma pack(4)
6833 typedef struct {
6834 mach_msg_header_t Head;
6835 /* start of the kernel processed data */
6836 mach_msg_body_t msgh_body;
6837 mach_msg_port_descriptor_t object;
6838 /* end of the kernel processed data */
6839 NDR_record_t NDR;
6840 vm_address_t address;
6841 vm_size_t size;
6842 vm_address_t mask;
6843 int flags;
6844 vm_offset_t offset;
6845 boolean_t copy;
6846 vm_prot_t cur_protection;
6847 vm_prot_t max_protection;
6848 vm_inherit_t inheritance;
6849 } Request;
6850 #pragma pack()
6852 Request *req = (Request *)ARG1;
6854 // GrP fixme check these
6855 PRINT("vm_map(in %s, at %#llx, size %llu, from %s ...)",
6856 name_for_port(MACH_REMOTE),
6857 (ULong)req->address, (ULong)req->size,
6858 name_for_port(req->object.name));
6860 MACH_ARG(vm_map.size) = req->size;
6861 MACH_ARG(vm_map.copy) = req->copy;
6862 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
6864 AFTER = POST_FN(vm_map);
6867 POST(vm_map)
6869 #pragma pack(4)
6870 typedef struct {
6871 mach_msg_header_t Head;
6872 NDR_record_t NDR;
6873 kern_return_t RetCode;
6874 vm_address_t address;
6875 mach_msg_trailer_t trailer;
6876 } Reply;
6877 #pragma pack()
6879 Reply *reply = (Reply *)ARG1;
6881 if (!reply->RetCode) {
6882 // GrP fixme check src and dest tasks
6883 PRINT("mapped at %#llx", (ULong)reply->address);
6884 // GrP fixme max prot
6885 ML_(notify_core_and_tool_of_mmap)(
6886 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
6887 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
6888 // GrP fixme VKI_MAP_PRIVATE if !copy?
6889 } else {
6890 PRINT("mig return %d", reply->RetCode);
6895 PRE(vm_remap)
6897 #pragma pack(4)
6898 typedef struct {
6899 mach_msg_header_t Head;
6900 /* start of the kernel processed data */
6901 mach_msg_body_t msgh_body;
6902 mach_msg_port_descriptor_t src_task;
6903 /* end of the kernel processed data */
6904 NDR_record_t NDR;
6905 vm_address_t target_address;
6906 vm_size_t size;
6907 vm_address_t mask;
6908 boolean_t anywhere;
6909 vm_address_t src_address;
6910 boolean_t copy;
6911 vm_inherit_t inheritance;
6912 } Request;
6913 #pragma pack()
6915 Request *req = (Request *)ARG1;
6917 // GrP fixme check src and dest tasks
6919 if (VG_(clo_trace_syscalls)) {
6920 mach_port_name_t source_task = req->src_task.name;
6921 if (source_task == mach_task_self()) {
6922 PRINT("vm_remap(mach_task_self(), "
6923 "to %#llx size %llu, from mach_task_self() at %#llx, ...)",
6924 (ULong)req->target_address,
6925 (ULong)req->size, (ULong)req->src_address);
6926 } else {
6927 PRINT("vm_remap(mach_task_self(), "
6928 "to %#llx size %llu, from task %u at %#llx, ...)",
6929 (ULong)req->target_address, (ULong)req->size,
6930 source_task, (ULong)req->src_address);
6934 // arg1 is task
6935 // vt->syscall_arg2 = req->target_address;
6936 MACH_ARG(vm_remap.size) = req->size;
6937 // vt->syscall_arg4 = req->copy;
6939 AFTER = POST_FN(vm_remap);
6942 POST(vm_remap)
6944 #pragma pack(4)
6945 typedef struct {
6946 mach_msg_header_t Head;
6947 NDR_record_t NDR;
6948 kern_return_t RetCode;
6949 vm_address_t target_address;
6950 vm_prot_t cur_protection;
6951 vm_prot_t max_protection;
6952 mach_msg_trailer_t trailer;
6953 } Reply;
6954 #pragma pack()
6956 Reply *reply = (Reply *)ARG1;
6958 if (!reply->RetCode) {
6959 // GrP fixme check src and dest tasks
6960 UInt prot = reply->cur_protection & reply->max_protection;
6961 // GrP fixme max prot
6962 PRINT("mapped at %#llx", (ULong)reply->target_address);
6963 ML_(notify_core_and_tool_of_mmap)(
6964 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
6965 prot, VKI_MAP_SHARED, -1, 0);
6966 // GrP fixme VKI_MAP_FIXED if !copy?
6967 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6968 } else {
6969 PRINT("mig return %d", reply->RetCode);
6974 PRE(mach_make_memory_entry_64)
6976 #pragma pack(4)
6977 typedef struct {
6978 mach_msg_header_t Head;
6979 /* start of the kernel processed data */
6980 mach_msg_body_t msgh_body;
6981 mach_msg_port_descriptor_t parent_entry;
6982 /* end of the kernel processed data */
6983 NDR_record_t NDR;
6984 memory_object_size_t size;
6985 memory_object_offset_t offset;
6986 vm_prot_t permission;
6987 } Request;
6988 #pragma pack()
6990 Request *req = (Request *)ARG1;
6992 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6993 name_for_port(MACH_REMOTE),
6994 req->size, req->offset, req->permission, req->parent_entry.type);
6996 AFTER = POST_FN(mach_make_memory_entry_64);
6999 POST(mach_make_memory_entry_64)
7001 #pragma pack(4)
7002 typedef struct {
7003 mach_msg_header_t Head;
7004 mach_msg_body_t msgh_body;
7005 mach_msg_port_descriptor_t object;
7006 NDR_record_t NDR;
7007 memory_object_size_t size;
7008 } Reply;
7009 #pragma pack()
7011 Reply *reply = (Reply *)ARG1;
7013 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
7014 assign_port_name(reply->object.name, "memory-%p");
7015 PRINT("%s", name_for_port(reply->object.name));
7020 PRE(vm_purgable_control)
7022 #pragma pack(4)
7023 typedef struct {
7024 mach_msg_header_t Head;
7025 NDR_record_t NDR;
7026 vm_address_t address;
7027 vm_purgable_t control;
7028 int state;
7029 } Request;
7030 #pragma pack()
7032 Request *req = (Request *)ARG1;
7034 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
7035 name_for_port(MACH_REMOTE),
7036 (ULong)req->address, req->control, req->state);
7038 // GrP fixme verify address?
7040 AFTER = POST_FN(vm_purgable_control);
7043 POST(vm_purgable_control)
7045 #pragma pack(4)
7046 typedef struct {
7047 mach_msg_header_t Head;
7048 NDR_record_t NDR;
7049 kern_return_t RetCode;
7050 int state;
7051 } Reply;
7052 #pragma pack()
7054 Reply *reply = (Reply *)ARG1;
7056 if (!reply->RetCode) {
7057 } else {
7058 PRINT("mig return %d", reply->RetCode);
7063 PRE(mach_vm_purgable_control)
7065 #pragma pack(4)
7066 typedef struct {
7067 mach_msg_header_t Head;
7068 NDR_record_t NDR;
7069 mach_vm_address_t address;
7070 vm_purgable_t control;
7071 int state;
7072 } Request;
7073 #pragma pack()
7075 Request *req = (Request *)ARG1;
7077 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
7078 name_for_port(MACH_REMOTE),
7079 (ULong)req->address, req->control, req->state);
7081 // GrP fixme verify address?
7083 AFTER = POST_FN(mach_vm_purgable_control);
7086 POST(mach_vm_purgable_control)
7088 #pragma pack(4)
7089 typedef struct {
7090 mach_msg_header_t Head;
7091 NDR_record_t NDR;
7092 kern_return_t RetCode;
7093 int state;
7094 } Reply;
7095 #pragma pack()
7097 Reply *reply = (Reply *)ARG1;
7099 if (!reply->RetCode) {
7100 } else {
7101 PRINT("mig return %d", reply->RetCode);
7106 PRE(mach_vm_allocate)
7108 #pragma pack(4)
7109 typedef struct {
7110 mach_msg_header_t Head;
7111 NDR_record_t NDR;
7112 mach_vm_address_t address;
7113 mach_vm_size_t size;
7114 int flags;
7115 } Request;
7116 #pragma pack()
7118 Request *req = (Request *)ARG1;
7120 PRINT("mach_vm_allocate (%s, at 0x%llx, size %llu, flags 0x%x)",
7121 name_for_port(MACH_REMOTE),
7122 req->address, req->size, req->flags);
7124 MACH_ARG(mach_vm_allocate.size) = req->size;
7125 MACH_ARG(mach_vm_allocate.flags) = req->flags;
7127 AFTER = POST_FN(mach_vm_allocate);
7130 POST(mach_vm_allocate)
7132 #pragma pack(4)
7133 typedef struct {
7134 mach_msg_header_t Head;
7135 NDR_record_t NDR;
7136 kern_return_t RetCode;
7137 mach_vm_address_t address;
7138 mach_msg_trailer_t trailer;
7139 } Reply;
7140 #pragma pack()
7142 Reply *reply = (Reply *)ARG1;
7144 if (!reply->RetCode) {
7145 if (MACH_REMOTE == vg_task_port) {
7146 PRINT("allocated at 0x%llx", reply->address);
7147 // requesting 0 bytes returns address 0 with no error
7148 if (MACH_ARG(mach_vm_allocate.size)) {
7149 ML_(notify_core_and_tool_of_mmap)(
7150 reply->address, MACH_ARG(mach_vm_allocate.size),
7151 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
7153 } else {
7154 PRINT("allocated at 0x%llx in remote task %s", reply->address,
7155 name_for_port(MACH_REMOTE));
7157 } else {
7158 PRINT("mig return %d", reply->RetCode);
7163 PRE(mach_vm_deallocate)
7165 #pragma pack(4)
7166 typedef struct {
7167 mach_msg_header_t Head;
7168 NDR_record_t NDR;
7169 mach_vm_address_t address;
7170 mach_vm_size_t size;
7171 } Request;
7172 #pragma pack()
7174 Request *req = (Request *)ARG1;
7176 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %llu)",
7177 name_for_port(MACH_REMOTE),
7178 req->address, req->size);
7180 MACH_ARG(mach_vm_deallocate.address) = req->address;
7181 MACH_ARG(mach_vm_deallocate.size) = req->size;
7183 AFTER = POST_FN(mach_vm_deallocate);
7185 // Must block to prevent race (other thread allocates and
7186 // notifies after we deallocate but before we notify)
7187 *flags &= ~SfMayBlock;
7190 POST(mach_vm_deallocate)
7192 #pragma pack(4)
7193 typedef struct {
7194 mach_msg_header_t Head;
7195 NDR_record_t NDR;
7196 kern_return_t RetCode;
7197 mach_msg_trailer_t trailer;
7198 } Reply;
7199 #pragma pack()
7201 Reply *reply = (Reply *)ARG1;
7203 if (!reply->RetCode) {
7204 if (MACH_REMOTE == vg_task_port) {
7205 if (MACH_ARG(mach_vm_deallocate.size)) {
7206 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
7207 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
7208 MACH_ARG(mach_vm_deallocate.size));
7209 // Must have cleared SfMayBlock in PRE to prevent race
7210 ML_(notify_core_and_tool_of_munmap)(start, end - start);
7213 } else {
7214 PRINT("mig return %d", reply->RetCode);
7219 PRE(mach_vm_protect)
7221 #pragma pack(4)
7222 typedef struct {
7223 mach_msg_header_t Head;
7224 NDR_record_t NDR;
7225 mach_vm_address_t address;
7226 mach_vm_size_t size;
7227 boolean_t set_maximum;
7228 vm_prot_t new_protection;
7229 } Request;
7230 #pragma pack()
7232 Request *req = (Request *)ARG1;
7234 PRINT("mach_vm_protect(%s, at 0x%llx, size %llu, set_max %d, prot %d)",
7235 name_for_port(MACH_REMOTE), req->address, req->size,
7236 req->set_maximum, req->new_protection);
7238 MACH_ARG(mach_vm_protect.address) = req->address;
7239 MACH_ARG(mach_vm_protect.size) = req->size;
7240 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
7241 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
7243 AFTER = POST_FN(mach_vm_protect);
7246 POST(mach_vm_protect)
7248 #pragma pack(4)
7249 typedef struct {
7250 mach_msg_header_t Head;
7251 NDR_record_t NDR;
7252 kern_return_t RetCode;
7253 mach_msg_trailer_t trailer;
7254 } Reply;
7255 #pragma pack()
7257 Reply *reply = (Reply *)ARG1;
7259 if (!reply->RetCode) {
7260 if (MACH_REMOTE == vg_task_port) {
7261 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
7262 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
7263 MACH_ARG(mach_vm_protect.size));
7264 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
7265 if (MACH_ARG(mach_vm_protect.set_maximum)) {
7266 // DDD: #warning GrP fixme mprotect max
7267 //VG_(mprotect_max_range)(start, end-start, prot);
7268 } else {
7269 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
7272 } else {
7273 PRINT("mig return %d", reply->RetCode);
7278 PRE(mach_vm_inherit)
7280 #pragma pack(4)
7281 typedef struct {
7282 mach_msg_header_t Head;
7283 NDR_record_t NDR;
7284 mach_vm_address_t address;
7285 mach_vm_size_t size;
7286 vm_inherit_t new_inheritance;
7287 } Request;
7288 #pragma pack()
7290 Request *req = (Request *)ARG1;
7292 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
7293 name_for_port(MACH_REMOTE),
7294 req->address, req->size, req->new_inheritance);
7296 AFTER = POST_FN(mach_vm_inherit);
7299 POST(mach_vm_inherit)
7301 #pragma pack(4)
7302 typedef struct {
7303 mach_msg_header_t Head;
7304 NDR_record_t NDR;
7305 kern_return_t RetCode;
7306 mach_msg_trailer_t trailer;
7307 } Reply;
7308 #pragma pack()
7310 Reply *reply = (Reply *)ARG1;
7312 if (!reply->RetCode) {
7313 // no V-visible side effects
7314 // GrP fixme except maybe fork/exec
7315 } else {
7316 PRINT("mig return %d", reply->RetCode);
7321 PRE(mach_vm_copy)
7323 #pragma pack(4)
7324 typedef struct {
7325 mach_msg_header_t Head;
7326 NDR_record_t NDR;
7327 mach_vm_address_t source_address;
7328 mach_vm_size_t size;
7329 mach_vm_address_t dest_address;
7330 } Request;
7331 #pragma pack()
7333 Request *req = (Request *)ARG1;
7335 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
7336 name_for_port(MACH_REMOTE),
7337 req->source_address, req->size, req->dest_address);
7339 // arg1 is task
7340 // vt->syscall_arg2 = req->source_address;
7341 // vt->syscall_arg3 = req->size;
7342 // vt->syscall_arg4 = req->dest_address;
7344 AFTER = POST_FN(mach_vm_copy);
7347 POST(mach_vm_copy)
7349 #pragma pack(4)
7350 typedef struct {
7351 mach_msg_header_t Head;
7352 NDR_record_t NDR;
7353 kern_return_t RetCode;
7354 mach_msg_trailer_t trailer;
7355 } Reply;
7356 #pragma pack()
7358 Reply *reply = (Reply *)ARG1;
7360 if (!reply->RetCode) {
7361 if (MACH_REMOTE == vg_task_port) {
7362 // GrP fixme set dest's initialization equal to src's
7363 // BUT vm_copy allocates no memory
7365 } else {
7366 PRINT("mig return %d", reply->RetCode);
7370 PRE(mach_vm_read_overwrite)
7372 #pragma pack(4)
7373 typedef struct {
7374 mach_msg_header_t Head;
7375 NDR_record_t NDR;
7376 mach_vm_address_t address;
7377 mach_vm_size_t size;
7378 mach_vm_address_t data;
7379 } Request;
7380 #pragma pack()
7382 Request *req = (Request *)ARG1;
7384 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
7385 name_for_port(MACH_REMOTE),
7386 req->address, req->size, req->data);
7388 AFTER = POST_FN(mach_vm_read_overwrite);
7391 POST(mach_vm_read_overwrite)
7393 #pragma pack(4)
7394 typedef struct {
7395 mach_msg_header_t Head;
7396 NDR_record_t NDR;
7397 kern_return_t RetCode;
7398 mach_vm_size_t outsize;
7399 } Reply;
7400 #pragma pack()
7402 Reply *reply = (Reply *)ARG1;
7404 if (!reply->RetCode) {
7405 if (MACH_REMOTE == vg_task_port) {
7406 // GrP fixme set dest's initialization equal to src's
7407 // BUT vm_copy allocates no memory
7409 } else {
7410 PRINT("mig return %d", reply->RetCode);
7414 PRE(mach_vm_map)
7416 #pragma pack(4)
7417 typedef struct {
7418 mach_msg_header_t Head;
7419 /* start of the kernel processed data */
7420 mach_msg_body_t msgh_body;
7421 mach_msg_port_descriptor_t object;
7422 /* end of the kernel processed data */
7423 NDR_record_t NDR;
7424 mach_vm_address_t address;
7425 mach_vm_size_t size;
7426 mach_vm_address_t mask;
7427 int flags;
7428 memory_object_offset_t offset;
7429 boolean_t copy;
7430 vm_prot_t cur_protection;
7431 vm_prot_t max_protection;
7432 vm_inherit_t inheritance;
7433 } Request;
7434 #pragma pack()
7436 Request *req = (Request *)ARG1;
7438 // GrP fixme check these
7439 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7440 name_for_port(req->Head.msgh_remote_port),
7441 name_for_port(req->object.name),
7442 req->address, req->size,
7443 req->cur_protection,
7444 req->max_protection);
7446 MACH_ARG(mach_vm_map.size) = req->size;
7447 MACH_ARG(mach_vm_map.copy) = req->copy;
7448 MACH_ARG(mach_vm_map.protection) =
7449 (req->cur_protection & req->max_protection);
7451 AFTER = POST_FN(mach_vm_map);
7454 POST(mach_vm_map)
7456 #pragma pack(4)
7457 typedef struct {
7458 mach_msg_header_t Head;
7459 NDR_record_t NDR;
7460 kern_return_t RetCode;
7461 mach_vm_address_t address;
7462 mach_msg_trailer_t trailer;
7463 } Reply;
7464 #pragma pack()
7466 Reply *reply = (Reply *)ARG1;
7468 if (!reply->RetCode) {
7469 // GrP fixme check src and dest tasks
7470 PRINT("mapped at 0x%llx", reply->address);
7471 # if 0
7472 // GrP fixme max prot
7473 ML_(notify_core_and_tool_of_mmap)(
7474 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
7475 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
7476 // GrP fixme VKI_MAP_PRIVATE if !copy?
7477 # else
7478 ML_(sync_mappings)("after", "mach_vm_map", 0);
7479 # endif
7480 } else {
7481 PRINT("mig return %d", reply->RetCode);
7486 PRE(mach_vm_remap)
7488 #pragma pack(4)
7489 typedef struct {
7490 mach_msg_header_t Head;
7491 /* start of the kernel processed data */
7492 mach_msg_body_t msgh_body;
7493 mach_msg_port_descriptor_t src_task;
7494 /* end of the kernel processed data */
7495 NDR_record_t NDR;
7496 mach_vm_address_t target_address;
7497 mach_vm_size_t size;
7498 mach_vm_offset_t mask;
7499 int flags;
7500 mach_vm_address_t src_address;
7501 boolean_t copy;
7502 vm_inherit_t inheritance;
7503 } Request;
7504 #pragma pack()
7506 Request *req = (Request *)ARG1;
7508 // GrP fixme check these
7509 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7510 name_for_port(MACH_REMOTE),
7511 req->target_address, req->size,
7512 name_for_port(req->src_task.name));
7514 MACH_ARG(mach_vm_remap.size) = req->size;
7515 MACH_ARG(mach_vm_remap.copy) = req->copy;
7517 AFTER = POST_FN(mach_vm_remap);
7520 POST(mach_vm_remap)
7522 #pragma pack(4)
7523 typedef struct {
7524 mach_msg_header_t Head;
7525 NDR_record_t NDR;
7526 kern_return_t RetCode;
7527 mach_vm_address_t target_address;
7528 vm_prot_t cur_protection;
7529 vm_prot_t max_protection;
7530 } Reply;
7531 #pragma pack()
7533 Reply *reply = (Reply *)ARG1;
7535 if (!reply->RetCode) {
7536 // GrP fixme check src and dest tasks
7537 PRINT("mapped at 0x%llx", reply->target_address);
7538 // GrP fixme max prot
7539 ML_(notify_core_and_tool_of_mmap)(
7540 reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
7541 reply->cur_protection, VKI_MAP_SHARED, -1, 0);
7542 // GrP fixme VKI_MAP_PRIVATE if !copy?
7543 } else {
7544 PRINT("mig return %d", reply->RetCode);
7549 PRE(mach_vm_region_recurse)
7551 #pragma pack(4)
7552 typedef struct {
7553 mach_msg_header_t Head;
7554 NDR_record_t NDR;
7555 mach_vm_address_t address;
7556 natural_t nesting_depth;
7557 mach_msg_type_number_t infoCnt;
7558 } Request;
7559 #pragma pack()
7561 Request *req = (Request *)ARG1;
7563 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7564 name_for_port(MACH_REMOTE),
7565 req->address, req->nesting_depth, req->infoCnt);
7567 AFTER = POST_FN(mach_vm_region_recurse);
7570 POST(mach_vm_region_recurse)
7572 #pragma pack(4)
7573 typedef struct {
7574 mach_msg_header_t Head;
7575 NDR_record_t NDR;
7576 kern_return_t RetCode;
7577 mach_vm_address_t address;
7578 mach_vm_size_t size;
7579 natural_t nesting_depth;
7580 mach_msg_type_number_t infoCnt;
7581 int info[19];
7582 } Reply;
7583 #pragma pack()
7585 Reply *reply = (Reply *)ARG1;
7587 if (!reply->RetCode) {
7588 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7589 reply->address, reply->size,
7590 reply->nesting_depth, reply->infoCnt);
7591 // GrP fixme mark info contents beyond infoCnt as bogus
7592 } else {
7593 PRINT("mig return %d", reply->RetCode);
7598 /* ---------------------------------------------------------------------
7599 mach_msg: messages to thread
7600 ------------------------------------------------------------------ */
7604 POST(thread_terminate)
7609 PRE(thread_terminate)
7611 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7612 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
7614 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
7616 AFTER = POST_FN(thread_terminate);
7618 if (self_terminate) {
7619 // Terminating this thread.
7620 // Copied from sys_exit.
7621 ThreadState *tst = VG_(get_ThreadState)(tid);
7622 tst->exitreason = VgSrc_ExitThread;
7623 tst->os_state.exitcode = 0; // GrP fixme anything better?
7624 // What we would like to do is:
7625 // SET_STATUS_Success(0);
7626 // but that doesn't work, because this is a MACH-class syscall,
7627 // and SET_STATUS_Success creates a UNIX-class syscall result.
7628 // Hence we have to laboriously construct the full SysRes "by hand"
7629 // and use that to set the syscall return status.
7630 #if defined(VGA_x86)
7631 SET_STATUS_from_SysRes(
7632 VG_(mk_SysRes_x86_darwin)(
7633 VG_DARWIN_SYSCALL_CLASS_MACH,
7634 False/*success*/, 0, 0
7637 #elif defined(VGA_amd64)
7638 SET_STATUS_from_SysRes(
7639 VG_(mk_SysRes_amd64_darwin)(
7640 VG_DARWIN_SYSCALL_CLASS_MACH,
7641 False/*success*/, 0, 0
7644 #else
7645 #error unknown architecture
7646 #endif
7647 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
7648 } else {
7649 // Terminating some other thread.
7650 // Do keep the scheduler lock while terminating any other thread.
7651 // Otherwise we might halt the other thread while it holds the lock,
7652 // which would deadlock the process.
7653 // GrP fixme good enough?
7654 // GrP fixme need to clean up other thread's valgrind data?
7659 POST(thread_create)
7664 PRE(thread_create)
7666 PRINT("thread_create(mach_task_self(), ...)");
7668 AFTER = POST_FN(thread_create);
7670 // GrP fixme
7671 VG_(core_panic)("thread_create() unimplemented");
7675 PRE(thread_create_running)
7677 #pragma pack(4)
7678 typedef struct {
7679 mach_msg_header_t Head;
7680 NDR_record_t NDR;
7681 thread_state_flavor_t flavor;
7682 mach_msg_type_number_t new_stateCnt;
7683 natural_t new_state[144];
7684 } Request;
7685 #pragma pack()
7687 Request *req;
7688 thread_state_t regs;
7689 ThreadState *new_thread;
7691 PRINT("thread_create_running(mach_task_self(), ...)");
7693 // The new thread will immediately begin execution,
7694 // so we need to hijack the register state here.
7696 req = (Request *)ARG1;
7697 regs = (thread_state_t)req->new_state;
7699 // Build virtual thread.
7700 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
7702 // Edit the thread state to send to the real kernel.
7703 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
7705 AFTER = POST_FN(thread_create_running);
7709 POST(thread_create_running)
7711 #pragma pack(4)
7712 typedef struct {
7713 mach_msg_header_t Head;
7714 /* start of the kernel processed data */
7715 mach_msg_body_t msgh_body;
7716 mach_msg_port_descriptor_t child_act;
7717 /* end of the kernel processed data */
7718 } Reply;
7719 #pragma pack()
7721 Reply *reply = (Reply *)ARG1;
7723 assign_port_name(reply->child_act.name, "thread-%p");
7724 PRINT("%s", name_for_port(reply->child_act.name));
7728 PRE(bsdthread_create)
7730 ThreadState *tst;
7732 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7733 ARG1, ARG2, ARG3, ARG4, ARG5);
7734 PRE_REG_READ5(pthread_t,"bsdthread_create",
7735 void *,"func", void *,"func_arg", void *,"stack",
7736 pthread_t,"thread", unsigned int,"flags");
7738 // The kernel will call V's pthread_hijack() to launch the thread.
7739 // Here we allocate the thread state and pass it to pthread_hijack()
7740 // via the func_arg parameter.
7742 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
7743 allocstack(tst->tid);
7745 tst->os_state.func_arg = (Addr)ARG2;
7746 ARG2 = (Word)tst;
7748 // Create a semaphore that pthread_hijack will signal once it starts
7749 // POST(bsdthread_create) needs to wait for the new memory map to appear
7750 semaphore_create(mach_task_self(), &tst->os_state.child_go,
7751 SYNC_POLICY_FIFO, 0);
7752 semaphore_create(mach_task_self(), &tst->os_state.child_done,
7753 SYNC_POLICY_FIFO, 0);
7756 POST(bsdthread_create)
7758 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7759 // We hold V's lock on the child's behalf.
7760 // If we return before letting pthread_hijack do its thing, V thinks
7761 // the new pthread struct is still unmapped when we return to libc,
7762 // causing false errors.
7764 ThreadState *tst = (ThreadState *)ARG2;
7765 semaphore_signal(tst->os_state.child_go);
7766 semaphore_wait(tst->os_state.child_done);
7767 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
7768 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
7770 // GrP fixme semaphore destroy needed when thread creation fails
7771 // GrP fixme probably other cleanup too
7772 // GrP fixme spinlocks might be good enough?
7774 // DDD: I'm not at all sure this is the right spot for this. It probably
7775 // should be in pthread_hijack instead, just before the call to
7776 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7777 // parent tid value there...
7778 vg_assert(VG_(owns_BigLock_LL)(tid));
7779 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
7783 PRE(bsdthread_terminate)
7785 ThreadState *tst;
7787 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7788 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
7789 PRE_REG_READ4(int,"bsdthread_terminate",
7790 void *,"freeaddr", size_t,"freesize",
7791 mach_port_t,"kport", mach_port_t,"joinsem");
7793 // Free memory and signal semaphore.
7794 // GrP fixme errors?
7795 if (ARG4) semaphore_signal((semaphore_t)ARG4);
7796 if (ARG1 && ARG2) {
7797 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
7798 # if DARWIN_VERS >= DARWIN_10_8
7799 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7800 the mig output. Work around it for the time being. */
7801 VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
7802 # else
7803 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
7804 # endif
7807 // Tell V to terminate the thread.
7808 // Copied from sys_exit.
7809 tst = VG_(get_ThreadState)(tid);
7810 tst->exitreason = VgSrc_ExitThread;
7811 tst->os_state.exitcode = 0; // GrP fixme anything better?
7812 SET_STATUS_Success(0);
7816 POST(thread_suspend)
7820 PRE(thread_suspend)
7822 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7823 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
7825 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
7827 AFTER = POST_FN(thread_suspend);
7829 if (self_suspend) {
7830 // Don't keep the scheduler lock while self-suspending.
7831 // Otherwise we might halt while still holding the lock,
7832 // which would deadlock the process.
7833 *flags |= SfMayBlock;
7834 } else {
7835 // Do keep the scheduler lock while suspending any other thread.
7836 // Otherwise we might halt the other thread while it holds the lock,
7837 // which would deadlock the process.
7838 *flags &= ~SfMayBlock;
7843 POST(thread_resume)
7847 PRE(thread_resume)
7849 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7850 Bool self_resume = (mh->msgh_request_port == MACH_THREAD);
7852 PRINT("thread_resume(%s)", name_for_port(mh->msgh_request_port));
7854 AFTER = POST_FN(thread_resume);
7856 if (self_resume) {
7857 // This doesn't make much sense. If we are resuming ourself, we can't
7858 // already be running. So I don't see how we can ever get here.
7859 vg_assert(0);
7860 } else {
7861 // Resuming some other thread. It might not yet come back to life
7862 // (if the suspend count is still above zero) so make sure we keep
7863 // holding the lock.
7864 *flags &= ~SfMayBlock;
7869 POST(thread_get_state)
7871 #pragma pack(4)
7872 typedef struct {
7873 mach_msg_header_t Head;
7874 NDR_record_t NDR;
7875 kern_return_t RetCode;
7876 mach_msg_type_number_t old_stateCnt;
7877 natural_t old_state[144];
7878 mach_msg_trailer_t trailer;
7879 } Reply;
7880 #pragma pack()
7882 Reply *reply = (Reply *)ARG1;
7883 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7884 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
7886 if (!reply->RetCode) {
7887 thread_state_from_vex((thread_state_t)reply->old_state,
7888 flavor, reply->old_stateCnt,
7889 &VG_(get_ThreadState)(tid)->arch.vex);
7890 } else {
7891 PRINT("mig return %d", reply->RetCode);
7895 PRE(thread_get_state)
7897 #pragma pack(4)
7898 typedef struct {
7899 mach_msg_header_t Head;
7900 NDR_record_t NDR;
7901 thread_state_flavor_t flavor;
7902 mach_msg_type_number_t old_stateCnt;
7903 } Request;
7904 #pragma pack()
7906 Request *req = (Request *)ARG1;
7907 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7909 // GrP fixme if (self) {
7910 PRINT("thread_get_state(%s, %d)",
7911 name_for_port(req->Head.msgh_request_port), req->flavor);
7912 /*} else {
7913 PRINT("thread_get_state(0x%x, %d)",
7914 req->Head.msgh_request_port, req->flavor);
7917 // Hack the thread state after making the real call.
7918 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
7919 MACH_ARG(thread_get_state.flavor) = req->flavor;
7921 AFTER = POST_FN(thread_get_state);
7925 PRE(thread_policy)
7927 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7928 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7930 // GrP fixme if (self) {
7931 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
7932 /*} else {
7933 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7936 AFTER = POST_FN(thread_policy);
7939 POST(thread_policy)
7944 PRE(thread_policy_set)
7946 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7948 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
7950 AFTER = POST_FN(thread_policy_set);
7953 POST(thread_policy_set)
7958 PRE(thread_info)
7960 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7962 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
7963 // GrP fixme does any thread info need to be hijacked?
7965 AFTER = POST_FN(thread_info);
7968 POST(thread_info)
7970 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7975 /* ---------------------------------------------------------------------
7976 mach_msg: messages to bootstrap port
7977 ------------------------------------------------------------------ */
7980 POST(bootstrap_register)
7982 #pragma pack(4)
7983 typedef struct {
7984 mach_msg_header_t Head;
7985 NDR_record_t NDR;
7986 kern_return_t RetCode;
7987 mach_msg_trailer_t trailer;
7988 } Reply;
7989 #pragma pack()
7991 Reply *reply = (Reply *)ARG1;
7993 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
7996 PRE(bootstrap_register)
7998 #pragma pack(4)
7999 typedef struct {
8000 mach_msg_header_t Head;
8001 /* start of the kernel processed data */
8002 mach_msg_body_t msgh_body;
8003 mach_msg_port_descriptor_t service_port;
8004 /* end of the kernel processed data */
8005 NDR_record_t NDR;
8006 name_t service_name;
8007 } Request;
8008 #pragma pack()
8010 Request *req = (Request *)ARG1;
8012 PRINT("bootstrap_register(port 0x%x, \"%s\")",
8013 req->service_port.name, req->service_name);
8015 /* The required entry in the allocated_ports list (mapping) might
8016 not exist, due perhaps to broken syscall wrappers (mach__N etc).
8017 Create a minimal entry so that assign_port_name below doesn't
8018 cause an assertion. */
8019 if (!port_exists(req->service_port.name)) {
8020 port_create_vanilla(req->service_port.name);
8023 assign_port_name(req->service_port.name, req->service_name);
8025 AFTER = POST_FN(bootstrap_register);
8029 POST(bootstrap_look_up)
8031 #pragma pack(4)
8032 typedef struct {
8033 mach_msg_header_t Head;
8034 /* start of the kernel processed data */
8035 mach_msg_body_t msgh_body;
8036 mach_msg_port_descriptor_t service_port;
8037 /* end of the kernel processed data */
8038 mach_msg_trailer_t trailer;
8039 } Reply;
8040 #pragma pack()
8042 Reply *reply = (Reply *)ARG1;
8044 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
8045 reply->service_port.name)
8047 assign_port_name(reply->service_port.name,
8048 MACH_ARG(bootstrap_look_up.service_name));
8049 PRINT("%s", name_for_port(reply->service_port.name));
8050 } else {
8051 PRINT("not found");
8053 VG_(free)(MACH_ARG(bootstrap_look_up.service_name));
8056 PRE(bootstrap_look_up)
8058 #pragma pack(4)
8059 typedef struct {
8060 mach_msg_header_t Head;
8061 NDR_record_t NDR;
8062 name_t service_name;
8063 } Request;
8064 #pragma pack()
8066 Request *req = (Request *)ARG1;
8068 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
8070 MACH_ARG(bootstrap_look_up.service_name) =
8071 VG_(strdup)("syswrap-darwin.bootstrap-name", req->service_name);
8073 AFTER = POST_FN(bootstrap_look_up);
8077 /* ---------------------------------------------------------------------
8078 mach_msg: receiver-specific handlers
8079 ------------------------------------------------------------------ */
8082 POST(mach_msg_receive)
8084 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8086 // GrP fixme don't know of anything interesting here currently
8087 // import_complex_message handles everything
8088 // PRINT("UNHANDLED reply %d", mh->msgh_id);
8090 // Assume the call may have mapped or unmapped memory
8091 ML_(sync_mappings)("after", "mach_msg_receive", mh->msgh_id);
8094 PRE(mach_msg_receive)
8096 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8098 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
8100 AFTER = POST_FN(mach_msg_receive);
8102 // no message sent, only listening for a reply
8103 // assume message may block
8104 *flags |= SfMayBlock;
8108 PRE(mach_msg_bootstrap)
8110 // message to bootstrap port
8112 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8114 switch (mh->msgh_id) {
8115 case 403:
8116 CALL_PRE(bootstrap_register);
8117 return;
8118 case 404:
8119 CALL_PRE(bootstrap_look_up);
8120 return;
8122 default:
8123 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
8124 mh->msgh_id, name_for_port(mh->msgh_request_port),
8125 mh->msgh_reply_port);
8126 return;
8131 PRE(mach_msg_host)
8133 // message to host self - check for host-level kernel calls
8135 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8137 switch (mh->msgh_id) {
8138 case 200:
8139 CALL_PRE(host_info);
8140 return;
8141 case 202:
8142 CALL_PRE(host_page_size);
8143 return;
8144 case 205:
8145 CALL_PRE(host_get_io_master);
8146 return;
8147 case 206:
8148 CALL_PRE(host_get_clock_service);
8149 return;
8150 case 217:
8151 CALL_PRE(host_request_notification);
8152 return;
8153 case 222:
8154 CALL_PRE(host_create_mach_voucher);
8155 return;
8157 case 412:
8158 CALL_PRE(host_get_special_port);
8159 return;
8161 default:
8162 // unknown message to host self
8163 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
8164 mh->msgh_id, name_for_port(mh->msgh_request_port),
8165 mh->msgh_reply_port);
8166 return;
8170 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
8171 // /usr/include/mach/mach_port.h et al (grep in /usr/include
8172 // for them)
8173 PRE(mach_msg_task)
8175 // message to a task port
8177 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8179 switch (mh->msgh_id) {
8180 case 3201:
8181 CALL_PRE(mach_port_type);
8182 return;
8183 case 3204:
8184 CALL_PRE(mach_port_allocate);
8185 return;
8186 case 3205:
8187 CALL_PRE(mach_port_destroy);
8188 return;
8189 case 3206:
8190 CALL_PRE(mach_port_deallocate);
8191 return;
8192 case 3207:
8193 CALL_PRE(mach_port_get_refs);
8194 return;
8195 case 3208:
8196 CALL_PRE(mach_port_mod_refs);
8197 return;
8198 case 3211:
8199 CALL_PRE(mach_port_get_set_status);
8200 return;
8201 case 3212:
8202 CALL_PRE(mach_port_move_member);
8203 return;
8204 case 3213:
8205 CALL_PRE(mach_port_request_notification);
8206 return;
8207 case 3214:
8208 CALL_PRE(mach_port_insert_right);
8209 return;
8210 case 3215:
8211 CALL_PRE(mach_port_extract_right);
8212 return;
8213 case 3217:
8214 CALL_PRE(mach_port_get_attributes);
8215 return;
8216 case 3218:
8217 CALL_PRE(mach_port_set_attributes);
8218 return;
8219 case 3226:
8220 CALL_PRE(mach_port_insert_member);
8221 return;
8222 case 3227:
8223 CALL_PRE(mach_port_extract_member);
8224 return;
8226 case 3229:
8227 CALL_PRE(mach_port_set_context);
8228 return;
8230 case 3402:
8231 CALL_PRE(task_threads);
8232 return;
8233 case 3403:
8234 CALL_PRE(mach_ports_register);
8235 return;
8236 case 3404:
8237 CALL_PRE(mach_ports_lookup);
8238 return;
8239 case 3405:
8240 CALL_PRE(task_info);
8241 return;
8242 case 3406:
8243 CALL_PRE(task_set_info);
8244 return;
8245 case 3407:
8246 CALL_PRE(task_suspend);
8247 return;
8248 case 3408:
8249 CALL_PRE(task_resume);
8250 return;
8251 case 3409:
8252 CALL_PRE(task_get_special_port);
8253 return;
8254 case 3410:
8255 CALL_PRE(task_set_special_port);
8256 return;
8257 case 3411:
8258 CALL_PRE(thread_create);
8259 return;
8260 case 3412:
8261 CALL_PRE(thread_create_running);
8262 return;
8264 case 3414:
8265 CALL_PRE(task_get_exception_ports);
8266 return;
8268 case 3418:
8269 CALL_PRE(semaphore_create);
8270 return;
8271 case 3419:
8272 CALL_PRE(semaphore_destroy);
8273 return;
8274 case 3420:
8275 CALL_PRE(task_policy_set);
8276 return;
8278 #if DARWIN_VERS >= DARWIN_10_12
8279 case 3444:
8280 CALL_PRE(task_register_dyld_image_infos);
8281 return;
8283 case 3447:
8284 CALL_PRE(task_register_dyld_shared_cache_image_info);
8285 return;
8286 #endif /* DARWIN_VERS >= DARWIN_10_12 */
8288 case 3801:
8289 CALL_PRE(vm_allocate);
8290 return;
8291 case 3802:
8292 CALL_PRE(vm_deallocate);
8293 return;
8294 case 3803:
8295 CALL_PRE(vm_protect);
8296 return;
8297 case 3804:
8298 CALL_PRE(vm_inherit);
8299 return;
8300 case 3805:
8301 CALL_PRE(vm_read);
8302 return;
8303 case 3808:
8304 CALL_PRE(vm_copy);
8305 return;
8306 case 3809:
8307 CALL_PRE(vm_read_overwrite);
8308 return;
8309 case 3812:
8310 CALL_PRE(vm_map);
8311 return;
8312 case 3814:
8313 CALL_PRE(vm_remap);
8314 return;
8315 case 3825:
8316 CALL_PRE(mach_make_memory_entry_64);
8317 return;
8318 case 3830:
8319 CALL_PRE(vm_purgable_control);
8320 return;
8322 case 4800:
8323 CALL_PRE(mach_vm_allocate);
8324 return;
8325 case 4801:
8326 CALL_PRE(mach_vm_deallocate);
8327 return;
8328 case 4802:
8329 CALL_PRE(mach_vm_protect);
8330 return;
8331 case 4803:
8332 CALL_PRE(mach_vm_inherit);
8333 return;
8334 case 4804:
8335 CALL_PRE(mach_vm_read);
8336 return;
8337 case 4807:
8338 CALL_PRE(mach_vm_copy);
8339 return;
8340 case 4808:
8341 CALL_PRE(mach_vm_read_overwrite);
8342 return;
8343 case 4811:
8344 CALL_PRE(mach_vm_map);
8345 return;
8346 case 4813:
8347 CALL_PRE(mach_vm_remap);
8348 return;
8349 case 4815:
8350 CALL_PRE(mach_vm_region_recurse);
8351 return;
8352 case 4817:
8353 CALL_PRE(mach_make_memory_entry_64);
8354 return;
8355 case 4818:
8356 CALL_PRE(mach_vm_purgable_control);
8357 return;
8359 default:
8360 // unknown message to task self
8361 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
8362 mh->msgh_id, name_for_port(mh->msgh_remote_port),
8363 mh->msgh_reply_port);
8364 return;
8369 PRE(mach_msg_thread)
8371 // message to local thread - check for thread-level kernel calls
8373 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8375 switch (mh->msgh_id) {
8376 case 3600:
8377 CALL_PRE(thread_terminate);
8378 return;
8379 case 3603:
8380 CALL_PRE(thread_get_state);
8381 return;
8382 case 3605:
8383 CALL_PRE(thread_suspend);
8384 return;
8385 case 3606:
8386 CALL_PRE(thread_resume);
8387 return;
8388 case 3612:
8389 CALL_PRE(thread_info);
8390 return;
8391 case 3616:
8392 CALL_PRE(thread_policy);
8393 return;
8394 case 3617:
8395 CALL_PRE(thread_policy_set);
8396 return;
8397 default:
8398 // unknown message to a thread
8399 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
8400 mh->msgh_id, name_for_port(mh->msgh_request_port),
8401 mh->msgh_reply_port);
8402 return;
8407 static int is_thread_port(mach_port_t port)
8409 if (port == 0) return False;
8411 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
8415 static int is_task_port(mach_port_t port)
8417 if (port == 0) return False;
8419 if (port == vg_task_port) return True;
8421 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
8425 /* ---------------------------------------------------------------------
8426 mach_msg: base handlers
8427 ------------------------------------------------------------------ */
8429 PRE(mach_msg)
8431 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8432 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8433 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8434 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
8435 // mach_port_t rcv_name = (mach_port_t)ARG5;
8436 size_t complex_header_size = 0;
8438 PRE_REG_READ7(long, "mach_msg",
8439 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
8440 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
8441 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
8442 mach_port_t,"notify");
8444 // Assume default POST handler until specified otherwise
8445 AFTER = NULL;
8447 // Assume call may block unless specified otherwise
8448 *flags |= SfMayBlock;
8450 if (option & MACH_SEND_MSG) {
8451 // Validate outgoing message header
8452 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8453 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
8454 // msgh_size not required, use parameter instead
8455 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8456 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
8457 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8458 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
8459 // msgh_reserved not required
8460 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8461 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
8463 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8464 // Validate typed message data and handle memory map changes.
8465 complex_header_size = export_complex_message(tid, mh);
8468 // GrP fixme handle sender-specified message trailer
8469 // (but is this only for too-secure processes?)
8470 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8471 # if DARWIN_VERS >= DARWIN_10_10
8472 if (mh->msgh_bits & MACH_SEND_TRAILER) {
8473 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8475 # else
8476 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
8477 # endif
8479 MACH_REMOTE = mh->msgh_remote_port;
8480 MACH_MSGH_ID = mh->msgh_id;
8483 if (option & MACH_RCV_MSG) {
8484 // Pre-validate receive buffer
8485 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
8488 // Call a PRE handler. The PRE handler may set an AFTER handler.
8490 if (!(option & MACH_SEND_MSG)) {
8491 // no message sent, receive only
8492 CALL_PRE(mach_msg_receive);
8493 return;
8495 else if (mh->msgh_request_port == vg_host_port) {
8496 // message sent to mach_host_self()
8497 CALL_PRE(mach_msg_host);
8498 return;
8500 else if (is_task_port(mh->msgh_request_port)) {
8501 // message sent to a task
8502 CALL_PRE(mach_msg_task);
8503 return;
8505 else if (mh->msgh_request_port == vg_bootstrap_port) {
8506 // message sent to bootstrap port
8507 CALL_PRE(mach_msg_bootstrap);
8508 return;
8510 else if (is_thread_port(mh->msgh_request_port)) {
8511 // message sent to one of this process's threads
8512 CALL_PRE(mach_msg_thread);
8513 return;
8515 else {
8516 // this is an attempt to optimize mapping sync
8517 // but there are always some cases hard to find
8518 #if 0
8519 Bool do_mapping_update = False;
8520 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8521 // which is obviously not true...
8522 switch (mh->msgh_id) {
8523 // com.apple.windowserver.active
8524 case 29008: // this one opens a port type 'a'
8526 // com.apple.windowserver.active 'a' port
8527 case 29000:
8528 case 29822:
8529 case 29820: // adds a vm mapping
8530 case 29809: // contains a ool mem
8531 case 29800: // opens a port type 'b'
8532 case 29873:
8533 case 29876: // adds a vm mapping
8535 // com.apple.windowserver.active 'b' port
8536 case 29624:
8537 case 29625:
8538 case 29506:
8539 case 29504:
8540 case 29509:
8541 case 29315:
8542 case 29236:
8543 case 29473:
8544 case 29268:
8545 case 29237: // contains a ool mem
8546 case 29360:
8547 case 29301:
8548 case 29287:
8549 case 29568:
8550 case 29570: // contains a ool mem
8551 case 29211:
8552 case 29569: // contains a ool mem
8553 case 29374:
8554 case 29246:
8555 case 29239:
8556 case 29272:
8557 if (mh->msgh_id == 29820 ||
8558 mh->msgh_id == 29876)
8559 do_mapping_update = True;
8561 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8562 mh->msgh_id, name_for_port(mh->msgh_request_port),
8563 mh->msgh_reply_port);
8564 break;
8566 // com.apple.FontServer
8567 case 13024:
8568 PRINT("com.apple.FontServerservice 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.notification_center
8574 case 78945698:
8575 case 78945701:
8576 case 78945695: // contains a ool mem
8577 case 78945694:
8578 case 78945700:
8579 if (mh->msgh_id == 78945695)
8580 do_mapping_update = False;
8581 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8582 mh->msgh_id, name_for_port(mh->msgh_request_port),
8583 mh->msgh_reply_port);
8584 break;
8586 // com.apple.CoreServices.coreservicesd
8587 case 10000:
8588 case 10019:
8589 case 10002: // adds vm mappings
8590 case 10003: // adds vm mappings
8591 case 14007:
8592 case 13000:
8593 case 13001:
8594 case 13011:
8595 case 13016: // contains a ool mem
8596 if (mh->msgh_id == 10002||
8597 mh->msgh_id == 10003)
8598 do_mapping_update = True;
8599 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8600 mh->msgh_id, name_for_port(mh->msgh_request_port),
8601 mh->msgh_reply_port);
8602 break;
8604 // com.apple.system.logger
8605 case 118:
8606 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8607 mh->msgh_id, name_for_port(mh->msgh_request_port),
8608 mh->msgh_reply_port);
8609 break;
8611 // com.apple.coreservices.launchservicesd, and others
8612 case 1999646836: // might adds vm mapping
8613 if (mh->msgh_id == 1999646836)
8614 do_mapping_update = True;
8615 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8616 mh->msgh_id, name_for_port(mh->msgh_request_port),
8617 mh->msgh_reply_port);
8618 break;
8620 // com.apple.ocspd
8621 case 33012:
8622 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8623 mh->msgh_id, name_for_port(mh->msgh_request_port),
8624 mh->msgh_reply_port);
8626 default:
8627 // arbitrary message to arbitrary port
8628 do_mapping_update = True;
8629 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
8630 mh->msgh_id, name_for_port(mh->msgh_request_port),
8631 mh->msgh_reply_port);
8634 // this is an optimization, don't check mapping on known mach_msg
8635 if (do_mapping_update)
8636 AFTER = POST_FN(mach_msg_unhandled);
8637 else
8638 AFTER = POST_FN(mach_msg_unhandled_check);
8639 #else
8640 AFTER = POST_FN(mach_msg_unhandled);
8641 #endif
8643 // Assume the entire message body may be read.
8644 // GrP fixme generates false positives for unknown protocols
8646 PRE_MEM_READ("mach_msg(payload)",
8647 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8648 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8650 return;
8654 POST(mach_msg)
8656 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8657 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8659 if (option & MACH_RCV_MSG) {
8660 if (RES != 0) {
8661 // error during send or receive
8662 // GrP fixme need to clean up port rights?
8663 } else {
8664 mach_msg_trailer_t *mt =
8665 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
8667 // Assume the entire received message and trailer is initialized
8668 // GrP fixme would being more specific catch any bugs?
8669 POST_MEM_WRITE((Addr)mh,
8670 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
8672 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8673 // Update memory map for out-of-line message data
8674 import_complex_message(tid, mh);
8679 // Call handler chosen by PRE(mach_msg)
8680 if (AFTER) {
8681 (*AFTER)(tid, arrghs, status);
8686 POST(mach_msg_unhandled)
8688 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8689 ML_(sync_mappings)("after", "mach_msg_receive-UNHANDLED", mh->msgh_id);
8692 POST(mach_msg_unhandled_check)
8694 if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
8695 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
8699 /* ---------------------------------------------------------------------
8700 other Mach traps
8701 ------------------------------------------------------------------ */
8703 PRE(mach_reply_port)
8705 PRINT("mach_reply_port()");
8708 POST(mach_reply_port)
8710 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
8711 PRINT("reply port %s", name_for_port(RES));
8715 PRE(mach_thread_self)
8717 PRINT("mach_thread_self()");
8720 POST(mach_thread_self)
8722 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
8723 PRINT("thread %#lx", RES);
8727 PRE(mach_host_self)
8729 PRINT("mach_host_self()");
8732 POST(mach_host_self)
8734 vg_host_port = RES;
8735 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
8736 PRINT("host %#lx", RES);
8740 PRE(mach_task_self)
8742 PRINT("mach_task_self()");
8745 POST(mach_task_self)
8747 vg_task_port = RES;
8748 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
8749 PRINT("task %#lx", RES);
8753 PRE(syscall_thread_switch)
8755 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8756 name_for_port(ARG1), SARG2, SARG3);
8757 PRE_REG_READ3(long, "syscall_thread_switch",
8758 mach_port_t,"thread", int,"option", natural_t,"timeout");
8760 *flags |= SfMayBlock;
8764 PRE(semaphore_signal)
8766 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
8767 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8771 PRE(semaphore_signal_all)
8773 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
8774 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
8778 PRE(semaphore_signal_thread)
8780 PRINT("semaphore_signal_thread(%s, %s)",
8781 name_for_port(ARG1), name_for_port(ARG2));
8782 PRE_REG_READ2(long, "semaphore_signal_thread",
8783 semaphore_t,"semaphore", mach_port_t,"thread");
8787 PRE(semaphore_wait)
8789 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
8790 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8792 *flags |= SfMayBlock;
8796 PRE(semaphore_wait_signal)
8798 PRINT("semaphore_wait_signal(%s, %s)",
8799 name_for_port(ARG1), name_for_port(ARG2));
8800 PRE_REG_READ2(long, "semaphore_wait_signal",
8801 semaphore_t,"wait_semaphore",
8802 semaphore_t,"signal_semaphore");
8804 *flags |= SfMayBlock;
8808 PRE(semaphore_timedwait)
8810 PRINT("semaphore_timedwait(%s, %g seconds)",
8811 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
8812 PRE_REG_READ3(long, "semaphore_wait_signal",
8813 semaphore_t,"semaphore",
8814 int,"wait_time_hi",
8815 int,"wait_time_lo");
8817 *flags |= SfMayBlock;
8821 PRE(semaphore_timedwait_signal)
8823 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8824 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
8825 PRE_REG_READ4(long, "semaphore_wait_signal",
8826 semaphore_t,"wait_semaphore",
8827 semaphore_t,"signal_semaphore",
8828 int,"wait_time_hi",
8829 int,"wait_time_lo");
8831 *flags |= SfMayBlock;
8835 PRE(__semwait_signal)
8837 /* 10.5 args: int cond_sem, int mutex_sem,
8838 int timeout, int relative,
8839 time_t tv_sec, time_t tv_nsec */
8840 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8841 name_for_port(ARG1), name_for_port(ARG2), SARG3, SARG4, SARG5, SARG6);
8842 PRE_REG_READ6(long, "__semwait_signal",
8843 int,"cond_sem", int,"mutex_sem",
8844 int,"timeout", int,"relative",
8845 vki_time_t,"tv_sec", int,"tv_nsec");
8847 *flags |= SfMayBlock;
8849 // GrP provided this alternative version for 10.6, but NjN
8850 // reckons the 10.5 is is still correct for 10.6. So, retaining
8851 // Greg's version as a comment just in case we need it later.
8852 //PRE(__old_semwait_signal)
8854 // /* 10.5 args: int cond_sem, int mutex_sem,
8855 // int timeout, int relative,
8856 // const timespec *ts */
8857 // PRINT("__old_semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8858 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8859 // PRE_REG_READ5(int, "__old_semwait_signal",
8860 // int,cond_sem, int,mutex_sem,
8861 // int,timeout, int,relative,
8862 // const struct vki_timespec *,ts);
8864 // if (ARG5) PRE_MEM_READ ("__old_semwait_signal(ts)",
8865 // ARG5, sizeof(struct vki_timespec));
8867 // *flags |= SfMayBlock;
8871 PRE(task_for_pid)
8873 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), SARG2, ARG3);
8874 PRE_REG_READ3(long, "task_for_pid",
8875 mach_port_t,"target",
8876 vki_pid_t, "pid", mach_port_t *,"task");
8877 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
8880 POST(task_for_pid)
8882 mach_port_t task;
8884 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
8886 task = *(mach_port_t *)ARG3;
8887 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
8888 PRINT("task 0x%x", task);
8892 PRE(pid_for_task)
8894 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
8895 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
8896 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
8899 POST(pid_for_task)
8901 vki_pid_t pid;
8903 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
8905 pid = *(vki_pid_t *)ARG2;
8906 PRINT("pid %u", pid);
8910 PRE(mach_timebase_info)
8912 PRINT("mach_timebase_info(%#lx)", ARG1);
8913 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8914 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
8917 POST(mach_timebase_info)
8919 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
8923 PRE(mach_wait_until)
8925 #if VG_WORDSIZE == 8
8926 PRINT("mach_wait_until(%lu)", ARG1);
8927 PRE_REG_READ1(long, "mach_wait_until",
8928 unsigned long long,"deadline");
8929 #else
8930 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
8931 PRE_REG_READ2(long, "mach_wait_until",
8932 int,"deadline_hi", int,"deadline_lo");
8933 #endif
8934 *flags |= SfMayBlock;
8938 PRE(mk_timer_create)
8940 PRINT("mk_timer_create()");
8941 PRE_REG_READ0(long, "mk_timer_create");
8944 POST(mk_timer_create)
8946 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
8950 PRE(mk_timer_destroy)
8952 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
8953 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
8955 // Must block to prevent race (other thread allocates and
8956 // notifies after we deallocate but before we notify)
8957 *flags &= ~SfMayBlock;
8960 POST(mk_timer_destroy)
8962 // Must have cleared SfMayBlock in PRE to prevent race
8963 record_port_destroy(ARG1);
8967 PRE(mk_timer_arm)
8969 #if VG_WORDSIZE == 8
8970 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
8971 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
8972 unsigned long,"expire_time");
8973 #else
8974 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
8975 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
8976 int,"expire_time_hi", int,"expire_time_lo");
8977 #endif
8981 PRE(mk_timer_cancel)
8983 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
8984 PRE_REG_READ2(long, "mk_timer_cancel",
8985 mach_port_t,"name", Addr,"result_time");
8986 if (ARG2) {
8987 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
8991 POST(mk_timer_cancel)
8993 if (ARG2) {
8994 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
8999 PRE(iokit_user_client_trap)
9001 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
9002 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9003 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
9004 mach_port_t,connect, unsigned int,index,
9005 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
9006 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
9008 // can't do anything else with this in general
9009 // might be able to use connect+index to choose something sometimes
9012 POST(iokit_user_client_trap)
9014 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
9018 PRE(swtch)
9020 PRINT("swtch ( )");
9021 PRE_REG_READ0(long, "swtch");
9023 *flags |= SfMayBlock;
9027 PRE(swtch_pri)
9029 PRINT("swtch_pri ( %ld )", SARG1);
9030 PRE_REG_READ1(long, "swtch_pri", int,"pri");
9032 *flags |= SfMayBlock;
9036 PRE(FAKE_SIGRETURN)
9038 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
9039 an explanation of what follows. */
9040 /* This handles the fake signal-return system call created by
9041 sigframe-x86-darwin.c. */
9042 /* See also comments just below on PRE(sigreturn). */
9044 PRINT("FAKE_SIGRETURN ( )");
9046 vg_assert(VG_(is_valid_tid)(tid));
9047 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9048 vg_assert(VG_(is_running_thread)(tid));
9050 /* Remove the signal frame from this thread's (guest) stack,
9051 in the process restoring the pre-signal guest state. */
9052 VG_(sigframe_destroy)(tid, True);
9054 /* Tell the driver not to update the guest state with the "result",
9055 and set a bogus result to keep it happy. */
9056 *flags |= SfNoWriteResult;
9057 SET_STATUS_Success(0);
9059 /* Check to see if any signals arose as a result of this. */
9060 *flags |= SfPollAfter;
9064 PRE(sigreturn)
9066 /* This is the "real" sigreturn. But because we construct all the
9067 signal frames ourselves (of course, in m_sigframe), this cannot
9068 happen as a result of normal signal delivery. I think it
9069 happens only when doing siglongjmp, in which case Darwin's Libc
9070 appears to use it for two different purposes: to mess with the
9071 per-thread sigaltstack flags (as per arg 2), or to restore the
9072 thread's state from a ucontext* (as per arg 1). */
9074 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
9076 vg_assert(VG_(is_valid_tid)(tid));
9077 vg_assert(tid >= 1 && tid < VG_N_THREADS);
9078 vg_assert(VG_(is_running_thread)(tid));
9080 if (ARG2 == VKI_UC_SET_ALT_STACK) {
9081 /* This is confusing .. the darwin kernel sources imply there is
9082 a per-thread on-altstack/not-on-altstack flag, which is set
9083 by this flag. Just ignore it and claim success for the time
9084 being. */
9085 VG_(debugLog)(1, "syswrap-darwin",
9086 "WARNING: Ignoring sigreturn( ..., "
9087 "UC_SET_ALT_STACK );\n");
9088 SET_STATUS_Success(0);
9089 return;
9091 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
9092 /* Ditto */
9093 VG_(debugLog)(1, "syswrap-darwin",
9094 "WARNING: Ignoring sigreturn( ..., "
9095 "UC_RESET_ALT_STACK );\n");
9096 SET_STATUS_Success(0);
9097 return;
9100 /* Otherwise claim this isn't supported. (Could be
9101 catastrophic).
9103 What do we have to do if we do need to support it?
9105 1. Change the second argument of VG_(sigframe_destroy) from
9106 "Bool isRT" to "UInt sysno", so we can pass the syscall
9107 number, so it can distinguish this case from the
9108 __NR_DARWIN_FAKE_SIGRETURN case.
9110 2. In VG_(sigframe_destroy), look at sysno to distinguish the
9111 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
9112 For this case, restore the thread's CPU state (or at least
9113 the integer regs) from the ucontext in ARG1 (and do all the
9114 other "signal-returns" stuff too).
9116 3. For (2), how do we know where the ucontext is? One way is to
9117 temporarily copy ARG1 into this thread's guest_EBX (or any
9118 other int reg), and have VG_(sigframe_destroy) read
9119 guest_EBX. Why is it ok to trash guest_EBX (or any other int
9120 reg)? Because VG_(sigframe_destroy) is just about to
9121 overwrite all the regs anyway -- since the primary purpose of
9122 calling it is to restore the register state from the ucontext
9123 pointed to by ARG1.
9125 Hey, it's uggerly. But at least it's documented.
9127 /* But in the meantime ... */
9128 VG_(debugLog)(0, "syswrap-darwin",
9129 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
9130 VG_(debugLog)(0, "syswrap-darwin",
9131 "WARNING: Thread/program/Valgrind "
9132 "will likely segfault now.\n");
9133 VG_(debugLog)(0, "syswrap-darwin",
9134 "WARNING: Please file a bug report at "
9135 "http://www.valgrind.org.\n");
9136 SET_STATUS_Failure( VKI_ENOSYS );
9140 /* ---------------------------------------------------------------------
9141 machine-dependent traps
9142 ------------------------------------------------------------------ */
9144 #if defined(VGA_x86)
9145 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
9147 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
9148 return VG_(calloc)("syswrap-darwin.ldt", nbytes, 1);
9150 #endif
9152 PRE(thread_fast_set_cthread_self)
9154 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
9155 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
9157 #if defined(VGA_x86)
9158 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
9160 VexGuestX86SegDescr *ldt;
9161 ThreadState *tst = VG_(get_ThreadState)(tid);
9162 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
9163 if (!ldt) {
9164 ldt = alloc_zeroed_x86_LDT();
9165 tst->arch.vex.guest_LDT = (HWord)ldt;
9167 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
9168 ldt[6].LdtEnt.Bits.LimitLow = 1;
9169 ldt[6].LdtEnt.Bits.LimitHi = 0;
9170 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
9171 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
9172 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
9173 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
9174 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
9175 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
9176 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
9177 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
9179 tst->os_state.pthread = ARG1;
9180 tst->arch.vex.guest_GS = 0x37;
9182 // What we would like to do is:
9183 // SET_STATUS_Success(0x37);
9184 // but that doesn't work, because this is a MDEP-class syscall,
9185 // and SET_STATUS_Success creates a UNIX-class syscall result.
9186 // Hence we have to laboriously construct the full SysRes "by hand"
9187 // and use that to set the syscall return status.
9188 SET_STATUS_from_SysRes(
9189 VG_(mk_SysRes_x86_darwin)(
9190 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9191 False, 0, 0x37
9196 #elif defined(VGA_amd64)
9197 // GrP fixme bigger hack than x86
9199 ThreadState *tst = VG_(get_ThreadState)(tid);
9200 tst->os_state.pthread = ARG1;
9201 tst->arch.vex.guest_GS_CONST = ARG1;
9202 // SET_STATUS_Success(0x60);
9203 // see comments on x86 case just above
9204 SET_STATUS_from_SysRes(
9205 VG_(mk_SysRes_amd64_darwin)(
9206 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
9207 False, 0, 0x60
9212 #else
9213 #error unknown architecture
9214 #endif
9218 /* ---------------------------------------------------------------------
9219 Added for OSX 10.6 (Snow Leopard)
9220 ------------------------------------------------------------------ */
9222 #if DARWIN_VERS >= DARWIN_10_6
9224 PRE(psynch_mutexwait)
9226 PRINT("psynch_mutexwait(BOGUS)");
9227 *flags |= SfMayBlock;
9229 POST(psynch_mutexwait)
9233 PRE(psynch_mutexdrop)
9235 PRINT("psynch_mutexdrop(BOGUS)");
9236 *flags |= SfMayBlock;
9238 POST(psynch_mutexdrop)
9242 PRE(psynch_cvbroad)
9244 PRINT("psynch_cvbroad(BOGUS)");
9246 POST(psynch_cvbroad)
9250 PRE(psynch_cvsignal)
9252 PRINT("psynch_cvsignal(BOGUS)");
9254 POST(psynch_cvsignal)
9258 PRE(psynch_cvwait)
9260 PRINT("psynch_cvwait(BOGUS)");
9261 *flags |= SfMayBlock;
9263 POST(psynch_cvwait)
9267 PRE(psynch_rw_rdlock)
9269 PRINT("psynch_rw_rdlock(BOGUS)");
9270 *flags |= SfMayBlock;
9272 POST(psynch_rw_rdlock)
9276 PRE(psynch_rw_wrlock)
9278 PRINT("psynch_rw_wrlock(BOGUS)");
9279 *flags |= SfMayBlock;
9281 POST(psynch_rw_wrlock)
9285 PRE(psynch_rw_unlock)
9287 PRINT("psynch_rw_unlock(BOGUS)");
9289 POST(psynch_rw_unlock)
9293 PRE(__thread_selfid)
9295 PRINT("__thread_selfid ()");
9296 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
9299 PRE(fsgetpath)
9301 #if VG_WORDSIZE == 4
9302 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
9303 ARG1, ARG2, ARG3,
9304 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
9305 LOHI64(ARG4, ARG5));
9306 PRE_REG_READ5(ssize_t, "fsgetpath",
9307 void*,"buf", size_t,"bufsize",
9308 fsid_t *,"fsid",
9309 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
9310 #else
9311 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
9312 ARG1, ARG2, ARG3,
9313 ((unsigned int *)ARG3)[0],
9314 ((unsigned int *)ARG3)[1], ARG4);
9315 PRE_REG_READ4(ssize_t, "fsgetpath",
9316 void*,"buf", size_t,"bufsize",
9317 fsid_t *,"fsid", uint64_t,"objid");
9318 #endif
9319 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
9320 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
9323 POST(fsgetpath)
9325 POST_MEM_WRITE(ARG1, RES);
9328 PRE(audit_session_self)
9330 PRINT("audit_session_self()");
9332 POST(audit_session_self)
9334 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
9335 PRINT("audit-session %#lx", RES);
9338 PRE(fgetattrlist)
9340 PRINT("fgetattrlist(%ld, %#lx, %#lx, %lu, %lu)",
9341 ARG1, ARG2, ARG3, ARG4, ARG5);
9342 PRE_REG_READ5(int, "fgetattrlist",
9343 int,fd, struct vki_attrlist *,attrList,
9344 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
9345 PRE_MEM_READ("fgetattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
9346 PRE_MEM_WRITE("fgetattrlist(attrBuf)", ARG3, ARG4);
9348 POST(fgetattrlist)
9350 if (ARG4 > sizeof(vki_uint32_t)) {
9351 // attrBuf is uint32_t size followed by attr data
9352 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
9353 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
9354 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
9355 // *sizep is bytes required for return value, including *sizep
9356 } else {
9357 // *sizep is actual bytes returned, including *sizep
9359 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
9363 #endif /* DARWIN_VERS >= DARWIN_10_6 */
9366 /* ---------------------------------------------------------------------
9367 Added for OSX 10.7 (Lion)
9368 ------------------------------------------------------------------ */
9370 #if DARWIN_VERS >= DARWIN_10_7
9372 PRE(psynch_cvclrprepost)
9374 PRINT("psynch_cvclrprepost(BOGUS)");
9375 *flags |= SfMayBlock;
9377 POST(psynch_cvclrprepost)
9381 #endif /* DARWIN_VERS >= DARWIN_10_7 */
9384 /* ---------------------------------------------------------------------
9385 Added for OSX 10.8 (Mountain Lion)
9386 ------------------------------------------------------------------ */
9388 /* About munge tags, eg munge_wllww.
9390 Means the syscall takes 5 args. For a 64 bit process each arg
9391 occupies one 64-bit value and so the mapping to ARGn macros is
9392 direct. For a 32 bit process, this is more complex: 'w' denotes a
9393 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
9394 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
9395 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
9396 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
9397 in order to get sane values for the arguments in 32-bit
9398 processes. */
9400 static void munge_wwl(UWord* a1, UWord* a2, ULong* a3,
9401 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4)
9403 # if defined(VGA_x86)
9404 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4);
9405 # else
9406 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9407 # endif
9410 static void munge_wll(UWord* a1, ULong* a2, ULong* a3,
9411 UWord aRG1, UWord aRG2, UWord aRG3,
9412 UWord aRG4, UWord aRG5)
9414 # if defined(VGA_x86)
9415 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9416 # else
9417 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
9418 # endif
9421 static void munge_wwlw(UWord* a1, UWord* a2, ULong* a3, UWord* a4,
9422 UWord aRG1, UWord aRG2, UWord aRG3,
9423 UWord aRG4, UWord aRG5)
9425 # if defined(VGA_x86)
9426 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4); *a4 = aRG5;
9427 # else
9428 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9429 # endif
9432 static void munge_wwwl(UWord* a1, UWord* a2, UWord* a3, ULong* a4,
9433 UWord aRG1, UWord aRG2, UWord aRG3,
9434 UWord aRG4, UWord aRG5)
9436 # if defined(VGA_x86)
9437 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = LOHI64(aRG4,aRG5);
9438 # else
9439 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
9440 # endif
9443 static void munge_wllww(UWord* a1, ULong* a2, ULong* a3, UWord* a4, UWord* a5,
9444 UWord aRG1, UWord aRG2, UWord aRG3,
9445 UWord aRG4, UWord aRG5, UWord aRG6, UWord aRG7)
9447 # if defined(VGA_x86)
9448 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
9449 *a4 = aRG6; *a5 = aRG7;
9450 # else
9451 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5;
9452 # endif
9455 static void munge_wwllww(UWord* a1, UWord* a2, ULong* a3,
9456 ULong* a4, UWord* a5, UWord* a6,
9457 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4,
9458 UWord aRG5, UWord aRG6, UWord aRG7, UWord aRG8)
9460 # if defined(VGA_x86)
9461 *a1 = aRG1; *a2 = aRG2;
9462 *a3 = LOHI64(aRG3,aRG4); *a4 = LOHI64(aRG5,aRG6);
9463 *a5 = aRG7; *a6 = aRG8;
9464 # else
9465 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5; *a6 = aRG6;
9466 # endif
9469 #if DARWIN_VERS >= DARWIN_10_8
9471 PRE(kernelrpc_mach_vm_allocate_trap)
9473 UWord a1; UWord a2; ULong a3; UWord a4;
9474 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9475 PRINT("kernelrpc_mach_vm_allocate_trap"
9476 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
9477 name_for_port(a1), *(void**)a2, a3, a4);
9478 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
9479 a2, sizeof(void*));
9481 POST(kernelrpc_mach_vm_allocate_trap)
9483 UWord a1; UWord a2; ULong a3; UWord a4;
9484 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9485 PRINT("address:%p size:%#llx", *(void**)a2, a3);
9486 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9487 POST_MEM_WRITE(a2, sizeof(void*));
9489 if (a1 == mach_task_self()) {
9490 # if 1
9491 ML_(sync_mappings)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
9492 # else
9493 /* This is nearly right, but not always -- sometimes the mapping
9494 appears to be r--, for some reason. Hence resync. */
9495 ML_(notify_core_and_tool_of_mmap)(
9496 *(UWord*)a2, a3,
9497 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9498 # endif
9502 PRE(kernelrpc_mach_vm_deallocate_trap)
9504 UWord a1; ULong a2; ULong a3;
9505 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9506 PRINT("kernelrpc_mach_vm_deallocate_trap"
9507 "(target:%#lx, address:%#llx, size:%#llx)", a1, a2, a3);
9509 POST(kernelrpc_mach_vm_deallocate_trap)
9511 UWord a1; ULong a2; ULong a3;
9512 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9513 // kernelrpc_mach_vm_deallocate_trap could be call with
9514 // address ==0 && size == 0,
9515 // we shall not notify any unmap then
9516 if (a3)
9517 ML_(notify_core_and_tool_of_munmap)(a2, a3);
9520 PRE(kernelrpc_mach_vm_protect_trap)
9522 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9523 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9524 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9525 PRINT("kernelrpc_mach_vm_protect_trap"
9526 "(task:%#lx, address:%#llx, size:%#llx,"
9527 " set_maximum:%#lx, new_prot:%#lx)", a1, a2, a3, a4, a5);
9529 POST(kernelrpc_mach_vm_protect_trap)
9531 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9532 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9533 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9534 if (/*a4 set_maximum == 0 && */a1 == mach_task_self()) {
9535 ML_(notify_core_and_tool_of_mprotect)((Addr)a2, (SizeT)a3, (Int)a5);
9536 VG_(di_notify_vm_protect)((Addr)a2, (SizeT)a3, (UInt)a5);
9540 PRE(kernelrpc_mach_port_allocate_trap)
9542 // munge_www -- no need to call helper
9543 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9544 ARG1, ARG2);
9545 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9546 ARG3, sizeof(mach_port_name_t));
9548 POST(kernelrpc_mach_port_allocate_trap)
9550 // munge_www -- no need to call helper
9551 POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
9552 PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
9553 record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
9556 PRE(kernelrpc_mach_port_destroy_trap)
9558 // munge_ww -- no need to call helper
9559 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
9560 record_port_destroy(ARG2);
9563 PRE(kernelrpc_mach_port_deallocate_trap)
9565 // munge_ww -- no need to call helper
9566 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9567 ARG1, ARG2);
9569 POST(kernelrpc_mach_port_deallocate_trap)
9571 // munge_ww -- no need to call helper
9574 PRE(kernelrpc_mach_port_mod_refs_trap)
9576 // munge_wwww -- no need to call helper
9577 PRINT("kernelrpc_mach_port_mod_refs_trap"
9578 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9579 ARG1, ARG2, ARG3, ARG4);
9582 PRE(kernelrpc_mach_port_move_member_trap)
9584 // munge_www -- no need to call helper
9585 PRINT("kernelrpc_mach_port_move_member_trap"
9586 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9587 ARG1, ARG2, ARG3);
9590 PRE(kernelrpc_mach_port_insert_right_trap)
9592 //munge_wwww -- no need to call helper
9593 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9594 "(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9597 PRE(kernelrpc_mach_port_insert_member_trap)
9599 // munge_www -- no need to call helper
9600 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9601 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9604 PRE(kernelrpc_mach_port_extract_member_trap)
9606 // munge_www -- no need to call helper
9607 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9608 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9611 PRE(iopolicysys)
9613 // munge_???
9614 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
9615 /* mem effects unknown */
9617 POST(iopolicysys)
9619 // munge_???
9622 PRE(process_policy)
9624 // munge_???
9625 PRINT("process_policy(FIXME)("
9626 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9627 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9628 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9629 /* mem effects unknown */
9631 POST(process_policy)
9633 // munge_???
9636 PRE(csops_audittoken)
9638 PRINT("csops_audittoken(%ld, %#lx, %#lx, %lu, %#lx)", SARG1, ARG2, ARG3, ARG4, ARG5);
9639 PRE_REG_READ5(int, "csops_audittoken",
9640 vki_pid_t, pid, uint32_t, ops,
9641 void *, useraddr, vki_size_t, usersize, void *, uaudittoken);
9643 if (ARG5 == 0) {
9644 SET_STATUS_Failure( VKI_EINVAL );
9645 return;
9648 PRE_MEM_WRITE( "csops_audittoken(useraddr)", ARG3, ARG4 );
9650 // If the pid is ours, don't mark the program as KILL or HARD
9651 // Maybe we should keep track of this for later calls to STATUS
9652 if (!ARG1 || VG_(getpid)() == ARG1) {
9653 switch (ARG2) {
9654 case VKI_CS_OPS_MARKINVALID:
9655 case VKI_CS_OPS_MARKHARD:
9656 case VKI_CS_OPS_MARKKILL:
9657 SET_STATUS_Success(0);
9662 POST(csops_audittoken)
9664 POST_MEM_WRITE( ARG3, ARG4 );
9667 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9670 /* ---------------------------------------------------------------------
9671 Added for OSX 10.9 (Mavericks)
9672 ------------------------------------------------------------------ */
9674 #if DARWIN_VERS >= DARWIN_10_9
9676 PRE(kernelrpc_mach_vm_map_trap)
9678 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9679 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9680 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9681 PRINT("kernelrpc_mach_vm_map_trap"
9682 "(target:%#lx, address:%p, size:%#llx,"
9683 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9684 a1, *(void**)a2, a3, a4, a5, a6);
9685 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2, sizeof(void*));
9687 POST(kernelrpc_mach_vm_map_trap)
9689 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9690 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9691 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9692 PRINT("-> address:%p", *(void**)a2);
9693 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9694 POST_MEM_WRITE(a2, sizeof(void*));
9696 ML_(notify_core_and_tool_of_mmap)(
9697 *(mach_vm_address_t*)a2, a3,
9698 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9699 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9702 PRE(kernelrpc_mach_port_construct_trap)
9704 UWord a1; UWord a2; ULong a3; UWord a4;
9705 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9706 PRINT("kernelrpc_mach_port_construct_trap"
9707 "(target: %s, options: %#lx, content: %llx, name: %p)",
9708 name_for_port(a1), a2, a3, *(mach_port_name_t**)a4);
9709 PRE_MEM_WRITE("kernelrpc_mach_port_construct_trap(name)", a4,
9710 sizeof(mach_port_name_t*));
9712 POST(kernelrpc_mach_port_construct_trap)
9714 UWord a1; UWord a2; ULong a3; UWord a4;
9715 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9716 PRINT("-> name:%p", *(mach_port_name_t**)a4);
9717 if (ML_(safe_to_deref)((mach_port_name_t*)a4, sizeof(mach_port_name_t*))) {
9718 POST_MEM_WRITE(a4, sizeof(mach_port_name_t*));
9722 PRE(kernelrpc_mach_port_destruct_trap)
9724 UWord a1; UWord a2; UWord a3; ULong a4;
9725 munge_wwwl(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9726 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9727 "(%lx,%lx,%lx,%llx)", a1, a2, a3, a4);
9730 PRE(kernelrpc_mach_port_guard_trap)
9732 UWord a1; UWord a2; ULong a3; UWord a4;
9733 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9734 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9735 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9738 PRE(kernelrpc_mach_port_unguard_trap)
9740 // munge_wwl
9741 UWord a1; UWord a2; ULong a3;
9742 munge_wwl(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4);
9743 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9744 "(%lx,%lx,%llx)", a1, a2, a3);
9747 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9750 /* ---------------------------------------------------------------------
9751 Added for OSX 10.10 (Yosemite)
9752 ------------------------------------------------------------------ */
9754 #if DARWIN_VERS >= DARWIN_10_10
9756 PRE(necp_match_policy)
9758 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9759 // struct necp_aggregate_result *returned_result)
9760 PRINT("necp_match_policy(FIXME)(%lx,%lu, %lx)", ARG1, ARG2, ARG3);
9761 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
9762 size_t, parameters_size, struct necp_aggregate_result*,
9763 returned_result);
9764 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
9766 POST(necp_match_policy)
9768 POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
9771 PRE(sysctlbyname)
9773 UWord name = ARG1;
9774 UWord namelen = ARG2;
9775 UWord oldp = ARG3;
9776 UWord oldlenp = ARG4;
9777 UWord newp = ARG5;
9778 UWord newlen = ARG6; // FIXME: or newlenp ??
9780 PRINT( "sysctlbyname ( %#lx,%lu, %#lx,%#lx, %#lx,%lu )",
9781 name, namelen, oldp, oldlenp, newp, newlen );
9783 PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
9784 void*, oldp, vki_size_t *, oldlenp,
9785 void*, newp, vki_size_t *, newlenp); // <---<<
9787 // reads name[0..namelen-1]
9788 PRE_MEM_READ("sysctlbyname(name)", name, namelen);
9790 if (VG_(clo_trace_syscalls)) {
9791 UInt i;
9792 const HChar* t_name = (const HChar*)name;
9793 VG_(printf)(" name: ");
9794 for (i = 0; i < namelen; i++) {
9795 VG_(printf)("%c", t_name[i]);
9797 VG_(printf)(" ");
9800 Bool is_kern_dot_userstack
9801 = False;
9803 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
9804 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
9806 POST(sysctlbyname)
9808 UWord oldp = ARG3;
9809 UWord oldlenp = ARG4;
9811 if (SUCCESS || ERR == VKI_ENOMEM) {
9812 // sysctl can write truncated data and return VKI_ENOMEM
9813 if (oldlenp) {
9814 POST_MEM_WRITE(oldlenp, sizeof(size_t));
9816 if (oldp && oldlenp) {
9817 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
9822 PRE(getattrlistbulk)
9824 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9825 // void *attributeBuffer, size_t bufferSize,
9826 // uint64_t options);
9827 // Presumably the last arg is value-pair in the 32 bit case.
9828 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9829 SARG1, ARG2, ARG3, ARG4, ARG5);
9830 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
9831 void*, attributeBuffer, size_t, bufferSize,
9832 uint32_t, options_lo32);
9833 PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
9834 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
9836 POST(getattrlistbulk)
9838 // FIXME: this isn't right. It seems as if what is returned is a
9839 // set of variable-length records -- see complication in
9840 // POST(getattrlist). For now, just paint the entire result buffer
9841 // as defined. Sigh.
9842 vg_assert(SUCCESS);
9843 if (ARG3 && /* "at least one output element was written" */RES > 0)
9844 POST_MEM_WRITE(ARG3, ARG4);
9847 PRE(faccessat)
9849 uint32_t fd = ARG1;
9850 PRINT("faccessat(fd:%d, path:%#lx(%s), amode:%#lx, flag:%#lx)",
9851 fd, ARG2, ARG2 ? (HChar*)ARG2 : "null", ARG3, ARG4);
9852 PRE_REG_READ4(int, "faccessat",
9853 int, fd, user_addr_t, path, int, amode, int, flag);
9855 if (fd != VKI_AT_FDCWD && !ML_(fd_allowed)(fd, "faccessat", tid, False)) {
9856 SET_STATUS_Failure( VKI_EBADF );
9858 PRE_MEM_RASCIIZ( "faccessat(path)", ARG2 );
9861 PRE(fstatat64)
9863 uint32_t fd = ARG1;
9864 PRINT("fstatat64(fd:%d, path:%#lx(%s), ub:%#lx, flag:%#lx)",
9865 fd, ARG2, ARG2 ? (HChar*)ARG2 : "null", ARG3, ARG4);
9866 PRE_REG_READ4(int, "fstatat64",
9867 int, fd, user_addr_t, path, user_addr_t, ub, int, flag);
9869 if (fd != VKI_AT_FDCWD && !ML_(fd_allowed)(fd, "fstatat64", tid, False)) {
9870 SET_STATUS_Failure( VKI_EBADF );
9872 PRE_MEM_RASCIIZ( "fstatat64(path)", ARG2 );
9873 PRE_MEM_WRITE( "fstatat64(ub)", ARG3, sizeof(struct vki_stat64) );
9875 POST(fstatat64)
9877 POST_MEM_WRITE( ARG3, sizeof(struct vki_stat64) );
9880 PRE(readlinkat)
9882 Word saved = SYSNO;
9884 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %ld )",
9885 SARG1, ARG2, (HChar*)ARG2, ARG3, SARG4);
9886 PRE_REG_READ4(long, "readlinkat",
9887 int, dfd, const char *, path, char *, buf, int, bufsiz);
9888 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
9889 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
9892 * Refer to coregrind/m_syswrap/syswrap-linux.c
9895 /* Normal case */
9896 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
9899 if (SUCCESS && RES > 0)
9900 POST_MEM_WRITE( ARG3, RES );
9903 PRE(bsdthread_ctl)
9905 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9906 // user_addr_t arg2, user_addr_t arg3)
9907 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9908 PRE_REG_READ4(int, "bsdthreadctl",
9909 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
9912 // syscalls.master says
9913 // int csrctl(uint32_t op, user_addr_t useraddr, user_addr_t usersize) NO_SYSCALL_STUB;
9914 // but https://github.com/search?q=repo%3Aapple-open-source%2Fmacos%20__csrctl&type=code says
9915 // int __csrctl(csr_op_t op, void *buffer, size_t size);
9916 PRE(csrctl)
9918 switch (ARG1) {
9919 case VKI_CSR_CHECK:
9920 PRINT("csrctl(op:CSR_CHECK, useraddr:%#lx, usersize:%#lx)", ARG2, ARG3);
9921 PRE_REG_READ3(int, "csrctl",
9922 uint32_t, op, void*, useraddr, size_t, usersize);
9923 PRE_MEM_READ( "csrctl(useraddr)", ARG2, ARG3 );
9924 break;
9926 case VKI_CSR_GET_ACTIVE_CONFIG:
9927 PRINT("csrctl(op:CSR_GET_ACTIVE_CONFIG, useraddr:%#lx, usersize:%#lx)", ARG2, ARG3);
9928 PRE_REG_READ3(int, "csrctl",
9929 uint32_t, op, void*, useraddr, size_t, usersize);
9930 PRE_MEM_WRITE( "csrctl(useraddr)", ARG2, ARG3 );
9931 break;
9933 default:
9934 PRINT("csrctl(op:%ld [??], useraddr:%#lx, usersize:%#lx)", ARG1, ARG2, ARG3);
9935 log_decaying("UNKNOWN csrctl %ld!", ARG1);
9936 break;
9939 POST(csrctl)
9941 vg_assert(SUCCESS);
9942 switch (ARG1) {
9943 case VKI_CSR_GET_ACTIVE_CONFIG:
9944 POST_MEM_WRITE( ARG2, ARG3 );
9945 break;
9947 default:
9948 break;
9952 PRE(guarded_open_dprotected_np)
9954 PRINT("guarded_open_dprotected_np("
9955 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9956 "dpclass:%#lx, dpflags: %#lx) FIXME",
9957 ARG1, (HChar*)ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
9960 PRE(guarded_write_np)
9962 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9963 ARG1, ARG2, ARG3, (ULong)ARG4);
9966 PRE(guarded_pwrite_np)
9968 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9969 ARG1, ARG2, ARG3, (ULong)ARG4, (Long)ARG5);
9972 PRE(guarded_writev_np)
9974 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9975 ARG1, ARG2, ARG3, (ULong)ARG4);
9978 PRE(openat)
9980 if (ARG3 & VKI_O_CREAT) {
9981 // 4-arg version
9982 PRINT("sys_openat ( %ld, %#" FMT_REGWORD "x(%s), %ld, %ld )",
9983 SARG1, ARG2, (HChar*)(Addr)ARG2, SARG3, SARG4);
9984 PRE_REG_READ4(long, "openat",
9985 int, dfd, const char *, filename, int, flags, int, mode);
9986 } else {
9987 // 3-arg version
9988 PRINT("sys_openat ( %ld, %#" FMT_REGWORD "x(%s), %ld )",
9989 SARG1, ARG2, (HChar*)(Addr)ARG2, SARG3);
9990 PRE_REG_READ3(long, "openat",
9991 int, dfd, const char *, filename, int, flags);
9993 PRE_MEM_RASCIIZ( "openat(filename)", ARG2 );
9995 /* For absolute filenames, dfd is ignored. If dfd is AT_FDCWD,
9996 filename is relative to cwd. When comparing dfd against AT_FDCWD,
9997 be sure only to compare the bottom 32 bits. */
9998 if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
9999 && *(Char *)(Addr)ARG2 != '/'
10000 && ((Int)ARG1) != ((Int)VKI_AT_FDCWD)
10001 && !ML_(fd_allowed)(ARG1, "openat", tid, False))
10002 SET_STATUS_Failure( VKI_EBADF );
10004 /* Otherwise handle normally */
10005 *flags |= SfMayBlock;
10008 POST(openat)
10010 vg_assert(SUCCESS);
10011 if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
10012 VG_(close)(RES);
10013 SET_STATUS_Failure( VKI_EMFILE );
10014 } else {
10015 if (VG_(clo_track_fds))
10016 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)(Addr)ARG2);
10020 #endif /* DARWIN_VERS >= DARWIN_10_10 */
10023 /* ---------------------------------------------------------------------
10024 Added for OSX 10.11 (El Capitan)
10025 ------------------------------------------------------------------ */
10027 #if DARWIN_VERS >= DARWIN_10_11
10029 PRE(kevent_qos)
10031 PRINT("kevent_qos( %ld, %#lx, %ld, %#lx, %ld, %#lx, %ld, %ld )",
10032 SARG1, ARG2, SARG3, ARG4, SARG5, ARG6, SARG7, ARG8);
10033 PRE_REG_READ8(int,"kevent_qos",
10034 int,kq,
10035 const struct vki_kevent_qos_s *,changelist,
10036 int,nchanges,
10037 struct vki_kevent_qos_s *,eventlist,
10038 int,nevents,
10039 void*,data_out,
10040 size_t*,data_available,
10041 unsigned int,flags);
10043 if (ARG3) PRE_MEM_READ ("kevent_qos(changelist)",
10044 ARG2, ARG3 * sizeof(struct vki_kevent_qos_s));
10045 if (ARG5) PRE_MEM_WRITE("kevent_qos(eventlist)",
10046 ARG4, ARG5 * sizeof(struct vki_kevent_qos_s));
10047 if (ARG7) PRE_MEM_WRITE("kevent_qos(data_out)",
10048 ARG6, ARG7 * sizeof(void*));
10050 *flags |= SfMayBlock;
10053 POST(kevent_qos)
10055 PRINT("kevent_qos ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent_qos_s));
10056 if (RES > 0) {
10057 ML_(sync_mappings)("after", "kevent_qos", 0);
10058 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent_qos_s));
10063 PRE(pselect)
10065 *flags |= SfMayBlock;
10066 PRINT("pselect ( %ld, %#lx, %#lx, %#lx, %#lx, %#lx )", SARG1, ARG2, ARG3,
10067 ARG4, ARG5, ARG6);
10068 PRE_REG_READ5(long, "pselect",
10069 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
10070 vki_fd_set *, exceptfds, struct vki_timeval *, timeout);
10071 // XXX: this possibly understates how much memory is read.
10072 if (ARG2 != 0)
10073 PRE_MEM_READ( "pselect(readfds)",
10074 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
10075 if (ARG3 != 0)
10076 PRE_MEM_READ( "pselect(writefds)",
10077 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
10078 if (ARG4 != 0)
10079 PRE_MEM_READ( "pselect(exceptfds)",
10080 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
10081 if (ARG5 != 0)
10082 PRE_timeval_READ( "pselect(timeout)", ARG5 );
10083 if (ARG6 != 0)
10084 PRE_MEM_READ( "pselect(sigmask)", ARG6, sizeof(vki_sigset_t) );
10087 #endif /* DARWIN_VERS >= DARWIN_10_11 */
10090 /* ---------------------------------------------------------------------
10091 Added for macOS 10.12 (Sierra)
10092 ------------------------------------------------------------------ */
10094 #if DARWIN_VERS >= DARWIN_10_12
10096 PRE(getentropy)
10098 PRINT("getentropy(buffer:%#lx, size:%ld)", ARG1, ARG2);
10099 PRE_REG_READ2(int, "getentropy",
10100 void*, buffer, size_t, size);
10101 PRE_MEM_WRITE( "getentropy(buffer)", ARG1, ARG2 );
10104 POST(getentropy)
10106 vg_assert(SUCCESS);
10107 POST_MEM_WRITE( ARG1, ARG2 );
10110 PRE(necp_open)
10112 PRINT("necp_open(%#lx)", ARG1);
10113 PRE_REG_READ1(int, "necp_open", int, flags);
10116 PRE(necp_client_action)
10118 PRINT("necp_client_action(%lu, %#lx, %#lx, %lu, %#lx, %lu)",
10119 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
10120 PRE_REG_READ6(int, "necp_client_action",
10121 int, necp_fd, uint32_t, action,
10122 unsigned char*, client_id, size_t, client_id_len,
10123 uint8_t*, buffer, size_t, buffer_size);
10125 switch (ARG2 /* request */) {
10126 case VKI_NECP_CLIENT_ACTION_ADD:
10127 if (ARG4 != sizeof(uuid_t) || ARG6 == 0 || ARG6 > VKI_NECP_MAX_CLIENT_PARAMETERS_SIZE) {
10128 SET_STATUS_Failure( VKI_EINVAL );
10130 PRE_MEM_WRITE( "necp_client_action(ADD, client_id)", ARG3, ARG4);
10131 PRE_MEM_READ( "necp_client_action(ADD, buffer)", ARG5, ARG6);
10132 break;
10133 case VKI_NECP_CLIENT_ACTION_CLAIM:
10134 if (ARG4 != sizeof(uuid_t)) {
10135 SET_STATUS_Failure( VKI_EINVAL );
10137 PRE_MEM_READ( "necp_client_action(CLAIM, client_id)", ARG3, ARG4);
10138 break;
10139 case VKI_NECP_CLIENT_ACTION_REMOVE:
10140 if (ARG4 != sizeof(uuid_t) || (ARG5 != 0 && ARG6 != VKI_IFNET_STATS_PER_FLOW_SIZE)) {
10141 SET_STATUS_Failure( VKI_EINVAL );
10143 PRE_MEM_READ( "necp_client_action(REMOVE, client_id)", ARG3, ARG4);
10144 PRE_MEM_READ( "necp_client_action(REMOVE, buffer)", ARG5, ARG6);
10145 break;
10146 case VKI_NECP_CLIENT_ACTION_COPY_PARAMETERS:
10147 if ((ARG3 != 0 && ARG4 != sizeof(uuid_t)) || ARG6 == 0) {
10148 SET_STATUS_Failure( VKI_EINVAL );
10150 if (ARG3 != 0) {
10151 PRE_MEM_READ( "necp_client_action(COPY_PARAMETERS, client_id)", ARG3, ARG4);
10153 PRE_MEM_READ( "necp_client_action(COPY_PARAMETERS, buffer)", ARG5, ARG6);
10154 break;
10155 case VKI_NECP_CLIENT_ACTION_COPY_RESULT:
10156 if ((ARG3 != 0 && ARG4 != sizeof(uuid_t)) || ARG6 == 0) {
10157 SET_STATUS_Failure( VKI_EINVAL );
10159 if (ARG3 != 0) {
10160 PRE_MEM_READ( "necp_client_action(COPY_RESULT, client_id)", ARG3, ARG4);
10162 PRE_MEM_READ( "necp_client_action(COPY_RESULT, buffer)", ARG5, ARG6);
10163 break;
10164 case VKI_NECP_CLIENT_ACTION_COPY_UPDATED_RESULT:
10165 if ((ARG3 != 0 && ARG4 != sizeof(uuid_t)) || ARG6 == 0) {
10166 SET_STATUS_Failure( VKI_EINVAL );
10168 if (ARG3 != 0) {
10169 PRE_MEM_READ( "necp_client_action(COPY_UPDATED_RESULT, client_id)", ARG3, ARG4);
10171 PRE_MEM_READ( "necp_client_action(COPY_UPDATED_RESULT, buffer)", ARG5, ARG6);
10172 break;
10173 case VKI_NECP_CLIENT_ACTION_COPY_LIST:
10174 if (ARG6 < sizeof(u_int32_t)) {
10175 SET_STATUS_Failure( VKI_EINVAL );
10177 PRE_MEM_READ( "necp_client_action(COPY_LIST, buffer)", ARG5, ARG6);
10178 break;
10179 case VKI_NECP_CLIENT_ACTION_AGENT:
10180 if (ARG4 != sizeof(uuid_t) || ARG6 == 0) {
10181 SET_STATUS_Failure( VKI_EINVAL );
10183 PRE_MEM_READ( "necp_client_action(AGENT, client_id)", ARG3, ARG4);
10184 PRE_MEM_READ( "necp_client_action(AGENT, buffer)", ARG5, ARG6);
10185 break;
10186 case VKI_NECP_CLIENT_ACTION_COPY_AGENT:
10187 if (ARG4 != sizeof(uuid_t) || ARG6 == 0) {
10188 SET_STATUS_Failure( VKI_EINVAL );
10190 PRE_MEM_READ( "necp_client_action(COPY_AGENT, client_id)", ARG3, ARG4);
10191 PRE_MEM_READ( "necp_client_action(COPY_AGENT, buffer)", ARG5, ARG6);
10192 PRE_MEM_WRITE( "necp_client_action(COPY_AGENT, buffer)", ARG5, ARG6);
10193 break;
10194 case VKI_NECP_CLIENT_ACTION_AGENT_USE:
10195 if (ARG4 != sizeof(uuid_t) || ARG6 != sizeof(struct vki_necp_agent_use_parameters)) {
10196 SET_STATUS_Failure( VKI_EINVAL );
10198 PRE_MEM_READ( "necp_client_action(AGENT_USE, client_id)", ARG3, ARG4);
10199 PRE_MEM_READ( "necp_client_action(AGENT_USE, buffer)", ARG5, ARG6);
10200 PRE_MEM_WRITE( "necp_client_action(AGENT_USE, buffer)", ARG5, ARG6);
10201 break;
10202 case VKI_NECP_CLIENT_ACTION_COPY_INTERFACE:
10203 if (ARG4 != sizeof(u_int32_t) || ARG6 < sizeof(struct vki_necp_interface_details_legacy)) {
10204 SET_STATUS_Failure( VKI_EINVAL );
10206 PRE_MEM_READ( "necp_client_action(COPY_INTERFACE, client_id)", ARG3, ARG4);
10207 PRE_MEM_WRITE( "necp_client_action(COPY_INTERFACE, buffer)", ARG5, ARG6);
10208 break;
10209 case VKI_NECP_CLIENT_ACTION_COPY_ROUTE_STATISTICS:
10210 if (ARG4 != sizeof(uuid_t) || ARG6 < VKI_NECP_STAT_COUNTS_SIZE) {
10211 SET_STATUS_Failure( VKI_EINVAL );
10213 PRE_MEM_READ( "necp_client_action(COPY_ROUTE_STATISTICS, client_id)", ARG3, ARG4);
10214 PRE_MEM_WRITE( "necp_client_action(COPY_ROUTE_STATISTICS, buffer)", ARG5, ARG6);
10215 break;
10216 case VKI_NECP_CLIENT_ACTION_UPDATE_CACHE:
10217 if (ARG4 != sizeof(uuid_t) || ARG6 != sizeof(struct vki_necp_cache_buffer)) {
10218 SET_STATUS_Failure( VKI_EINVAL );
10220 PRE_MEM_READ( "necp_client_action(UPDATE_CACHE, client_id)", ARG3, ARG4);
10221 PRE_MEM_READ( "necp_client_action(UPDATE_CACHE, buffer)", ARG5, ARG6);
10222 break;
10223 case VKI_NECP_CLIENT_ACTION_COPY_CLIENT_UPDATE:
10224 if (ARG4 != sizeof(uuid_t) || ARG6 == 0) {
10225 SET_STATUS_Failure( VKI_EINVAL );
10227 PRE_MEM_WRITE( "necp_client_action(COPY_CLIENT_UPDATE, client_id)", ARG3, ARG4);
10228 PRE_MEM_WRITE( "necp_client_action(COPY_CLIENT_UPDATE, buffer)", ARG5, ARG6);
10229 break;
10230 case VKI_NECP_CLIENT_ACTION_SIGN:
10231 if (ARG4 < sizeof(struct vki_necp_client_signable) || ARG6 != VKI_NECP_CLIENT_ACTION_SIGN_TAG_LENGTH) {
10232 SET_STATUS_Failure( VKI_EINVAL );
10234 PRE_MEM_READ( "necp_client_action(SIGN, client_id)", ARG3, ARG4);
10235 PRE_MEM_WRITE( "necp_client_action(SIGN, buffer)", ARG5, ARG6);
10236 break;
10237 default:
10238 VG_(printf)("UNKNOWN necp_client_action action %#lx\n", ARG2);
10239 break;
10243 static const HChar *ulop_name(int op)
10245 switch (op) {
10246 case VKI_UL_UNFAIR_LOCK: return "UL_UNFAIR_LOCK";
10247 case VKI_UL_COMPARE_AND_WAIT: return "UL_COMPARE_AND_WAIT";
10248 default: return "??";
10252 PRE(ulock_wake)
10254 uint ul_opcode = ARG1 & VKI_UL_OPCODE_MASK;
10255 uint ul_flags = ARG1 & VKI_UL_FLAGS_MASK;
10256 switch (ul_opcode) {
10257 case VKI_UL_UNFAIR_LOCK:
10258 case VKI_UL_COMPARE_AND_WAIT: {
10259 const char* name = ulop_name(ul_opcode);
10260 if (ul_flags & VKI_ULF_WAKE_THREAD) {
10261 PRINT("ulock_wake(operation:%s (flags: %#x), addr:%#lx, wake_value:%s)",
10262 name, ul_flags, ARG2, name_for_port(ARG3));
10263 } else {
10264 PRINT("ulock_wake(operation:%s (flags: %#x), addr:%#lx, wake_value:%ld /*unused*/)",
10265 name, ul_flags, ARG2, ARG3);
10267 PRE_REG_READ3(int, "ulock_wake",
10268 uint32_t, operation, void*, addr, uint64_t, wake_value);
10269 break;
10272 default:
10273 PRINT("ulock_wake(operation:%ld (opcode: %u [??], flags: %#x), addr:%#lx, wake_value:%ld)", ARG1, ul_opcode, ul_flags, ARG2, ARG3);
10274 log_decaying("UNKNOWN ulock_wake %ld (opcode: %u [??], flags: %#x)!", ARG1, ul_opcode, ul_flags);
10275 break;
10279 PRE(ulock_wait)
10281 uint ul_opcode = ARG1 & VKI_UL_OPCODE_MASK;
10282 uint ul_flags = ARG1 & VKI_UL_FLAGS_MASK;
10284 switch (ul_opcode) {
10285 case VKI_UL_UNFAIR_LOCK:
10286 case VKI_UL_COMPARE_AND_WAIT: {
10287 const char* name = ulop_name(ul_opcode);
10288 PRINT("ulock_wait(operation:%s (flags: %#x), addr:%#lx, value:%ld, timeout:%ld)",
10289 name, ul_flags, ARG2, ARG3, ARG4);
10290 PRE_REG_READ4(int, "ulock_wait",
10291 uint32_t, operation, void*, addr, uint64_t, value, uint32_t, timeout);
10292 PRE_MEM_READ("ulock_wait(addr)", ARG2, 4 );
10293 break;
10296 default:
10297 PRINT("ulock_wait(operation:%ld (opcode: %u [??], flags: %#x), addr:%#lx, value:%ld, timeout:%ld)", ARG1, ul_opcode, ul_flags, ARG2, ARG3, ARG4);
10298 log_decaying("UNKNOWN ulock_wait %ld (opcode: %u [??], flags: %#x)!", ARG1, ul_opcode, ul_flags);
10299 break;
10302 *flags |= SfMayBlock;
10305 PRE(terminate_with_payload)
10307 PRINT("terminate_with_payload"
10308 "(pid: %ld, reason_namespace:%ld, reason_code:%ld, payload:%#lx, payload_size:%ld, reason_string:%s, reason_flags:%#x)",
10309 ARG1, ARG2, ARG3, ARG4, ARG5, (char*)ARG6, (uint)ARG7);
10310 PRE_REG_READ7(int, "terminate_with_payload", int, pid,
10311 uint32_t, reason_namespace, uint64_t, reason_code, void*, payload,
10312 uint32_t, payload_size, const char*, reason_string, uint64_t, reason_flags);
10313 PRE_MEM_READ("abort_with_payload(payload)", ARG4, ARG5);
10314 PRE_MEM_RASCIIZ("abort_with_payload(reason_string)", ARG6);
10317 PRE(abort_with_payload)
10319 PRINT("abort_with_payload"
10320 "(reason_namespace:%ld, reason_code:%ld, payload:%#lx, payload_size:%ld, reason_string:%s, reason_flags:%#x)",
10321 ARG1, ARG2, ARG3, ARG4, (char*)ARG5, (uint)ARG6);
10322 PRE_REG_READ6(uint32_t, "abort_with_payload",
10323 uint32_t, reason_namespace, uint64_t, reason_code, void*, payload,
10324 uint32_t, payload_size, const char*, reason_string, uint64_t, reason_flags);
10325 PRE_MEM_READ("abort_with_payload(payload)", ARG3, ARG4);
10326 PRE_MEM_RASCIIZ("abort_with_payload(reason_string)", ARG5);
10329 PRE(host_create_mach_voucher_trap)
10331 // munge_wwww -- no need to call helper
10332 PRINT("host_create_mach_voucher_trap"
10333 "(host:%s, recipes:%#lx, recipes_size:%ld, voucher:%#lx)",
10334 name_for_port(ARG1), ARG2, ARG3, ARG4);
10335 PRE_MEM_READ( "host_create_mach_voucher_trap(recipes)", ARG2, ARG3 );
10336 PRE_MEM_WRITE( "host_create_mach_voucher_trap(voucher)", ARG4, sizeof(mach_port_name_t) );
10338 POST(host_create_mach_voucher_trap)
10340 vg_assert(SUCCESS);
10341 POST_MEM_WRITE( ARG4, sizeof(mach_port_name_t) );
10344 PRE(task_register_dyld_image_infos)
10346 //#pragma pack(4)
10347 // typedef struct {
10348 // mach_msg_header_t Head;
10349 // /* start of the kernel processed data */
10350 // mach_msg_body_t msgh_body;
10351 // mach_msg_ool_descriptor_t dyld_images;
10352 // /* end of the kernel processed data */
10353 // NDR_record_t NDR;
10354 // mach_msg_type_number_t dyld_imagesCnt;
10355 // } Request;
10356 //#pragma pack()
10358 // Request *req = (Request *)ARG1;
10360 PRINT("task_register_dyld_image_infos(%s)", name_for_port(MACH_REMOTE));
10362 AFTER = POST_FN(task_register_dyld_image_infos);
10365 POST(task_register_dyld_image_infos)
10367 #pragma pack(4)
10368 typedef struct {
10369 mach_msg_header_t Head;
10370 NDR_record_t NDR;
10371 kern_return_t RetCode;
10372 } Reply;
10373 #pragma pack()
10375 Reply *reply = (Reply *)ARG1;
10376 if (!reply->RetCode) {
10377 } else {
10378 PRINT("mig return %d", reply->RetCode);
10382 PRE(task_register_dyld_shared_cache_image_info)
10384 //#pragma pack(4)
10385 // typedef struct {
10386 // mach_msg_header_t Head;
10387 // NDR_record_t NDR;
10388 // dyld_kernel_image_info_t dyld_cache_image;
10389 // boolean_t no_cache;
10390 // boolean_t private_cache;
10391 // } Request;
10392 //#pragma pack()
10394 // Request *req = (Request *)ARG1;
10396 PRINT("task_register_dyld_shared_cache_image_info(%s)",
10397 name_for_port(MACH_REMOTE));
10399 AFTER = POST_FN(task_register_dyld_shared_cache_image_info);
10402 POST(task_register_dyld_shared_cache_image_info)
10404 #pragma pack(4)
10405 typedef struct {
10406 mach_msg_header_t Head;
10407 NDR_record_t NDR;
10408 kern_return_t RetCode;
10409 } Reply;
10410 #pragma pack()
10412 Reply *reply = (Reply *)ARG1;
10413 if (!reply->RetCode) {
10414 } else {
10415 PRINT("mig return %d", reply->RetCode);
10419 PRE(mach_generate_activity_id)
10421 // munge_www -- no need to call helper
10422 PRINT("mach_generate_activity_id"
10423 "(target:%s, count:%ld)",
10424 name_for_port(ARG1), ARG2);
10425 PRE_REG_READ3(long, "mach_generate_activity_id",
10426 mach_port_name_t, target, int, count, uint64_t *, activity_id);
10427 if (ARG2 <= 0 || ARG2 > MACH_ACTIVITY_ID_COUNT_MAX) {
10428 SET_STATUS_Failure( VKI_EINVAL );
10430 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10431 PRE_MEM_WRITE( "mach_generate_activity_id(activity_id)", ARG3, sizeof(vki_uint64_t) );
10432 } else {
10433 SET_STATUS_Failure( VKI_EFAULT );
10437 POST(mach_generate_activity_id)
10439 if (ML_(safe_to_deref)( (void*)ARG3, sizeof(vki_uint64_t*) )) {
10440 POST_MEM_WRITE( ARG3, sizeof(vki_uint64_t) );
10441 PRINT("-> activity_id:%#llx", *(uint64_t*)ARG3);
10445 #endif /* DARWIN_VERS >= DARWIN_10_12 */
10447 /* ---------------------------------------------------------------------
10448 Added for macOS 10.13 (High Sierra)
10449 ------------------------------------------------------------------ */
10451 #if DARWIN_VERS >= DARWIN_10_13
10453 PRE(openat_nocancel)
10455 if (ARG3 & VKI_O_CREAT) {
10456 // 4-arg version
10457 PRINT("openat_nocancel ( %ld, %#" FMT_REGWORD "x(%s), %ld, %ld )",
10458 SARG1, ARG2, (HChar*)(Addr)ARG2, SARG3, SARG4);
10459 PRE_REG_READ4(long, "openat_nocancel",
10460 int, dfd, const char *, filename, int, flags, int, mode);
10461 } else {
10462 // 3-arg version
10463 PRINT("openat_nocancel ( %ld, %#" FMT_REGWORD "x(%s), %ld )",
10464 SARG1, ARG2, (HChar*)(Addr)ARG2, SARG3);
10465 PRE_REG_READ3(long, "openat_nocancel",
10466 int, dfd, const char *, filename, int, flags);
10468 PRE_MEM_RASCIIZ( "openat_nocancel(filename)", ARG2 );
10470 /* For absolute filenames, dfd is ignored. If dfd is AT_FDCWD,
10471 filename is relative to cwd. When comparing dfd against AT_FDCWD,
10472 be sure only to compare the bottom 32 bits. */
10473 if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
10474 && *(Char *)(Addr)ARG2 != '/'
10475 && ((Int)ARG1) != ((Int)VKI_AT_FDCWD)
10476 && !ML_(fd_allowed)(ARG1, "openat_nocancel", tid, False))
10477 SET_STATUS_Failure( VKI_EBADF );
10479 /* Otherwise handle normally */
10480 *flags |= SfMayBlock;
10482 POST(openat_nocancel)
10484 vg_assert(SUCCESS);
10485 if (!ML_(fd_allowed)(RES, "openat_nocancel", tid, True)) {
10486 VG_(close)(RES);
10487 SET_STATUS_Failure( VKI_EMFILE );
10488 } else {
10489 if (VG_(clo_track_fds))
10490 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)(Addr)ARG2);
10494 PRE(kevent_id)
10496 PRINT("kevent_id(id:%ld, changelist:%#lx, nchanges:%ld, eventlist:%#lx, nevents:%ld, data_out:%#lx, data_available:%ld, flags:%lx)",
10497 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
10498 PRE_REG_READ8(int,"kevent_id",
10499 uint64_t,id,
10500 const struct vki_kevent_qos_s *,changelist,
10501 int,nchanges,
10502 struct vki_kevent_qos_s *,eventlist,
10503 int,nevents,
10504 void*,data_out,
10505 size_t*,data_available,
10506 unsigned int,flags);
10508 if (ARG3) PRE_MEM_READ ("kevent_id(changelist)",
10509 ARG2, ARG3 * sizeof(struct vki_kevent_qos_s));
10510 if (ARG5) PRE_MEM_WRITE("kevent_id(eventlist)",
10511 ARG4, ARG5 * sizeof(struct vki_kevent_qos_s));
10512 if (ARG7) PRE_MEM_WRITE ("kevent_id(data_out)",
10513 ARG6, ARG7 * sizeof(void*));
10515 *flags |= SfMayBlock;
10518 POST(kevent_id)
10520 PRINT("kevent_id ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent_qos_s));
10521 if (RES > 0) {
10522 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent_qos_s));
10526 PRE(thread_get_special_reply_port)
10528 PRINT("thread_get_special_reply_port()");
10531 POST(thread_get_special_reply_port)
10533 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "special-reply-%p");
10534 PRINT("special reply port %s", name_for_port(RES));
10537 #endif /* DARWIN_VERS >= DARWIN_10_13 */
10539 /* ---------------------------------------------------------------------
10540 syscall tables
10541 ------------------------------------------------------------------ */
10543 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
10545 #define MACX_(sysno, name) \
10546 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10548 #define MACXY(sysno, name) \
10549 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10551 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
10554 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
10555 unfortunately misused for Mach too, causing assertion failures
10556 // _____ : unimplemented in valgrind
10557 GEN : handlers are in syswrap-generic.c
10558 MAC : handlers are in this file
10559 X_ : PRE handler only
10560 XY : PRE and POST handlers
10562 const SyscallTableEntry ML_(syscall_table)[] = {
10563 // _____(__NR_syscall), // 0
10564 MACX_(__NR_exit, exit),
10565 GENX_(__NR_fork, sys_fork),
10566 GENXY(__NR_read, sys_read),
10567 GENX_(__NR_write, sys_write),
10568 GENXY(__NR_open, sys_open),
10569 GENX_(__NR_close, sys_close),
10570 GENXY(__NR_wait4, sys_wait4),
10571 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
10572 GENX_(__NR_link, sys_link),
10573 GENX_(__NR_unlink, sys_unlink),
10574 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
10575 GENX_(__NR_chdir, sys_chdir),
10576 GENX_(__NR_fchdir, sys_fchdir),
10577 GENX_(__NR_mknod, sys_mknod),
10578 GENX_(__NR_chmod, sys_chmod),
10579 GENX_(__NR_chown, sys_chown),
10580 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
10581 MACXY(__NR_getfsstat, getfsstat),
10582 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
10583 GENX_(__NR_getpid, sys_getpid), // 20
10584 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
10585 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
10586 GENX_(__NR_setuid, sys_setuid),
10587 GENX_(__NR_getuid, sys_getuid),
10588 GENX_(__NR_geteuid, sys_geteuid),
10589 MACX_(__NR_ptrace, ptrace),
10590 MACXY(__NR_recvmsg, recvmsg),
10591 MACX_(__NR_sendmsg, sendmsg),
10592 MACXY(__NR_recvfrom, recvfrom),
10593 MACXY(__NR_accept, accept),
10594 MACXY(__NR_getpeername, getpeername),
10595 MACXY(__NR_getsockname, getsockname),
10596 GENX_(__NR_access, sys_access),
10597 MACX_(__NR_chflags, chflags),
10598 MACX_(__NR_fchflags, fchflags),
10599 GENX_(__NR_sync, sys_sync),
10600 GENX_(__NR_kill, sys_kill),
10601 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
10602 GENX_(__NR_getppid, sys_getppid),
10603 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
10604 GENXY(__NR_dup, sys_dup),
10605 MACXY(__NR_pipe, pipe),
10606 GENX_(__NR_getegid, sys_getegid),
10607 #if DARWIN_VERS >= DARWIN_10_7
10608 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
10609 #else
10610 // _____(__NR_profil),
10611 #endif
10612 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
10613 MACXY(__NR_sigaction, sigaction),
10614 GENX_(__NR_getgid, sys_getgid),
10615 MACXY(__NR_sigprocmask, sigprocmask),
10616 MACXY(__NR_getlogin, getlogin),
10617 // _____(__NR_setlogin),
10618 // _____(__NR_acct),
10619 MACXY(__NR_sigpending, sigpending),
10620 GENXY(__NR_sigaltstack, sys_sigaltstack),
10621 MACXY(__NR_ioctl, ioctl),
10622 // _____(__NR_reboot),
10623 // _____(__NR_revoke),
10624 GENX_(__NR_symlink, sys_symlink), // 57
10625 GENX_(__NR_readlink, sys_readlink),
10626 GENX_(__NR_execve, sys_execve),
10627 GENX_(__NR_umask, sys_umask), // 60
10628 GENX_(__NR_chroot, sys_chroot),
10629 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
10630 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
10631 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
10632 GENX_(__NR_msync, sys_msync),
10633 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
10634 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
10635 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
10636 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
10637 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
10638 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
10639 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
10640 GENXY(__NR_munmap, sys_munmap),
10641 GENXY(__NR_mprotect, sys_mprotect),
10642 GENX_(__NR_madvise, sys_madvise),
10643 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
10644 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
10645 GENXY(__NR_mincore, sys_mincore),
10646 GENXY(__NR_getgroups, sys_getgroups),
10647 // _____(__NR_setgroups), // 80
10648 GENX_(__NR_getpgrp, sys_getpgrp),
10649 GENX_(__NR_setpgid, sys_setpgid),
10650 GENXY(__NR_setitimer, sys_setitimer),
10651 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
10652 // _____(__NR_swapon),
10653 GENXY(__NR_getitimer, sys_getitimer),
10654 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
10655 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
10656 MACXY(__NR_getdtablesize, getdtablesize),
10657 GENXY(__NR_dup2, sys_dup2),
10658 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
10659 MACXY(__NR_fcntl, fcntl),
10660 GENX_(__NR_select, sys_select),
10661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
10662 GENX_(__NR_fsync, sys_fsync),
10663 GENX_(__NR_setpriority, sys_setpriority),
10664 MACXY(__NR_socket, socket),
10665 MACX_(__NR_connect, connect),
10666 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
10667 GENX_(__NR_getpriority, sys_getpriority), // 100
10668 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
10669 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
10670 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
10671 MACX_(__NR_bind, bind),
10672 MACX_(__NR_setsockopt, setsockopt),
10673 MACX_(__NR_listen, listen),
10674 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
10675 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
10676 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
10677 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
10678 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
10679 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
10680 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
10681 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
10682 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
10683 GENXY(__NR_gettimeofday, sys_gettimeofday),
10684 GENXY(__NR_getrusage, sys_getrusage),
10685 MACXY(__NR_getsockopt, getsockopt),
10686 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
10687 GENXY(__NR_readv, sys_readv), // 120
10688 GENX_(__NR_writev, sys_writev),
10689 // _____(__NR_settimeofday),
10690 GENX_(__NR_fchown, sys_fchown),
10691 GENX_(__NR_fchmod, sys_fchmod),
10692 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
10693 // _____(__NR_setreuid),
10694 // _____(__NR_setregid),
10695 GENX_(__NR_rename, sys_rename),
10696 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
10697 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
10698 GENX_(__NR_flock, sys_flock),
10699 MACXY(__NR_mkfifo, mkfifo),
10700 MACX_(__NR_sendto, sendto),
10701 MACX_(__NR_shutdown, shutdown),
10702 MACXY(__NR_socketpair, socketpair),
10703 GENX_(__NR_mkdir, sys_mkdir),
10704 GENX_(__NR_rmdir, sys_rmdir),
10705 GENX_(__NR_utimes, sys_utimes),
10706 MACX_(__NR_futimes, futimes),
10707 // _____(__NR_adjtime), // 140
10708 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
10709 MACXY(__NR_gethostuuid, gethostuuid),
10710 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
10711 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
10712 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
10713 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
10714 GENX_(__NR_setsid, sys_setsid),
10715 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
10716 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
10717 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
10718 // _____(__NR_getpgid),
10719 // _____(__NR_setprivexec),
10720 GENXY(__NR_pread, sys_pread64),
10721 GENX_(__NR_pwrite, sys_pwrite64),
10722 // _____(__NR_nfssvc),
10723 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
10724 GENXY(__NR_statfs, sys_statfs),
10725 GENXY(__NR_fstatfs, sys_fstatfs),
10726 // _____(__NR_unmount),
10727 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
10728 // _____(__NR_getfh),
10729 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
10730 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
10731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
10732 // _____(__NR_quotactl),
10733 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
10734 MACX_(__NR_mount, mount),
10735 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
10736 MACXY(__NR_csops, csops), // code-signing ops
10737 #if DARWIN_VERS >= DARWIN_10_8
10738 MACXY(__NR_csops_audittoken, csops_audittoken), // 170
10739 #else
10740 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
10741 #endif
10742 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
10743 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
10744 // _____(__NR_waitid),
10745 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
10746 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
10747 // _____(__NR_add_profil),
10748 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
10749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
10750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
10751 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
10752 GENX_(__NR_setgid, sys_setgid),
10753 MACX_(__NR_setegid, setegid),
10754 MACX_(__NR_seteuid, seteuid),
10755 MACX_(__NR_sigreturn, sigreturn),
10756 // _____(__NR_chud),
10757 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
10758 #if DARWIN_VERS >= DARWIN_10_6
10759 // _____(__NR_fdatasync),
10760 #else
10761 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
10762 #endif
10763 GENXY(__NR_stat, sys_newstat),
10764 GENXY(__NR_fstat, sys_newfstat),
10765 GENXY(__NR_lstat, sys_newlstat),
10766 MACX_(__NR_pathconf, pathconf),
10767 MACX_(__NR_fpathconf, fpathconf),
10768 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
10769 GENXY(__NR_getrlimit, sys_getrlimit),
10770 GENX_(__NR_setrlimit, sys_setrlimit),
10771 MACXY(__NR_getdirentries, getdirentries),
10772 MACXY(__NR_mmap, mmap),
10773 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
10774 MACX_(__NR_lseek, lseek),
10775 GENX_(__NR_truncate, sys_truncate64), // 200
10776 GENX_(__NR_ftruncate, sys_ftruncate64),
10777 MACXY(__NR___sysctl, __sysctl),
10778 GENX_(__NR_mlock, sys_mlock),
10779 GENX_(__NR_munlock, sys_munlock),
10780 // _____(__NR_undelete),
10781 // _____(__NR_ATsocket),
10782 // _____(__NR_ATgetmsg),
10783 // _____(__NR_ATputmsg),
10784 // _____(__NR_ATPsndreq),
10785 // _____(__NR_ATPsndrsp),
10786 // _____(__NR_ATPgetreq),
10787 // _____(__NR_ATPgetrsp),
10788 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
10789 #if DARWIN_VERS >= DARWIN_10_6
10790 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
10791 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
10792 #else
10793 // _____(__NR_kqueue_from_portset_np),
10794 // _____(__NR_kqueue_portset_np),
10795 #endif
10796 // _____(__NR_mkcomplex),
10797 // _____(__NR_statv),
10798 // _____(__NR_lstatv),
10799 // _____(__NR_fstatv),
10800 MACXY(__NR_getattrlist, getattrlist), // 220
10801 MACX_(__NR_setattrlist, setattrlist),
10802 MACXY(__NR_getdirentriesattr, getdirentriesattr),
10803 MACX_(__NR_exchangedata, exchangedata),
10804 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
10805 // _____(__NR_searchfs),
10806 GENX_(__NR_delete, sys_unlink),
10807 // _____(__NR_copyfile),
10808 #if DARWIN_VERS >= DARWIN_10_6
10809 MACX_(__NR_fgetattrlist, fgetattrlist), // 228
10810 // _____(__NR_fsetattrlist),
10811 #else
10812 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
10813 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
10814 #endif
10815 GENXY(__NR_poll, sys_poll),
10816 MACX_(__NR_watchevent, watchevent),
10817 MACXY(__NR_waitevent, waitevent),
10818 MACX_(__NR_modwatch, modwatch),
10819 MACXY(__NR_getxattr, getxattr),
10820 MACXY(__NR_fgetxattr, fgetxattr),
10821 MACX_(__NR_setxattr, setxattr),
10822 MACX_(__NR_fsetxattr, fsetxattr),
10823 MACX_(__NR_removexattr, removexattr),
10824 MACX_(__NR_fremovexattr, fremovexattr),
10825 MACXY(__NR_listxattr, listxattr), // 240
10826 MACXY(__NR_flistxattr, flistxattr),
10827 MACXY(__NR_fsctl, fsctl),
10828 MACX_(__NR_initgroups, initgroups),
10829 MACXY(__NR_posix_spawn, posix_spawn),
10830 #if DARWIN_VERS >= DARWIN_10_6
10831 // _____(__NR_ffsctl),
10832 #else
10833 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
10834 #endif
10835 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
10836 // _____(__NR_nfsclnt),
10837 // _____(__NR_fhopen),
10838 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
10839 // _____(__NR_minherit),
10840 // _____(__NR_semsys),
10841 // _____(__NR_msgsys),
10842 // _____(__NR_shmsys),
10843 MACXY(__NR_semctl, semctl),
10844 MACX_(__NR_semget, semget),
10845 MACX_(__NR_semop, semop),
10846 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
10847 // _____(__NR_msgctl),
10848 // _____(__NR_msgget),
10849 // _____(__NR_msgsnd), // 260
10850 // _____(__NR_msgrcv),
10851 MACXY(__NR_shmat, shmat),
10852 MACXY(__NR_shmctl, shmctl),
10853 MACXY(__NR_shmdt, shmdt),
10854 MACX_(__NR_shmget, shmget),
10855 MACXY(__NR_shm_open, shm_open),
10856 MACXY(__NR_shm_unlink, shm_unlink),
10857 MACX_(__NR_sem_open, sem_open),
10858 MACX_(__NR_sem_close, sem_close),
10859 MACX_(__NR_sem_unlink, sem_unlink),
10860 MACX_(__NR_sem_wait, sem_wait),
10861 MACX_(__NR_sem_trywait, sem_trywait),
10862 MACX_(__NR_sem_post, sem_post),
10863 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
10864 // has become sysctlbyname. See below.
10865 MACXY(__NR_sem_init, sem_init),
10866 MACX_(__NR_sem_destroy, sem_destroy),
10867 MACX_(__NR_open_extended, open_extended), // 277
10868 // _____(__NR_umask_extended),
10869 MACXY(__NR_stat_extended, stat_extended),
10870 MACXY(__NR_lstat_extended, lstat_extended), // 280
10871 MACXY(__NR_fstat_extended, fstat_extended),
10872 MACX_(__NR_chmod_extended, chmod_extended),
10873 MACX_(__NR_fchmod_extended,fchmod_extended),
10874 MACXY(__NR_access_extended,access_extended),
10875 MACX_(__NR_settid, settid),
10876 #if DARWIN_VERS >= DARWIN_10_8
10877 MACX_(__NR_gettid, gettid), // 286
10878 #endif
10879 // _____(__NR_setsgroups),
10880 // _____(__NR_getsgroups),
10881 // _____(__NR_setwgroups),
10882 // _____(__NR_getwgroups),
10883 // _____(__NR_mkfifo_extended),
10884 // _____(__NR_mkdir_extended),
10885 // _____(__NR_identitysvc),
10886 // _____(__NR_shared_region_check_np),
10887 // _____(__NR_shared_region_map_np),
10888 #if DARWIN_VERS >= DARWIN_10_6
10889 // _____(__NR_vm_pressure_monitor),
10890 // _____(__NR_psynch_rw_longrdlock),
10891 // _____(__NR_psynch_rw_yieldwrlock),
10892 // _____(__NR_psynch_rw_downgrade),
10893 // _____(__NR_psynch_rw_upgrade),
10894 MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
10895 MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
10896 MACXY(__NR_psynch_cvbroad, psynch_cvbroad), // 303
10897 MACXY(__NR_psynch_cvsignal, psynch_cvsignal), // 304
10898 MACXY(__NR_psynch_cvwait, psynch_cvwait), // 305
10899 MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
10900 MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
10901 MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
10902 // _____(__NR_psynch_rw_unlock2),
10903 #else
10904 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
10905 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
10906 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
10907 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
10908 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
10909 // _____(__NR___pthread_mutex_destroy),
10910 // _____(__NR___pthread_mutex_init),
10911 // _____(__NR___pthread_mutex_lock),
10912 // _____(__NR___pthread_mutex_trylock),
10913 // _____(__NR___pthread_mutex_unlock),
10914 // _____(__NR___pthread_cond_init),
10915 // _____(__NR___pthread_cond_destroy),
10916 // _____(__NR___pthread_cond_broadcast),
10917 // _____(__NR___pthread_cond_signal),
10918 #endif
10919 // _____(__NR_getsid),
10920 // _____(__NR_settid_with_pid),
10921 #if DARWIN_VERS >= DARWIN_10_7
10922 MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
10923 #else
10924 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // old __pthread_cond_timedwait
10925 #endif
10926 // _____(__NR_aio_fsync),
10927 MACX_(__NR_aio_return, aio_return),
10928 MACX_(__NR_aio_suspend, aio_suspend),
10929 // _____(__NR_aio_cancel),
10930 MACX_(__NR_aio_error, aio_error),
10931 MACXY(__NR_aio_read, aio_read),
10932 MACX_(__NR_aio_write, aio_write),
10933 // _____(__NR_lio_listio), // 320
10934 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
10936 #if DARWIN_VERS >= DARWIN_10_8
10937 MACXY(__NR_iopolicysys, iopolicysys),
10938 MACXY(__NR_process_policy, process_policy),
10939 #else
10940 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
10941 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
10942 #endif
10943 // _____(__NR_mlockall),
10944 // _____(__NR_munlockall),
10945 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
10946 MACX_(__NR_issetugid, issetugid),
10947 MACX_(__NR___pthread_kill, __pthread_kill),
10948 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
10949 MACXY(__NR___sigwait, __sigwait), // 330
10950 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
10951 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
10952 MACX_(__NR___pthread_canceled, __pthread_canceled),
10953 MACX_(__NR___semwait_signal, __semwait_signal),
10954 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
10955 MACXY(__NR_proc_info, proc_info), // 336
10956 MACXY(__NR_sendfile, sendfile),
10957 MACXY(__NR_stat64, stat64),
10958 MACXY(__NR_fstat64, fstat64),
10959 MACXY(__NR_lstat64, lstat64), // 340
10960 MACXY(__NR_stat64_extended, stat64_extended),
10961 MACXY(__NR_lstat64_extended, lstat64_extended),
10962 MACXY(__NR_fstat64_extended, fstat64_extended),
10963 MACXY(__NR_getdirentries64, getdirentries64),
10964 MACXY(__NR_statfs64, statfs64),
10965 MACXY(__NR_fstatfs64, fstatfs64),
10966 MACXY(__NR_getfsstat64, getfsstat64),
10967 MACX_(__NR___pthread_chdir, __pthread_chdir),
10968 MACX_(__NR___pthread_fchdir, __pthread_fchdir),
10969 // _____(__NR_audit),
10970 MACXY(__NR_auditon, auditon),
10971 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
10972 // _____(__NR_getauid),
10973 // _____(__NR_setauid),
10974 // _____(__NR_getaudit),
10975 // _____(__NR_setaudit),
10976 MACXY(__NR_getaudit_addr, getaudit_addr),
10977 // _____(__NR_setaudit_addr),
10978 // _____(__NR_auditctl),
10979 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
10980 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
10981 MACXY(__NR_kqueue, kqueue),
10982 MACXY(__NR_kevent, kevent),
10983 GENX_(__NR_lchown, sys_lchown),
10984 // _____(__NR_stack_snapshot),
10985 MACX_(__NR_bsdthread_register, bsdthread_register),
10986 MACX_(__NR_workq_open, workq_open),
10987 MACXY(__NR_workq_ops, workq_ops),
10988 #if DARWIN_VERS >= DARWIN_10_6
10989 MACXY(__NR_kevent64, kevent64),
10990 #else
10991 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
10992 #endif
10993 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // old semwait_signal
10994 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // old semwait_signal_nocancel
10995 #if DARWIN_VERS >= DARWIN_10_6
10996 MACX_(__NR___thread_selfid, __thread_selfid),
10997 #else
10998 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
10999 #endif
11000 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
11001 #if DARWIN_VERS < DARWIN_10_11
11002 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
11003 #endif
11004 #if DARWIN_VERS < DARWIN_10_13
11005 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
11006 #endif
11007 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
11008 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
11009 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
11010 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
11011 // _____(__NR___mac_execve), // 380
11012 MACX_(__NR___mac_syscall, __mac_syscall),
11013 // _____(__NR___mac_get_file),
11014 // _____(__NR___mac_set_file),
11015 // _____(__NR___mac_get_link),
11016 // _____(__NR___mac_set_link),
11017 // _____(__NR___mac_get_proc),
11018 // _____(__NR___mac_set_proc),
11019 // _____(__NR___mac_get_fd),
11020 // _____(__NR___mac_set_fd),
11021 // _____(__NR___mac_get_pid),
11022 // _____(__NR___mac_get_lcid),
11023 // _____(__NR___mac_get_lctx),
11024 // _____(__NR___mac_set_lctx),
11025 // _____(__NR_setlcid),
11026 // _____(__NR_getlcid),
11027 // GrP fixme need any special nocancel handling?
11028 GENXY(__NR_read_nocancel, sys_read),
11029 GENX_(__NR_write_nocancel, sys_write),
11030 GENXY(__NR_open_nocancel, sys_open),
11031 GENX_(__NR_close_nocancel, sys_close),
11032 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
11033 MACXY(__NR_recvmsg_nocancel, recvmsg),
11034 MACX_(__NR_sendmsg_nocancel, sendmsg),
11035 MACXY(__NR_recvfrom_nocancel, recvfrom),
11036 MACXY(__NR_accept_nocancel, accept),
11037 GENX_(__NR_msync_nocancel, sys_msync),
11038 MACXY(__NR_fcntl_nocancel, fcntl),
11039 GENX_(__NR_select_nocancel, sys_select),
11040 GENX_(__NR_fsync_nocancel, sys_fsync),
11041 MACX_(__NR_connect_nocancel, connect),
11042 MACX_(__NR_sigsuspend_nocancel, sigsuspend),
11043 GENXY(__NR_readv_nocancel, sys_readv),
11044 GENX_(__NR_writev_nocancel, sys_writev),
11045 MACX_(__NR_sendto_nocancel, sendto),
11046 GENXY(__NR_pread_nocancel, sys_pread64),
11047 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
11048 // _____(__NR_waitid_nocancel),
11049 GENXY(__NR_poll_nocancel, sys_poll),
11050 // _____(__NR_msgsnd_nocancel),
11051 // _____(__NR_msgrcv_nocancel),
11052 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
11053 // _____(__NR_aio_suspend_nocancel),
11054 // _____(__NR___sigwait_nocancel),
11055 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
11056 // _____(__NR___mac_mount),
11057 // _____(__NR___mac_get_mount),
11058 // _____(__NR___mac_getfsstat),
11059 #if DARWIN_VERS >= DARWIN_10_6
11060 MACXY(__NR_fsgetpath, fsgetpath),
11061 MACXY(__NR_audit_session_self, audit_session_self),
11062 // _____(__NR_audit_session_join),
11063 #endif
11064 #if DARWIN_VERS >= DARWIN_10_9
11065 MACX_(__NR_fileport_makeport, fileport_makeport),
11066 // _____(__NR_fileport_makefd), // 431
11067 // _____(__NR_audit_session_port), // 432
11068 // _____(__NR_pid_suspend), // 433
11069 // _____(__NR_pid_resume), // 434
11070 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(435)), // ???
11071 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(436)), // ???
11072 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(437)), // ???
11073 // _____(__NR_shared_region_map_and_slide_np), // 438
11074 // _____(__NR_kas_info), // 439
11075 // _____(__NR_memorystatus_control), // 440
11076 MACX_(__NR_guarded_open_np, guarded_open_np),
11077 MACX_(__NR_guarded_close_np, guarded_close_np),
11078 MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
11079 MACX_(__NR_change_fdguard_np, change_fdguard_np),
11080 MACX_(__NR_connectx, connectx),
11081 MACX_(__NR_disconnectx, disconnectx),
11082 #endif
11083 #if DARWIN_VERS >= DARWIN_10_10
11084 MACXY(__NR_sysctlbyname, sysctlbyname), // 274
11085 MACXY(__NR_necp_match_policy, necp_match_policy), // 460
11086 MACXY(__NR_getattrlistbulk, getattrlistbulk), // 461
11087 MACXY(__NR_openat, openat), // 463
11088 #if DARWIN_VERS >= DARWIN_10_13
11089 MACXY(__NR_openat_nocancel, openat_nocancel), // 464
11090 #endif
11091 MACX_(__NR_faccessat, faccessat), // 466
11092 MACXY(__NR_fstatat64, fstatat64), // 470
11093 MACX_(__NR_readlinkat, readlinkat), // 473
11094 MACX_(__NR_bsdthread_ctl, bsdthread_ctl), // 478
11095 MACXY(__NR_csrctl, csrctl), // 483
11096 MACX_(__NR_guarded_open_dprotected_np, guarded_open_dprotected_np), // 484
11097 MACX_(__NR_guarded_write_np, guarded_write_np), // 485
11098 MACX_(__NR_guarded_pwrite_np, guarded_pwrite_np), // 486
11099 MACX_(__NR_guarded_writev_np, guarded_writev_np), // 487
11100 // _____(__NR___mremap_encrypted), // 489
11101 #endif
11102 #if DARWIN_VERS >= DARWIN_10_11
11103 // _____(__NR_kdebug_trace_string), // 178
11104 MACXY(__NR_kevent_qos, kevent_qos), // 374
11105 MACX_(__NR_pselect, pselect), // 394
11106 // _____(__NR_netagent_trigger), // 490
11107 // _____(__NR_stack_snapshot_with_config), // 491
11108 // _____(__NR_microstackshot), // 492
11109 // _____(__NR_grab_pgo_data), // 493
11110 // _____(__NR_persona), // 494
11111 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(495)), // ???
11112 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(496)), // ???
11113 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(497)), // ???
11114 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(498)), // ???
11115 // _____(__NR_work_interval_ctl), // 499
11116 #endif
11117 #if DARWIN_VERS >= DARWIN_10_12
11118 // _____(__NR_kdebug_typefilter), // 177
11119 // _____(__NR_clonefileat), // 462
11120 // _____(__NR_renameatx_np), // 488
11121 MACXY(__NR_getentropy, getentropy), // 500
11122 MACX_(__NR_necp_open, necp_open), // 501
11123 MACX_(__NR_necp_client_action, necp_client_action), // 502
11124 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(503)), // ???
11125 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(504)), // ???
11126 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(505)), // ???
11127 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(506)), // ???
11128 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(507)), // ???
11129 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(508)), // ???
11130 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(509)), // ???
11131 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(510)), // ???
11132 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(511)), // ???
11133 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(512)), // ???
11134 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(513)), // ???
11135 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(514)), // ???
11136 MACX_(__NR_ulock_wait, ulock_wait), // 515
11137 MACX_(__NR_ulock_wake, ulock_wake), // 516
11138 // _____(__NR_fclonefileat), // 517
11139 // _____(__NR_fs_snapshot), // 518
11140 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(519)), // ???
11141 MACX_(__NR_terminate_with_payload, terminate_with_payload), // 520
11142 MACX_(__NR_abort_with_payload, abort_with_payload), // 521
11143 #endif
11144 #if DARWIN_VERS >= DARWIN_10_13
11145 // _____(__NR_thread_selfcounts), // 186
11146 MACXY(__NR_kevent_id, kevent_id), // 375
11147 // _____(__NR_necp_session_open), // 522
11148 // _____(__NR_necp_session_action), // 523
11149 // _____(__NR_setattrlistat), // 524
11150 // _____(__NR_net_qos_guideline), // 525
11151 // _____(__NR_fmount), // 526
11152 // _____(__NR_ntp_adjtime), // 527
11153 // _____(__NR_ntp_gettime), // 528
11154 // _____(__NR_os_fault_with_payload), // 529
11155 #endif
11156 // _____(__NR_MAXSYSCALL)
11157 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
11161 // Mach traps use negative syscall numbers.
11162 // Use ML_(mach_trap_table)[-mach_trap_number] .
11163 // cf xnu sources osfmk/kern/syscall_sw.c
11165 const SyscallTableEntry ML_(mach_trap_table)[] = {
11166 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
11167 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
11168 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
11169 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
11170 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
11171 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
11172 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
11173 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
11174 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
11175 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
11177 # if DARWIN_VERS >= DARWIN_10_8
11178 MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
11179 # else
11180 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
11181 # endif
11183 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
11185 # if DARWIN_VERS >= DARWIN_10_8
11186 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
11187 # else
11188 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
11189 # endif
11191 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
11193 # if DARWIN_VERS >= DARWIN_10_8
11194 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
11195 # endif
11197 # if DARWIN_VERS >= DARWIN_10_9
11198 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
11199 # endif
11201 # if DARWIN_VERS < DARWIN_10_8
11202 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
11203 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
11204 # endif
11206 # if DARWIN_VERS >= DARWIN_10_8
11207 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
11208 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
11209 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
11210 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
11211 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
11212 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
11213 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
11214 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
11215 # else
11216 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
11217 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
11218 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
11219 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
11220 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
11221 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
11222 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
11223 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
11224 # endif
11226 # if DARWIN_VERS >= DARWIN_10_9
11227 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
11228 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
11229 # else
11230 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
11231 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
11232 # endif
11234 MACXY(__NR_mach_reply_port, mach_reply_port),
11235 MACXY(__NR_thread_self_trap, mach_thread_self),
11236 MACXY(__NR_task_self_trap, mach_task_self),
11237 MACXY(__NR_host_self_trap, mach_host_self),
11238 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
11239 MACXY(__NR_mach_msg_trap, mach_msg),
11240 // _____(__NR_mach_msg_overwrite_trap),
11241 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
11242 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
11243 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
11244 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
11245 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
11246 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
11247 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
11248 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
11250 # if DARWIN_VERS >= DARWIN_10_9
11251 MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
11252 MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
11253 # else
11254 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
11255 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
11256 # endif
11258 # if DARWIN_VERS >= DARWIN_10_12
11259 MACXY(__NR_mach_generate_activity_id, mach_generate_activity_id),
11260 # elif DARWIN_VERS >= DARWIN_10_10
11261 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
11262 # elif defined(VGA_x86) || DARWIN_VERS == DARWIN_10_9
11263 // _____(__NR_map_fd),
11264 # else
11265 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
11266 # endif
11268 // _____(__NR_task_name_for_pid),
11269 MACXY(__NR_task_for_pid, task_for_pid),
11270 MACXY(__NR_pid_for_task, pid_for_task),
11271 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
11272 #if defined(VGA_x86)
11273 // _____(__NR_macx_swapon),
11274 // _____(__NR_macx_swapoff),
11275 #else
11276 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
11277 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
11278 #endif
11279 #if DARWIN_VERS >= DARWIN_10_13
11280 MACXY(__NR_thread_get_special_reply_port, thread_get_special_reply_port),
11281 #else
11282 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
11283 #endif /* DARWIN_VERS >= DARWIN_10_13 */
11284 #if defined(VGA_x86)
11285 // _____(__NR_macx_triggers),
11286 // _____(__NR_macx_backing_store_suspend),
11287 // _____(__NR_macx_backing_store_recovery),
11288 #else
11289 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
11290 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
11291 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
11292 #endif
11293 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
11294 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
11295 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
11296 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
11297 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
11298 MACX_(__NR_swtch_pri, swtch_pri),
11299 MACX_(__NR_swtch, swtch), // -60
11300 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
11301 // _____(__NR_clock_sleep_trap),
11302 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
11303 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
11304 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
11305 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
11306 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
11307 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
11308 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
11309 #if DARWIN_VERS >= DARWIN_10_12
11310 MACXY(__NR_host_create_mach_voucher_trap, host_create_mach_voucher_trap),
11311 #else
11312 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
11313 #endif
11314 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
11315 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
11316 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
11317 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
11318 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
11319 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
11320 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
11321 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
11322 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
11323 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
11324 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
11325 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
11326 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
11327 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
11328 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
11329 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
11330 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
11331 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
11332 MACXY(__NR_mach_timebase_info, mach_timebase_info),
11333 MACX_(__NR_mach_wait_until, mach_wait_until),
11334 MACXY(__NR_mk_timer_create, mk_timer_create),
11335 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
11336 MACX_(__NR_mk_timer_arm, mk_timer_arm),
11337 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
11338 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
11339 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
11340 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
11341 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
11342 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
11343 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
11347 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
11348 // calling convention instead of the syscall convention.
11349 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
11351 #if defined(VGA_x86)
11352 const SyscallTableEntry ML_(mdep_trap_table)[] = {
11353 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
11355 #elif defined(VGA_amd64)
11356 const SyscallTableEntry ML_(mdep_trap_table)[] = {
11357 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
11359 #else
11360 #error unknown architecture
11361 #endif
11363 const UInt ML_(syscall_table_size) =
11364 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
11366 const UInt ML_(mach_trap_table_size) =
11367 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
11369 const UInt ML_(mdep_trap_table_size) =
11370 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
11372 #endif // defined(VGO_darwin)
11374 /*--------------------------------------------------------------------*/
11375 /*--- end ---*/
11376 /*--------------------------------------------------------------------*/