2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #if defined(VGO_darwin)
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_vkiscnums.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_xarray.h"
39 #include "pub_core_clientstate.h"
40 #include "pub_core_debuglog.h"
41 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
42 #include "pub_core_transtab.h" // VG_(discard_translations)
43 #include "pub_core_libcbase.h"
44 #include "pub_core_libcassert.h"
45 #include "pub_core_libcfile.h"
46 #include "pub_core_libcprint.h"
47 #include "pub_core_libcproc.h"
48 #include "pub_core_libcsignal.h"
49 #include "pub_core_machine.h" // VG_(get_SP)
50 #include "pub_core_mallocfree.h"
51 #include "pub_core_options.h"
52 #include "pub_core_oset.h"
53 #include "pub_core_scheduler.h"
54 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
55 #include "pub_core_signals.h"
56 #include "pub_core_stacks.h"
57 #include "pub_core_syscall.h"
58 #include "pub_core_syswrap.h"
59 #include "pub_core_tooliface.h"
60 #include "pub_core_wordfm.h"
62 #include "priv_types_n_macros.h"
63 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
64 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
65 #include "priv_syswrap-main.h"
67 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
68 #include <mach/mach.h>
69 #include <mach/mach_vm.h>
70 #include <semaphore.h>
71 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
73 #define msgh_request_port msgh_remote_port
74 #define msgh_reply_port msgh_local_port
75 #define BOOTSTRAP_MAX_NAME_LEN 128
76 typedef HChar name_t
[BOOTSTRAP_MAX_NAME_LEN
];
78 typedef uint64_t mig_addr_t
;
82 static mach_port_t vg_host_port
= 0;
83 static mach_port_t vg_task_port
= 0;
84 static mach_port_t vg_bootstrap_port
= 0;
86 // Run a thread from beginning to end and return the thread's
87 // scheduler-return-code.
88 static VgSchedReturnCode
thread_wrapper(Word
/*ThreadId*/ tidW
)
90 VgSchedReturnCode ret
;
91 ThreadId tid
= (ThreadId
)tidW
;
92 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
94 VG_(debugLog
)(1, "syswrap-darwin",
95 "thread_wrapper(tid=%u): entry\n",
98 vg_assert(tst
->status
== VgTs_Init
);
100 /* make sure we get the CPU lock before doing anything significant */
101 VG_(acquire_BigLock
)(tid
, "thread_wrapper");
104 VG_(printf
)("thread tid %u started: stack = %p\n",
107 /* Make sure error reporting is enabled in the new thread. */
108 tst
->err_disablement_level
= 0;
110 VG_TRACK(pre_thread_first_insn
, tid
);
112 tst
->os_state
.lwpid
= VG_(gettid
)();
113 tst
->os_state
.threadgroup
= VG_(getpid
)();
115 /* Thread created with all signals blocked; scheduler will set the
118 ret
= VG_(scheduler
)(tid
);
120 vg_assert(VG_(is_exiting
)(tid
));
122 vg_assert(tst
->status
== VgTs_Runnable
);
123 vg_assert(VG_(is_running_thread
)(tid
));
125 VG_(debugLog
)(1, "syswrap-darwin",
126 "thread_wrapper(tid=%u): done\n",
129 /* Return to caller, still holding the lock. */
135 /* Allocate a stack for this thread, if it doesn't already have one.
136 Returns the initial stack pointer value to use, or 0 if allocation
139 Addr
allocstack ( ThreadId tid
)
141 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
145 /* Either the stack_base and stack_init_SP are both zero (in which
146 case a stack hasn't been allocated) or they are both non-zero,
147 in which case it has. */
149 if (tst
->os_state
.valgrind_stack_base
== 0)
150 vg_assert(tst
->os_state
.valgrind_stack_init_SP
== 0);
152 if (tst
->os_state
.valgrind_stack_base
!= 0)
153 vg_assert(tst
->os_state
.valgrind_stack_init_SP
!= 0);
155 /* If no stack is present, allocate one. */
157 if (tst
->os_state
.valgrind_stack_base
== 0) {
158 stack
= VG_(am_alloc_VgStack
)( &initial_SP
);
160 tst
->os_state
.valgrind_stack_base
= (Addr
)stack
;
161 tst
->os_state
.valgrind_stack_init_SP
= initial_SP
;
165 VG_(debugLog
)( 2, "syswrap-darwin", "stack for tid %u at %p; init_SP=%p\n",
167 (void*)tst
->os_state
.valgrind_stack_base
,
168 (void*)tst
->os_state
.valgrind_stack_init_SP
);
170 vg_assert(VG_IS_32_ALIGNED(tst
->os_state
.valgrind_stack_init_SP
));
172 return tst
->os_state
.valgrind_stack_init_SP
;
176 void find_stack_segment(ThreadId tid
, Addr sp
)
178 ML_(guess_and_register_stack
) (sp
, VG_(get_ThreadState
)(tid
));
182 /* Run a thread all the way to the end, then do appropriate exit actions
183 (this is the last-one-out-turn-off-the-lights bit).
185 static void run_a_thread_NORETURN ( Word tidW
)
188 VgSchedReturnCode src
;
189 ThreadId tid
= (ThreadId
)tidW
;
192 VG_(debugLog
)(1, "syswrap-darwin",
193 "run_a_thread_NORETURN(tid=%u): pre-thread_wrapper\n",
196 tst
= VG_(get_ThreadState
)(tid
);
199 /* Run the thread all the way through. */
200 src
= thread_wrapper(tid
);
202 VG_(debugLog
)(1, "syswrap-darwin",
203 "run_a_thread_NORETURN(tid=%u): post-thread_wrapper\n",
206 c
= VG_(count_living_threads
)();
207 vg_assert(c
>= 1); /* stay sane */
209 /* Deregister thread's stack. */
210 if (tst
->os_state
.stk_id
!= NULL_STK_ID
)
211 VG_(deregister_stack
)(tst
->os_state
.stk_id
);
213 // Tell the tool this thread is exiting
214 VG_TRACK( pre_thread_ll_exit
, tid
);
216 /* If the thread is exiting with errors disabled, complain loudly;
217 doing so is bad (does the user know this has happened?) Also,
218 in all cases, be paranoid and clear the flag anyway so that the
219 thread slot is safe in this respect if later reallocated. This
220 should be unnecessary since the flag should be cleared when the
221 slot is reallocated, in thread_wrapper(). */
222 if (tst
->err_disablement_level
> 0) {
224 "WARNING: exiting thread has error reporting disabled.\n"
225 "WARNING: possibly as a result of some mistake in the use\n"
226 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
230 "run_a_thread_NORETURN(tid=%u): "
231 "WARNING: exiting thread has err_disablement_level = %u\n",
232 tid
, tst
->err_disablement_level
235 tst
->err_disablement_level
= 0;
239 VG_(debugLog
)(1, "syswrap-darwin",
240 "run_a_thread_NORETURN(tid=%u): "
241 "last one standing\n",
244 /* We are the last one standing. Keep hold of the lock and
245 carry on to show final tool results, then exit the entire system.
246 Use the continuation pointer set at startup in m_main. */
247 ( * VG_(address_of_m_main_shutdown_actions_NORETURN
) ) (tid
, src
);
251 mach_msg_header_t msg
;
253 VG_(debugLog
)(1, "syswrap-darwin",
254 "run_a_thread_NORETURN(tid=%u): "
255 "not last one standing\n",
258 /* OK, thread is dead, but others still exist. Just exit. */
260 /* This releases the run lock */
261 VG_(exit_thread
)(tid
);
262 vg_assert(tst
->status
== VgTs_Zombie
);
264 /* tid is now invalid. */
266 // GrP fixme exit race
267 msg
.msgh_bits
= MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE
);
268 msg
.msgh_request_port
= VG_(gettid
)();
269 msg
.msgh_reply_port
= 0;
270 msg
.msgh_id
= 3600; // thread_terminate
272 tst
->status
= VgTs_Empty
;
273 // GrP fixme race here! new thread may claim this V thread stack
274 // before we get out here!
275 // GrP fixme use bsdthread_terminate for safe cleanup?
276 mach_msg(&msg
, MACH_SEND_MSG
|MACH_MSG_OPTION_NONE
,
277 sizeof(msg
), 0, 0, MACH_MSG_TIMEOUT_NONE
, 0);
279 // DDD: This is reached sometimes on none/tests/manythreads, maybe
280 // because of the race above.
281 VG_(core_panic
)("Thread exit failed?\n");
289 /* Allocate a stack for the main thread, and run it all the way to the
290 end. Although we already have a working VgStack
291 (VG_(interim_stack)) it's better to allocate a new one, so that
292 overflow detection works uniformly for all threads.
294 void VG_(main_thread_wrapper_NORETURN
)(ThreadId tid
)
297 VG_(debugLog
)(1, "syswrap-darwin",
298 "entering VG_(main_thread_wrapper_NORETURN)\n");
300 sp
= allocstack(tid
);
302 /* If we can't even allocate the first thread's stack, we're hosed.
304 vg_assert2(sp
!= 0, "Cannot allocate main thread's stack.");
306 /* shouldn't be any other threads around yet */
307 vg_assert( VG_(count_living_threads
)() == 1 );
309 call_on_new_stack_0_1(
310 (Addr
)sp
, /* stack */
311 0, /*bogus return address*/
312 run_a_thread_NORETURN
, /* fn to call */
313 (Word
)tid
/* arg to give it */
321 void start_thread_NORETURN ( Word arg
)
323 ThreadState
* tst
= (ThreadState
*)arg
;
324 ThreadId tid
= tst
->tid
;
326 run_a_thread_NORETURN ( (Word
)tid
);
332 void VG_(cleanup_thread
) ( ThreadArchState
* arch
)
337 /* ---------------------------------------------------------------------
338 Message reporting, with duplicate removal
339 ------------------------------------------------------------------ */
341 static WordFM
* decaying_string_table
= NULL
; /* HChar* -> UWord */
343 static Word
decaying_string_table_cmp ( UWord s1
, UWord s2
) {
344 return (Word
)VG_(strcmp
)( (HChar
*)s1
, (HChar
*)s2
);
347 static void log_decaying ( const HChar
* format
, ... ) PRINTF_CHECK(1, 2);
348 static void log_decaying ( const HChar
* format
, ... )
350 // get the message into a stack-allocated string.
352 VG_(memset
)(buf
, 0, sizeof(buf
));
354 va_start(vargs
,format
);
355 (void) VG_(vsnprintf
)(buf
, sizeof(buf
), format
, vargs
);
357 buf
[sizeof(buf
)-1] = 0;
359 // Now see if it already exists in the table of strings that we have.
360 if (!decaying_string_table
) {
361 decaying_string_table
362 = VG_(newFM
)( VG_(malloc
), "syswrap-darwin.pd.1",
363 VG_(free
), decaying_string_table_cmp
);
366 const HChar
* key
= NULL
;
368 if (!VG_(lookupFM
)(decaying_string_table
,
369 (UWord
*)&key
, &val
, (UWord
)&buf
[0])) {
370 // We haven't seen this string before, so strdup it and add
372 vg_assert(key
== NULL
&& val
== 0);
373 key
= VG_(strdup
)("syswrap-darwin.pd.2", buf
);
374 VG_(addToFM
)(decaying_string_table
, (UWord
)key
, (UWord
)0);
377 vg_assert(key
!= NULL
&& key
!= &buf
[0]);
379 // So, finally, |key| is in the tree, and |val| is what it is
380 // currently associated with. Increment that counter.
382 Bool b
= VG_(addToFM
)(decaying_string_table
, (UWord
)key
, (UWord
)val
);
385 if (-1 != VG_(log2
)( (UInt
)val
)) {
387 VG_(dmsg
)("%s\n", key
);
389 VG_(dmsg
)("%s (repeated %lu times)\n", key
, val
);
394 /* ---------------------------------------------------------------------
395 Mach port tracking (based on syswrap-generic's fd tracker)
396 ------------------------------------------------------------------ */
398 /* One of these is allocated for each open port. */
399 typedef struct OpenPort
402 mach_port_type_t type
; /* right type(s) */
403 Int send_count
; /* number of send rights */
404 HChar
*name
; /* bootstrap name or NULL */
405 ExeContext
*where
; /* first allocation only */
406 struct OpenPort
*next
, *prev
;
409 // strlen("0x12345678")
410 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
412 /* List of allocated ports. */
413 static OpenPort
*allocated_ports
;
415 /* Count of open ports. */
416 static Int allocated_port_count
= 0;
418 /* Create an entry for |port|, with no other info. Assumes it doesn't
420 static void port_create_vanilla(mach_port_t port
)
423 = VG_(calloc
)("syswrap-darwin.port_create_vanilla", sizeof(OpenPort
), 1);
425 /* Add it to the list. */
426 op
->next
= allocated_ports
;
427 if (allocated_ports
) allocated_ports
->prev
= op
;
428 allocated_ports
= op
;
429 allocated_port_count
++;
432 __attribute__((unused
))
433 static Bool
port_exists(mach_port_t port
)
437 /* Check to see if this port is already open. */
440 if (i
->port
== port
) {
449 static OpenPort
*info_for_port(mach_port_t port
)
452 if (!port
) return NULL
;
456 if (i
->port
== port
) {
466 // Give a port a name, without changing its refcount
467 // GrP fixme don't override name if it already has a specific one
468 __private_extern__
void assign_port_name(mach_port_t port
, const HChar
*name
)
474 i
= info_for_port(port
);
477 if (i
->name
) VG_(free
)(i
->name
);
479 VG_(malloc
)("syswrap-darwin.mach-port-name",
480 VG_(strlen
)(name
) + PORT_STRLEN
+ 1);
481 VG_(sprintf
)(i
->name
, name
, port
);
485 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
486 static const HChar
*name_for_port(mach_port_t port
)
488 static HChar buf
[8 + PORT_STRLEN
+ 1];
492 if (port
== VG_(gettid
)()) return "mach_thread_self()";
493 if (port
== 0) return "NULL";
497 if (i
->port
== port
) {
503 VG_(sprintf
)(buf
, "NONPORT-%#x", port
);
507 /* Note the fact that a port was just deallocated. */
510 void record_port_mod_refs(mach_port_t port
, mach_port_type_t right
, Int delta
)
512 OpenPort
*i
= allocated_ports
;
516 if(i
->port
== port
) {
517 vg_assert(right
!= MACH_PORT_TYPE_DEAD_NAME
);
518 if (right
& MACH_PORT_TYPE_SEND
) {
519 // send rights are refcounted
520 if (delta
== INT_MIN
) delta
= -i
->send_count
; // INT_MIN == destroy
521 i
->send_count
+= delta
;
522 if (i
->send_count
> 0) i
->type
|= MACH_PORT_TYPE_SEND
;
523 else i
->type
&= ~MACH_PORT_TYPE_SEND
;
525 right
= right
& ~MACH_PORT_TYPE_SEND
;
527 // other rights are not refcounted
530 } else if (delta
< 0) {
535 if (i
->type
!= 0) return;
537 // Port has no rights left. Kill it.
538 // VG_(printf)("deleting port %p %s", i->port, i->name);
540 i
->prev
->next
= i
->next
;
542 allocated_ports
= i
->next
;
544 i
->next
->prev
= i
->prev
;
548 allocated_port_count
--;
554 VG_(printf
)("UNKNOWN Mach port modified (port %#x delta %d)\n", port
, delta
);
558 void record_port_insert_rights(mach_port_t port
, mach_msg_type_name_t type
)
561 case MACH_MSG_TYPE_PORT_NAME
:
562 // this task has no rights for the name
564 case MACH_MSG_TYPE_PORT_RECEIVE
:
565 // this task gets receive rights
566 record_port_mod_refs(port
, MACH_PORT_TYPE_RECEIVE
, 1);
568 case MACH_MSG_TYPE_PORT_SEND
:
569 // this task gets a send right
570 record_port_mod_refs(port
, MACH_PORT_TYPE_SEND
, 1);
572 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
573 // this task gets send-once rights
574 record_port_mod_refs(port
, MACH_PORT_TYPE_SEND_ONCE
, 1);
583 void record_port_dealloc(mach_port_t port
)
585 // deletes 1 send or send-once right (port can't have both)
586 record_port_mod_refs(port
, MACH_PORT_TYPE_SEND_RIGHTS
, -1);
590 void record_port_destroy(mach_port_t port
)
592 // deletes all rights to port
593 record_port_mod_refs(port
, MACH_PORT_TYPE_ALL_RIGHTS
, INT_MIN
);
597 /* Note the fact that a Mach port was just allocated or transferred.
598 If the port is already known, increment its reference count. */
599 void record_named_port(ThreadId tid
, mach_port_t port
,
600 mach_port_right_t right
, const HChar
*name
)
605 /* Check to see if this port is already open. */
608 if (i
->port
== port
) {
609 if (right
!= -1) record_port_mod_refs(port
, MACH_PORT_TYPE(right
), 1);
615 /* Not already one: allocate an OpenPort */
617 i
= VG_(malloc
)("syswrap-darwin.mach-port", sizeof(OpenPort
));
620 i
->next
= allocated_ports
;
621 if(allocated_ports
) allocated_ports
->prev
= i
;
623 allocated_port_count
++;
626 i
->where
= (tid
== -1) ? NULL
: VG_(record_ExeContext
)(tid
, 0);
629 i
->type
= MACH_PORT_TYPE(right
);
630 i
->send_count
= (right
== MACH_PORT_RIGHT_SEND
) ? 1 : 0;
636 assign_port_name(port
, name
);
641 // Record opening of a nameless port.
642 static void record_unnamed_port(ThreadId tid
, mach_port_t port
, mach_port_right_t right
)
644 record_named_port(tid
, port
, right
, "unnamed-%p");
648 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
649 void VG_(show_open_ports
)(void)
653 VG_(message
)(Vg_UserMsg
,
654 "MACH PORTS: %d open at exit.\n", allocated_port_count
);
656 for (i
= allocated_ports
; i
; i
= i
->next
) {
658 VG_(message
)(Vg_UserMsg
, "Open Mach port 0x%x: %s\n", i
->port
,
661 VG_(message
)(Vg_UserMsg
, "Open Mach port 0x%x\n", i
->port
);
665 VG_(pp_ExeContext
)(i
->where
);
666 VG_(message
)(Vg_UserMsg
, "\n");
670 VG_(message
)(Vg_UserMsg
, "\n");
674 /* ---------------------------------------------------------------------
676 ------------------------------------------------------------------ */
679 enum { CheckAlways
=1, CheckEvery20
, CheckNever
}
682 static const HChar
* show_CheckHowOften ( CheckHowOften cho
) {
684 case CheckAlways
: return "Always ";
685 case CheckEvery20
: return "Every20";
686 case CheckNever
: return "Never ";
687 default: vg_assert(0);
691 /* Statistics for one particular resync-call set of arguments,
692 as specified by key1, key2 and key3. */
700 ULong n_mappings_added
;
701 ULong n_mappings_removed
;
705 static Bool
cmp_eqkeys_SyncStats ( SyncStats
* ss1
, SyncStats
* ss2
) {
706 return ss1
->key3
== ss2
->key3
707 && 0 == VG_(strcmp
)(ss1
->key1
, ss2
->key1
)
708 && 0 == VG_(strcmp
)(ss1
->key2
, ss2
->key2
);
711 /* The filter data. */
712 #define N_SYNCSTATS 1000
713 static Int syncstats_used
= 0;
714 static SyncStats syncstats
[N_SYNCSTATS
];
716 /* Statistics overall, for the filter. */
717 static ULong n_syncsRequested
= 0; // Total number requested
718 static ULong n_syncsPerformed
= 0; // Number carried out (the rest skipped)
722 void update_syncstats ( CheckHowOften cho
,
723 const HChar
* key1
, const HChar
* key2
,
725 UInt n_mappings_added
, UInt n_mappings_removed
)
727 SyncStats dummy
= { CheckAlways
, key1
, key2
, key3
, 0, 0, 0 };
729 for (i
= 0; i
< syncstats_used
; i
++) {
730 if (cmp_eqkeys_SyncStats(&syncstats
[i
], &dummy
))
733 vg_assert(i
>= 0 && i
<= syncstats_used
);
734 if (i
== syncstats_used
) {
736 vg_assert(syncstats_used
< N_SYNCSTATS
);
738 syncstats
[i
] = dummy
;
739 syncstats
[i
].cho
= cho
;
741 vg_assert(cmp_eqkeys_SyncStats(&syncstats
[i
], &dummy
));
742 syncstats
[i
].n_checks
++;
743 syncstats
[i
].n_mappings_added
+= (ULong
)n_mappings_added
;
744 syncstats
[i
].n_mappings_removed
+= (ULong
)n_mappings_removed
;
746 static UInt reorder_ctr
= 0;
747 if (i
> 0 && 0 == (1 & reorder_ctr
++)) {
748 SyncStats tmp
= syncstats
[i
-1];
749 syncstats
[i
-1] = syncstats
[i
];
755 static void maybe_show_syncstats ( void )
760 if (0 == (n_syncsRequested
& 0xFF)) {
761 VG_(printf
)("Resync filter: %'llu requested, %'llu performed (%llu%%)\n",
762 n_syncsRequested
, n_syncsPerformed
,
763 (100 * n_syncsPerformed
) /
764 (n_syncsRequested
== 0 ? 1 : n_syncsRequested
));
765 for (i
= 0; i
< syncstats_used
; i
++) {
766 if (i
>= 40) break; // just show the top 40
767 VG_(printf
)(" [%3d] (%s) upd %6llu diff %4llu+,%3llu-"
769 i
, show_CheckHowOften(syncstats
[i
].cho
),
770 syncstats
[i
].n_checks
,
771 syncstats
[i
].n_mappings_added
,
772 syncstats
[i
].n_mappings_removed
,
773 syncstats
[i
].key1
, syncstats
[i
].key2
,
774 (ULong
)syncstats
[i
].key3
);
776 if (i
< syncstats_used
) {
777 VG_(printf
)(" and %d more entries not shown.\n", syncstats_used
- i
);
784 Bool
ML_(sync_mappings
)(const HChar
* when
, const HChar
* where
, UWord num
)
786 // If VG(clo_resync_filter) == 0, the filter is disabled, and
787 // we must always honour the resync request.
789 // If VG(clo_resync_filter) == 1, the filter is enabled,
790 // so we try to avoid doing the sync if possible, but keep
793 // If VG(clo_resync_filter) == 2, the filter is enabled,
794 // so we try to avoid doing the sync if possible, and also
795 // periodically show stats, so that the filter can be updated.
798 if (VG_(clo_resync_filter
) >= 2)
799 maybe_show_syncstats();
803 // Usually the number of segments added/removed in a single call is very
804 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
805 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
806 // because we can't do dynamic allocation within VG_(get_changed_segments),
807 // because it's in m_aspacemgr.
808 ChangedSeg
* css
= NULL
;
814 // -------------- BEGIN resync-filter-kludge --------------
816 // Some kludges to try and avoid the worst case cost hit of doing
817 // zillions of resyncs (huge). The idea is that many of the most
818 // common resyncs never appear to cause a delta, so we just ignore
819 // them (CheckNever). Then, a bunch of them also happen a lot, but
820 // only very occasionally cause a delta. We resync after 20 of those
821 // (CheckEvery20). Finally, the rest form a long tail, so we always
822 // resync after those (CheckAlways).
824 // Assume this is kernel-version and word-size specific, so develop
825 // filters accordingly. This might be overly conservative --
828 # define STREQ(_s1, _s2) (0 == VG_(strcmp)((_s1),(_s2)))
829 Bool when_in
= STREQ(when
, "in");
830 Bool when_after
= STREQ(when
, "after");
831 Bool where_mmr
= STREQ(where
, "mach_msg_receive");
832 Bool where_mmrU
= STREQ(where
, "mach_msg_receive-UNHANDLED");
833 Bool where_iuct
= STREQ(where
, "iokit_user_client_trap");
834 Bool where_MwcN
= STREQ(where
, "ML_(wqthread_continue_NORETURN)");
835 Bool where_woQR
= STREQ(where
, "workq_ops(QUEUE_REQTHREADS)");
836 Bool where_woQ2
= STREQ(where
, "workq_ops(QUEUE_REQTHREADS2)");
837 Bool where_woTR
= STREQ(where
, "workq_ops(THREAD_RETURN)");
838 Bool where_ke64
= STREQ(where
, "kevent64");
842 1 >= ( (where_mmr
? 1 : 0) + (where_mmrU
? 1 : 0)
843 + (where_iuct
? 1 : 0) + (where_MwcN
? 1 : 0)
844 + (where_woQR
? 1 : 0) + (where_woQ2
? 1 : 0)
845 + (where_woTR
? 1 : 0) + (where_ke64
? 1 : 0)
847 // merely to stop gcc complaining of non-use in the case where
848 // there's no filter:
849 vg_assert(when_in
== True
|| when_in
== False
);
850 vg_assert(when_after
== True
|| when_after
== False
);
852 CheckHowOften check
= CheckAlways
;
854 # if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
855 /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
856 if (when_after
&& where_mmr
) {
857 // "after mach_msg_receive <number>"
859 case 0x00000000: // upd 12414 diff 36+,0-
860 check
= CheckEvery20
;
867 if (when_after
&& where_mmrU
) {
868 // "after mach_msg_receive-UNHANDLED <number>"
870 case 0x00000000: // upd 16687 diff 73+,0-
871 case 0x00000001: // upd 5106 diff 89+,0-
872 case 0x00000002: // upd 1609 diff 1+,0-
873 case 0x00000003: // upd 1987 diff 6+,0-
874 // case 0x00000b95: // upd 2894 diff 57+,1- <==dangerous
875 case 0x000072d9: // upd 2616 diff 11+,0-
876 case 0x000072cb: // upd 2616 diff 9+,0-
877 case 0x000074d5: // upd 172 diff 0+,0-
878 check
= CheckEvery20
;
885 if (when_in
&& where_MwcN
&& num
== 0x00000000) {
886 // in ML_(wqthread_continue_NORETURN) 0x00000000
887 // upd 4346 diff 0+,0-
888 check
= CheckEvery20
;
891 if (when_after
&& where_woQR
&& num
== 0x00000000) {
892 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
893 // upd 14434 diff 102+,0-
894 check
= CheckEvery20
;
896 /* if (when_after && where_woQ2 && num == 0x00000000) {
897 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
898 // upd XXXX diff XX+,0-
899 check = CheckEvery20;
902 if (when_after
&& where_woTR
&& num
== 0x00000000) {
903 // after workq_ops(THREAD_RETURN) 0x00000000
904 // upd 14434 diff 102+,0-
905 check
= CheckEvery20
;
908 if (when_after
&& where_ke64
&& num
== 0x00000000) {
909 // after kevent64 0x00000000
910 // upd 1736 diff 78+,0-
911 check
= CheckEvery20
;
913 /* ----------- END filter for 64-bit 10.9.x ----------- */
914 # endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
916 # if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
917 /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
918 if (when_after
&& where_mmr
) {
919 // "after mach_msg_receive <number>"
921 case 0x00000000: // upd 2380 diff 23+,0-
922 check
= CheckEvery20
;
929 if (when_after
&& where_mmrU
) {
930 // "after mach_msg_receive-UNHANDLED <number>"
932 case 0x00000000: // upd 2370 diff 93+,1- <==dangerous
933 case 0x0000004f: // upd 212 diff 2+,0-
934 case 0x00000b95: // upd 9826 diff 163+,1- diff scale, dangerous
935 case 0x00000ba5: // upd 304 diff 0+,0-
936 case 0x0000157f: // upd 201 diff 2+,0-
937 case 0x0000157d: // upd 197 diff 1+,0-
938 case 0x0000333d: // upd 112 diff 0+,0-
939 case 0x0000333f: // upd 223 diff 10+,0-
940 case 0x000072cd: // upd 8286 diff 98+,0- diff scale
941 case 0x000072ae: // upd 193 diff 10+,0-
942 case 0x000072ec: // upd 319 diff 7+,0-
943 case 0x77303074: // upd 113 diff 3+,0-
944 case 0x10000000: // upd 314 diff 6+,0-
945 check
= CheckEvery20
;
952 if (when_in
&& where_MwcN
&& num
== 0x00000000) {
953 // in ML_(wqthread_continue_NORETURN) 0x00000000
954 // upd 1110 diff 37+,0-
955 check
= CheckEvery20
;
958 if (when_after
&& where_woQR
&& num
== 0x00000000) {
959 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
960 // upd 1099 diff 37+,0-
961 check
= CheckEvery20
;
963 /* if (when_after && where_woQ2 && num == 0x00000000) {
964 // after workq_ops(QUEUE_REQTHREADS2) 0x00000000
965 // upd XXXX diff XX+,0-
966 check = CheckEvery20;
969 if (when_after
&& where_woTR
&& num
== 0x00000000) {
970 // after workq_ops(THREAD_RETURN) 0x00000000
972 check
= CheckEvery20
;
975 if (when_after
&& where_ke64
&& num
== 0x00000000) {
976 // after kevent64 0x00000000
977 // upd 1463 diff 15+,0-
978 check
= CheckEvery20
;
980 /* ----------- END filter for 64-bit 10.10.x ----------- */
981 # endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
983 /* Regardless of what the filter says, force a sync every 1 time in
984 1000, to stop things getting too far out of sync. */
986 static UInt ctr1k
= 0;
988 if ((ctr1k
% 1000) == 0)
992 /* If the filter is disabled, we must always check. */
993 if (VG_(clo_resync_filter
) == 0)
1000 // only resync once every 20th time
1001 static UInt ctr10
= 0;
1003 if ((ctr10
% 20) != 0) return False
;
1012 // --------------- END resync-filter-kludge ---------------
1014 if (0 || VG_(clo_trace_syscalls
)) {
1015 VG_(debugLog
)(0, "syswrap-darwin",
1016 "sync_mappings (%s) (\"%s\", \"%s\", 0x%lx)\n",
1017 show_CheckHowOften(check
), when
, where
, num
);
1020 // 16 is enough for most cases, but small enough that overflow happens
1021 // occasionally and thus the overflow path gets some test coverage.
1025 VG_(free
)(css
); // css is NULL on first iteration; that's ok.
1026 css
= VG_(calloc
)("sys_wrap.sync_mappings",
1027 css_size
, sizeof(ChangedSeg
));
1028 ok
= VG_(get_changed_segments
)(when
, where
, css
, css_size
, &css_used
);
1032 UInt css_added
= 0, css_removed
= 0;
1034 // Now add/remove them.
1035 for (i
= 0; i
< css_used
; i
++) {
1036 ChangedSeg
* cs
= &css
[i
];
1039 ML_(notify_core_and_tool_of_mmap
)(
1040 cs
->start
, cs
->end
- cs
->start
+ 1,
1041 cs
->prot
, VKI_MAP_PRIVATE
, 0, cs
->offset
);
1042 // should this call VG_(di_notify_mmap) also?
1045 ML_(notify_core_and_tool_of_munmap
)(
1046 cs
->start
, cs
->end
- cs
->start
+ 1);
1048 if (VG_(clo_trace_syscalls
)) {
1050 VG_(debugLog
)(0, "syswrap-darwin",
1051 " added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
1052 cs
->start
, cs
->end
+ 1, (UInt
)cs
->prot
, where
, when
);
1054 VG_(debugLog
)(0, "syswrap-darwin",
1055 " removed region 0x%010lx..0x%010lx at %s (%s)\n",
1056 cs
->start
, cs
->end
+ 1, where
, when
);
1064 VG_(debugLog
)(0, "syswrap-darwin", "SYNC: %d %s %s\n",
1065 css_used
, when
, where
);
1067 // Update the stats, so we can derive the filter above.
1069 update_syncstats(check
, when
, where
, num
, css_added
, css_removed
);
1071 return css_used
> 0;
1074 /* ---------------------------------------------------------------------
1076 ------------------------------------------------------------------ */
1078 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
1079 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
1081 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
1082 #define POST_FN(name) vgSysWrap_darwin_##name##_after
1084 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
1085 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
1087 #if VG_WORDSIZE == 4
1088 // Combine two 32-bit values into a 64-bit value
1089 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
1090 # if defined(VGA_x86)
1091 # define LOHI64(lo,hi) ( ((ULong)(UInt)(lo)) | (((ULong)(UInt)(hi)) << 32) )
1093 # error unknown architecture
1097 // Retrieve the current Mach thread
1098 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1100 // Set the POST handler for a mach_msg derivative
1101 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1103 // Set or get values saved from Mach messages
1104 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x
1105 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port
1106 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id
1108 /* ---------------------------------------------------------------------
1109 darwin ioctl wrapper
1110 ------------------------------------------------------------------ */
1114 *flags
|= SfMayBlock
;
1116 /* Handle ioctls that don't take an arg first */
1117 switch (ARG2
/* request */) {
1122 case VKI_TIOCPTYGRANT
:
1123 case VKI_TIOCPTYUNLK
:
1124 case VKI_DTRACEHIOC_REMOVE
:
1126 case VKI_BIOCPROMISC
:
1127 PRINT("ioctl ( %lu, 0x%lx )", ARG1
, ARG2
);
1128 PRE_REG_READ2(long, "ioctl",
1129 unsigned int, fd
, unsigned int, request
);
1132 PRINT("ioctl ( %lu, 0x%lx, %#lx )", ARG1
, ARG2
, ARG3
);
1133 PRE_REG_READ3(long, "ioctl",
1134 unsigned int, fd
, unsigned int, request
, unsigned long, arg
);
1137 switch (ARG2
/* request */) {
1138 case VKI_TIOCGWINSZ
:
1139 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3
, sizeof(struct vki_winsize
) );
1141 case VKI_TIOCSWINSZ
:
1142 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3
, sizeof(struct vki_winsize
) );
1145 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3
, sizeof(unsigned int) );
1148 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3
, sizeof(unsigned int) );
1151 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3
, sizeof(unsigned int) );
1154 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3
, sizeof(unsigned int) );
1157 /* Get process group ID for foreground processing group. */
1158 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3
, sizeof(vki_pid_t
) );
1161 /* Set a process group ID? */
1162 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3
, sizeof(vki_pid_t
) );
1165 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3
, sizeof(int) );
1168 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3
, sizeof(int) );
1170 case VKI_FIONREAD
: /* identical to SIOCINQ */
1171 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3
, sizeof(int) );
1175 /* These all use struct ifreq AFAIK */
1176 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1177 case VKI_SIOCGIFFLAGS
: /* get flags */
1178 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1179 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1180 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3
, sizeof(struct vki_ifreq
));
1182 case VKI_SIOCGIFMTU
: /* get MTU size */
1183 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1184 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1185 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3
, sizeof(struct vki_ifreq
));
1187 case VKI_SIOCGIFADDR
: /* get PA address */
1188 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1189 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1190 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3
, sizeof(struct vki_ifreq
));
1192 case VKI_SIOCGIFNETMASK
: /* get network PA mask */
1193 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1194 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1195 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3
, sizeof(struct vki_ifreq
));
1197 case VKI_SIOCGIFMETRIC
: /* get metric */
1198 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1199 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1200 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3
, sizeof(struct vki_ifreq
));
1202 case VKI_SIOCGIFDSTADDR
: /* get remote PA address */
1203 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1204 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1205 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3
, sizeof(struct vki_ifreq
));
1207 case VKI_SIOCGIFBRDADDR
: /* get broadcast PA address */
1208 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1209 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1210 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3
, sizeof(struct vki_ifreq
));
1212 case VKI_SIOCGIFCONF
: /* get iface list */
1214 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1215 KERNEL_DO_SYSCALL(tid,RES);
1216 if (!VG_(is_kerror)(RES) && RES == 0)
1217 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1219 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1220 (Addr
)&((struct vki_ifconf
*)ARG3
)->ifc_len
,
1221 sizeof(((struct vki_ifconf
*)ARG3
)->ifc_len
));
1222 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1223 (Addr
)&((struct vki_ifconf
*)ARG3
)->vki_ifc_buf
,
1224 sizeof(((struct vki_ifconf
*)ARG3
)->vki_ifc_buf
));
1226 // TODO len must be readable and writable
1227 // buf pointer only needs to be readable
1228 struct vki_ifconf
*ifc
= (struct vki_ifconf
*) ARG3
;
1229 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1230 (Addr
)(ifc
->vki_ifc_buf
), ifc
->ifc_len
);
1234 case VKI_SIOCSIFFLAGS
: /* set flags */
1235 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1236 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1237 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1238 (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_flags
,
1239 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_flags
) );
1241 case VKI_SIOCSIFADDR
: /* set PA address */
1242 case VKI_SIOCSIFDSTADDR
: /* set remote PA address */
1243 case VKI_SIOCSIFBRDADDR
: /* set broadcast PA address */
1244 case VKI_SIOCSIFNETMASK
: /* set network PA mask */
1245 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1246 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1247 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1248 (Addr
)&((struct vki_ifreq
*)ARG3
)->ifr_addr
,
1249 sizeof(((struct vki_ifreq
*)ARG3
)->ifr_addr
) );
1251 case VKI_SIOCSIFMETRIC
: /* set metric */
1252 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1253 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1254 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1255 (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_metric
,
1256 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_metric
) );
1258 case VKI_SIOCSIFMTU
: /* set MTU size */
1259 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1260 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1261 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1262 (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_mtu
,
1263 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_mtu
) );
1265 /* Routing table calls. */
1266 #ifdef VKI_SIOCADDRT
1267 case VKI_SIOCADDRT
: /* add routing table entry */
1268 case VKI_SIOCDELRT
: /* delete routing table entry */
1269 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3
,
1270 sizeof(struct vki_rtentry
));
1275 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3
, sizeof(int) );
1278 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3
, sizeof(int) );
1279 //tst->sys_flags &= ~SfMayBlock;
1283 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3
, sizeof(int) );
1286 case VKI_DTRACEHIOC_ADDDOF
:
1291 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3
, sizeof(struct vki_termios
) );
1294 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3
, sizeof(struct vki_termios
) );
1297 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3
, sizeof(int) );
1300 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3
, sizeof(int) );
1302 case VKI_TIOCPTYGNAME
:
1303 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3
, 128 );
1313 case VKI_BIOCSETF
: /* set BPF filter */
1315 * struct bpf_program has a 32-bit count of instructions,
1316 * followed by a pointer to an array of those instructions.
1317 * In 64-bit mode, there's padding between those two elements.
1319 * So that we don't bogusly complain about the padding bytes,
1320 * we just report that we read bf_len and and bf_insns.
1322 * We then make sure that what bf_insns points to is valid.
1324 PRE_MEM_READ( "ioctl(BIOCSETF)",
1325 (Addr
)&((struct vki_bpf_program
*)ARG3
)->vki_bf_len
,
1326 sizeof(((struct vki_bpf_program
*)ARG3
)->vki_bf_len
) );
1327 PRE_MEM_READ( "ioctl(BIOCSETF)",
1328 (Addr
)&((struct vki_bpf_program
*)ARG3
)->vki_bf_insns
,
1329 sizeof(((struct vki_bpf_program
*)ARG3
)->vki_bf_insns
) );
1331 /* bf_len * sizeof (*bf_insns) */
1332 struct vki_bpf_program
*bp
= (struct vki_bpf_program
*)ARG3
;
1333 if ( bp
->bf_insns
!= NULL
)
1334 PRE_MEM_READ( "ioctl(BIOCSETF) points to a struct bpf_program whose bf_insns member",
1335 (Addr
)(bp
->vki_bf_insns
),
1336 bp
->vki_bf_len
* sizeof(*bp
->vki_bf_insns
) );
1339 case VKI_BIOCSETIF
: /* set BPF interface */
1340 PRE_MEM_RASCIIZ( "ioctl(BIOCSETIF)",
1341 (Addr
)((struct vki_ifreq
*)ARG3
)->vki_ifr_name
);
1343 case VKI_BIOCSRTIMEOUT
: /* set BPF timeout */
1345 * 64-bit struct timeval starts with a 64-bit "seconds since the
1346 * Epoch" value, followed by a 32-bit microseconds value. The
1347 * resulting structure is padded to a multiple of 8 bytes, so
1348 * there are 4 padding bytes at the end.
1350 * So that we don't bogusly complain about the padding bytes,
1351 * we just report that we read tv_sec and tv_usec.
1353 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1354 (Addr
)&((struct vki_timeval
*)ARG3
)->vki_tv_sec
,
1355 sizeof(((struct vki_timeval
*)ARG3
)->vki_tv_sec
) );
1356 PRE_MEM_READ( "ioctl(BIOCSRTIMEOUT)",
1357 (Addr
)&((struct vki_timeval
*)ARG3
)->vki_tv_usec
,
1358 sizeof(((struct vki_timeval
*)ARG3
)->vki_tv_usec
) );
1360 case VKI_BIOCGDLTLIST
: /* get list of BPF DLTs */
1361 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1362 (Addr
)&((struct vki_bpf_dltlist
*)ARG3
)->vki_bfl_list
,
1363 sizeof(((struct vki_bpf_dltlist
*)ARG3
)->vki_bfl_list
) );
1365 /* bfl_len * sizeof (*bfl_list) */
1366 struct vki_bpf_dltlist
*bdl
= (struct vki_bpf_dltlist
*)ARG3
;
1367 if ( bdl
->bfl_list
!= NULL
)
1368 PRE_MEM_READ( "ioctl(BIOCGDLTLIST).bfl_len",
1369 (Addr
)&((struct vki_bpf_dltlist
*)ARG3
)->vki_bfl_len
,
1370 sizeof(((struct vki_bpf_dltlist
*)ARG3
)->vki_bfl_len
) );
1371 PRE_MEM_WRITE( "ioctl(BIOCGDLTLIST) points to a struct bpf_dltlist whose bfl_list member",
1372 (Addr
)(bdl
->vki_bfl_list
),
1373 bdl
->bfl_len
* sizeof(*bdl
->vki_bfl_list
) );
1378 ML_(PRE_unknown_ioctl
)(tid
, ARG2
, ARG3
);
1387 switch (ARG2
/* request */) {
1388 case VKI_TIOCGWINSZ
:
1389 POST_MEM_WRITE( ARG3
, sizeof(struct vki_winsize
) );
1391 case VKI_TIOCSWINSZ
:
1397 POST_MEM_WRITE( ARG3
, sizeof(unsigned int) );
1400 /* Get process group ID for foreground processing group. */
1401 POST_MEM_WRITE( ARG3
, sizeof(vki_pid_t
) );
1404 /* Set a process group ID? */
1405 POST_MEM_WRITE( ARG3
, sizeof(vki_pid_t
) );
1413 case VKI_FIONREAD
: /* identical to SIOCINQ */
1414 POST_MEM_WRITE( ARG3
, sizeof(int) );
1417 /* These all use struct ifreq AFAIK */
1418 case VKI_SIOCGIFFLAGS
: /* get flags */
1419 POST_MEM_WRITE( (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_flags
,
1420 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_flags
) );
1422 case VKI_SIOCGIFMTU
: /* get MTU size */
1423 POST_MEM_WRITE( (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_mtu
,
1424 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_mtu
) );
1426 case VKI_SIOCGIFADDR
: /* get PA address */
1427 case VKI_SIOCGIFDSTADDR
: /* get remote PA address */
1428 case VKI_SIOCGIFBRDADDR
: /* get broadcast PA address */
1429 case VKI_SIOCGIFNETMASK
: /* get network PA mask */
1431 (Addr
)&((struct vki_ifreq
*)ARG3
)->ifr_addr
,
1432 sizeof(((struct vki_ifreq
*)ARG3
)->ifr_addr
) );
1434 case VKI_SIOCGIFMETRIC
: /* get metric */
1436 (Addr
)&((struct vki_ifreq
*)ARG3
)->vki_ifr_metric
,
1437 sizeof(((struct vki_ifreq
*)ARG3
)->vki_ifr_metric
) );
1439 case VKI_SIOCGIFCONF
: /* get iface list */
1441 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1442 KERNEL_DO_SYSCALL(tid,RES);
1443 if (!VG_(is_kerror)(RES) && RES == 0)
1444 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1446 if (RES
== 0 && ARG3
) {
1447 struct vki_ifconf
*ifc
= (struct vki_ifconf
*) ARG3
;
1448 if (ifc
->vki_ifc_buf
!= NULL
)
1449 POST_MEM_WRITE( (Addr
)(ifc
->vki_ifc_buf
), ifc
->ifc_len
);
1453 case VKI_SIOCSIFFLAGS
: /* set flags */
1454 case VKI_SIOCSIFDSTADDR
: /* set remote PA address */
1455 case VKI_SIOCSIFBRDADDR
: /* set broadcast PA address */
1456 case VKI_SIOCSIFNETMASK
: /* set network PA mask */
1457 case VKI_SIOCSIFMETRIC
: /* set metric */
1458 case VKI_SIOCSIFADDR
: /* set PA address */
1459 case VKI_SIOCSIFMTU
: /* set MTU size */
1462 #ifdef VKI_SIOCADDRT
1463 /* Routing table calls. */
1464 case VKI_SIOCADDRT
: /* add routing table entry */
1465 case VKI_SIOCDELRT
: /* delete routing table entry */
1470 POST_MEM_WRITE(ARG3
, sizeof(int));
1476 POST_MEM_WRITE( ARG3
, sizeof(int) );
1479 case VKI_DTRACEHIOC_REMOVE
:
1480 case VKI_DTRACEHIOC_ADDDOF
:
1485 POST_MEM_WRITE( ARG3
, sizeof(struct vki_termios
));
1490 POST_MEM_WRITE( ARG3
, sizeof(int) );
1494 case VKI_TIOCPTYGNAME
:
1495 POST_MEM_WRITE( ARG3
, 128);
1497 case VKI_TIOCSBRK
: /* set break bit */
1498 case VKI_TIOCCBRK
: /* clear break bit */
1499 case VKI_TIOCPTYGRANT
:
1500 case VKI_TIOCPTYUNLK
:
1504 case VKI_BIOCGDLTLIST
: /* get list of BPF DLTs */
1505 if (RES
== 0 && ARG3
) {
1506 /* bfl_len * sizeof (*bfl_list) */
1507 struct vki_bpf_dltlist
*bdl
= (struct vki_bpf_dltlist
*)ARG3
;
1508 if ( bdl
->vki_bfl_list
!= NULL
)
1509 POST_MEM_WRITE( (Addr
)(bdl
->vki_bfl_list
),
1510 bdl
->bfl_len
* sizeof(*bdl
->vki_bfl_list
) );
1515 ML_(POST_unknown_ioctl
)(tid
, RES
, ARG2
, ARG3
);
1521 /* ---------------------------------------------------------------------
1522 darwin fcntl wrapper
1523 ------------------------------------------------------------------ */
1524 static const HChar
*name_for_fcntl(UWord cmd
) {
1525 #define F(n) case VKI_##n: return #n
1533 F(F_GLOBAL_NOCACHE
);
1537 # if DARWIN_VERS < DARWIN_10_9
1539 F(F_WRITEBOOTSTRAP
);
1545 # if DARWIN_VERS >= DARWIN_10_9
1548 # if DARWIN_VERS >= DARWIN_10_11
1549 F(F_ADDFILESIGS_FOR_DYLD_SIM
);
1551 F(F_ADDFILESIGS_RETURN
);
1562 // These ones ignore ARG3.
1566 PRINT("fcntl ( %lu, %lu )", ARG1
,ARG2
);
1567 PRE_REG_READ2(long, "fcntl", unsigned int, fd
, unsigned int, cmd
);
1570 // These ones use ARG3 as "arg".
1575 PRINT("fcntl[ARG3=='arg'] ( %lu, %lu, %lu )", ARG1
,ARG2
,ARG3
);
1576 PRE_REG_READ3(long, "fcntl",
1577 unsigned int, fd
, unsigned int, cmd
, unsigned long, arg
);
1580 // These ones use ARG3 as "lock".
1584 PRINT("fcntl[ARG3=='lock'] ( %lu, %lu, %#lx )", ARG1
,ARG2
,ARG3
);
1585 PRE_REG_READ3(long, "fcntl",
1586 unsigned int, fd
, unsigned int, cmd
,
1587 struct flock64
*, lock
);
1588 // GrP fixme mem read sizeof(flock64)
1589 if (ARG2
== VKI_F_SETLKW
)
1590 *flags
|= SfMayBlock
;
1592 # if DARWIN_VERS >= DARWIN_10_10
1593 case VKI_F_SETLKWTIMEOUT
:
1594 PRINT("fcntl[ARG3=='locktimeout'] ( %lu, %lu, %#lx )", ARG1
,ARG2
,ARG3
);
1595 PRE_REG_READ3(long, "fcntl",
1596 unsigned int, fd
, unsigned int, cmd
,
1597 struct flocktimeout
*, lock
);
1598 *flags
|= SfMayBlock
;
1603 case VKI_F_CHKCLEAN
:
1606 case VKI_F_FULLFSYNC
:
1607 case VKI_F_FREEZE_FS
:
1609 case VKI_F_GLOBAL_NOCACHE
:
1610 PRINT("fcntl ( %lu, %s, %lu )", ARG1
, name_for_fcntl(ARG1
), ARG2
);
1611 PRE_REG_READ2(long, "fcntl", unsigned int, fd
, unsigned int, cmd
);
1615 case VKI_F_PREALLOCATE
:
1616 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1617 PRE_REG_READ3(long, "fcntl",
1618 unsigned int, fd
, unsigned int, cmd
,
1619 struct fstore
*, fstore
);
1621 struct vki_fstore
*fstore
= (struct vki_fstore
*)ARG3
;
1622 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1623 fstore
->fst_flags
);
1624 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1625 fstore
->fst_posmode
);
1626 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1627 fstore
->fst_offset
);
1628 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)",
1629 fstore
->fst_length
);
1630 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)",
1631 fstore
->fst_bytesalloc
);
1637 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1638 PRE_REG_READ3(long, "fcntl",
1639 unsigned int, fd
, unsigned int, cmd
,
1640 vki_off_t
*, offset
);
1644 case VKI_F_RDADVISE
:
1645 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1646 PRE_REG_READ3(long, "fcntl",
1647 unsigned int, fd
, unsigned int, cmd
,
1648 struct vki_radvisory
*, radvisory
);
1650 struct vki_radvisory
*radvisory
= (struct vki_radvisory
*)ARG3
;
1651 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)",
1652 radvisory
->ra_offset
);
1653 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)",
1654 radvisory
->ra_count
);
1658 # if DARWIN_VERS < DARWIN_10_9
1659 // struct fbootstraptransfer
1660 case VKI_F_READBOOTSTRAP
:
1661 case VKI_F_WRITEBOOTSTRAP
:
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 fbootstraptransfer
*, bootstrap
);
1666 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1667 ARG3
, sizeof(struct vki_fbootstraptransfer
) );
1671 // struct log2phys (out)
1672 case VKI_F_LOG2PHYS
:
1673 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1674 PRE_REG_READ3(long, "fcntl",
1675 unsigned int, fd
, unsigned int, cmd
,
1676 struct log2phys
*, l2p
);
1677 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1678 ARG3
, sizeof(struct vki_log2phys
) );
1681 // char[maxpathlen] (out)
1683 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1684 PRE_REG_READ3(long, "fcntl",
1685 unsigned int, fd
, unsigned int, cmd
,
1687 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1688 ARG3
, VKI_MAXPATHLEN
);
1691 // char[maxpathlen] (in)
1692 case VKI_F_PATHPKG_CHECK
:
1693 PRINT("fcntl ( %lu, %s, %#lx '%s')", ARG1
, name_for_fcntl(ARG2
), ARG3
,
1695 PRE_REG_READ3(long, "fcntl",
1696 unsigned int, fd
, unsigned int, cmd
,
1698 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3
);
1701 case VKI_F_ADDSIGS
: /* Add detached signatures (for code signing) */
1702 PRINT("fcntl ( %lu, %s )", ARG1
, name_for_fcntl(ARG2
));
1703 PRE_REG_READ3(long, "fcntl",
1704 unsigned int, fd
, unsigned int, cmd
,
1705 vki_fsignatures_t
*, sigs
);
1708 vki_fsignatures_t
*fsigs
= (vki_fsignatures_t
*)ARG3
;
1709 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1710 fsigs
->fs_blob_start
);
1711 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)",
1712 fsigs
->fs_blob_size
);
1714 if (fsigs
->fs_blob_start
)
1715 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)",
1716 (Addr
)fsigs
->fs_blob_start
, fsigs
->fs_blob_size
);
1720 case VKI_F_ADDFILESIGS
: /* Add signature from same file (used by dyld for shared libs) */
1721 PRINT("fcntl ( %lu, %s, %#lx )", ARG1
, name_for_fcntl(ARG2
), ARG3
);
1722 PRE_REG_READ3(long, "fcntl",
1723 unsigned int, fd
, unsigned int, cmd
,
1724 vki_fsignatures_t
*, sigs
);
1727 vki_fsignatures_t
*fsigs
= (vki_fsignatures_t
*)ARG3
;
1728 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_start)",
1729 fsigs
->fs_blob_start
);
1730 PRE_FIELD_READ( "fcntl(F_ADDFILESIGS, fsigs->fs_blob_size)",
1731 fsigs
->fs_blob_size
);
1735 # if DARWIN_VERS >= DARWIN_10_11
1736 case VKI_F_ADDFILESIGS_FOR_DYLD_SIM
: /* Add signature from same file, only if it is signed
1737 by Apple used by dyld for simulator */
1741 case VKI_F_BARRIERFSYNC
: /* fsync + issue barrier to drive */
1745 case VKI_F_ADDFILESIGS_RETURN
: /* Add signature from same file, return end offset in
1746 structure on success */
1752 PRINT("fcntl ( %lu, %lu [??] )", ARG1
, ARG2
);
1753 log_decaying("UNKNOWN fcntl %lu!", ARG2
);
1763 if (!ML_(fd_allowed
)(RES
, "fcntl(DUPFD)", tid
, True
)) {
1765 SET_STATUS_Failure( VKI_EMFILE
);
1767 if (VG_(clo_track_fds
))
1768 ML_(record_fd_open_named
)(tid
, RES
);
1781 # if DARWIN_VERS >= DARWIN_10_10
1782 case VKI_F_SETLKWTIMEOUT
:
1786 case VKI_F_PREALLOCATE
:
1788 struct vki_fstore
*fstore
= (struct vki_fstore
*)ARG3
;
1789 POST_FIELD_WRITE( fstore
->fst_bytesalloc
);
1793 case VKI_F_LOG2PHYS
:
1794 POST_MEM_WRITE( ARG3
, sizeof(struct vki_log2phys
) );
1798 POST_MEM_WRITE( ARG3
, 1+VG_(strlen
)((char *)ARG3
) );
1799 PRINT("\"%s\"", (char*)ARG3
);
1803 // DDD: ugh, missing lots of cases here, not nice
1808 /* ---------------------------------------------------------------------
1810 ------------------------------------------------------------------ */
1814 PRINT("futimes ( %ld, %#lx )", SARG1
, ARG2
);
1815 PRE_REG_READ2(long, "futimes", int, fd
, struct timeval
*, tvp
);
1816 if (!ML_(fd_allowed
)(ARG1
, "futimes", tid
, False
)) {
1817 SET_STATUS_Failure( VKI_EBADF
);
1818 } else if (ARG2
!= 0) {
1819 PRE_timeval_READ( "futimes(tvp[0])", ARG2
);
1820 PRE_timeval_READ( "futimes(tvp[1])", ARG2
+sizeof(struct vki_timeval
) );
1826 PRINT("semget ( %ld, %ld, %ld )", SARG1
, SARG2
, SARG3
);
1827 PRE_REG_READ3(long, "semget", vki_key_t
, key
, int, nsems
, int, semflg
);
1832 *flags
|= SfMayBlock
;
1833 PRINT("semop ( %ld, %#lx, %lu )", SARG1
, ARG2
, ARG3
);
1834 PRE_REG_READ3(long, "semop",
1835 int, semid
, struct sembuf
*, sops
, vki_size_t
, nsoops
);
1836 ML_(generic_PRE_sys_semop
)(tid
, ARG1
,ARG2
,ARG3
);
1844 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1
, SARG2
, SARG3
, ARG4
);
1845 PRE_REG_READ4(long, "semctl",
1846 int, semid
, int, semnum
, int, cmd
, struct semid_ds
*, arg
);
1850 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1
, SARG2
, SARG3
, ARG4
);
1851 PRE_REG_READ4(long, "semctl",
1852 int, semid
, int, semnum
, int, cmd
, unsigned short *, arg
);
1855 PRINT("semctl ( %ld, %ld, %ld, %#lx )", SARG1
, SARG2
, SARG3
, ARG4
);
1856 PRE_REG_READ4(long, "semctl",
1857 int, semid
, int, semnum
, int, cmd
, int, arg
);
1860 PRINT("semctl ( %ld, %ld, %ld )", SARG1
, SARG2
, SARG3
);
1861 PRE_REG_READ3(long, "semctl",
1862 int, semid
, int, semnum
, int, cmd
);
1865 ML_(generic_PRE_sys_semctl
)(tid
, ARG1
,ARG2
,ARG3
,ARG4
);
1869 ML_(generic_POST_sys_semctl
)(tid
, RES
,ARG1
,ARG2
,ARG3
,ARG4
);
1874 if (ARG2
& VKI_O_CREAT
) {
1876 PRINT("sem_open ( %#lx(%s), %ld, %lu, %lu )",
1877 ARG1
, (HChar
*)ARG1
, SARG2
, ARG3
, ARG4
);
1878 PRE_REG_READ4(vki_sem_t
*, "sem_open",
1879 const char *, name
, int, oflag
, vki_mode_t
, mode
,
1880 unsigned int, value
);
1883 PRINT("sem_open ( %#lx(%s), %ld )", ARG1
, (HChar
*)ARG1
, SARG2
);
1884 PRE_REG_READ2(vki_sem_t
*, "sem_open",
1885 const char *, name
, int, oflag
);
1887 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1
);
1889 /* Otherwise handle normally */
1890 *flags
|= SfMayBlock
;
1895 PRINT("sem_close( %#lx )", ARG1
);
1896 PRE_REG_READ1(int, "sem_close", vki_sem_t
*, sem
);
1901 PRINT("sem_unlink( %#lx(%s) )", ARG1
, (HChar
*)ARG1
);
1902 PRE_REG_READ1(int, "sem_unlink", const char *, name
);
1903 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1
);
1908 PRINT("sem_post( %#lx )", ARG1
);
1909 PRE_REG_READ1(int, "sem_post", vki_sem_t
*, sem
);
1910 *flags
|= SfMayBlock
;
1915 PRINT("sem_destroy( %#lx )", ARG1
);
1916 PRE_REG_READ1(int, "sem_destroy", vki_sem_t
*, sem
);
1917 PRE_MEM_READ("sem_destroy(sem)", ARG1
, sizeof(vki_sem_t
));
1922 PRINT("sem_init( %#lx, %ld, %lu )", ARG1
, SARG2
, ARG3
);
1923 PRE_REG_READ3(int, "sem_init", vki_sem_t
*, sem
,
1924 int, pshared
, unsigned int, value
);
1925 PRE_MEM_WRITE("sem_init(sem)", ARG1
, sizeof(vki_sem_t
));
1930 POST_MEM_WRITE(ARG1
, sizeof(vki_sem_t
));
1935 PRINT("sem_wait( %#lx )", ARG1
);
1936 PRE_REG_READ1(int, "sem_wait", vki_sem_t
*, sem
);
1937 *flags
|= SfMayBlock
;
1942 PRINT("sem_trywait( %#lx )", ARG1
);
1943 PRE_REG_READ1(int, "sem_trywait", vki_sem_t
*, sem
);
1944 *flags
|= SfMayBlock
;
1954 if (!ML_(fd_allowed
)(RES
, "kqueue", tid
, True
)) {
1956 SET_STATUS_Failure( VKI_EMFILE
);
1958 if (VG_(clo_track_fds
)) {
1959 ML_(record_fd_open_with_given_name
)(tid
, RES
, NULL
);
1964 PRE(fileport_makeport
)
1966 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1970 PRE(guarded_open_np
)
1972 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1973 ARG1
, (char*)ARG1
, ARG2
, ARG3
, ARG4
);
1976 PRE(guarded_kqueue_np
)
1978 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1982 POST(guarded_kqueue_np
)
1984 if (!ML_(fd_allowed
)(RES
, "guarded_kqueue_np", tid
, True
)) {
1986 SET_STATUS_Failure( VKI_EMFILE
);
1988 if (VG_(clo_track_fds
)) {
1989 ML_(record_fd_open_with_given_name
)(tid
, RES
, NULL
);
1994 PRE(guarded_close_np
)
1996 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
2000 PRE(change_fdguard_np
)
2002 PRINT("change_fdguard_np(fd:%#lx, guard:%#lx, guardflags:%#lx, nguard:%#lx, nguardflags:%#lx, fdflagsp:%#lx) FIXME",
2003 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
);
2008 PRINT("connectx(s:%#lx, src:%#lx, srclen:%#lx, dsts:%#lx, dstlen:%#lx, ifscope:%#lx, aid:%#lx, out_cid:%#lx) FIXME",
2009 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
, ARG8
);
2014 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
2021 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2022 SARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
);
2023 PRE_REG_READ6(int,"kevent", int,kq
,
2024 const struct vki_kevent
*,changelist
, int,nchanges
,
2025 struct vki_kevent
*,eventlist
, int,nevents
,
2026 const struct vki_timespec
*,timeout
);
2028 if (ARG3
) PRE_MEM_READ ("kevent(changelist)",
2029 ARG2
, ARG3
* sizeof(struct vki_kevent
));
2030 if (ARG5
) PRE_MEM_WRITE("kevent(eventlist)",
2031 ARG4
, ARG5
* sizeof(struct vki_kevent
));
2032 if (ARG6
) PRE_MEM_READ ("kevent(timeout)",
2033 ARG6
, sizeof(struct vki_timespec
));
2035 *flags
|= SfMayBlock
;
2040 PRINT("kevent ret %ld dst %#lx (%zu)", RES
, ARG4
, sizeof(struct vki_kevent
));
2041 if (RES
> 0) POST_MEM_WRITE(ARG4
, RES
* sizeof(struct vki_kevent
));
2047 PRINT("kevent64( %ld, %#lx, %ld, %#lx, %ld, %#lx )",
2048 SARG1
, ARG2
, SARG3
, ARG4
, SARG5
, ARG6
);
2049 PRE_REG_READ6(int,"kevent64", int,kq
,
2050 const struct vki_kevent64
*,changelist
, int,nchanges
,
2051 struct vki_kevent64
*,eventlist
, int,nevents
,
2052 const struct vki_timespec
*,timeout
);
2054 if (ARG3
) PRE_MEM_READ ("kevent64(changelist)",
2055 ARG2
, ARG3
* sizeof(struct vki_kevent64
));
2056 if (ARG5
) PRE_MEM_WRITE("kevent64(eventlist)",
2057 ARG4
, ARG5
* sizeof(struct vki_kevent64
));
2058 if (ARG6
) PRE_MEM_READ ("kevent64(timeout)",
2059 ARG6
, sizeof(struct vki_timespec
));
2061 *flags
|= SfMayBlock
;
2066 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES
, ARG4
, sizeof(struct vki_kevent64
));
2068 ML_(sync_mappings
)("after", "kevent64", 0);
2069 POST_MEM_WRITE(ARG4
, RES
* sizeof(struct vki_kevent64
));
2074 Addr pthread_starter
= 0;
2075 Addr wqthread_starter
= 0;
2076 SizeT pthread_structsize
= 0;
2078 PRE(bsdthread_register
)
2080 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1
, ARG2
, ARG3
);
2081 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart",
2082 void *,"wqthread", size_t,"pthsize");
2084 pthread_starter
= ARG1
;
2085 wqthread_starter
= ARG2
;
2086 pthread_structsize
= ARG3
;
2087 ARG1
= (Word
)&pthread_hijack_asm
;
2088 ARG2
= (Word
)&wqthread_hijack_asm
;
2093 PRINT("workq_open()");
2094 PRE_REG_READ0(int, "workq_open");
2096 // This creates lots of threads and thread stacks under the covers,
2097 // but we ignore them all until some work item starts running on it.
2100 static const HChar
*workqop_name(int op
)
2103 case VKI_WQOPS_QUEUE_ADD
: return "QUEUE_ADD";
2104 case VKI_WQOPS_QUEUE_REMOVE
: return "QUEUE_REMOVE";
2105 case VKI_WQOPS_THREAD_RETURN
: return "THREAD_RETURN";
2106 case VKI_WQOPS_THREAD_SETCONC
: return "THREAD_SETCONC";
2107 case VKI_WQOPS_QUEUE_NEWSPISUPP
: return "QUEUE_NEWSPISUPP";
2108 case VKI_WQOPS_QUEUE_REQTHREADS
: return "QUEUE_REQTHREADS";
2109 case VKI_WQOPS_QUEUE_REQTHREADS2
: return "QUEUE_REQTHREADS2";
2110 case VKI_WQOPS_THREAD_KEVENT_RETURN
: return "THREAD_KEVENT_RETURN";
2111 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY
: return "SET_EVENT_MANAGER_PRIORITY";
2112 case VKI_WQOPS_THREAD_WORKLOOP_RETURN
: return "THREAD_WORKLOOP_RETURN";
2113 case VKI_WQOPS_SHOULD_NARROW
: return "SHOULD_NARROW";
2114 default: return "?";
2121 PRINT("workq_ops( %ld(%s), %#lx, %ld )", SARG1
, workqop_name(ARG1
), ARG2
,
2123 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2127 case VKI_WQOPS_QUEUE_ADD
:
2128 case VKI_WQOPS_QUEUE_REMOVE
:
2129 // GrP fixme need anything here?
2130 // GrP fixme may block?
2132 case VKI_WQOPS_THREAD_RETURN
: {
2133 // The interesting case. The kernel will do one of two things:
2134 // 1. Return normally. We continue; libc proceeds to stop the thread.
2135 // V does nothing special here.
2136 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2137 // new work item, and never returns from workq_ops.
2138 // V handles this by longjmp() from wqthread_hijack back to the
2139 // scheduler, which continues at the new client SP/IP/state.
2140 // This works something like V's signal handling.
2141 // To the tool, this looks like workq_ops() sometimes returns
2142 // to a strange address.
2143 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
2144 tst
->os_state
.wq_jmpbuf_valid
= True
;
2145 *flags
|= SfMayBlock
; // GrP fixme true?
2148 case VKI_WQOPS_THREAD_SETCONC
:
2149 // RK fixme need anything here?
2150 // RK fixme may block?
2152 case VKI_WQOPS_QUEUE_NEWSPISUPP
:
2153 // JRS don't think we need to do anything here -- this just checks
2154 // whether some newer functionality is supported
2156 case VKI_WQOPS_QUEUE_REQTHREADS
:
2157 case VKI_WQOPS_QUEUE_REQTHREADS2
:
2158 // JRS uh, looks like it queues up a bunch of threads, or some such?
2159 *flags
|= SfMayBlock
; // the kernel sources take a spinlock, so play safe
2161 case VKI_WQOPS_THREAD_KEVENT_RETURN
:
2162 // RK fixme need anything here?
2163 // perhaps similar to VKI_WQOPS_THREAD_RETURN above?
2165 case VKI_WQOPS_SET_EVENT_MANAGER_PRIORITY
:
2166 // RK fixme this just sets scheduling priorities - don't think we need
2167 // to do anything here
2169 case VKI_WQOPS_THREAD_WORKLOOP_RETURN
:
2170 case VKI_WQOPS_SHOULD_NARROW
:
2171 // RK fixme need anything here?
2172 // RK fixme may block?
2175 VG_(printf
)("UNKNOWN workq_ops option %ld\n", ARG1
);
2181 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
2182 tst
->os_state
.wq_jmpbuf_valid
= False
;
2184 case VKI_WQOPS_THREAD_RETURN
:
2185 ML_(sync_mappings
)("after", "workq_ops(THREAD_RETURN)", 0);
2187 case VKI_WQOPS_QUEUE_REQTHREADS
:
2188 ML_(sync_mappings
)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2190 case VKI_WQOPS_QUEUE_REQTHREADS2
:
2191 ML_(sync_mappings
)("after", "workq_ops(QUEUE_REQTHREADS2)", 0);
2202 PRINT("__mac_syscall( %#lx(%s), %ld, %#lx )",
2203 ARG1
, (HChar
*)ARG1
, SARG2
, ARG3
);
2204 PRE_REG_READ3(int,"__mac_syscall", char *,"policy",
2205 int,"call", void *,"arg");
2207 // GrP fixme check call's arg?
2208 // GrP fixme check policy?
2212 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2213 More like syswrap-generic's sys_exit_group. */
2219 PRINT("darwin exit( %ld )", SARG1
);
2220 PRE_REG_READ1(void, "exit", int, status
);
2222 tst
= VG_(get_ThreadState
)(tid
);
2224 /* A little complex; find all the threads with the same threadgroup
2225 as this one (including this one), and mark them to exit */
2226 for (t
= 1; t
< VG_N_THREADS
; t
++) {
2227 if ( /* not alive */
2228 VG_(threads
)[t
].status
== VgTs_Empty
2229 /* GrP fixme zombie? */
2233 VG_(threads
)[t
].exitreason
= VgSrc_ExitProcess
;
2234 VG_(threads
)[t
].os_state
.exitcode
= ARG1
;
2237 VG_(get_thread_out_of_syscall
)(t
); /* unblock it, if blocked */
2240 /* We have to claim the syscall already succeeded. */
2241 SET_STATUS_Success(0);
2247 PRINT("sigaction ( %ld, %#lx, %#lx )", SARG1
, ARG2
, ARG3
);
2248 PRE_REG_READ3(long, "sigaction",
2249 int, signum
, vki_sigaction_toK_t
*, act
,
2250 vki_sigaction_fromK_t
*, oldact
);
2253 vki_sigaction_toK_t
*sa
= (vki_sigaction_toK_t
*)ARG2
;
2254 PRE_MEM_READ( "sigaction(act->sa_handler)",
2255 (Addr
)&sa
->ksa_handler
, sizeof(sa
->ksa_handler
));
2256 PRE_MEM_READ( "sigaction(act->sa_mask)",
2257 (Addr
)&sa
->sa_mask
, sizeof(sa
->sa_mask
));
2258 PRE_MEM_READ( "sigaction(act->sa_flags)",
2259 (Addr
)&sa
->sa_flags
, sizeof(sa
->sa_flags
));
2262 PRE_MEM_WRITE( "sigaction(oldact)",
2263 ARG3
, sizeof(vki_sigaction_fromK_t
));
2265 SET_STATUS_from_SysRes(
2266 VG_(do_sys_sigaction
)(ARG1
, (const vki_sigaction_toK_t
*)ARG2
,
2267 (vki_sigaction_fromK_t
*)ARG3
)
2273 if (RES
== 0 && ARG3
!= 0)
2274 POST_MEM_WRITE( ARG3
, sizeof(vki_sigaction_fromK_t
));
2280 PRINT("__pthread_kill ( %#lx, %ld )", ARG1
, SARG2
);
2281 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t
*, thread
, int, sig
);
2285 PRE(__pthread_sigmask
)
2287 // arguments are identical to sigprocmask (how, sigset_t*, sigset_t*).
2289 PRINT("__pthread_sigmask ( %ld, %#lx, %#lx )", SARG1
, ARG2
, ARG3
);
2290 PRE_REG_READ3(long, "__pthread_sigmask",
2291 int, how
, vki_sigset_t
*, set
, vki_sigset_t
*, oldset
);
2293 PRE_MEM_READ( "__pthread_sigmask(set)", ARG2
, sizeof(vki_sigset_t
));
2295 PRE_MEM_WRITE( "__pthread_sigmask(oldset)", ARG3
, sizeof(vki_sigset_t
));
2297 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
2298 value of 'how' is irrelevant, and it appears that Darwin's libc
2299 passes zero, which is not equal to any of
2300 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
2301 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
2302 value independently of the other args. Solution: in this case,
2303 simply pass a valid (but irrelevant) value for 'how'. */
2304 /* Also, in this case the new set is passed to the kernel by
2305 reference, not value, as in some other sigmask related Darwin
2308 if (ARG2
== 0 /* the new-set is NULL */
2309 && ARG1
!= VKI_SIG_BLOCK
2310 && ARG1
!= VKI_SIG_UNBLOCK
&& ARG1
!= VKI_SIG_SETMASK
) {
2311 arg1
= VKI_SIG_SETMASK
;
2313 SET_STATUS_from_SysRes(
2314 VG_(do_sys_sigprocmask
) ( tid
, arg1
, (vki_sigset_t
*)ARG2
,
2315 (vki_sigset_t
*)ARG3
)
2319 *flags
|= SfPollAfter
;
2321 POST(__pthread_sigmask
)
2324 if (RES
== 0 && ARG3
!= 0)
2325 POST_MEM_WRITE( ARG3
, sizeof(vki_sigset_t
));
2329 PRE(__pthread_canceled
)
2331 *flags
|= SfMayBlock
; /* might kill this thread??? */
2332 /* I don't think so -- I think it just changes the cancellation
2333 state. But taking no chances. */
2334 PRINT("__pthread_canceled ( %#lx )", ARG1
);
2335 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1
);
2339 PRE(__pthread_markcancel
)
2341 *flags
|= SfMayBlock
; /* might kill this thread??? */
2342 PRINT("__pthread_markcancel ( %#lx )", ARG1
);
2343 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1
);
2344 /* Just let it go through. No idea if this is correct. */
2348 PRE(__disable_threadsignal
)
2351 PRINT("__disable_threadsignal(%ld, %ld, %ld)", SARG1
, SARG2
, SARG3
);
2352 /* I don't think this really looks at its arguments. So don't
2353 bother to check them. */
2355 VG_(sigfillset
)( &set
);
2356 SET_STATUS_from_SysRes(
2357 VG_(do_sys_sigprocmask
) ( tid
, VKI_SIG_BLOCK
, &set
, NULL
)
2360 /* We don't expect that blocking all signals for this thread could
2361 cause any more to be delivered (how could it?), but just in case
2364 *flags
|= SfPollAfter
;
2368 PRE(__pthread_chdir
)
2370 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1
, (HChar
*)ARG1
);
2371 PRE_REG_READ1(long, "__pthread_chdir", const char *, path
);
2372 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1
);
2377 PRE(__pthread_fchdir
)
2379 PRINT("__pthread_fchdir ( %lu )", ARG1
);
2380 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd
);
2386 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2387 SARG1
, SARG2
, SARG3
, SARG4
, SARG5
, SARG6
);
2389 Don't check anything - some clients pass fewer arguments.
2390 PRE_REG_READ6(long, "kdebug_trace",
2391 int,"code", int,"arg1", int,"arg2",
2392 int,"arg3", int,"arg4", int,"arg5");
2399 PRINT("seteuid(%lu)", ARG1
);
2400 PRE_REG_READ1(long, "seteuid", vki_uid_t
, "uid");
2406 PRINT("setegid(%lu)", ARG1
);
2407 PRE_REG_READ1(long, "setegid", vki_uid_t
, "uid");
2412 PRINT("settid(%lu, %lu)", ARG1
, ARG2
);
2413 PRE_REG_READ2(long, "settid", vki_uid_t
, "uid", vki_gid_t
, "gid");
2419 PRE_REG_READ0(long, gettid
);
2422 /* XXX need to check whether we need POST operations for
2423 * waitevent, watchevent, modwatch -- jpeach
2427 PRINT("watchevent(%#lx, %#lx)", ARG1
, ARG2
);
2428 PRE_REG_READ2(long, "watchevent",
2429 vki_eventreq
*, "event", unsigned int, "eventmask");
2431 PRE_MEM_READ("watchevent(event)", ARG1
, sizeof(vki_eventreq
));
2432 PRE_MEM_READ("watchevent(eventmask)", ARG2
, sizeof(unsigned int));
2433 *flags
|= SfMayBlock
;
2436 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
2439 PRINT("waitevent(%#lx, %#lx)", ARG1
, ARG2
);
2440 PRE_REG_READ2(long, "waitevent",
2441 vki_eventreq
*, "event", struct timeval
*, "timeout");
2442 PRE_MEM_WRITE("waitevent(event)", ARG1
, sizeof(vki_eventreq
));
2444 if (ARG2
&& ARG2
!= WAITEVENT_FAST_POLL
) {
2445 PRE_timeval_READ("waitevent(timeout)", ARG2
);
2448 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2449 *flags
|= SfMayBlock
;
2454 POST_MEM_WRITE(ARG1
, sizeof(vki_eventreq
));
2459 PRINT("modwatch(%#lx, %#lx)", ARG1
, ARG2
);
2460 PRE_REG_READ2(long, "modwatch",
2461 vki_eventreq
*, "event", unsigned int, "eventmask");
2463 PRE_MEM_READ("modwatch(event)", ARG1
, sizeof(vki_eventreq
));
2464 PRE_MEM_READ("modwatch(eventmask)", ARG2
, sizeof(unsigned int));
2469 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2470 ARG1
, (HChar
*)ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
, ARG5
, SARG6
);
2472 PRE_REG_READ6(vki_ssize_t
, "getxattr",
2473 const char *, path
, char *, name
, void *, value
,
2474 vki_size_t
, size
, uint32_t, position
, int, options
);
2475 PRE_MEM_RASCIIZ("getxattr(path)", ARG1
);
2476 PRE_MEM_RASCIIZ("getxattr(name)", ARG2
);
2478 PRE_MEM_WRITE( "getxattr(value)", ARG3
, ARG4
);
2483 vg_assert((vki_ssize_t
)RES
>= 0);
2485 POST_MEM_WRITE(ARG3
, (vki_ssize_t
)RES
);
2490 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2491 SARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
, ARG5
, SARG6
);
2493 PRE_REG_READ6(vki_ssize_t
, "fgetxattr",
2494 int, fd
, char *, name
, void *, value
,
2495 vki_size_t
, size
, uint32_t, position
, int, options
);
2496 PRE_MEM_RASCIIZ("getxattr(name)", ARG2
);
2497 PRE_MEM_WRITE( "getxattr(value)", ARG3
, ARG4
);
2502 vg_assert((vki_ssize_t
)RES
>= 0);
2503 POST_MEM_WRITE(ARG3
, (vki_ssize_t
)RES
);
2508 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2509 ARG1
, (HChar
*)ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
, ARG5
, SARG6
);
2510 PRE_REG_READ6(int, "setxattr",
2511 const char *,"path", char *,"name", void *,"value",
2512 vki_size_t
,"size", uint32_t,"position", int,"options" );
2514 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1
);
2515 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2
);
2516 PRE_MEM_READ( "setxattr(value)", ARG3
, ARG4
);
2522 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2523 SARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
, ARG5
, SARG6
);
2524 PRE_REG_READ6(int, "fsetxattr",
2525 int,"fd", char *,"name", void *,"value",
2526 vki_size_t
,"size", uint32_t,"position", int,"options" );
2528 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2
);
2529 PRE_MEM_READ( "fsetxattr(value)", ARG3
, ARG4
);
2535 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2536 ARG1
, (HChar
*)ARG1
, ARG2
, (HChar
*)ARG2
, SARG3
);
2537 PRE_REG_READ3(int, "removexattr",
2538 const char*, "path", char*, "attrname", int, "options");
2539 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1
);
2540 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2
);
2546 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2547 SARG1
, ARG2
, (HChar
*)ARG2
, SARG3
);
2548 PRE_REG_READ3(int, "fremovexattr",
2549 int, "fd", char*, "attrname", int, "options");
2550 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2
);
2556 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2557 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, SARG4
);
2558 PRE_REG_READ4 (long, "listxattr",
2559 const char *,"path", char *,"namebuf",
2560 vki_size_t
,"size", int,"options" );
2562 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1
);
2563 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2
, ARG3
);
2564 *flags
|= SfMayBlock
;
2569 vg_assert((vki_ssize_t
)RES
>= 0);
2570 POST_MEM_WRITE( ARG2
, (vki_ssize_t
)RES
);
2576 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2577 SARG1
, ARG2
, ARG3
, SARG4
);
2578 PRE_REG_READ4 (long, "flistxattr",
2579 int, "fd", char *,"namebuf",
2580 vki_size_t
,"size", int,"options" );
2581 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2
, ARG3
);
2582 *flags
|= SfMayBlock
;
2587 vg_assert((vki_ssize_t
)RES
>= 0);
2588 POST_MEM_WRITE( ARG2
, (vki_ssize_t
)RES
);
2595 PRINT("shmat ( %ld, %#lx, %ld )", SARG1
, ARG2
, SARG3
);
2596 PRE_REG_READ3(long, "shmat",
2597 int, shmid
, const void *, shmaddr
, int, shmflg
);
2598 arg2tmp
= ML_(generic_PRE_sys_shmat
)(tid
, ARG1
,ARG2
,ARG3
);
2600 SET_STATUS_Failure( VKI_EINVAL
);
2602 ARG2
= arg2tmp
; // used in POST
2606 ML_(generic_POST_sys_shmat
)(tid
, RES
,ARG1
,ARG2
,ARG3
);
2611 PRINT("shmctl ( %ld, %ld, %#lx )", SARG1
, SARG2
, ARG3
);
2612 PRE_REG_READ3(long, "shmctl",
2613 int, shmid
, int, cmd
, struct vki_shmid_ds
*, buf
);
2614 ML_(generic_PRE_sys_shmctl
)(tid
, ARG1
,ARG2
,ARG3
);
2618 ML_(generic_POST_sys_shmctl
)(tid
, RES
,ARG1
,ARG2
,ARG3
);
2623 PRINT("shmdt ( %#lx )",ARG1
);
2624 PRE_REG_READ1(long, "shmdt", const void *, shmaddr
);
2625 if (!ML_(generic_PRE_sys_shmdt
)(tid
, ARG1
))
2626 SET_STATUS_Failure( VKI_EINVAL
);
2630 ML_(generic_POST_sys_shmdt
)(tid
, RES
,ARG1
);
2635 PRINT("shmget ( %ld, %lu, %ld )", SARG1
, ARG2
, SARG3
);
2636 PRE_REG_READ3(long, "shmget", vki_key_t
, key
, vki_size_t
, size
, int, shmflg
);
2641 PRINT("shm_open(%#lx(%s), %ld, %lu)", ARG1
, (HChar
*)ARG1
, SARG2
, ARG3
);
2642 PRE_REG_READ3(long, "shm_open",
2643 const char *,"name", int,"flags", vki_mode_t
,"mode");
2645 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1
);
2647 *flags
|= SfMayBlock
;
2652 if (!ML_(fd_allowed
)(RES
, "shm_open", tid
, True
)) {
2654 SET_STATUS_Failure( VKI_EMFILE
);
2656 if (VG_(clo_track_fds
))
2657 ML_(record_fd_open_with_given_name
)(tid
, RES
, (HChar
*)ARG1
);
2663 *flags
|= SfMayBlock
;
2664 PRINT("shm_unlink ( %#lx(%s) )", ARG1
, (HChar
*)ARG1
);
2665 PRE_REG_READ1(long, "shm_unlink", const char *, pathname
);
2666 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1
);
2670 /* My reading of the man page suggests that a call may cause memory
2671 mappings to change: "if no references exist at the time of the
2672 call to shm_unlink(), the resources are reclaimed immediately".
2673 So we need to resync here, sigh. */
2674 ML_(sync_mappings
)("after", "shm_unlink", 0);
2679 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2680 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
2681 PRE_REG_READ4(int, "stat_extended", char *, file_name
, struct stat
*, buf
,
2682 void *, fsacl
, vki_size_t
*, fsacl_size
);
2683 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1
);
2684 PRE_MEM_WRITE( "stat_extended(buf)", ARG2
, sizeof(struct vki_stat
) );
2685 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2686 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2687 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2691 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat
) );
2692 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2693 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2694 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2700 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2701 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
2702 PRE_REG_READ4(int, "lstat_extended", char *, file_name
, struct stat
*, buf
,
2703 void *, fsacl
, vki_size_t
*, fsacl_size
);
2704 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1
);
2705 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2
, sizeof(struct vki_stat
) );
2706 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2707 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2708 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2710 POST(lstat_extended
)
2712 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat
) );
2713 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2714 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2715 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2721 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2722 SARG1
, ARG2
, ARG3
, ARG4
);
2723 PRE_REG_READ4(int, "fstat_extended", int, fd
, struct stat
*, buf
,
2724 void *, fsacl
, vki_size_t
*, fsacl_size
);
2725 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2
, sizeof(struct vki_stat
) );
2726 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2727 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2728 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2730 POST(fstat_extended
)
2732 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat
) );
2733 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2734 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2735 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2739 PRE(stat64_extended
)
2741 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2742 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
2743 PRE_REG_READ4(int, "stat64_extended", char *, file_name
, struct stat64
*, buf
,
2744 void *, fsacl
, vki_size_t
*, fsacl_size
);
2745 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1
);
2746 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2
, sizeof(struct vki_stat64
) );
2747 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2748 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2749 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2751 POST(stat64_extended
)
2753 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
2754 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2755 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2756 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2760 PRE(lstat64_extended
)
2762 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2763 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
2764 PRE_REG_READ4(int, "lstat64_extended", char *, file_name
, struct stat64
*, buf
,
2765 void *, fsacl
, vki_size_t
*, fsacl_size
);
2766 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1
);
2767 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2
, sizeof(struct vki_stat64
) );
2768 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2769 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2770 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2772 POST(lstat64_extended
)
2774 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
2775 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2776 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2777 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2781 PRE(fstat64_extended
)
2783 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2784 SARG1
, ARG2
, ARG3
, ARG4
);
2785 PRE_REG_READ4(int, "fstat64_extended", int, fd
, struct stat64
*, buf
,
2786 void *, fsacl
, vki_size_t
*, fsacl_size
);
2787 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2
, sizeof(struct vki_stat64
) );
2788 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2789 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3
, *(vki_size_t
*)ARG4
);
2790 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4
, sizeof(vki_size_t
) );
2792 POST(fstat64_extended
)
2794 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
2795 if (ML_(safe_to_deref
)( (void*)ARG4
, sizeof(vki_size_t
) ))
2796 POST_MEM_WRITE( ARG3
, *(vki_size_t
*)ARG4
);
2797 POST_MEM_WRITE( ARG4
, sizeof(vki_size_t
) );
2801 PRE(fchmod_extended
)
2803 /* DDD: Note: this is not really correct. Handling of
2804 chmod_extended is broken in the same way. */
2805 PRINT("fchmod_extended ( %lu, %lu, %lu, %lu, %#lx )",
2806 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
2807 PRE_REG_READ5(long, "fchmod_extended",
2808 unsigned int, fildes
,
2812 void* /*really,user_addr_t*/, xsecurity
);
2813 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2814 is just way wrong. [The trouble is with the size, which depends on a
2815 non-trival kernel computation] */
2817 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5
,
2818 sizeof(struct vki_kauth_filesec
) );
2824 /* DDD: Note: this is not really correct. Handling of
2825 fchmod_extended is broken in the same way. */
2826 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2827 ARG1
, ARG1
? (HChar
*)ARG1
: "(null)", ARG2
, ARG3
, ARG4
, ARG5
);
2828 PRE_REG_READ5(long, "chmod_extended",
2829 unsigned int, fildes
,
2833 void* /*really,user_addr_t*/, xsecurity
);
2834 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1
);
2835 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2836 is just way wrong. [The trouble is with the size, which depends on a
2837 non-trival kernel computation] */
2839 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5
,
2840 sizeof(struct vki_kauth_filesec
) );
2846 /* DDD: Note: this is not really correct. Handling of
2847 {,f}chmod_extended is broken in the same way. */
2848 PRINT("open_extended ( %#lx(%s), %ld, %lu, %lu, %lu, %#lx )",
2849 ARG1
, ARG1
? (HChar
*)ARG1
: "(null)",
2850 SARG2
, ARG3
, ARG4
, ARG5
, ARG6
);
2851 PRE_REG_READ6(long, "open_extended",
2857 void* /*really,user_addr_t*/, xsecurity
);
2858 PRE_MEM_RASCIIZ("open_extended(path)", ARG1
);
2859 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2860 is just way wrong. [The trouble is with the size, which depends on a
2861 non-trival kernel computation] */
2863 PRE_MEM_READ( "open_extended(xsecurity)", ARG6
,
2864 sizeof(struct vki_kauth_filesec
) );
2867 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2868 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2869 // by one or more strings. Each accessx_descriptor contains a field,
2870 // 'ad_name_offset', which points to one of the strings (or it can contain
2871 // zero which means "reuse the string from the previous accessx_descriptor").
2873 // What's really ridiculous is that we are only given the size of the overall
2874 // buffer, not the number of accessx_descriptors, nor the number of strings.
2875 // The kernel determines the number of accessx_descriptors by walking through
2876 // them one by one, checking that the ad_name_offset points within the buffer,
2877 // past the current point (or that it's a zero, unless its the first
2878 // descriptor); if so, we assume that this really is an accessx_descriptor,
2879 // if not, we assume we've hit the strings section. Gah.
2881 // This affects us here because number of entries in the 'results' buffer is
2882 // determined by the number of accessx_descriptors. So we have to know that
2883 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2884 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2885 // computation after the syscall has succeeded, because the kernel will have
2886 // checked for all the zillion different ways this syscall can fail, and we'll
2887 // know we have a well-formed 'entries' buffer. This means we might miss some
2888 // uses of unaddressable memory but oh well.
2890 PRE(access_extended
)
2892 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2893 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
2894 // XXX: the accessx_descriptor struct contains padding, so this can cause
2895 // unnecessary undefined value errors. But you arguably shouldn't be
2896 // passing undefined values to the kernel anyway...
2897 PRE_REG_READ4(int, "access_extended", void *, entries
, vki_size_t
, size
,
2898 vki_errno_t
*, results
, vki_uid_t
*, uid
);
2899 PRE_MEM_READ("access_extended(entries)", ARG1
, ARG2
);
2901 // XXX: as mentioned above, this check is too hard to do before the
2903 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2905 POST(access_extended
)
2907 // 'n_descs' is the number of descriptors we think are in the buffer. We
2908 // start with the maximum possible value, which occurs if we have the
2909 // shortest possible string section. The shortest string section allowed
2910 // consists of a single one-char string (plus the NUL char). Hence the
2912 struct vki_accessx_descriptor
* entries
= (struct vki_accessx_descriptor
*)ARG1
;
2914 Int n_descs
= (size
- 2) / sizeof(struct accessx_descriptor
);
2915 Int i
; // Current position in the descriptors section array.
2916 Int u
; // Upper bound on the length of the descriptors array
2917 // (recomputed each time around the loop)
2918 vg_assert(n_descs
> 0);
2920 // Step through the descriptors, lowering 'n_descs' until we know we've
2921 // reached the string section.
2922 for (i
= 0; True
; i
++) {
2923 // If we're past our estimate, we must be one past the end of the
2924 // descriptors section (ie. at the start of the string section). Stop.
2928 // Get the array index for the string, but pretend momentarily that it
2929 // is actually another accessx_descriptor. That gives us an upper bound
2930 // on the length of the descriptors section. (Unless the index is zero,
2931 // in which case we have no new info.)
2932 u
= entries
[i
].ad_name_offset
/ sizeof(struct vki_accessx_descriptor
);
2938 // If the upper bound is below our current estimate, revise that
2939 // estimate downwards.
2945 vg_assert(n_descs
<= VKI_ACCESSX_MAX_DESCRIPTORS
);
2947 POST_MEM_WRITE( ARG3
, n_descs
* sizeof(vki_errno_t
) );
2953 PRINT("chflags ( %#lx(%s), %lu )", ARG1
, (HChar
*)ARG1
, ARG2
);
2954 PRE_REG_READ2(int, "chflags", const char *,path
, unsigned int,flags
);
2955 PRE_MEM_RASCIIZ("chflags(path)", ARG1
);
2957 // GrP fixme sanity-check flags value?
2962 PRINT("fchflags ( %ld, %lu )", SARG1
, ARG2
);
2963 PRE_REG_READ2(int, "fchflags", int,fd
, unsigned int,flags
);
2965 // GrP fixme sanity-check flags value?
2970 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1
, (HChar
*)ARG1
, ARG2
);
2971 PRE_REG_READ2(long, "stat", const char *,path
, struct stat64
*,buf
);
2972 PRE_MEM_RASCIIZ("stat64(path)", ARG1
);
2973 PRE_MEM_WRITE( "stat64(buf)", ARG2
, sizeof(struct vki_stat64
) );
2977 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
2982 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1
, (HChar
*)ARG1
, ARG2
);
2983 PRE_REG_READ2(long, "stat", const char *,path
, struct stat64
*,buf
);
2984 PRE_MEM_RASCIIZ("lstat64(path)", ARG1
);
2985 PRE_MEM_WRITE( "lstat64(buf)", ARG2
, sizeof(struct vki_stat64
) );
2989 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
2994 PRINT("fstat64 ( %lu, %#lx )", ARG1
,ARG2
);
2995 PRE_REG_READ2(long, "fstat", unsigned int, fd
, struct stat64
*, buf
);
2996 PRE_MEM_WRITE( "fstat64(buf)", ARG2
, sizeof(struct vki_stat64
) );
3000 POST_MEM_WRITE( ARG2
, sizeof(struct vki_stat64
) );
3005 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1
, SARG2
, SARG3
);
3006 PRE_REG_READ3(int, "getfsstat",
3007 struct vki_statfs
*, buf
, int, bufsize
, int, flags
);
3009 // ARG2 is a BYTE SIZE
3010 PRE_MEM_WRITE("getfsstat(buf)", ARG1
, ARG2
);
3016 // RES is a STRUCT COUNT
3017 POST_MEM_WRITE(ARG1
, RES
* sizeof(struct vki_statfs
));
3023 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1
, SARG2
, SARG3
);
3024 PRE_REG_READ3(int, "getfsstat64",
3025 struct vki_statfs64
*, buf
, int, bufsize
, int, flags
);
3027 // ARG2 is a BYTE SIZE
3028 PRE_MEM_WRITE("getfsstat64(buf)", ARG1
, ARG2
);
3034 // RES is a STRUCT COUNT
3035 POST_MEM_WRITE(ARG1
, RES
* sizeof(struct vki_statfs64
));
3041 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
3042 // We are conservative and check everything, except the memory pointed to
3044 *flags
|= SfMayBlock
;
3045 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
3046 ARG1
, (HChar
*)ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
);
3047 PRE_REG_READ4(long, "mount",
3048 const char *, type
, const char *, dir
,
3049 int, flags
, void *, data
);
3050 PRE_MEM_RASCIIZ( "mount(type)", ARG1
);
3051 PRE_MEM_RASCIIZ( "mount(dir)", ARG2
);
3055 static void scan_attrlist(ThreadId tid
, struct vki_attrlist
*attrList
,
3056 void *attrBuf
, SizeT attrBufSize
,
3057 void (*fn
)(ThreadId
, void *attrData
, SizeT size
)
3064 static const attrspec commonattr
[] = {
3065 // This order is important.
3066 #if DARWIN_VERS >= DARWIN_10_6
3067 { ATTR_CMN_RETURNED_ATTRS
, sizeof(attribute_set_t
) },
3069 { ATTR_CMN_NAME
, -1 },
3070 { ATTR_CMN_DEVID
, sizeof(dev_t
) },
3071 { ATTR_CMN_FSID
, sizeof(fsid_t
) },
3072 { ATTR_CMN_OBJTYPE
, sizeof(fsobj_type_t
) },
3073 { ATTR_CMN_OBJTAG
, sizeof(fsobj_tag_t
) },
3074 { ATTR_CMN_OBJID
, sizeof(fsobj_id_t
) },
3075 { ATTR_CMN_OBJPERMANENTID
, sizeof(fsobj_id_t
) },
3076 { ATTR_CMN_PAROBJID
, sizeof(fsobj_id_t
) },
3077 { ATTR_CMN_SCRIPT
, sizeof(text_encoding_t
) },
3078 { ATTR_CMN_CRTIME
, sizeof(struct timespec
) },
3079 { ATTR_CMN_MODTIME
, sizeof(struct timespec
) },
3080 { ATTR_CMN_CHGTIME
, sizeof(struct timespec
) },
3081 { ATTR_CMN_ACCTIME
, sizeof(struct timespec
) },
3082 { ATTR_CMN_BKUPTIME
, sizeof(struct timespec
) },
3083 { ATTR_CMN_FNDRINFO
, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
3084 { ATTR_CMN_OWNERID
, sizeof(uid_t
) },
3085 { ATTR_CMN_GRPID
, sizeof(gid_t
) },
3086 { ATTR_CMN_ACCESSMASK
, sizeof(uint32_t) },
3087 { ATTR_CMN_NAMEDATTRCOUNT
, sizeof(uint32_t) },
3088 { ATTR_CMN_NAMEDATTRLIST
, -1 },
3089 { ATTR_CMN_FLAGS
, sizeof(uint32_t) },
3090 { ATTR_CMN_USERACCESS
, sizeof(uint32_t) },
3091 { ATTR_CMN_EXTENDED_SECURITY
, -1 },
3092 { ATTR_CMN_UUID
, sizeof(guid_t
) },
3093 { ATTR_CMN_GRPUUID
, sizeof(guid_t
) },
3094 { ATTR_CMN_FILEID
, sizeof(uint64_t) },
3095 { ATTR_CMN_PARENTID
, sizeof(uint64_t) },
3096 #if DARWIN_VERS >= DARWIN_10_6
3097 { ATTR_CMN_FULLPATH
, -1 },
3099 #if DARWIN_VERS >= DARWIN_10_8
3100 { ATTR_CMN_ADDEDTIME
, -1 },
3104 static const attrspec volattr
[] = {
3105 // This order is important.
3106 { ATTR_VOL_INFO
, 0 },
3107 { ATTR_VOL_FSTYPE
, sizeof(uint32_t) },
3108 { ATTR_VOL_SIGNATURE
, sizeof(uint32_t) },
3109 { ATTR_VOL_SIZE
, sizeof(off_t
) },
3110 { ATTR_VOL_SPACEFREE
, sizeof(off_t
) },
3111 { ATTR_VOL_SPACEAVAIL
, sizeof(off_t
) },
3112 { ATTR_VOL_MINALLOCATION
, sizeof(off_t
) },
3113 { ATTR_VOL_ALLOCATIONCLUMP
, sizeof(off_t
) },
3114 { ATTR_VOL_IOBLOCKSIZE
, sizeof(uint32_t) },
3115 { ATTR_VOL_OBJCOUNT
, sizeof(uint32_t) },
3116 { ATTR_VOL_FILECOUNT
, sizeof(uint32_t) },
3117 { ATTR_VOL_DIRCOUNT
, sizeof(uint32_t) },
3118 { ATTR_VOL_MAXOBJCOUNT
, sizeof(uint32_t) },
3119 { ATTR_VOL_MOUNTPOINT
, -1 },
3120 { ATTR_VOL_NAME
, -1 },
3121 { ATTR_VOL_MOUNTFLAGS
, sizeof(uint32_t) },
3122 { ATTR_VOL_MOUNTEDDEVICE
, -1 },
3123 { ATTR_VOL_ENCODINGSUSED
, sizeof(uint64_t) },
3124 { ATTR_VOL_CAPABILITIES
, sizeof(vol_capabilities_attr_t
) },
3125 #if DARWIN_VERS >= DARWIN_10_6
3126 { ATTR_VOL_UUID
, sizeof(uuid_t
) },
3128 { ATTR_VOL_ATTRIBUTES
, sizeof(vol_attributes_attr_t
) },
3131 static const attrspec dirattr
[] = {
3132 // This order is important.
3133 { ATTR_DIR_LINKCOUNT
, sizeof(uint32_t) },
3134 { ATTR_DIR_ENTRYCOUNT
, sizeof(uint32_t) },
3135 { ATTR_DIR_MOUNTSTATUS
, sizeof(uint32_t) },
3138 static const attrspec fileattr
[] = {
3139 // This order is important.
3140 { ATTR_FILE_LINKCOUNT
, sizeof(uint32_t) },
3141 { ATTR_FILE_TOTALSIZE
, sizeof(off_t
) },
3142 { ATTR_FILE_ALLOCSIZE
, sizeof(off_t
) },
3143 { ATTR_FILE_IOBLOCKSIZE
, sizeof(uint32_t) },
3144 { ATTR_FILE_CLUMPSIZE
, sizeof(uint32_t) },
3145 { ATTR_FILE_DEVTYPE
, sizeof(uint32_t) },
3146 { ATTR_FILE_FILETYPE
, sizeof(uint32_t) },
3147 { ATTR_FILE_FORKCOUNT
, sizeof(uint32_t) },
3148 { ATTR_FILE_FORKLIST
, -1 },
3149 { ATTR_FILE_DATALENGTH
, sizeof(off_t
) },
3150 { ATTR_FILE_DATAALLOCSIZE
, sizeof(off_t
) },
3151 { ATTR_FILE_DATAEXTENTS
, sizeof(extentrecord
) },
3152 { ATTR_FILE_RSRCLENGTH
, sizeof(off_t
) },
3153 { ATTR_FILE_RSRCALLOCSIZE
, sizeof(off_t
) },
3154 { ATTR_FILE_RSRCEXTENTS
, sizeof(extentrecord
) },
3157 static const attrspec forkattr
[] = {
3158 // This order is important.
3159 { ATTR_FORK_TOTALSIZE
, sizeof(off_t
) },
3160 { ATTR_FORK_ALLOCSIZE
, sizeof(off_t
) },
3164 static const attrspec
*attrdefs
[5] = {
3165 commonattr
, volattr
, dirattr
, fileattr
, forkattr
3171 vg_assert(attrList
->bitmapcount
== 5);
3172 VG_(memcpy
)(a
, &attrList
->commonattr
, sizeof(a
));
3174 dend
= d
+ attrBufSize
;
3176 #if DARWIN_VERS >= DARWIN_10_6
3177 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3178 if (a
[0] & ATTR_CMN_RETURNED_ATTRS
) {
3179 // fixme range check this?
3180 a
[0] &= ~ATTR_CMN_RETURNED_ATTRS
;
3181 fn(tid
, d
, sizeof(attribute_set_t
));
3182 VG_(memcpy
)(a
, d
, sizeof(a
));
3186 for (g
= 0; g
< 5; g
++) {
3187 for (i
= 0; attrdefs
[g
][i
].attrBit
; i
++) {
3188 uint32_t bit
= attrdefs
[g
][i
].attrBit
;
3189 int32_t size
= attrdefs
[g
][i
].attrSize
;
3192 a
[g
] &= ~bit
; // clear bit for error check later
3194 attrreference_t
*ref
= (attrreference_t
*)d
;
3195 size
= MIN(sizeof(attrreference_t
), dend
- d
);
3197 if (size
>= sizeof(attrreference_t
) &&
3198 d
+ ref
->attr_dataoffset
< dend
)
3200 fn(tid
, d
+ ref
->attr_dataoffset
,
3201 MIN(ref
->attr_length
, dend
- (d
+ ref
->attr_dataoffset
)));
3206 size
= MIN(size
, dend
- d
);
3211 if ((uintptr_t)d
% 4) d
+= 4 - ((uintptr_t)d
% 4);
3212 if (d
> dend
) d
= dend
;
3216 // Known bits are cleared. Die if any bits are left.
3218 VG_(message
)(Vg_UserMsg
, "UNKNOWN attrlist flags %d:0x%x\n", g
, a
[g
]);
3223 static void get1attr(ThreadId tid
, void *attrData
, SizeT attrDataSize
)
3225 POST_MEM_WRITE((Addr
)attrData
, attrDataSize
);
3228 static void set1attr(ThreadId tid
, void *attrData
, SizeT attrDataSize
)
3230 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr
)attrData
, attrDataSize
);
3235 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3236 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
3237 PRE_REG_READ5(int, "getattrlist",
3238 const char *,path
, struct vki_attrlist
*,attrList
,
3239 void *,attrBuf
, vki_size_t
,attrBufSize
, unsigned int,options
);
3240 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1
);
3241 PRE_MEM_READ("getattrlist(attrList)", ARG2
, sizeof(struct vki_attrlist
));
3242 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3
, ARG4
);
3247 if (ARG4
> sizeof(vki_uint32_t
)) {
3248 // attrBuf is uint32_t size followed by attr data
3249 vki_uint32_t
*sizep
= (vki_uint32_t
*)ARG3
;
3250 POST_MEM_WRITE(ARG3
, sizeof(vki_uint32_t
));
3251 if (ARG5
& FSOPT_REPORT_FULLSIZE
) {
3252 // *sizep is bytes required for return value, including *sizep
3254 // *sizep is actual bytes returned, including *sizep
3256 scan_attrlist(tid
, (struct vki_attrlist
*)ARG2
, sizep
+1, MIN(*sizep
, ARG4
), &get1attr
);
3263 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3264 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
3265 PRE_REG_READ5(int, "setattrlist",
3266 const char *,path
, struct vki_attrlist
*,attrList
,
3267 void *,attrBuf
, vki_size_t
,attrBufSize
, unsigned int,options
);
3268 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1
);
3269 PRE_MEM_READ("setattrlist(attrList)", ARG2
, sizeof(struct vki_attrlist
));
3270 scan_attrlist(tid
, (struct vki_attrlist
*)ARG2
, (void*)ARG3
, ARG4
, &set1attr
);
3274 PRE(getdirentriesattr
)
3276 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %lu, %#lx, %#lx, %#lx, %lu)",
3277 SARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
, ARG8
);
3278 PRE_REG_READ8(int, "getdirentriesattr",
3279 int,fd
, struct vki_attrlist
*,attrList
,
3280 void *,attrBuf
, size_t,attrBufSize
,
3281 unsigned int *,count
, unsigned int *,basep
,
3282 unsigned int *,newState
, unsigned int,options
);
3283 PRE_MEM_READ("getdirentriesattr(attrList)",
3284 ARG2
, sizeof(struct vki_attrlist
));
3285 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3
, ARG4
);
3286 PRE_MEM_READ("getdirentriesattr(count)", ARG5
, sizeof(unsigned int));
3287 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5
, sizeof(unsigned int));
3288 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6
, sizeof(unsigned int));
3289 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7
, sizeof(unsigned int));
3291 POST(getdirentriesattr
)
3297 POST_MEM_WRITE(ARG5
, sizeof(unsigned int));
3298 POST_MEM_WRITE(ARG6
, sizeof(unsigned int));
3299 POST_MEM_WRITE(ARG7
, sizeof(unsigned int));
3301 // return buffer is concatenation of variable-size structs
3302 count
= *(unsigned int *)ARG5
;
3304 end
= (char *)ARG3
+ ARG4
;
3305 for (i
= 0; i
< count
; i
++) {
3306 vg_assert(p
< end
); // failure is kernel bug or Valgrind bug
3307 p
+= *(unsigned int *)p
;
3310 POST_MEM_WRITE(ARG3
, p
- (char *)ARG3
);
3312 PRINT("got %d records, %ld/%lu bytes\n",
3313 count
, (Addr
)p
-(Addr
)ARG3
, ARG4
);
3318 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3319 ARG1
, (HChar
*)ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
);
3320 PRE_REG_READ3(int, "exchangedata",
3321 char *, path1
, char *, path2
, unsigned long, options
);
3322 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1
);
3323 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2
);
3328 PRINT("fsctl ( %#lx(%s), %lu, %#lx, %lu )",
3329 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
);
3330 PRE_REG_READ4( long, "fsctl",
3331 char *,"path", unsigned int,"request",
3332 void *,"data", unsigned int,"options");
3334 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1
);
3337 case VKI_afpfsByteRangeLock2FSCTL
: {
3338 struct vki_ByteRangeLockPB2
*pb
= (struct vki_ByteRangeLockPB2
*)ARG3
;
3339 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3341 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3343 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3345 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3347 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3350 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3353 // GrP fixme check fd
3356 case VKI_FSIOC_SYNC_VOLUME
:
3357 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3
, sizeof(int) );
3361 // fsctl requests use ioctl encoding
3362 ML_(PRE_unknown_ioctl
)(tid
, ARG2
, ARG3
);
3370 case VKI_afpfsByteRangeLock2FSCTL
: {
3371 struct vki_ByteRangeLockPB2
*pb
= (struct vki_ByteRangeLockPB2
*)ARG3
;
3372 POST_FIELD_WRITE(pb
->retRangeStart
);
3375 case VKI_FSIOC_SYNC_VOLUME
:
3379 // fsctl requests use ioctl encoding
3380 ML_(POST_unknown_ioctl
)(tid
, RES
, ARG2
, ARG3
);
3387 PRINT("initgroups(%s, %#lx, %lu)", (HChar
*)ARG1
, ARG2
, ARG3
);
3388 PRE_REG_READ3(long, "initgroups",
3389 int, setlen
, vki_gid_t
*, gidset
, vki_uid_t
, gmuid
);
3390 PRE_MEM_READ("gidset", ARG2
, ARG1
* sizeof(vki_gid_t
));
3394 //--------- posix_spawn ---------//
3395 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3396 the simpler AIX equivalent (syswrap-aix5.c). */
3397 // Pre_read a char** argument.
3398 static void pre_argv_envp(Addr a
, ThreadId tid
, const HChar
* s1
, const HChar
* s2
)
3402 Addr
* a_p
= (Addr
*)a
;
3403 PRE_MEM_READ( s1
, (Addr
)a_p
, sizeof(Addr
) );
3407 PRE_MEM_RASCIIZ( s2
, a_deref
);
3411 static SysRes
simple_pre_exec_check ( const HChar
* exe_name
,
3412 Bool trace_this_child
)
3416 Bool setuid_allowed
;
3418 // Check it's readable
3419 res
= VG_(open
)(exe_name
, VKI_O_RDONLY
, 0);
3420 if (sr_isError(res
)) {
3426 // Check we have execute permissions. We allow setuid executables
3427 // to be run only in the case when we are not simulating them, that
3428 // is, they to be run natively.
3429 setuid_allowed
= trace_this_child
? False
: True
;
3430 ret
= VG_(check_executable
)(NULL
/*&is_setuid*/,
3431 exe_name
, setuid_allowed
);
3433 return VG_(mk_SysRes_Error
)(ret
);
3435 return VG_(mk_SysRes_Success
)(0);
3439 HChar
* path
= NULL
; /* path to executable */
3440 HChar
** envp
= NULL
;
3441 HChar
** argv
= NULL
;
3443 HChar
* launcher_basename
= NULL
;
3446 Bool trace_this_child
;
3450 posix_spawn_file_actions_t* file_actions
3454 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3455 ARG1
, ARG2
, ARG2
? (HChar
*)ARG2
: "(null)", ARG3
, ARG4
, ARG5
);
3457 /* Standard pre-syscall checks */
3459 PRE_REG_READ5(int, "posix_spawn", vki_pid_t
*, pid
, char*, path
,
3460 void*, file_actions
, char**, argv
, char**, envp
);
3461 PRE_MEM_WRITE("posix_spawn(pid)", ARG1
, sizeof(vki_pid_t
) );
3462 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2
);
3463 // DDD: check file_actions
3465 pre_argv_envp( ARG4
, tid
, "posix_spawn(argv)",
3466 "posix_spawn(argv[i])" );
3468 pre_argv_envp( ARG5
, tid
, "posix_spawn(envp)",
3469 "posix_spawn(envp[i])" );
3472 VG_(printf
)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3473 ARG1
, ARG2
, ARG2
? (HChar
*)ARG2
: "(null)", ARG3
, ARG4
, ARG5
);
3475 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3476 syswrap-generic.c. */
3478 /* Check that the name at least begins in client-accessible storage. */
3479 if (ARG2
== 0 /* obviously bogus */
3480 || !VG_(am_is_valid_for_client
)( ARG2
, 1, VKI_PROT_READ
)) {
3481 SET_STATUS_Failure( VKI_EFAULT
);
3485 // Decide whether or not we want to follow along
3486 { // Make 'child_argv' be a pointer to the child's arg vector
3487 // (skipping the exe name)
3488 const HChar
** child_argv
= (const HChar
**)ARG4
;
3489 if (child_argv
&& child_argv
[0] == NULL
)
3491 trace_this_child
= VG_(should_we_trace_this_child
)( (HChar
*)ARG2
, child_argv
);
3494 // Do the important checks: it is a file, is executable, permissions are
3495 // ok, etc. We allow setuid executables to run only in the case when
3496 // we are not simulating them, that is, they to be run natively.
3497 res
= simple_pre_exec_check( (const HChar
*)ARG2
, trace_this_child
);
3498 if (sr_isError(res
)) {
3499 SET_STATUS_Failure( sr_Err(res
) );
3503 /* If we're tracing the child, and the launcher name looks bogus
3504 (possibly because launcher.c couldn't figure it out, see
3505 comments therein) then we have no option but to fail. */
3506 if (trace_this_child
3507 && (VG_(name_of_launcher
) == NULL
3508 || VG_(name_of_launcher
)[0] != '/')) {
3509 SET_STATUS_Failure( VKI_ECHILD
); /* "No child processes" */
3513 /* Ok. So let's give it a try. */
3514 VG_(debugLog
)(1, "syswrap", "Posix_spawn of %s\n", (HChar
*)ARG2
);
3516 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3517 So, we should not terminate gdbserver : this is still the parent
3518 running, which will terminate its gdbserver when exiting.
3519 If the child process is traced, it will start a fresh gdbserver
3520 after posix_spawn. */
3522 // Set up the child's exe path.
3524 if (trace_this_child
) {
3526 // We want to exec the launcher. Get its pre-remembered path.
3527 path
= VG_(name_of_launcher
);
3528 // VG_(name_of_launcher) should have been acquired by m_main at
3529 // startup. The following two assertions should be assured by
3530 // the "If we're tracking the child .." test just above here.
3532 vg_assert(path
[0] == '/');
3533 launcher_basename
= path
;
3536 path
= (HChar
*)ARG2
;
3539 // Set up the child's environment.
3541 // Remove the valgrind-specific stuff from the environment so the
3542 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3543 // This is done unconditionally, since if we are tracing the child,
3544 // the child valgrind will set up the appropriate client environment.
3545 // Nb: we make a copy of the environment before trying to mangle it
3546 // as it might be in read-only memory (this was bug #101881).
3548 // Then, if tracing the child, set VALGRIND_LIB for it.
3553 envp
= VG_(env_clone
)( (HChar
**)ARG5
);
3555 VG_(env_remove_valgrind_env_stuff
)( envp
, /* ro_strings */ False
, NULL
);
3558 if (trace_this_child
) {
3559 // Set VALGRIND_LIB in ARG5 (the environment)
3560 VG_(env_setenv
)( &envp
, VALGRIND_LIB
, VG_(libdir
));
3563 // Set up the child's args. If not tracing it, they are
3564 // simply ARG4. Otherwise, they are
3566 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3568 // except that the first VG_(args_for_valgrind_noexecpass) args
3571 if (!trace_this_child
) {
3572 argv
= (HChar
**)ARG4
;
3574 vg_assert( VG_(args_for_valgrind
) );
3575 vg_assert( VG_(args_for_valgrind_noexecpass
) >= 0 );
3576 vg_assert( VG_(args_for_valgrind_noexecpass
)
3577 <= VG_(sizeXA
)( VG_(args_for_valgrind
) ) );
3578 /* how many args in total will there be? */
3579 // launcher basename
3582 tot_args
+= VG_(sizeXA
)( VG_(args_for_valgrind
) );
3583 tot_args
-= VG_(args_for_valgrind_noexecpass
);
3584 // name of client exe
3586 // args for client exe, skipping [0]
3587 arg2copy
= (HChar
**)ARG4
;
3588 if (arg2copy
&& arg2copy
[0]) {
3589 for (i
= 1; arg2copy
[i
]; i
++)
3593 argv
= VG_(malloc
)( "di.syswrap.pre_sys_execve.1",
3594 (tot_args
+1) * sizeof(HChar
*) );
3597 argv
[j
++] = launcher_basename
;
3598 for (i
= 0; i
< VG_(sizeXA
)( VG_(args_for_valgrind
) ); i
++) {
3599 if (i
< VG_(args_for_valgrind_noexecpass
))
3601 argv
[j
++] = * (HChar
**) VG_(indexXA
)( VG_(args_for_valgrind
), i
);
3603 argv
[j
++] = (HChar
*)ARG2
;
3604 if (arg2copy
&& arg2copy
[0])
3605 for (i
= 1; arg2copy
[i
]; i
++)
3606 argv
[j
++] = arg2copy
[i
];
3609 vg_assert(j
== tot_args
+1);
3612 /* DDD: sort out the signal state. What signal
3613 state does the child inherit from the parent? */
3617 VG_(printf
)("posix_spawn: %s\n", path
);
3618 for (cpp
= argv
; cpp
&& *cpp
; cpp
++)
3619 VG_(printf
)("argv: %s\n", *cpp
);
3621 for (cpp
= envp
; cpp
&& *cpp
; cpp
++)
3622 VG_(printf
)("env: %s\n", *cpp
);
3625 /* Let the call go through as usual. However, we have to poke
3626 the altered arguments back into the argument slots. */
3631 /* not to mention .. */
3632 *flags
|= SfMayBlock
;
3638 POST_MEM_WRITE( ARG1
, sizeof(vki_pid_t
) );
3645 PRINT("socket ( %ld, %ld, %ld )", SARG1
, SARG2
, SARG3
);
3646 PRE_REG_READ3(long, "socket", int, domain
, int, type
, int, protocol
);
3653 r
= ML_(generic_POST_sys_socket
)(tid
, VG_(mk_SysRes_Success
)(RES
));
3654 SET_STATUS_from_SysRes(r
);
3660 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3661 SARG1
, SARG2
, SARG3
, ARG4
, SARG5
);
3662 PRE_REG_READ5(long, "setsockopt",
3663 int, s
, int, level
, int, optname
,
3664 const void *, optval
, vki_socklen_t
, optlen
);
3665 ML_(generic_PRE_sys_setsockopt
)(tid
, ARG1
,ARG2
,ARG3
,ARG4
,ARG5
);
3671 Addr optval_p
= ARG4
;
3672 Addr optlen_p
= ARG5
;
3673 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3674 SARG1
, SARG2
, SARG3
, ARG4
, ARG5
);
3675 PRE_REG_READ5(long, "getsockopt",
3676 int, s
, int, level
, int, optname
,
3677 void *, optval
, vki_socklen_t
*, optlen
);
3678 /* int getsockopt(int socket, int level, int option_name,
3679 void *restrict option_value,
3680 socklen_t *restrict option_len); */
3681 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3682 if (optval_p
!= (Addr
)NULL
) {
3683 ML_(buf_and_len_pre_check
) ( tid
, optval_p
, optlen_p
,
3684 "socketcall.getsockopt(optval)",
3685 "socketcall.getsockopt(optlen)" );
3687 // DDD: #warning GrP fixme darwin-specific sockopts
3692 Addr optval_p
= ARG4
;
3693 Addr optlen_p
= ARG5
;
3695 if (optval_p
!= (Addr
)NULL
) {
3696 ML_(buf_and_len_post_check
) ( tid
, VG_(mk_SysRes_Success
)(RES
),
3698 "socketcall.getsockopt(optlen_out)" );
3699 // DDD: #warning GrP fixme darwin-specific sockopts
3706 *flags
|= SfMayBlock
;
3707 PRINT("connect ( %ld, %#lx, %ld )", SARG1
, ARG2
, SARG3
);
3708 PRE_REG_READ3(long, "connect",
3709 int, sockfd
, struct sockaddr
*, serv_addr
, int, addrlen
);
3710 ML_(generic_PRE_sys_connect
)(tid
, ARG1
,ARG2
,ARG3
);
3716 *flags
|= SfMayBlock
;
3717 PRINT("accept ( %ld, %#lx, %#lx )", SARG1
, ARG2
, SARG3
);
3718 PRE_REG_READ3(long, "accept",
3719 int, s
, struct sockaddr
*, addr
, int *, addrlen
);
3720 ML_(generic_PRE_sys_accept
)(tid
, ARG1
,ARG2
,ARG3
);
3727 r
= ML_(generic_POST_sys_accept
)(tid
, VG_(mk_SysRes_Success
)(RES
),
3729 SET_STATUS_from_SysRes(r
);
3734 *flags
|= SfMayBlock
;
3735 PRINT("mkfifo ( %#lx(%s), %lx )", ARG1
, (HChar
*)ARG1
, ARG2
);
3736 PRE_REG_READ2(long, "mkfifo", const char *, path
, vki_mode_t
, mode
);
3737 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1
);
3743 if (!ML_(fd_allowed
)(RES
, "mkfifo", tid
, True
)) {
3745 SET_STATUS_Failure( VKI_EMFILE
);
3747 if (VG_(clo_track_fds
))
3748 ML_(record_fd_open_with_given_name
)(tid
, RES
, (HChar
*)ARG1
);
3754 *flags
|= SfMayBlock
;
3755 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3756 SARG1
, (HChar
*)ARG2
, SARG3
, ARG4
, ARG5
, SARG6
);
3757 PRE_REG_READ6(long, "sendto",
3758 int, s
, const void *, msg
, int, len
,
3759 unsigned int, flags
,
3760 const struct sockaddr
*, to
, int, tolen
);
3761 ML_(generic_PRE_sys_sendto
)(tid
, ARG1
,ARG2
,ARG3
,ARG4
,ARG5
,ARG6
);
3766 #if VG_WORDSIZE == 4
3767 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3768 SARG1
, SARG2
, LOHI64(ARG3
, ARG4
), ARG5
, ARG6
, SARG7
);
3770 PRE_REG_READ7(long, "sendfile",
3771 int, fromfd
, int, tofd
,
3772 vki_uint32_t
, offset_low32
, vki_uint32_t
, offset_high32
,
3773 vki_uint64_t
*, nwritten
, struct sf_hdtr
*, sf_header
, int, flags
);
3774 PRE_MEM_WRITE("sendfile(nwritten)", ARG5
, sizeof(vki_uint64_t
));
3775 if (ARG6
) PRE_MEM_WRITE("sendfile(sf_header)", ARG6
, sizeof(struct sf_hdtr
));
3777 PRINT("sendfile(%ld, %ld, %lu, %#lx, %#lx, %ld)",
3778 SARG1
, SARG2
, ARG3
, ARG4
, ARG5
, SARG6
);
3780 PRE_REG_READ6(long, "sendfile",
3781 int, fromfd
, int, tofd
,
3782 vki_uint64_t
, offset
,
3783 vki_uint64_t
*, nwritten
, struct sf_hdtr
*, sf_header
, int, flags
);
3784 PRE_MEM_WRITE("sendfile(nwritten)", ARG4
, sizeof(vki_uint64_t
));
3785 if (ARG5
) PRE_MEM_WRITE("sendfile(sf_header)", ARG5
, sizeof(struct sf_hdtr
));
3788 *flags
|= SfMayBlock
;
3792 #if VG_WORDSIZE == 4
3793 POST_MEM_WRITE(ARG5
, sizeof(vki_uint64_t
));
3794 if (ARG6
) POST_MEM_WRITE(ARG6
, sizeof(struct sf_hdtr
));
3796 POST_MEM_WRITE(ARG4
, sizeof(vki_uint64_t
));
3797 if (ARG5
) POST_MEM_WRITE(ARG5
, sizeof(struct sf_hdtr
));
3803 *flags
|= SfMayBlock
;
3804 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3805 SARG1
, ARG2
, SARG3
, ARG4
, ARG5
, ARG6
);
3806 PRE_REG_READ6(long, "recvfrom",
3807 int, s
, void *, buf
, int, len
, unsigned int, flags
,
3808 struct sockaddr
*, from
, int *, fromlen
);
3809 ML_(generic_PRE_sys_recvfrom
)(tid
, ARG1
,ARG2
,ARG3
,ARG4
,ARG5
,ARG6
);
3815 ML_(generic_POST_sys_recvfrom
)(tid
, VG_(mk_SysRes_Success
)(RES
),
3816 ARG1
,ARG2
,ARG3
,ARG4
,ARG5
,ARG6
);
3822 *flags
|= SfMayBlock
;
3823 PRINT("sendmsg ( %ld, %#lx, %ld )", SARG1
, ARG2
, SARG3
);
3824 PRE_REG_READ3(long, "sendmsg",
3825 int, s
, const struct msghdr
*, msg
, int, flags
);
3826 ML_(generic_PRE_sys_sendmsg
)(tid
, "msg", (struct vki_msghdr
*)ARG2
);
3832 *flags
|= SfMayBlock
;
3833 PRINT("recvmsg ( %ld, %#lx, %ld )", SARG1
, ARG2
, SARG3
);
3834 PRE_REG_READ3(long, "recvmsg", int, s
, struct msghdr
*, msg
, int, flags
);
3835 ML_(generic_PRE_sys_recvmsg
)(tid
, "msg", (struct vki_msghdr
*)ARG2
);
3840 ML_(generic_POST_sys_recvmsg
)(tid
, "msg", (struct vki_msghdr
*)ARG2
, RES
);
3846 *flags
|= SfMayBlock
;
3847 PRINT("shutdown ( %ld, %ld )", SARG1
, SARG2
);
3848 PRE_REG_READ2(int, "shutdown", int, s
, int, how
);
3854 PRINT("bind ( %ld, %#lx, %ld )", SARG1
, ARG2
, SARG3
);
3855 PRE_REG_READ3(long, "bind",
3856 int, sockfd
, struct sockaddr
*, my_addr
, int, addrlen
);
3857 ML_(generic_PRE_sys_bind
)(tid
, ARG1
,ARG2
,ARG3
);
3863 PRINT("listen ( %ld, %ld )", SARG1
, SARG2
);
3864 PRE_REG_READ2(long, "listen", int, s
, int, backlog
);
3870 PRINT("getsockname ( %ld, %#lx, %#lx )", SARG1
, ARG2
, ARG3
);
3871 PRE_REG_READ3(long, "getsockname",
3872 int, s
, struct sockaddr
*, name
, int *, namelen
);
3873 ML_(generic_PRE_sys_getsockname
)(tid
, ARG1
,ARG2
,ARG3
);
3879 ML_(generic_POST_sys_getsockname
)(tid
, VG_(mk_SysRes_Success
)(RES
),
3886 PRINT("getpeername ( %ld, %#lx, %#lx )", SARG1
, ARG2
, ARG3
);
3887 PRE_REG_READ3(long, "getpeername",
3888 int, s
, struct sockaddr
*, name
, int *, namelen
);
3889 ML_(generic_PRE_sys_getpeername
)(tid
, ARG1
,ARG2
,ARG3
);
3895 ML_(generic_POST_sys_getpeername
)(tid
, VG_(mk_SysRes_Success
)(RES
),
3902 PRINT("socketpair ( %ld, %ld, %ld, %#lx )", SARG1
, SARG2
, SARG3
, ARG4
);
3903 PRE_REG_READ4(long, "socketpair",
3904 int, d
, int, type
, int, protocol
, int *, sv
);
3905 ML_(generic_PRE_sys_socketpair
)(tid
, ARG1
,ARG2
,ARG3
,ARG4
);
3911 ML_(generic_POST_sys_socketpair
)(tid
, VG_(mk_SysRes_Success
)(RES
),
3912 ARG1
,ARG2
,ARG3
,ARG4
);
3918 PRINT("gethostuuid ( %#lx, %#lx )", ARG1
, ARG2
);
3919 PRE_REG_READ2(int,"gethostuuid",
3921 const struct vki_timespec
*,"timeout");
3923 PRE_MEM_WRITE("uuid_buf", ARG1
, 16);
3924 PRE_MEM_READ("timeout", ARG2
, sizeof(struct vki_timespec
));
3926 *flags
|= SfMayBlock
;
3932 POST_MEM_WRITE(ARG1
, 16);
3935 /* Darwin pipe() returns the two descriptors in two registers. */
3939 PRE_REG_READ0(int, "pipe");
3949 if (!ML_(fd_allowed
)(p0
, "pipe", tid
, True
) ||
3950 !ML_(fd_allowed
)(p1
, "pipe", tid
, True
)) {
3953 SET_STATUS_Failure( VKI_EMFILE
);
3955 if (VG_(clo_track_fds
)) {
3956 ML_(record_fd_open_nameless
)(tid
, p0
);
3957 ML_(record_fd_open_nameless
)(tid
, p1
);
3965 PRINT("getlogin ( %#lx, %lu )", ARG1
, ARG2
);
3966 PRE_REG_READ2(long, "getlogin",
3967 char *,"namebuf", unsigned int,"namelen");
3969 PRE_MEM_WRITE("getlogin(namebuf)", ARG1
, ARG2
);
3974 POST_MEM_WRITE(ARG1
, ARG2
);
3980 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", SARG1
, SARG2
, ARG3
, SARG4
);
3981 PRE_REG_READ4(long, "ptrace",
3982 int,"request", vki_pid_t
,"pid",
3983 vki_caddr_t
,"addr", int,"data");
3985 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3987 // GrP fixme anything needed?
3993 PRINT("issetugid ( )");
3994 PRE_REG_READ0(long, "issetugid");
4000 PRINT("getdtablesize ( )");
4001 PRE_REG_READ0(long, "getdtablesize");
4006 // Subtract Valgrind's fd range from client's dtable
4007 if (RES
> VG_(fd_hard_limit
)) SET_STATUS_Success(VG_(fd_hard_limit
));
4012 PRINT("lseek ( %lu, %ld, %ld )", ARG1
, SARG2
, SARG3
);
4013 PRE_REG_READ4(vki_off_t
, "lseek",
4014 unsigned int,fd
, int,offset_hi
, int,offset_lo
,
4015 unsigned int,whence
);
4021 PRINT("pathconf(%#lx(%s), %ld)", ARG1
, (HChar
*)ARG1
, SARG2
);
4022 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
4023 PRE_MEM_RASCIIZ("pathconf(path)", ARG1
);
4029 PRINT("fpathconf(%ld, %ld)", SARG1
, SARG2
);
4030 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
4032 if (!ML_(fd_allowed
)(ARG1
, "fpathconf", tid
, False
))
4033 SET_STATUS_Failure( VKI_EBADF
);
4039 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", SARG1
, ARG2
, SARG3
, ARG4
);
4040 PRE_REG_READ4(int, "getdirentries",
4041 int, fd
, char *, buf
, int, nbytes
, long *, basep
);
4042 PRE_MEM_WRITE("getdirentries(basep)", ARG4
, sizeof(long));
4043 PRE_MEM_WRITE("getdirentries(buf)", ARG2
, ARG3
);
4048 POST_MEM_WRITE(ARG4
, sizeof(long));
4049 // GrP fixme be specific about d_name?
4050 POST_MEM_WRITE(ARG2
, RES
);
4054 PRE(getdirentries64
)
4056 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", SARG1
, ARG2
, ARG3
, ARG4
);
4057 PRE_REG_READ4(vki_ssize_t
, "getdirentries",
4058 int,fd
, char *,buf
, vki_size_t
,nbytes
, vki_off_t
*,basep
);
4059 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
4060 to valid memory and the kernel doesn't modify it. I can't
4061 determine the conditions under which that happens. But it
4062 causes Memcheck to complain, confusingly. So disable this check
4065 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
4067 PRE_MEM_WRITE("getdirentries64(buf)", ARG2
, ARG3
);
4069 POST(getdirentries64
)
4071 /* Disabled; see comments in the PRE wrapper.
4072 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
4074 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
4075 POST_MEM_WRITE(ARG2
, RES
);
4081 PRINT("statfs64 ( %#lx(%s), %#lx )", ARG1
, (HChar
*)ARG1
, ARG2
);
4082 PRE_REG_READ2(long, "statfs64", const char *, path
, struct statfs64
*, buf
);
4083 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1
);
4084 PRE_MEM_WRITE( "statfs64(buf)", ARG2
, sizeof(struct vki_statfs64
) );
4088 POST_MEM_WRITE( ARG2
, sizeof(struct vki_statfs64
) );
4094 PRINT("fstatfs64 ( %lu, %#lx )", ARG1
, ARG2
);
4095 PRE_REG_READ2(long, "fstatfs64",
4096 unsigned int, fd
, struct statfs
*, buf
);
4097 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2
, sizeof(struct vki_statfs64
) );
4101 POST_MEM_WRITE( ARG2
, sizeof(struct vki_statfs64
) );
4106 PRINT("csops ( %ld, %#lx, %#lx, %lu )", SARG1
, ARG2
, ARG3
, ARG4
);
4107 PRE_REG_READ4(int, "csops",
4108 vki_pid_t
, pid
, uint32_t, ops
,
4109 void *, useraddr
, vki_size_t
, usersize
);
4111 PRE_MEM_WRITE( "csops(useraddr)", ARG3
, ARG4
);
4113 // If the pid is ours, don't mark the program as KILL or HARD
4114 // Maybe we should keep track of this for later calls to STATUS
4115 if (!ARG1
|| VG_(getpid
)() == ARG1
) {
4117 case VKI_CS_OPS_MARKINVALID
:
4118 case VKI_CS_OPS_MARKHARD
:
4119 case VKI_CS_OPS_MARKKILL
:
4120 SET_STATUS_Success(0);
4126 POST_MEM_WRITE( ARG3
, ARG4
);
4131 PRINT("auditon ( %ld, %#lx, %lu )", SARG1
, ARG2
, ARG3
);
4132 PRE_REG_READ3(int,"auditon",
4133 int,"cmd", void*,"data", unsigned int,"length");
4137 case VKI_A_SETPOLICY
:
4138 case VKI_A_SETKMASK
:
4139 case VKI_A_SETQCTRL
:
4141 case VKI_A_SETCLASS
:
4142 case VKI_A_SETPMASK
:
4143 case VKI_A_SETFSIZE
:
4144 #if DARWIN_VERS >= DARWIN_10_6
4145 case VKI_A_SENDTRIGGER
:
4147 // kernel reads data..data+length
4148 PRE_MEM_READ("auditon(data)", ARG2
, ARG3
);
4151 case VKI_A_GETKMASK
:
4152 case VKI_A_GETPOLICY
:
4153 case VKI_A_GETQCTRL
:
4154 case VKI_A_GETFSIZE
:
4156 // kernel writes data..data+length
4157 // GrP fixme be precise about what gets written
4158 PRE_MEM_WRITE("auditon(data)", ARG2
, ARG3
);
4162 case VKI_A_GETCLASS
:
4163 case VKI_A_GETPINFO
:
4164 case VKI_A_GETPINFO_ADDR
:
4165 #if DARWIN_VERS >= DARWIN_10_6
4166 case VKI_A_GETSINFO_ADDR
:
4168 // kernel reads and writes data..data+length
4169 // GrP fixme be precise about what gets read and written
4170 PRE_MEM_READ("auditon(data)", ARG2
, ARG3
);
4171 PRE_MEM_WRITE("auditon(data)", ARG2
, ARG3
);
4174 case VKI_A_SETKAUDIT
:
4176 case VKI_A_SETUMASK
:
4177 case VKI_A_SETSMASK
:
4178 case VKI_A_GETKAUDIT
:
4182 // unimplemented on darwin
4186 VG_(message
)(Vg_UserMsg
, "UNKNOWN auditon cmd %ld\n", ARG1
);
4194 case VKI_A_SETPOLICY
:
4195 case VKI_A_SETKMASK
:
4196 case VKI_A_SETQCTRL
:
4198 case VKI_A_SETCLASS
:
4199 case VKI_A_SETPMASK
:
4200 case VKI_A_SETFSIZE
:
4201 #if DARWIN_VERS >= DARWIN_10_6
4202 case VKI_A_SENDTRIGGER
:
4204 // kernel reads data..data+length
4207 case VKI_A_GETKMASK
:
4208 case VKI_A_GETPOLICY
:
4209 case VKI_A_GETQCTRL
:
4210 case VKI_A_GETFSIZE
:
4212 // kernel writes data..data+length
4213 // GrP fixme be precise about what gets written
4214 POST_MEM_WRITE(ARG2
, ARG3
);
4218 case VKI_A_GETCLASS
:
4219 case VKI_A_GETPINFO
:
4220 case VKI_A_GETPINFO_ADDR
:
4221 #if DARWIN_VERS >= DARWIN_10_6
4222 case VKI_A_GETSINFO_ADDR
:
4224 // kernel reads and writes data..data+length
4225 // GrP fixme be precise about what gets read and written
4226 POST_MEM_WRITE(ARG2
, ARG3
);
4229 case VKI_A_SETKAUDIT
:
4231 case VKI_A_SETUMASK
:
4232 case VKI_A_SETSMASK
:
4233 case VKI_A_GETKAUDIT
:
4237 // unimplemented on darwin
4247 PRINT("getaudit_addr(%#lx, %ld)", ARG1
, SARG2
);
4248 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
4249 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1
, ARG2
);
4253 POST_MEM_WRITE(ARG1
, ARG2
);
4260 if (0) VG_(am_do_sync_check
)("(PRE_MMAP)",__FILE__
,__LINE__
);
4262 #if VG_WORDSIZE == 4
4263 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %llu )",
4264 ARG1
, ARG2
, SARG3
, SARG4
, SARG5
, LOHI64(ARG6
, ARG7
) );
4265 PRE_REG_READ7(Addr
, "mmap",
4266 Addr
,start
, vki_size_t
,length
, int,prot
, int,flags
, int,fd
,
4267 unsigned long,offset_hi
, unsigned long,offset_lo
);
4268 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4269 // V's mechanism for now
4270 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4271 // (Off64T)LOHI64(ARG6, ARG7) );
4273 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4274 ARG1
, ARG2
, SARG3
, SARG4
, SARG5
, SARG6
);
4275 PRE_REG_READ6(long, "mmap",
4276 Addr
,start
, vki_size_t
,length
, int,prot
, int,flags
, int,fd
,
4278 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4282 // SET_STATUS_from_SysRes(r);
4288 ML_(notify_core_and_tool_of_mmap
)(RES
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
);
4289 // Try to load symbols from the region
4290 VG_(di_notify_mmap
)( (Addr
)RES
, False
/*allow_SkFileV*/,
4291 -1/*don't use_fd*/ );
4292 ML_(sync_mappings
)("after", "mmap", 0);
4297 /* This function holds common elements of PRE(__sysctl) and
4298 PRE(sysctlbyname). */
4299 static void common_PRE_sysctl (
4301 ThreadId tid
, /*OUT*/SyscallStatus
* status
, /*OUT*/UWord
* flags
,
4303 Bool is_kern_dot_userstack
,
4304 UWord oldp
, UWord oldlenp
,
4305 UWord newp
, UWord newlen
)
4309 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp
, sizeof(size_t));
4311 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4312 PRE_MEM_READ("sysctl(oldlenp)", oldlenp
, sizeof(size_t));
4313 PRE_MEM_WRITE("sysctl(oldp)", oldp
, *(size_t*)oldlenp
);
4317 PRE_MEM_READ("sysctl(newp)", newp
, newlen
);
4320 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4321 // (executable path and arguments and environment
4323 if (is_kern_dot_userstack
) {
4324 // Intercept sysctl(kern.usrstack). The kernel's reply
4325 // would be Valgrind's stack, not the client's stack.
4326 // GrP fixme kern_usrstack64 */
4327 if (newp
|| newlen
) {
4328 SET_STATUS_Failure(VKI_EPERM
); // USRSTACK is read-only */
4330 Addr
* t_oldp
= (Addr
*)oldp
;
4331 size_t* t_oldlenp
= (size_t*)oldlenp
;
4333 // According to some searches on the net, it looks like
4334 // USRSTACK gives the address of the byte following the
4335 // highest byte of the stack. As VG_(clstk_end) is the
4336 // address of the highest addressable byte, we add 1.
4337 Addr stack_end
= VG_(clstk_end
)+1;
4338 size_t oldlen
= *t_oldlenp
;
4339 // always return actual size
4340 *t_oldlenp
= sizeof(Addr
);
4341 if (t_oldp
&& oldlen
>= sizeof(Addr
)) {
4342 // oldp is big enough. copy value and return 0
4343 *t_oldp
= stack_end
;
4344 SET_STATUS_Success(0);
4346 // oldp isn't big enough. copy as much as possible
4347 // and return ENOMEM
4348 if (t_oldp
) VG_(memcpy
)(t_oldp
, &stack_end
, oldlen
);
4349 SET_STATUS_Failure(VKI_ENOMEM
);
4355 if (!SUCCESS
&& !FAILURE
) {
4356 // Don't set SfPostOnFail if we've already handled it locally.
4357 *flags
|= SfPostOnFail
;
4365 UWord namelen
= ARG2
;
4367 UWord oldlenp
= ARG4
;
4369 UWord newlen
= ARG6
;
4371 PRINT( "__sysctl ( %#lx, %lu, %#lx, %#lx, %#lx, %#lx )",
4372 name
, namelen
, oldp
, oldlenp
, newp
, newlen
);
4374 PRE_REG_READ6(int, "__sysctl", int*, name
, unsigned int, namelen
,
4375 void*, oldp
, vki_size_t
*, oldlenp
,
4376 void*, newp
, vki_size_t
*, newlenp
);
4378 PRE_MEM_READ("sysctl(name)", name
, namelen
); // reads name[0..namelen-1]
4380 if (VG_(clo_trace_syscalls
)) {
4382 Int
* t_name
= (Int
*)name
;
4383 VG_(printf
)(" mib: [ ");
4384 for (i
= 0; i
< namelen
; i
++) {
4385 VG_(printf
)("%d ", t_name
[i
]);
4390 Int vKI_KERN_USRSTACKXX
4391 = VG_WORDSIZE
== 4 ? VKI_KERN_USRSTACK32
: VKI_KERN_USRSTACK64
;
4392 Bool is_kern_dot_userstack
4393 = name
&& namelen
== 2
4394 && ((Int
*)name
)[0] == VKI_CTL_KERN
4395 && ((Int
*)name
)[1] == vKI_KERN_USRSTACKXX
;
4397 common_PRE_sysctl( /*IMPLICIT ARGS*/tid
,status
,flags
,/*!IMPLICIT_ARGS*/
4398 is_kern_dot_userstack
, oldp
, oldlenp
, newp
, newlen
);
4404 UWord oldlenp
= ARG4
;
4406 if (SUCCESS
|| ERR
== VKI_ENOMEM
) {
4407 // sysctl can write truncated data and return VKI_ENOMEM
4409 POST_MEM_WRITE(oldlenp
, sizeof(size_t));
4411 if (oldp
&& oldlenp
) {
4412 POST_MEM_WRITE(oldp
, *(size_t*)oldlenp
);
4420 PRINT( "sigpending ( %#lx )", ARG1
);
4421 PRE_REG_READ1(long, "sigpending", vki_sigset_t
*, set
);
4422 PRE_MEM_WRITE( "sigpending(set)", ARG1
, sizeof(vki_sigset_t
));
4426 POST_MEM_WRITE( ARG1
, sizeof(vki_sigset_t
) ) ;
4433 PRINT("sigprocmask ( %ld, %#lx, %#lx )", SARG1
, ARG2
, ARG3
);
4434 PRE_REG_READ3(long, "sigprocmask",
4435 int, how
, vki_sigset_t
*, set
, vki_sigset_t
*, oldset
);
4437 PRE_MEM_READ( "sigprocmask(set)", ARG2
, sizeof(vki_sigset_t
));
4439 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3
, sizeof(vki_sigset_t
));
4441 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4442 value of 'how' is irrelevant, and it appears that Darwin's libc
4443 passes zero, which is not equal to any of
4444 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4445 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4446 value independently of the other args. Solution: in this case,
4447 simply pass a valid (but irrelevant) value for 'how'. */
4448 /* Also, in this case the new set is passed to the kernel by
4449 reference, not value, as in some other sigmask related Darwin
4452 if (ARG2
== 0 /* the new-set is NULL */
4453 && ARG1
!= VKI_SIG_BLOCK
4454 && ARG1
!= VKI_SIG_UNBLOCK
&& ARG1
!= VKI_SIG_SETMASK
) {
4455 arg1
= VKI_SIG_SETMASK
;
4457 SET_STATUS_from_SysRes(
4458 VG_(do_sys_sigprocmask
) ( tid
, arg1
, (vki_sigset_t
*)ARG2
,
4459 (vki_sigset_t
*)ARG3
)
4463 *flags
|= SfPollAfter
;
4469 if (RES
== 0 && ARG3
!= 0)
4470 POST_MEM_WRITE( ARG3
, sizeof(vki_sigset_t
));
4476 /* Just hand this off to the kernel. Is that really correct? And
4477 shouldn't we at least set SfPollAfter? These questions apply to
4478 all the Linux versions too. */
4479 /* I think the first arg is the 32-bit signal mask (by value), and
4480 the other two args are ignored. */
4481 *flags
|= SfMayBlock
;
4482 PRINT("sigsuspend ( mask=0x%08lx )", ARG1
);
4483 PRE_REG_READ1(int, "sigsuspend", int, sigmask
);
4487 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4488 and 32-bit wrappers are different.
4490 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4491 length in the usual way. I have seen values NULL, 0 passed in some
4492 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4493 basis that they don't do anything if the length is zero, so it's OK
4494 for the buffer pointer to be NULL in that case (meaning they don't
4497 int proc_info(int32_t callnum, int32_t pid,
4498 uint32_t flavor, uint64_t arg,
4499 user_addr_t buffer, int32_t buffersize)
4503 #if VG_WORDSIZE == 4
4504 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4505 (Int
)ARG1
, (Int
)ARG2
, (UInt
)ARG3
, LOHI64(ARG4
,ARG5
), ARG6
, (Int
)ARG7
);
4506 PRE_REG_READ7(int, "proc_info",
4507 int, callnum
, int, pid
, unsigned int, flavor
,
4508 vki_uint32_t
, arg_low32
,
4509 vki_uint32_t
, arg_high32
,
4510 void*, buffer
, int, buffersize
);
4511 PRE_MEM_WRITE("proc_info(buffer)", ARG6
, ARG7
);
4513 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4514 (Int
)ARG1
, (Int
)ARG2
, (UInt
)ARG3
, (ULong
)ARG4
, ARG5
, (Int
)ARG6
);
4515 PRE_REG_READ6(int, "proc_info",
4516 int, callnum
, int, pid
, unsigned int, flavor
,
4517 unsigned long long int, arg
,
4518 void*, buffer
, int, buffersize
);
4519 PRE_MEM_WRITE("proc_info(buffer)", ARG5
, ARG6
);
4525 #if VG_WORDSIZE == 4
4528 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4529 if (ARG1
== 5 && ARG3
== 2 && LOHI64(ARG4
,ARG5
) == 0 )
4531 const HChar
* new_name
= (const HChar
*) ARG6
;
4532 if (new_name
) { // Paranoia
4533 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
4534 SizeT new_len
= VG_(strlen
)(new_name
);
4536 /* Don't bother reusing the memory. This is a rare event. */
4538 VG_(realloc
)("syscall(proc_info)", tst
->thread_name
, new_len
+ 1);
4539 VG_(strcpy
)(tst
->thread_name
, new_name
);
4543 POST_MEM_WRITE(ARG6
, ARG7
);
4547 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4548 if (ARG1
== 5 && ARG3
== 2 && ARG4
== 0 )
4550 const HChar
* new_name
= (const HChar
*) ARG5
;
4551 if (new_name
) { // Paranoia
4552 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
4553 SizeT new_len
= VG_(strlen
)(new_name
);
4555 /* Don't bother reusing the memory. This is a rare event. */
4557 VG_(realloc
)("syscall(proc_info)", tst
->thread_name
, new_len
+ 1);
4558 VG_(strcpy
)(tst
->thread_name
, new_name
);
4562 POST_MEM_WRITE(ARG5
, ARG6
);
4567 /* ---------------------------------------------------------------------
4569 ------------------------------------------------------------------ */
4571 // We must record the aiocbp for each aio_read() in a table so that when
4572 // aio_return() is called we can mark the memory written asynchronously by
4573 // aio_read() as having been written. We don't have to do this for
4574 // aio_write(). See bug 197227 for more details.
4575 static OSet
* aiocbp_table
= NULL
;
4576 static Bool aio_init_done
= False
;
4578 static void aio_init(void)
4580 aiocbp_table
= VG_(OSetWord_Create
)(VG_(malloc
), "syswrap.aio", VG_(free
));
4581 aio_init_done
= True
;
4584 static Bool was_a_successful_aio_read
= False
;
4588 struct vki_aiocb
* aiocbp
= (struct vki_aiocb
*)ARG1
;
4589 // This assumes that the kernel looks at the struct pointer, but not the
4590 // contents of the struct.
4591 PRINT( "aio_return ( %#lx )", ARG1
);
4592 PRE_REG_READ1(long, "aio_return", struct vki_aiocb
*, aiocbp
);
4594 if (!aio_init_done
) aio_init();
4595 was_a_successful_aio_read
= VG_(OSetWord_Remove
)(aiocbp_table
, (UWord
)aiocbp
);
4599 // If we found the aiocbp in our own table it must have been an aio_read(),
4600 // so mark the buffer as written. If we didn't find it, it must have been
4601 // an aio_write() or a bogus aio_return() (eg. a second one on the same
4602 // aiocbp). Either way, the buffer won't have been written so we don't
4603 // have to mark the buffer as written.
4604 if (was_a_successful_aio_read
) {
4605 struct vki_aiocb
* aiocbp
= (struct vki_aiocb
*)ARG1
;
4606 POST_MEM_WRITE((Addr
)aiocbp
->aio_buf
, aiocbp
->aio_nbytes
);
4607 was_a_successful_aio_read
= False
;
4613 // This assumes that the kernel looks at the struct pointers in the list,
4614 // but not the contents of the structs.
4615 PRINT( "aio_suspend ( %#lx )", ARG1
);
4616 PRE_REG_READ3(long, "aio_suspend",
4617 const struct vki_aiocb
*, aiocbp
, int, nent
,
4618 const struct vki_timespec
*, timeout
);
4620 PRE_MEM_READ("aio_suspend(list)", ARG1
, ARG2
* sizeof(struct vki_aiocb
*));
4622 PRE_MEM_READ ("aio_suspend(timeout)", ARG3
, sizeof(struct vki_timespec
));
4627 // This assumes that the kernel looks at the struct pointer, but not the
4628 // contents of the struct.
4629 PRINT( "aio_error ( %#lx )", ARG1
);
4630 PRE_REG_READ1(long, "aio_error", struct vki_aiocb
*, aiocbp
);
4635 struct vki_aiocb
* aiocbp
= (struct vki_aiocb
*)ARG1
;
4637 PRINT( "aio_read ( %#lx )", ARG1
);
4638 PRE_REG_READ1(long, "aio_read", struct vki_aiocb
*, aiocbp
);
4639 PRE_MEM_READ( "aio_read(aiocbp)", ARG1
, sizeof(struct vki_aiocb
));
4641 if (ML_(safe_to_deref
)(aiocbp
, sizeof(struct vki_aiocb
))) {
4642 if (ML_(fd_allowed
)(aiocbp
->aio_fildes
, "aio_read", tid
, /*isNewFd*/False
)) {
4643 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4644 (Addr
)aiocbp
->aio_buf
, aiocbp
->aio_nbytes
);
4646 SET_STATUS_Failure( VKI_EBADF
);
4649 SET_STATUS_Failure( VKI_EINVAL
);
4654 // We have to record the fact that there is an asynchronous read request
4655 // pending. When a successful aio_return() occurs for this aiocb, then we
4656 // will mark the memory as having been defined.
4657 struct vki_aiocb
* aiocbp
= (struct vki_aiocb
*)ARG1
;
4658 if (!aio_init_done
) aio_init();
4659 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4660 // should have caused the aio_read() to fail and we shouldn't have reached
4662 VG_(OSetWord_Insert
)(aiocbp_table
, (UWord
)aiocbp
);
4667 struct vki_aiocb
* aiocbp
= (struct vki_aiocb
*)ARG1
;
4669 PRINT( "aio_write ( %#lx )", ARG1
);
4670 PRE_REG_READ1(long, "aio_write", struct vki_aiocb
*, aiocbp
);
4671 PRE_MEM_READ( "aio_write(aiocbp)", ARG1
, sizeof(struct vki_aiocb
));
4673 if (ML_(safe_to_deref
)(aiocbp
, sizeof(struct vki_aiocb
))) {
4674 if (ML_(fd_allowed
)(aiocbp
->aio_fildes
, "aio_write", tid
, /*isNewFd*/False
)) {
4675 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4676 (Addr
)aiocbp
->aio_buf
, aiocbp
->aio_nbytes
);
4678 SET_STATUS_Failure( VKI_EBADF
);
4681 SET_STATUS_Failure( VKI_EINVAL
);
4685 /* ---------------------------------------------------------------------
4686 mach_msg: formatted messages
4687 ------------------------------------------------------------------ */
4689 static size_t desc_size(mach_msg_descriptor_t
*desc
)
4691 switch (desc
->type
.type
) {
4692 case MACH_MSG_PORT_DESCRIPTOR
: return sizeof(desc
->port
);
4693 case MACH_MSG_OOL_DESCRIPTOR
: return sizeof(desc
->out_of_line
);
4694 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
: return sizeof(desc
->out_of_line
);
4695 case MACH_MSG_OOL_PORTS_DESCRIPTOR
: return sizeof(desc
->ool_ports
);
4697 VG_(printf
)("UNKNOWN mach message descriptor %d\n", desc
->type
.type
);
4698 return sizeof(desc
->type
); // guess
4703 static void assign_port_names(mach_msg_ool_ports_descriptor_t
*desc
,
4707 mach_port_t
*ports
= (mach_port_t
*)desc
->address
;
4708 for (i
= 0; i
< desc
->count
; i
++) {
4709 assign_port_name(ports
[i
], name
);
4714 static void import_complex_message(ThreadId tid
, mach_msg_header_t
*mh
)
4716 mach_msg_body_t
*body
;
4717 mach_msg_size_t count
, i
;
4719 mach_msg_descriptor_t
*desc
;
4721 vg_assert(mh
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
);
4723 body
= (mach_msg_body_t
*)(mh
+1);
4724 count
= body
->msgh_descriptor_count
;
4725 p
= (uint8_t *)(body
+1);
4727 for (i
= 0; i
< count
; i
++) {
4728 desc
= (mach_msg_descriptor_t
*)p
;
4729 p
+= desc_size(desc
);
4731 switch (desc
->type
.type
) {
4732 case MACH_MSG_PORT_DESCRIPTOR
:
4734 record_unnamed_port(tid
, desc
->port
.name
, -1);
4735 record_port_insert_rights(desc
->port
.name
, desc
->port
.disposition
);
4736 PRINT("got port %s;\n", name_for_port(desc
->port
.name
));
4739 case MACH_MSG_OOL_DESCRIPTOR
:
4740 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4741 // out-of-line memory - map it
4742 // GrP fixme how is VOLATILE different? do we care?
4743 // GrP fixme do other flags tell us anything? assume shared for now
4744 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4745 // GrP fixme protection
4746 if (desc
->out_of_line
.size
> 0) {
4747 Addr start
= VG_PGROUNDDN((Addr
)desc
->out_of_line
.address
);
4748 Addr end
= VG_PGROUNDUP((Addr
)desc
->out_of_line
.address
+
4749 (Addr
)desc
->out_of_line
.size
);
4750 PRINT("got ool mem %p..%p;\n", desc
->out_of_line
.address
,
4751 (char*)desc
->out_of_line
.address
+desc
->out_of_line
.size
);
4753 ML_(notify_core_and_tool_of_mmap
)(
4754 start
, end
- start
, VKI_PROT_READ
|VKI_PROT_WRITE
,
4755 VKI_MAP_PRIVATE
, -1, 0);
4757 // GrP fixme mark only un-rounded part as initialized
4760 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
4761 // out-of-line array of ports - map it
4762 // GrP fixme see fixmes above
4763 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
));
4765 if (desc
->ool_ports
.count
> 0) {
4766 Addr start
= VG_PGROUNDDN((Addr
)desc
->ool_ports
.address
);
4767 Addr end
= VG_PGROUNDUP((Addr
)desc
->ool_ports
.address
+ desc
->ool_ports
.count
* sizeof(mach_port_t
));
4768 mach_port_t
*ports
= (mach_port_t
*)desc
->ool_ports
.address
;
4770 ML_(notify_core_and_tool_of_mmap
)(
4771 start
, end
- start
, VKI_PROT_READ
|VKI_PROT_WRITE
,
4772 VKI_MAP_PRIVATE
, -1, 0);
4775 for (i
= 0; i
< desc
->ool_ports
.count
; i
++) {
4776 record_unnamed_port(tid
, ports
[i
], -1);
4777 record_port_insert_rights(ports
[i
], desc
->port
.disposition
);
4778 PRINT(" %s", name_for_port(ports
[i
]));
4785 VG_(printf
)("UNKNOWN Mach descriptor type %u!\n", desc
->type
.type
);
4792 static void pre_port_desc_read(ThreadId tid
, mach_msg_port_descriptor_t
*desc2
)
4797 mach_msg_size_t pad1
;
4799 uint8_t disposition
;
4801 } *desc
= (void*)desc2
;
4804 PRE_FIELD_READ("msg->desc.port.name", desc
->name
);
4805 PRE_FIELD_READ("msg->desc.port.disposition", desc
->disposition
);
4806 PRE_FIELD_READ("msg->desc.port.type", desc
->type
);
4810 static void pre_ool_desc_read(ThreadId tid
, mach_msg_ool_descriptor_t
*desc2
)
4815 #if VG_WORDSIZE != 8
4816 mach_msg_size_t size
;
4822 #if VG_WORDSIZE == 8
4823 mach_msg_size_t size
;
4825 } *desc
= (void*)desc2
;
4828 PRE_FIELD_READ("msg->desc.out_of_line.address", desc
->address
);
4829 PRE_FIELD_READ("msg->desc.out_of_line.size", desc
->size
);
4830 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc
->deallocate
);
4831 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc
->copy
);
4832 PRE_FIELD_READ("msg->desc.out_of_line.type", desc
->type
);
4835 static void pre_oolports_desc_read(ThreadId tid
,
4836 mach_msg_ool_ports_descriptor_t
*desc2
)
4841 #if VG_WORDSIZE != 8
4842 mach_msg_size_t size
;
4846 uint8_t disposition
;
4848 #if VG_WORDSIZE == 8
4849 mach_msg_size_t size
;
4851 } *desc
= (void*)desc2
;
4854 PRE_FIELD_READ("msg->desc.ool_ports.address", desc
->address
);
4855 PRE_FIELD_READ("msg->desc.ool_ports.size", desc
->size
);
4856 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc
->deallocate
);
4857 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc
->copy
);
4858 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc
->disposition
);
4859 PRE_FIELD_READ("msg->desc.ool_ports.type", desc
->type
);
4863 // Returns the size of the descriptor area
4864 // (mach_msg_body_t + any mach_msg_descriptor_t)
4865 static size_t export_complex_message(ThreadId tid
, mach_msg_header_t
*mh
)
4867 mach_msg_body_t
*body
;
4868 mach_msg_size_t count
, i
;
4870 mach_msg_descriptor_t
*desc
;
4872 vg_assert(mh
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
);
4874 body
= (mach_msg_body_t
*)(mh
+1);
4875 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr
)body
, sizeof(*body
));
4877 count
= body
->msgh_descriptor_count
;
4878 p
= (uint8_t *)(body
+1);
4880 for (i
= 0; i
< count
; i
++) {
4881 desc
= (mach_msg_descriptor_t
*)p
;
4882 p
+= desc_size(desc
);
4884 switch (desc
->type
.type
) {
4885 case MACH_MSG_PORT_DESCRIPTOR
:
4886 // single port; no memory map effects
4887 pre_port_desc_read(tid
, &desc
->port
);
4890 case MACH_MSG_OOL_DESCRIPTOR
:
4891 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR
:
4892 // out-of-line memory - unmap it if it's marked dealloc
4893 // GrP fixme need to remap if message fails?
4894 // GrP fixme how is VOLATILE different? do we care?
4895 // GrP fixme struct is different for lp64
4896 pre_ool_desc_read(tid
, &desc
->out_of_line
);
4898 if (desc
->out_of_line
.deallocate
&& desc
->out_of_line
.size
> 0) {
4899 vm_size_t size
= desc
->out_of_line
.size
;
4900 Addr start
= VG_PGROUNDDN((Addr
)desc
->out_of_line
.address
);
4901 Addr end
= VG_PGROUNDUP((Addr
)desc
->out_of_line
.address
+ size
);
4902 PRINT("kill ool mem %p..%#lx; ", desc
->out_of_line
.address
,
4903 (Addr
)desc
->out_of_line
.address
+ size
);
4904 ML_(notify_core_and_tool_of_munmap
)(start
, end
- start
);
4908 case MACH_MSG_OOL_PORTS_DESCRIPTOR
:
4909 // out-of-line array of ports - unmap it if it's marked dealloc
4910 // GrP fixme need to remap if message fails?
4911 // GrP fixme struct different for lp64
4912 pre_oolports_desc_read(tid
, &desc
->ool_ports
);
4914 if (desc
->ool_ports
.deallocate
&& desc
->ool_ports
.count
> 0) {
4915 vm_size_t size
= desc
->ool_ports
.count
* sizeof(mach_port_t
);
4916 Addr start
= VG_PGROUNDDN((Addr
)desc
->ool_ports
.address
);
4917 Addr end
= VG_PGROUNDUP((Addr
)desc
->ool_ports
.address
+ size
);
4918 PRINT("kill ool port array %p..%#lx; ", desc
->ool_ports
.address
,
4919 (Addr
)desc
->ool_ports
.address
+ size
);
4920 ML_(notify_core_and_tool_of_munmap
)(start
, end
- start
);
4924 VG_(printf
)("UNKNOWN Mach descriptor type %u!\n", desc
->type
.type
);
4929 return (size_t)((Addr
)p
- (Addr
)body
);
4933 /* ---------------------------------------------------------------------
4934 mach_msg: host-related messages
4935 ------------------------------------------------------------------ */
4942 mach_msg_header_t Head
;
4944 kern_return_t RetCode
;
4945 mach_msg_type_number_t host_info_outCnt
;
4946 integer_t host_info_out
[14];
4950 Reply
*reply
= (Reply
*)ARG1
;
4952 if (reply
->RetCode
) PRINT("mig return %d", reply
->RetCode
);
4959 mach_msg_header_t Head
;
4961 host_flavor_t flavor
;
4962 mach_msg_type_number_t host_info_outCnt
;
4966 Request
*req
= (Request
*)ARG1
;
4968 PRINT("host_info(mach_host_self(), flavor %d)", req
->flavor
);
4970 AFTER
= POST_FN(host_info
);
4974 POST(host_page_size
)
4978 mach_msg_header_t Head
;
4980 kern_return_t RetCode
;
4981 vm_size_t out_page_size
;
4985 Reply
*reply
= (Reply
*)ARG1
;
4987 if (!reply
->RetCode
) {
4988 PRINT("page size %llu", (ULong
)reply
->out_page_size
);
4990 PRINT("mig return %d", reply
->RetCode
);
4996 PRINT("host_page_size(mach_host_self(), ...)");
4998 AFTER
= POST_FN(host_page_size
);
5002 POST(host_get_io_master
)
5006 mach_msg_header_t Head
;
5007 /* start of the kernel processed data */
5008 mach_msg_body_t msgh_body
;
5009 mach_msg_port_descriptor_t io_master
;
5010 /* end of the kernel processed data */
5014 Reply
*reply
= (Reply
*)ARG1
;
5016 assign_port_name(reply
->io_master
.name
, "io_master-%p");
5017 PRINT("%s", name_for_port(reply
->io_master
.name
));
5020 PRE(host_get_io_master
)
5024 mach_msg_header_t Head
;
5028 // Request *req = (Request *)ARG1;
5030 PRINT("host_get_io_master(mach_host_self())");
5032 AFTER
= POST_FN(host_get_io_master
);
5036 POST(host_get_clock_service
)
5040 mach_msg_header_t Head
;
5041 /* start of the kernel processed data */
5042 mach_msg_body_t msgh_body
;
5043 mach_msg_port_descriptor_t clock_serv
;
5044 /* end of the kernel processed data */
5048 Reply
*reply
= (Reply
*)ARG1
;
5050 assign_port_name(reply
->clock_serv
.name
, "clock-%p");
5051 PRINT("%s", name_for_port(reply
->clock_serv
.name
));
5054 PRE(host_get_clock_service
)
5058 mach_msg_header_t Head
;
5060 clock_id_t clock_id
;
5064 Request
*req
= (Request
*)ARG1
;
5066 PRINT("host_get_clock_service(mach_host_self(), %d)", req
->clock_id
);
5068 AFTER
= POST_FN(host_get_clock_service
);
5072 PRE(host_request_notification
)
5076 mach_msg_header_t Head
;
5077 /* start of the kernel processed data */
5078 mach_msg_body_t msgh_body
;
5079 mach_msg_port_descriptor_t notify_port
;
5080 /* end of the kernel processed data */
5082 host_flavor_t notify_type
;
5086 Request
*req
= (Request
*)ARG1
;
5088 if (MACH_REMOTE
== mach_task_self()) {
5089 if (req
->notify_type
== 0) {
5090 PRINT("host_request_notification(mach_host_self(), %s, %s)",
5091 "HOST_NOTIFY_CALENDAR_CHANGE",
5092 name_for_port(req
->notify_port
.name
));
5094 PRINT("host_request_notification(mach_host_self(), %d, %s)",
5096 name_for_port(req
->notify_port
.name
));
5099 PRINT("host_request_notification(%s, %d, %s)",
5100 name_for_port(MACH_REMOTE
),
5102 name_for_port(req
->notify_port
.name
));
5105 // GrP fixme only do this on success
5106 assign_port_name(req
->notify_port
.name
, "host_notify-%p");
5110 PRE(host_create_mach_voucher
)
5114 mach_msg_header_t Head
;
5116 mach_msg_type_number_t recipesCnt
;
5117 uint8_t recipes
[5120];
5121 Request
*req
= (Request
*)ARG1
;
5123 PRINT("host_create_mach_voucher(count %u)",
5126 AFTER
= POST_FN(host_create_mach_voucher
);
5130 POST(host_create_mach_voucher
)
5134 mach_msg_header_t Head
;
5135 /* start of the kernel processed data */
5136 mach_msg_body_t msgh_body
;
5137 mach_msg_port_descriptor_t voucher
;
5138 /* end of the kernel processed data */
5142 Reply
*reply
= (Reply
*)ARG1
;
5144 // RK fixme properly parse this return type
5145 PRINT("got voucher %#x ", reply
->voucher
.name
);
5149 PRE(host_get_special_port
)
5153 mach_msg_header_t Head
;
5160 Request
*req
= (Request
*)ARG1
;
5162 PRINT("host_get_special_port(node %d)", req
->node
);
5164 switch (req
->which
) {
5166 PRINT("host_get_special_port(%s, HOST_PORT)",
5167 name_for_port(MACH_REMOTE
));
5169 case HOST_PRIV_PORT
:
5170 PRINT("host_get_special_port(%s, HOST_PRIV_PORT)",
5171 name_for_port(MACH_REMOTE
));
5173 case HOST_IO_MASTER_PORT
:
5174 PRINT("host_get_special_port(%s, HOST_IO_MASTER_PORT)",
5175 name_for_port(MACH_REMOTE
));
5177 // Not provided by kernel
5178 case HOST_DYNAMIC_PAGER_PORT
:
5179 PRINT("host_get_special_port(%s, HOST_DYNAMIC_PAGER_PORT)",
5180 name_for_port(MACH_REMOTE
));
5182 case HOST_AUDIT_CONTROL_PORT
:
5183 PRINT("host_get_special_port(%s, HOST_AUDIT_CONTROL_PORT)",
5184 name_for_port(MACH_REMOTE
));
5186 case HOST_USER_NOTIFICATION_PORT
:
5187 PRINT("host_get_special_port(%s, HOST_USER_NOTIFICATION_PORT)",
5188 name_for_port(MACH_REMOTE
));
5193 PRINT("host_get_special_port(%s, %d)",
5194 name_for_port(MACH_REMOTE
), req
->which
);
5198 MACH_ARG(host_get_special_port
.which
) = req
->which
;
5200 AFTER
= POST_FN(host_get_special_port
);
5204 POST(host_get_special_port
)
5208 mach_msg_header_t Head
;
5209 /* start of the kernel processed data */
5210 mach_msg_body_t msgh_body
;
5211 mach_msg_port_descriptor_t port
;
5212 /* end of the kernel processed data */
5216 Reply
*reply
= (Reply
*)ARG1
;
5218 PRINT("got port %#x ", reply
->port
.name
);
5220 /* The required entry in the allocated_ports list (mapping) might
5221 not exist, due perhaps to broken syscall wrappers (mach__N etc).
5222 Create a minimal entry so that assign_port_name below doesn't
5223 cause an assertion. */
5224 if (!port_exists(reply
->port
.name
)) {
5225 port_create_vanilla(reply
->port
.name
);
5228 switch (MACH_ARG(host_get_special_port
.which
)) {
5230 assign_port_name(reply
->port
.name
, "port-%p");
5232 case HOST_PRIV_PORT
:
5233 assign_port_name(reply
->port
.name
, "priv-%p");
5235 case HOST_IO_MASTER_PORT
:
5236 assign_port_name(reply
->port
.name
, "io-master-%p");
5238 // Not provided by kernel
5239 case HOST_DYNAMIC_PAGER_PORT
:
5240 assign_port_name(reply
->port
.name
, "dynamic-pager-%p");
5242 case HOST_AUDIT_CONTROL_PORT
:
5243 assign_port_name(reply
->port
.name
, "audit-control-%p");
5245 case HOST_USER_NOTIFICATION_PORT
:
5246 assign_port_name(reply
->port
.name
, "user-notification-%p");
5251 assign_port_name(reply
->port
.name
, "special-%p");
5255 PRINT("%s", name_for_port(reply
->port
.name
));
5258 /* ---------------------------------------------------------------------
5259 mach_msg: messages to a task
5260 ------------------------------------------------------------------ */
5262 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
5263 // these structs are derived. They obviously relate to the various
5264 // .def files in the xnu sources, and can also be found in some
5265 // form in /usr/include/mach/*.h, but not sure how these all
5266 // relate to each other.
5268 PRE(mach_port_set_context
)
5272 mach_msg_header_t Head
;
5274 mach_port_name_t name
;
5275 mach_vm_address_t context
;
5279 Request
*req
= (Request
*)ARG1
;
5281 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
5282 name_for_port(MACH_REMOTE
),
5283 name_for_port(req
->name
), req
->context
);
5285 AFTER
= POST_FN(mach_port_set_context
);
5288 POST(mach_port_set_context
)
5292 mach_msg_header_t Head
;
5294 kern_return_t RetCode
;
5300 // JRS 2011-Aug-25 FIXME completely bogus
5301 PRE(task_get_exception_ports
)
5305 mach_msg_header_t Head
;
5307 exception_mask_t exception_mask
;
5311 PRINT("task_get_exception_ports(BOGUS)");
5312 AFTER
= POST_FN(task_get_exception_ports
);
5315 POST(task_get_exception_ports
)
5319 mach_msg_header_t Head
;
5320 /* start of the kernel processed data */
5321 mach_msg_body_t msgh_body
;
5322 mach_msg_port_descriptor_t old_handlers
[32];
5323 /* end of the kernel processed data */
5325 mach_msg_type_number_t masksCnt
;
5326 exception_mask_t masks
[32];
5327 exception_behavior_t old_behaviors
[32];
5328 thread_state_flavor_t old_flavors
[32];
5334 ///////////////////////////////////////////////////
5340 mach_msg_header_t Head
;
5342 mach_port_name_t name
;
5346 Request
*req
= (Request
*)ARG1
;
5348 PRINT("mach_port_type(%s, %s, ...)",
5349 name_for_port(MACH_REMOTE
), name_for_port(req
->name
));
5351 AFTER
= POST_FN(mach_port_type
);
5354 POST(mach_port_type
)
5359 PRE(mach_port_extract_member
)
5363 mach_msg_header_t Head
;
5365 mach_port_name_t name
;
5366 mach_port_name_t pset
;
5370 Request
*req
= (Request
*)ARG1
;
5372 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5373 name_for_port(MACH_REMOTE
),
5374 req
->name
, req
->pset
);
5376 AFTER
= POST_FN(mach_port_extract_member
);
5378 // GrP fixme port tracker?
5381 POST(mach_port_extract_member
)
5385 mach_msg_header_t Head
;
5387 kern_return_t RetCode
;
5391 Reply
*reply
= (Reply
*)ARG1
;
5393 if (reply
->RetCode
) PRINT("mig return %d", reply
->RetCode
);
5397 PRE(mach_port_allocate
)
5401 mach_msg_header_t Head
;
5403 mach_port_right_t right
;
5407 Request
*req
= (Request
*)ARG1
;
5409 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req
->right
);
5411 MACH_ARG(mach_port_allocate
.right
) = req
->right
;
5413 AFTER
= POST_FN(mach_port_allocate
);
5416 POST(mach_port_allocate
)
5420 mach_msg_header_t Head
;
5422 kern_return_t RetCode
;
5423 mach_port_name_t name
;
5427 Reply
*reply
= (Reply
*)ARG1
;
5429 if (!reply
->RetCode
) {
5430 if (MACH_REMOTE
== vg_task_port
) {
5431 // GrP fixme port tracking is too imprecise
5432 // vg_assert(!port_exists(reply->name));
5433 record_unnamed_port(tid
, reply
->name
, MACH_ARG(mach_port_allocate
.right
));
5434 PRINT("got port 0x%x", reply
->name
);
5436 VG_(printf
)("UNKNOWN inserted port 0x%x into remote task\n", reply
->name
);
5439 PRINT("mig return %d", reply
->RetCode
);
5444 PRE(mach_port_deallocate
)
5448 mach_msg_header_t Head
;
5450 mach_port_name_t name
;
5454 Request
*req
= (Request
*)ARG1
;
5456 PRINT("mach_port_deallocate(%s, %s)",
5457 name_for_port(MACH_REMOTE
),
5458 name_for_port(req
->name
));
5460 MACH_ARG(mach_port
.port
) = req
->name
;
5462 AFTER
= POST_FN(mach_port_deallocate
);
5464 // Must block to prevent race (other thread allocates and
5465 // notifies after we deallocate but before we notify)
5466 *flags
&= ~SfMayBlock
;
5469 POST(mach_port_deallocate
)
5473 mach_msg_header_t Head
;
5475 kern_return_t RetCode
;
5479 Reply
*reply
= (Reply
*)ARG1
;
5481 if (!reply
->RetCode
) {
5482 if (MACH_REMOTE
== vg_task_port
) {
5483 // Must have cleared SfMayBlock in PRE to prevent race
5484 record_port_dealloc(MACH_ARG(mach_port
.port
));
5486 VG_(printf
)("UNKNOWN remote port dealloc\n");
5489 PRINT("mig return %d", reply
->RetCode
);
5494 PRE(mach_port_get_refs
)
5498 mach_msg_header_t Head
;
5500 mach_port_name_t name
;
5501 mach_port_right_t right
;
5505 Request
*req
= (Request
*)ARG1
;
5507 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5508 name_for_port(MACH_REMOTE
),
5509 name_for_port(req
->name
), req
->right
);
5511 MACH_ARG(mach_port_mod_refs
.port
) = req
->name
;
5512 MACH_ARG(mach_port_mod_refs
.right
) = req
->right
;
5514 AFTER
= POST_FN(mach_port_get_refs
);
5517 POST(mach_port_get_refs
)
5521 mach_msg_header_t Head
;
5523 kern_return_t RetCode
;
5524 mach_port_urefs_t refs
;
5528 Reply
*reply
= (Reply
*)ARG1
;
5530 if (!reply
->RetCode
) {
5531 PRINT("got refs=%d", reply
->refs
);
5533 PRINT("mig return %d", reply
->RetCode
);
5538 PRE(mach_port_mod_refs
)
5542 mach_msg_header_t Head
;
5544 mach_port_name_t name
;
5545 mach_port_right_t right
;
5546 mach_port_delta_t delta
;
5550 Request
*req
= (Request
*)ARG1
;
5552 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5553 name_for_port(MACH_REMOTE
),
5554 name_for_port(req
->name
), req
->right
, req
->delta
);
5556 MACH_ARG(mach_port_mod_refs
.port
) = req
->name
;
5557 MACH_ARG(mach_port_mod_refs
.right
) = req
->right
;
5558 MACH_ARG(mach_port_mod_refs
.delta
) = req
->delta
;
5560 AFTER
= POST_FN(mach_port_mod_refs
);
5562 // Must block to prevent race (other thread allocates and
5563 // notifies after we deallocate but before we notify)
5564 *flags
&= ~SfMayBlock
;
5567 POST(mach_port_mod_refs
)
5571 mach_msg_header_t Head
;
5573 kern_return_t RetCode
;
5577 Reply
*reply
= (Reply
*)ARG1
;
5579 if (!reply
->RetCode
) {
5580 if (MACH_REMOTE
== vg_task_port
) {
5581 // Must have cleared SfMayBlock in PRE to prevent race
5582 record_port_mod_refs(MACH_ARG(mach_port_mod_refs
.port
),
5583 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs
.right
)),
5584 MACH_ARG(mach_port_mod_refs
.delta
));
5586 VG_(printf
)("UNKNOWN remote port mod refs\n");
5589 PRINT("mig return %d", reply
->RetCode
);
5594 PRE(mach_port_get_set_status
)
5598 mach_msg_header_t Head
;
5600 mach_port_name_t name
;
5604 Request
*req
= (Request
*)ARG1
;
5606 PRINT("mach_port_get_set_status(%s, %s)",
5607 name_for_port(MACH_REMOTE
),
5608 name_for_port(req
->name
));
5610 AFTER
= POST_FN(mach_port_get_set_status
);
5613 POST(mach_port_get_set_status
)
5617 mach_msg_header_t Head
;
5618 /* start of the kernel processed data */
5619 mach_msg_body_t msgh_body
;
5620 mach_msg_ool_descriptor_t members
;
5621 /* end of the kernel processed data */
5623 mach_msg_type_number_t membersCnt
;
5624 mach_msg_trailer_t trailer
;
5628 // Reply *reply = (Reply *)ARG1;
5630 // GrP fixme nothing to do?
5634 PRE(mach_port_move_member
)
5638 mach_msg_header_t Head
;
5640 mach_port_name_t member
;
5641 mach_port_name_t after
;
5645 Request
*req
= (Request
*)ARG1
;
5647 PRINT("mach_port_move_member(%s, %s, %s)",
5648 name_for_port(MACH_REMOTE
),
5649 name_for_port(req
->member
),
5650 name_for_port(req
->after
));
5652 MACH_ARG(mach_port_move_member.member) = req->member;
5653 MACH_ARG(mach_port_move_member.after) = req->after;
5655 AFTER
= POST_FN(mach_port_move_member
);
5658 POST(mach_port_move_member
)
5662 mach_msg_header_t Head
;
5664 kern_return_t RetCode
;
5665 mach_msg_trailer_t trailer
;
5669 Reply
*reply
= (Reply
*)ARG1
;
5671 if (!reply
->RetCode
) {
5672 // fixme port set tracker?
5674 PRINT("mig return %d", reply
->RetCode
);
5679 PRE(mach_port_destroy
)
5683 mach_msg_header_t Head
;
5685 mach_port_name_t name
;
5689 Request
*req
= (Request
*)ARG1
;
5691 PRINT("mach_port_destroy(%s, %s)",
5692 name_for_port(MACH_REMOTE
),
5693 name_for_port(req
->name
));
5695 MACH_ARG(mach_port
.port
) = req
->name
;
5697 AFTER
= POST_FN(mach_port_destroy
);
5699 // Must block to prevent race (other thread allocates and
5700 // notifies after we deallocate but before we notify)
5701 *flags
&= ~SfMayBlock
;
5704 POST(mach_port_destroy
)
5708 mach_msg_header_t Head
;
5710 kern_return_t RetCode
;
5714 Reply
*reply
= (Reply
*)ARG1
;
5716 if (!reply
->RetCode
) {
5717 if (MACH_REMOTE
== vg_task_port
) {
5718 // Must have cleared SfMayBlock in PRE to prevent race
5719 record_port_destroy(MACH_ARG(mach_port
.port
));
5721 VG_(printf
)("UNKNOWN remote port destroy\n");
5724 PRINT("mig return %d", reply
->RetCode
);
5729 PRE(mach_port_request_notification
)
5733 mach_msg_header_t Head
;
5734 /* start of the kernel processed data */
5735 mach_msg_body_t msgh_body
;
5736 mach_msg_port_descriptor_t notify
;
5737 /* end of the kernel processed data */
5739 mach_port_name_t name
;
5740 mach_msg_id_t msgid
;
5741 mach_port_mscount_t sync
;
5745 Request
*req
= (Request
*)ARG1
;
5747 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5748 name_for_port(MACH_REMOTE
),
5749 name_for_port(req
->name
), req
->msgid
, req
->sync
,
5750 req
->notify
.name
, req
->notify
.disposition
);
5752 AFTER
= POST_FN(mach_port_request_notification
);
5755 POST(mach_port_request_notification
)
5757 // GrP fixme port tracker? not sure
5761 PRE(mach_port_insert_right
)
5765 mach_msg_header_t Head
;
5766 /* start of the kernel processed data */
5767 mach_msg_body_t msgh_body
;
5768 mach_msg_port_descriptor_t poly
;
5769 /* end of the kernel processed data */
5771 mach_port_name_t name
;
5775 Request
*req
= (Request
*)ARG1
;
5777 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5778 name_for_port(MACH_REMOTE
),
5779 name_for_port(req
->name
), req
->poly
.name
, req
->poly
.disposition
);
5781 AFTER
= POST_FN(mach_port_insert_right
);
5783 if (MACH_REMOTE
== mach_task_self()) {
5784 // GrP fixme import_complex_message handles everything?
5785 // what about export_complex_message for MOVE variants?
5787 VG_(printf
)("UNKNOWN mach_port_insert_right into remote task!\n");
5788 // GrP fixme also may remove rights from this task?
5791 // GrP fixme port tracker?
5794 POST(mach_port_insert_right
)
5799 PRE(mach_port_extract_right
)
5803 mach_msg_header_t Head
;
5805 mach_port_name_t name
;
5806 mach_msg_type_name_t msgt_name
;
5810 Request
*req
= (Request
*)ARG1
;
5812 PRINT("mach_port_extract_right(%s, %s, %d)",
5813 name_for_port(MACH_REMOTE
),
5814 name_for_port(req
->name
), req
->msgt_name
);
5816 AFTER
= POST_FN(mach_port_extract_right
);
5818 // fixme port tracker?
5821 POST(mach_port_extract_right
)
5823 // fixme import_complex_message handles the returned result, right?
5827 PRE(mach_port_get_attributes
)
5831 mach_msg_header_t Head
;
5833 mach_port_name_t name
;
5834 mach_port_flavor_t flavor
;
5835 mach_msg_type_number_t port_info_outCnt
;
5839 Request
*req
= (Request
*)ARG1
;
5841 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5842 name_for_port(MACH_REMOTE
),
5843 name_for_port(req
->name
), req
->flavor
, req
->port_info_outCnt
);
5845 AFTER
= POST_FN(mach_port_get_attributes
);
5848 POST(mach_port_get_attributes
)
5853 PRE(mach_port_set_attributes
)
5857 mach_msg_header_t Head
;
5859 mach_port_name_t name
;
5860 mach_port_flavor_t flavor
;
5861 mach_msg_type_number_t port_infoCnt
;
5862 integer_t port_info
[10];
5866 Request
*req
= (Request
*)ARG1
;
5868 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5869 name_for_port(MACH_REMOTE
),
5870 name_for_port(req
->name
), req
->flavor
, req
->port_infoCnt
);
5872 AFTER
= POST_FN(mach_port_set_attributes
);
5875 POST(mach_port_set_attributes
)
5880 PRE(mach_port_insert_member
)
5884 mach_msg_header_t Head
;
5886 mach_port_name_t name
;
5887 mach_port_name_t pset
;
5891 Request
*req
= (Request
*)ARG1
;
5893 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5894 name_for_port(MACH_REMOTE
), req
->name
, req
->pset
);
5896 AFTER
= POST_FN(mach_port_insert_member
);
5898 // GrP fixme port tracker?
5901 POST(mach_port_insert_member
)
5906 PRE(task_get_special_port
)
5910 mach_msg_header_t Head
;
5916 Request
*req
= (Request
*)ARG1
;
5918 switch (req
->which_port
) {
5919 case TASK_KERNEL_PORT
:
5920 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5921 name_for_port(MACH_REMOTE
));
5923 case TASK_HOST_PORT
:
5924 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5925 name_for_port(MACH_REMOTE
));
5927 case TASK_BOOTSTRAP_PORT
:
5928 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5929 name_for_port(MACH_REMOTE
));
5931 #if DARWIN_VERS < DARWIN_10_8
5932 /* These disappeared in 10.8 */
5933 case TASK_WIRED_LEDGER_PORT
:
5934 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5935 name_for_port(MACH_REMOTE
));
5937 case TASK_PAGED_LEDGER_PORT
:
5938 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5939 name_for_port(MACH_REMOTE
));
5943 PRINT("task_get_special_port(%s, %d)",
5944 name_for_port(MACH_REMOTE
), req
->which_port
);
5948 MACH_ARG(task_get_special_port
.which_port
) = req
->which_port
;
5950 AFTER
= POST_FN(task_get_special_port
);
5953 POST(task_get_special_port
)
5957 mach_msg_header_t Head
;
5958 /* start of the kernel processed data */
5959 mach_msg_body_t msgh_body
;
5960 mach_msg_port_descriptor_t special_port
;
5961 /* end of the kernel processed data */
5965 Reply
*reply
= (Reply
*)ARG1
;
5967 PRINT("got port %#x ", reply
->special_port
.name
);
5969 switch (MACH_ARG(task_get_special_port
.which_port
)) {
5970 case TASK_BOOTSTRAP_PORT
:
5971 vg_bootstrap_port
= reply
->special_port
.name
;
5972 assign_port_name(reply
->special_port
.name
, "bootstrap");
5974 case TASK_KERNEL_PORT
:
5975 assign_port_name(reply
->special_port
.name
, "kernel");
5977 case TASK_HOST_PORT
:
5978 assign_port_name(reply
->special_port
.name
, "host");
5980 #if DARWIN_VERS < DARWIN_10_8
5981 /* These disappeared in 10.8 */
5982 case TASK_WIRED_LEDGER_PORT
:
5983 assign_port_name(reply
->special_port
.name
, "wired-ledger");
5985 case TASK_PAGED_LEDGER_PORT
:
5986 assign_port_name(reply
->special_port
.name
, "paged-ledger");
5990 assign_port_name(reply
->special_port
.name
, "special-%p");
5994 PRINT("%s", name_for_port(reply
->special_port
.name
));
5998 PRE(task_set_special_port
)
6002 mach_msg_header_t Head
;
6003 /* start of the kernel processed data */
6004 mach_msg_body_t msgh_body
;
6005 mach_msg_port_descriptor_t special_port
;
6006 /* end of the kernel processed data */
6012 Request
*req
= (Request
*)ARG1
;
6014 PRINT("got port %#x ", req
->special_port
.name
);
6016 // MACH_ARG(task_set_special_port.which_port) = req->which_port;
6017 PRINT("%s", name_for_port(req
->special_port
.name
));
6019 AFTER
= POST_FN(task_set_special_port
);
6022 POST(task_set_special_port
)
6026 mach_msg_header_t Head
;
6028 kern_return_t RetCode
;
6032 Reply
*reply
= (Reply
*)ARG1
;
6033 if (!reply
->RetCode
) {
6035 PRINT("mig return %d", reply
->RetCode
);
6040 PRE(semaphore_create
)
6044 mach_msg_header_t Head
;
6051 Request
*req
= (Request
*)ARG1
;
6053 PRINT("semaphore_create(%s, ..., %d, %d)",
6054 name_for_port(MACH_REMOTE
), req
->policy
, req
->value
);
6056 AFTER
= POST_FN(semaphore_create
);
6059 POST(semaphore_create
)
6063 mach_msg_header_t Head
;
6064 /* start of the kernel processed data */
6065 mach_msg_body_t msgh_body
;
6066 mach_msg_port_descriptor_t semaphore
;
6067 /* end of the kernel processed data */
6068 mach_msg_trailer_t trailer
;
6072 Reply
*reply
= (Reply
*)ARG1
;
6074 assign_port_name(reply
->semaphore
.name
, "semaphore-%p");
6075 PRINT("%s", name_for_port(reply
->semaphore
.name
));
6079 PRE(semaphore_destroy
)
6083 mach_msg_header_t Head
;
6084 /* start of the kernel processed data */
6085 mach_msg_body_t msgh_body
;
6086 mach_msg_port_descriptor_t semaphore
;
6087 /* end of the kernel processed data */
6088 mach_msg_trailer_t trailer
;
6092 Request
*req
= (Request
*)ARG1
;
6094 PRINT("semaphore_destroy(%s, %s)",
6095 name_for_port(MACH_REMOTE
), name_for_port(req
->semaphore
.name
));
6097 record_port_destroy(req
->semaphore
.name
);
6099 AFTER
= POST_FN(semaphore_destroy
);
6102 POST(semaphore_destroy
)
6106 mach_msg_header_t Head
;
6108 kern_return_t RetCode
;
6109 mach_msg_trailer_t trailer
;
6113 Reply
*reply
= (Reply
*)ARG1
;
6114 if (!reply
->RetCode
) {
6116 PRINT("mig return %d", reply
->RetCode
);
6120 PRE(task_policy_set
)
6124 mach_msg_header_t Head
;
6126 task_policy_flavor_t flavor
;
6127 mach_msg_type_number_t policy_infoCnt
;
6128 integer_t policy_info
[16];
6132 Request
*req
= (Request
*)ARG1
;
6134 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE
), req
->flavor
);
6136 AFTER
= POST_FN(task_policy_set
);
6139 POST(task_policy_set
)
6143 mach_msg_header_t Head
;
6145 kern_return_t RetCode
;
6149 Reply
*reply
= (Reply
*)ARG1
;
6150 if (!reply
->RetCode
) {
6152 PRINT("mig return %d", reply
->RetCode
);
6157 PRE(mach_ports_register
)
6161 mach_msg_header_t Head
;
6162 /* start of the kernel processed data */
6163 mach_msg_body_t msgh_body
;
6164 mach_msg_ool_ports_descriptor_t init_port_set
;
6165 /* end of the kernel processed data */
6167 mach_msg_type_number_t init_port_setCnt
;
6171 // Request *req = (Request *)ARG1;
6173 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE
));
6175 AFTER
= POST_FN(mach_ports_register
);
6178 POST(mach_ports_register
)
6182 mach_msg_header_t Head
;
6184 kern_return_t RetCode
;
6188 Reply
*reply
= (Reply
*)ARG1
;
6189 if (!reply
->RetCode
) {
6191 PRINT("mig return %d", reply
->RetCode
);
6196 PRE(mach_ports_lookup
)
6200 mach_msg_header_t Head
;
6204 // Request *req = (Request *)ARG1;
6206 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE
));
6208 AFTER
= POST_FN(mach_ports_lookup
);
6211 POST(mach_ports_lookup
)
6215 mach_msg_header_t Head
;
6216 /* start of the kernel processed data */
6217 mach_msg_body_t msgh_body
;
6218 mach_msg_ool_ports_descriptor_t init_port_set
;
6219 /* end of the kernel processed data */
6221 mach_msg_type_number_t init_port_setCnt
;
6225 // Reply *reply = (Reply *)ARG1;
6233 mach_msg_header_t Head
;
6235 task_flavor_t flavor
;
6236 mach_msg_type_number_t task_info_outCnt
;
6240 Request
*req
= (Request
*)ARG1
;
6242 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE
), req
->flavor
);
6244 AFTER
= POST_FN(task_info
);
6251 mach_msg_header_t Head
;
6253 kern_return_t RetCode
;
6254 mach_msg_type_number_t task_info_outCnt
;
6255 integer_t task_info_out
[52];
6259 Reply
*reply
= (Reply
*)ARG1
;
6260 if (!reply
->RetCode
) {
6262 PRINT("mig return %d", reply
->RetCode
);
6271 mach_msg_header_t Head
;
6273 task_flavor_t flavor
;
6274 mach_msg_type_number_t task_info_inCnt
;
6275 integer_t task_info_in
[52];
6279 Request
*req
= (Request
*)ARG1
;
6281 PRINT("task_set_info(%s) flavor:%d", name_for_port(MACH_REMOTE
), req
->flavor
);
6283 AFTER
= POST_FN(task_set_info
);
6290 mach_msg_header_t Head
;
6292 kern_return_t RetCode
;
6296 Reply
*reply
= (Reply
*)ARG1
;
6297 if (!reply
->RetCode
) {
6299 PRINT("mig return %d", reply
->RetCode
);
6307 mach_msg_header_t Head
;
6311 // Request *req = (Request *)ARG1;
6313 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE
));
6315 AFTER
= POST_FN(task_threads
);
6322 mach_msg_header_t Head
;
6323 /* start of the kernel processed data */
6324 mach_msg_body_t msgh_body
;
6325 mach_msg_ool_ports_descriptor_t act_list
;
6326 /* end of the kernel processed data */
6328 mach_msg_type_number_t act_listCnt
;
6329 mach_msg_trailer_t trailer
;
6333 Reply
*reply
= (Reply
*)ARG1
;
6335 if (MACH_REMOTE
== vg_task_port
) {
6336 assign_port_names(&reply
->act_list
, "thread-%p");
6338 assign_port_names(&reply
->act_list
, "remote-thread-%p");
6345 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE
));
6347 if (MACH_REMOTE
== vg_task_port
) {
6348 // GrP fixme self-suspend
6351 // suspend other - no problem
6354 AFTER
= POST_FN(task_suspend
);
6364 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE
));
6366 if (MACH_REMOTE
== vg_task_port
) {
6367 // GrP fixme self-resume
6370 // resume other - no problem
6373 AFTER
= POST_FN(task_resume
);
6385 mach_msg_header_t Head
;
6387 vm_address_t address
;
6393 Request
*req
= (Request
*)ARG1
;
6395 PRINT("vm_allocate (%s, at %#llx, size %llu, flags %#x)",
6396 name_for_port(MACH_REMOTE
),
6397 (ULong
)req
->address
, (ULong
)req
->size
, req
->flags
);
6399 MACH_ARG(vm_allocate
.size
) = req
->size
;
6400 MACH_ARG(vm_allocate
.flags
) = req
->flags
;
6402 AFTER
= POST_FN(vm_allocate
);
6409 mach_msg_header_t Head
;
6411 kern_return_t RetCode
;
6412 vm_address_t address
;
6413 mach_msg_trailer_t trailer
;
6417 Reply
*reply
= (Reply
*)ARG1
;
6419 if (!reply
->RetCode
) {
6420 if (MACH_REMOTE
== vg_task_port
) {
6421 PRINT("allocated at %#llx", (ULong
)reply
->address
);
6422 // requesting 0 bytes returns address 0 with no error
6423 if (MACH_ARG(vm_allocate
.size
)) {
6424 ML_(notify_core_and_tool_of_mmap
)(
6425 reply
->address
, MACH_ARG(vm_allocate
.size
),
6426 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_ANON
, -1, 0);
6429 PRINT("allocated at %#llx in remote task %s",
6430 (ULong
)reply
->address
,
6431 name_for_port(MACH_REMOTE
));
6434 PRINT("mig return %d", reply
->RetCode
);
6443 mach_msg_header_t Head
;
6445 vm_address_t address
;
6450 Request
*req
= (Request
*)ARG1
;
6452 PRINT("vm_deallocate(%s, at %#llx, size %llu)",
6453 name_for_port(MACH_REMOTE
),
6454 (ULong
)req
->address
, (ULong
)req
->size
);
6456 MACH_ARG(vm_deallocate
.address
) = req
->address
;
6457 MACH_ARG(vm_deallocate
.size
) = req
->size
;
6459 AFTER
= POST_FN(vm_deallocate
);
6461 // Must block to prevent race (other thread allocates and
6462 // notifies after we deallocate but before we notify)
6463 *flags
&= ~SfMayBlock
;
6470 mach_msg_header_t Head
;
6472 kern_return_t RetCode
;
6473 mach_msg_trailer_t trailer
;
6477 Reply
*reply
= (Reply
*)ARG1
;
6479 if (!reply
->RetCode
) {
6480 if (MACH_REMOTE
== vg_task_port
) {
6481 if (MACH_ARG(vm_deallocate
.size
)) {
6482 Addr start
= VG_PGROUNDDN(MACH_ARG(vm_deallocate
.address
));
6483 Addr end
= VG_PGROUNDUP(MACH_ARG(vm_deallocate
.address
) +
6484 MACH_ARG(vm_deallocate
.size
));
6485 // Must have cleared SfMayBlock in PRE to prevent race
6486 ML_(notify_core_and_tool_of_munmap
)(start
, end
- start
);
6490 PRINT("mig return %d", reply
->RetCode
);
6499 mach_msg_header_t Head
;
6501 vm_address_t address
;
6503 boolean_t set_maximum
;
6504 vm_prot_t new_protection
;
6508 Request
*req
= (Request
*)ARG1
;
6510 PRINT("vm_protect(%s, at %#llx, size %llu, set_max %d, prot %d)",
6511 name_for_port(MACH_REMOTE
),
6512 (ULong
)req
->address
, (ULong
)req
->size
,
6513 req
->set_maximum
, req
->new_protection
);
6515 MACH_ARG(vm_protect
.address
) = req
->address
;
6516 MACH_ARG(vm_protect
.size
) = req
->size
;
6517 MACH_ARG(vm_protect
.set_maximum
) = req
->set_maximum
;
6518 MACH_ARG(vm_protect
.new_protection
) = req
->new_protection
;
6520 AFTER
= POST_FN(vm_protect
);
6527 mach_msg_header_t Head
;
6529 kern_return_t RetCode
;
6530 mach_msg_trailer_t trailer
;
6534 Reply
*reply
= (Reply
*)ARG1
;
6536 if (!reply
->RetCode
) {
6537 if (MACH_REMOTE
== vg_task_port
) {
6538 Addr start
= VG_PGROUNDDN(MACH_ARG(vm_protect
.address
));
6539 Addr end
= VG_PGROUNDUP(MACH_ARG(vm_protect
.address
) +
6540 MACH_ARG(vm_protect
.size
));
6541 UInt prot
= MACH_ARG(vm_protect
.new_protection
);
6542 if (MACH_ARG(vm_protect
.set_maximum
)) {
6543 // GrP fixme mprotect max
6544 VG_(printf
)("UNKNOWN vm_protect set maximum");
6545 //VG_(mprotect_max_range)(start, end-start, prot);
6547 ML_(notify_core_and_tool_of_mprotect
)(start
, end
-start
, prot
);
6548 VG_(di_notify_vm_protect
)(start
, end
-start
, prot
);
6552 PRINT("mig return %d", reply
->RetCode
);
6561 mach_msg_header_t Head
;
6563 vm_address_t address
;
6565 vm_inherit_t new_inheritance
;
6569 Request
*req
= (Request
*)ARG1
;
6571 PRINT("vm_inherit(%s, at %#llx, size %llu, value %d)",
6572 name_for_port(MACH_REMOTE
),
6573 (ULong
)req
->address
, (ULong
)req
->size
,
6574 req
->new_inheritance
);
6576 AFTER
= POST_FN(vm_inherit
);
6583 mach_msg_header_t Head
;
6585 kern_return_t RetCode
;
6586 mach_msg_trailer_t trailer
;
6590 Reply
*reply
= (Reply
*)ARG1
;
6592 if (!reply
->RetCode
) {
6593 if (MACH_REMOTE
== vg_task_port
) {
6594 // GrP fixme do something?
6597 PRINT("mig return %d", reply
->RetCode
);
6606 mach_msg_header_t Head
;
6608 vm_address_t address
;
6613 Request
*req
= (Request
*)ARG1
;
6615 PRINT("vm_read(from %s at %#llx size %llu)",
6616 name_for_port(MACH_REMOTE
),
6617 (ULong
)req
->address
, (ULong
)req
->size
);
6619 MACH_ARG(vm_read
.addr
) = req
->address
;
6620 MACH_ARG(vm_read
.size
) = req
->size
;
6622 AFTER
= POST_FN(vm_read
);
6629 mach_msg_header_t Head
;
6630 /* start of the kernel processed data */
6631 mach_msg_body_t msgh_body
;
6632 mach_msg_ool_descriptor_t data
;
6633 /* end of the kernel processed data */
6635 mach_msg_type_number_t dataCnt
;
6639 // Reply *reply = (Reply *)ARG1;
6641 if (MACH_REMOTE
== vg_task_port
) {
6642 // vm_read from self
6643 // GrP fixme copy initialized state
6653 mach_msg_header_t Head
;
6655 mach_vm_address_t address
;
6656 mach_vm_size_t size
;
6660 Request
*req
= (Request
*)ARG1
;
6662 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6663 name_for_port(MACH_REMOTE
), req
->address
, req
->size
);
6665 MACH_ARG(mach_vm_read
.addr
) = req
->address
;
6666 MACH_ARG(mach_vm_read
.size
) = req
->size
;
6668 AFTER
= POST_FN(mach_vm_read
);
6675 mach_msg_header_t Head
;
6676 /* start of the kernel processed data */
6677 mach_msg_body_t msgh_body
;
6678 mach_msg_ool_descriptor_t data
;
6679 /* end of the kernel processed data */
6681 mach_msg_type_number_t dataCnt
;
6685 // Reply *reply = (Reply *)ARG1;
6687 if (MACH_REMOTE
== vg_task_port
) {
6688 // vm_read from self
6689 // GrP fixme copy initialized state
6694 PRE(vm_read_overwrite
)
6698 mach_msg_header_t Head
;
6700 vm_address_t address
;
6706 Request
*req
= (Request
*)ARG1
;
6708 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6709 name_for_port(MACH_REMOTE
),
6710 (ULong
)req
->address
, (ULong
)req
->size
, (ULong
)req
->data
);
6712 MACH_ARG(vm_read_overwrite
.addr
) = req
->address
;
6713 MACH_ARG(vm_read_overwrite
.size
) = req
->size
;
6714 MACH_ARG(vm_read_overwrite
.data
) = req
->data
;
6716 PRE_MEM_WRITE("vm_read_overwrite(data)", req
->data
, req
->size
);
6718 AFTER
= POST_FN(vm_read_overwrite
);
6721 POST(vm_read_overwrite
)
6725 mach_msg_header_t Head
;
6727 kern_return_t RetCode
;
6732 Reply
*reply
= (Reply
*)ARG1
;
6734 if (reply
->RetCode
) {
6735 PRINT("mig return %d", reply
->RetCode
);
6737 PRINT("read %llu bytes", (unsigned long long)reply
->outsize
);
6738 if (MACH_REMOTE
== vg_task_port
) {
6739 // vm_read_overwrite from self
6740 // GrP fixme copy initialized state
6741 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite
.data
), reply
->outsize
);
6743 // vm_read_overwrite from remote
6744 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite
.data
), reply
->outsize
);
6754 mach_msg_header_t Head
;
6756 vm_address_t source_address
;
6758 vm_address_t dest_address
;
6762 Request
*req
= (Request
*)ARG1
;
6764 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6765 name_for_port(MACH_REMOTE
),
6766 (ULong
)req
->source_address
,
6767 (ULong
)req
->size
, (ULong
)req
->dest_address
);
6769 MACH_ARG(vm_copy
.src
) = req
->source_address
;
6770 MACH_ARG(vm_copy
.dst
) = req
->dest_address
;
6771 MACH_ARG(vm_copy
.size
) = req
->size
;
6773 AFTER
= POST_FN(vm_copy
);
6780 mach_msg_header_t Head
;
6782 kern_return_t RetCode
;
6783 mach_msg_trailer_t trailer
;
6787 Reply
*reply
= (Reply
*)ARG1
;
6789 if (!reply
->RetCode
) {
6790 if (MACH_REMOTE
== vg_task_port
) {
6791 // GrP fixme set dst's initialization equal to src's
6792 // and wipe any symbols or translations in dst
6795 PRINT("mig return %d", reply
->RetCode
);
6804 mach_msg_header_t Head
;
6805 /* start of the kernel processed data */
6806 mach_msg_body_t msgh_body
;
6807 mach_msg_port_descriptor_t object
;
6808 /* end of the kernel processed data */
6810 vm_address_t address
;
6816 vm_prot_t cur_protection
;
6817 vm_prot_t max_protection
;
6818 vm_inherit_t inheritance
;
6822 Request
*req
= (Request
*)ARG1
;
6824 // GrP fixme check these
6825 PRINT("vm_map(in %s, at %#llx, size %llu, from %s ...)",
6826 name_for_port(MACH_REMOTE
),
6827 (ULong
)req
->address
, (ULong
)req
->size
,
6828 name_for_port(req
->object
.name
));
6830 MACH_ARG(vm_map
.size
) = req
->size
;
6831 MACH_ARG(vm_map
.copy
) = req
->copy
;
6832 MACH_ARG(vm_map
.protection
) = (req
->cur_protection
& req
->max_protection
);
6834 AFTER
= POST_FN(vm_map
);
6841 mach_msg_header_t Head
;
6843 kern_return_t RetCode
;
6844 vm_address_t address
;
6845 mach_msg_trailer_t trailer
;
6849 Reply
*reply
= (Reply
*)ARG1
;
6851 if (!reply
->RetCode
) {
6852 // GrP fixme check src and dest tasks
6853 PRINT("mapped at %#llx", (ULong
)reply
->address
);
6854 // GrP fixme max prot
6855 ML_(notify_core_and_tool_of_mmap
)(
6856 reply
->address
, VG_PGROUNDUP(MACH_ARG(vm_map
.size
)),
6857 MACH_ARG(vm_map
.protection
), VKI_MAP_SHARED
, -1, 0);
6858 // GrP fixme VKI_MAP_PRIVATE if !copy?
6860 PRINT("mig return %d", reply
->RetCode
);
6869 mach_msg_header_t Head
;
6870 /* start of the kernel processed data */
6871 mach_msg_body_t msgh_body
;
6872 mach_msg_port_descriptor_t src_task
;
6873 /* end of the kernel processed data */
6875 vm_address_t target_address
;
6879 vm_address_t src_address
;
6881 vm_inherit_t inheritance
;
6885 Request
*req
= (Request
*)ARG1
;
6887 // GrP fixme check src and dest tasks
6889 if (VG_(clo_trace_syscalls
)) {
6890 mach_port_name_t source_task
= req
->src_task
.name
;
6891 if (source_task
== mach_task_self()) {
6892 PRINT("vm_remap(mach_task_self(), "
6893 "to %#llx size %llu, from mach_task_self() at %#llx, ...)",
6894 (ULong
)req
->target_address
,
6895 (ULong
)req
->size
, (ULong
)req
->src_address
);
6897 PRINT("vm_remap(mach_task_self(), "
6898 "to %#llx size %llu, from task %u at %#llx, ...)",
6899 (ULong
)req
->target_address
, (ULong
)req
->size
,
6900 source_task
, (ULong
)req
->src_address
);
6905 // vt->syscall_arg2 = req->target_address;
6906 MACH_ARG(vm_remap
.size
) = req
->size
;
6907 // vt->syscall_arg4 = req->copy;
6909 AFTER
= POST_FN(vm_remap
);
6916 mach_msg_header_t Head
;
6918 kern_return_t RetCode
;
6919 vm_address_t target_address
;
6920 vm_prot_t cur_protection
;
6921 vm_prot_t max_protection
;
6922 mach_msg_trailer_t trailer
;
6926 Reply
*reply
= (Reply
*)ARG1
;
6928 if (!reply
->RetCode
) {
6929 // GrP fixme check src and dest tasks
6930 UInt prot
= reply
->cur_protection
& reply
->max_protection
;
6931 // GrP fixme max prot
6932 PRINT("mapped at %#llx", (ULong
)reply
->target_address
);
6933 ML_(notify_core_and_tool_of_mmap
)(
6934 reply
->target_address
, VG_PGROUNDUP(MACH_ARG(vm_remap
.size
)),
6935 prot
, VKI_MAP_SHARED
, -1, 0);
6936 // GrP fixme VKI_MAP_FIXED if !copy?
6937 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6939 PRINT("mig return %d", reply
->RetCode
);
6944 PRE(mach_make_memory_entry_64
)
6948 mach_msg_header_t Head
;
6949 /* start of the kernel processed data */
6950 mach_msg_body_t msgh_body
;
6951 mach_msg_port_descriptor_t parent_entry
;
6952 /* end of the kernel processed data */
6954 memory_object_size_t size
;
6955 memory_object_offset_t offset
;
6956 vm_prot_t permission
;
6960 Request
*req
= (Request
*)ARG1
;
6962 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6963 name_for_port(MACH_REMOTE
),
6964 req
->size
, req
->offset
, req
->permission
, req
->parent_entry
.type
);
6966 AFTER
= POST_FN(mach_make_memory_entry_64
);
6969 POST(mach_make_memory_entry_64
)
6973 mach_msg_header_t Head
;
6974 mach_msg_body_t msgh_body
;
6975 mach_msg_port_descriptor_t object
;
6977 memory_object_size_t size
;
6981 Reply
*reply
= (Reply
*)ARG1
;
6983 if (reply
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
6984 assign_port_name(reply
->object
.name
, "memory-%p");
6985 PRINT("%s", name_for_port(reply
->object
.name
));
6990 PRE(vm_purgable_control
)
6994 mach_msg_header_t Head
;
6996 vm_address_t address
;
6997 vm_purgable_t control
;
7002 Request
*req
= (Request
*)ARG1
;
7004 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
7005 name_for_port(MACH_REMOTE
),
7006 (ULong
)req
->address
, req
->control
, req
->state
);
7008 // GrP fixme verify address?
7010 AFTER
= POST_FN(vm_purgable_control
);
7013 POST(vm_purgable_control
)
7017 mach_msg_header_t Head
;
7019 kern_return_t RetCode
;
7024 Reply
*reply
= (Reply
*)ARG1
;
7026 if (!reply
->RetCode
) {
7028 PRINT("mig return %d", reply
->RetCode
);
7033 PRE(mach_vm_purgable_control
)
7037 mach_msg_header_t Head
;
7039 mach_vm_address_t address
;
7040 vm_purgable_t control
;
7045 Request
*req
= (Request
*)ARG1
;
7047 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
7048 name_for_port(MACH_REMOTE
),
7049 (ULong
)req
->address
, req
->control
, req
->state
);
7051 // GrP fixme verify address?
7053 AFTER
= POST_FN(mach_vm_purgable_control
);
7056 POST(mach_vm_purgable_control
)
7060 mach_msg_header_t Head
;
7062 kern_return_t RetCode
;
7067 Reply
*reply
= (Reply
*)ARG1
;
7069 if (!reply
->RetCode
) {
7071 PRINT("mig return %d", reply
->RetCode
);
7076 PRE(mach_vm_allocate
)
7080 mach_msg_header_t Head
;
7082 mach_vm_address_t address
;
7083 mach_vm_size_t size
;
7088 Request
*req
= (Request
*)ARG1
;
7090 PRINT("mach_vm_allocate (%s, at 0x%llx, size %llu, flags 0x%x)",
7091 name_for_port(MACH_REMOTE
),
7092 req
->address
, req
->size
, req
->flags
);
7094 MACH_ARG(mach_vm_allocate
.size
) = req
->size
;
7095 MACH_ARG(mach_vm_allocate
.flags
) = req
->flags
;
7097 AFTER
= POST_FN(mach_vm_allocate
);
7100 POST(mach_vm_allocate
)
7104 mach_msg_header_t Head
;
7106 kern_return_t RetCode
;
7107 mach_vm_address_t address
;
7108 mach_msg_trailer_t trailer
;
7112 Reply
*reply
= (Reply
*)ARG1
;
7114 if (!reply
->RetCode
) {
7115 if (MACH_REMOTE
== vg_task_port
) {
7116 PRINT("allocated at 0x%llx", reply
->address
);
7117 // requesting 0 bytes returns address 0 with no error
7118 if (MACH_ARG(mach_vm_allocate
.size
)) {
7119 ML_(notify_core_and_tool_of_mmap
)(
7120 reply
->address
, MACH_ARG(mach_vm_allocate
.size
),
7121 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_ANON
, -1, 0);
7124 PRINT("allocated at 0x%llx in remote task %s", reply
->address
,
7125 name_for_port(MACH_REMOTE
));
7128 PRINT("mig return %d", reply
->RetCode
);
7133 PRE(mach_vm_deallocate
)
7137 mach_msg_header_t Head
;
7139 mach_vm_address_t address
;
7140 mach_vm_size_t size
;
7144 Request
*req
= (Request
*)ARG1
;
7146 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %llu)",
7147 name_for_port(MACH_REMOTE
),
7148 req
->address
, req
->size
);
7150 MACH_ARG(mach_vm_deallocate
.address
) = req
->address
;
7151 MACH_ARG(mach_vm_deallocate
.size
) = req
->size
;
7153 AFTER
= POST_FN(mach_vm_deallocate
);
7155 // Must block to prevent race (other thread allocates and
7156 // notifies after we deallocate but before we notify)
7157 *flags
&= ~SfMayBlock
;
7160 POST(mach_vm_deallocate
)
7164 mach_msg_header_t Head
;
7166 kern_return_t RetCode
;
7167 mach_msg_trailer_t trailer
;
7171 Reply
*reply
= (Reply
*)ARG1
;
7173 if (!reply
->RetCode
) {
7174 if (MACH_REMOTE
== vg_task_port
) {
7175 if (MACH_ARG(mach_vm_deallocate
.size
)) {
7176 Addr start
= VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate
.address
));
7177 Addr end
= VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate
.address
) +
7178 MACH_ARG(mach_vm_deallocate
.size
));
7179 // Must have cleared SfMayBlock in PRE to prevent race
7180 ML_(notify_core_and_tool_of_munmap
)(start
, end
- start
);
7184 PRINT("mig return %d", reply
->RetCode
);
7189 PRE(mach_vm_protect
)
7193 mach_msg_header_t Head
;
7195 mach_vm_address_t address
;
7196 mach_vm_size_t size
;
7197 boolean_t set_maximum
;
7198 vm_prot_t new_protection
;
7202 Request
*req
= (Request
*)ARG1
;
7204 PRINT("mach_vm_protect(%s, at 0x%llx, size %llu, set_max %d, prot %d)",
7205 name_for_port(MACH_REMOTE
), req
->address
, req
->size
,
7206 req
->set_maximum
, req
->new_protection
);
7208 MACH_ARG(mach_vm_protect
.address
) = req
->address
;
7209 MACH_ARG(mach_vm_protect
.size
) = req
->size
;
7210 MACH_ARG(mach_vm_protect
.set_maximum
) = req
->set_maximum
;
7211 MACH_ARG(mach_vm_protect
.new_protection
) = req
->new_protection
;
7213 AFTER
= POST_FN(mach_vm_protect
);
7216 POST(mach_vm_protect
)
7220 mach_msg_header_t Head
;
7222 kern_return_t RetCode
;
7223 mach_msg_trailer_t trailer
;
7227 Reply
*reply
= (Reply
*)ARG1
;
7229 if (!reply
->RetCode
) {
7230 if (MACH_REMOTE
== vg_task_port
) {
7231 Addr start
= VG_PGROUNDDN(MACH_ARG(mach_vm_protect
.address
));
7232 Addr end
= VG_PGROUNDUP(MACH_ARG(mach_vm_protect
.address
) +
7233 MACH_ARG(mach_vm_protect
.size
));
7234 UInt prot
= MACH_ARG(mach_vm_protect
.new_protection
);
7235 if (MACH_ARG(mach_vm_protect
.set_maximum
)) {
7236 // DDD: #warning GrP fixme mprotect max
7237 //VG_(mprotect_max_range)(start, end-start, prot);
7239 ML_(notify_core_and_tool_of_mprotect
)(start
, end
-start
, prot
);
7243 PRINT("mig return %d", reply
->RetCode
);
7248 PRE(mach_vm_inherit
)
7252 mach_msg_header_t Head
;
7254 mach_vm_address_t address
;
7255 mach_vm_size_t size
;
7256 vm_inherit_t new_inheritance
;
7260 Request
*req
= (Request
*)ARG1
;
7262 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
7263 name_for_port(MACH_REMOTE
),
7264 req
->address
, req
->size
, req
->new_inheritance
);
7266 AFTER
= POST_FN(mach_vm_inherit
);
7269 POST(mach_vm_inherit
)
7273 mach_msg_header_t Head
;
7275 kern_return_t RetCode
;
7276 mach_msg_trailer_t trailer
;
7280 Reply
*reply
= (Reply
*)ARG1
;
7282 if (!reply
->RetCode
) {
7283 // no V-visible side effects
7284 // GrP fixme except maybe fork/exec
7286 PRINT("mig return %d", reply
->RetCode
);
7295 mach_msg_header_t Head
;
7297 mach_vm_address_t source_address
;
7298 mach_vm_size_t size
;
7299 mach_vm_address_t dest_address
;
7303 Request
*req
= (Request
*)ARG1
;
7305 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
7306 name_for_port(MACH_REMOTE
),
7307 req
->source_address
, req
->size
, req
->dest_address
);
7310 // vt->syscall_arg2 = req->source_address;
7311 // vt->syscall_arg3 = req->size;
7312 // vt->syscall_arg4 = req->dest_address;
7314 AFTER
= POST_FN(mach_vm_copy
);
7321 mach_msg_header_t Head
;
7323 kern_return_t RetCode
;
7324 mach_msg_trailer_t trailer
;
7328 Reply
*reply
= (Reply
*)ARG1
;
7330 if (!reply
->RetCode
) {
7331 if (MACH_REMOTE
== vg_task_port
) {
7332 // GrP fixme set dest's initialization equal to src's
7333 // BUT vm_copy allocates no memory
7336 PRINT("mig return %d", reply
->RetCode
);
7340 PRE(mach_vm_read_overwrite
)
7344 mach_msg_header_t Head
;
7346 mach_vm_address_t address
;
7347 mach_vm_size_t size
;
7348 mach_vm_address_t data
;
7352 Request
*req
= (Request
*)ARG1
;
7354 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
7355 name_for_port(MACH_REMOTE
),
7356 req
->address
, req
->size
, req
->data
);
7358 AFTER
= POST_FN(mach_vm_read_overwrite
);
7361 POST(mach_vm_read_overwrite
)
7365 mach_msg_header_t Head
;
7367 kern_return_t RetCode
;
7368 mach_vm_size_t outsize
;
7372 Reply
*reply
= (Reply
*)ARG1
;
7374 if (!reply
->RetCode
) {
7375 if (MACH_REMOTE
== vg_task_port
) {
7376 // GrP fixme set dest's initialization equal to src's
7377 // BUT vm_copy allocates no memory
7380 PRINT("mig return %d", reply
->RetCode
);
7388 mach_msg_header_t Head
;
7389 /* start of the kernel processed data */
7390 mach_msg_body_t msgh_body
;
7391 mach_msg_port_descriptor_t object
;
7392 /* end of the kernel processed data */
7394 mach_vm_address_t address
;
7395 mach_vm_size_t size
;
7396 mach_vm_address_t mask
;
7398 memory_object_offset_t offset
;
7400 vm_prot_t cur_protection
;
7401 vm_prot_t max_protection
;
7402 vm_inherit_t inheritance
;
7406 Request
*req
= (Request
*)ARG1
;
7408 // GrP fixme check these
7409 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7410 name_for_port(req
->Head
.msgh_remote_port
),
7411 name_for_port(req
->object
.name
),
7412 req
->address
, req
->size
,
7413 req
->cur_protection
,
7414 req
->max_protection
);
7416 MACH_ARG(mach_vm_map
.size
) = req
->size
;
7417 MACH_ARG(mach_vm_map
.copy
) = req
->copy
;
7418 MACH_ARG(mach_vm_map
.protection
) =
7419 (req
->cur_protection
& req
->max_protection
);
7421 AFTER
= POST_FN(mach_vm_map
);
7428 mach_msg_header_t Head
;
7430 kern_return_t RetCode
;
7431 mach_vm_address_t address
;
7432 mach_msg_trailer_t trailer
;
7436 Reply
*reply
= (Reply
*)ARG1
;
7438 if (!reply
->RetCode
) {
7439 // GrP fixme check src and dest tasks
7440 PRINT("mapped at 0x%llx", reply
->address
);
7442 // GrP fixme max prot
7443 ML_(notify_core_and_tool_of_mmap
)(
7444 reply
->address
, VG_PGROUNDUP(MACH_ARG(mach_vm_map
.size
)),
7445 MACH_ARG(mach_vm_map
.protection
), VKI_MAP_SHARED
, -1, 0);
7446 // GrP fixme VKI_MAP_PRIVATE if !copy?
7448 ML_(sync_mappings
)("after", "mach_vm_map", 0);
7451 PRINT("mig return %d", reply
->RetCode
);
7460 mach_msg_header_t Head
;
7461 /* start of the kernel processed data */
7462 mach_msg_body_t msgh_body
;
7463 mach_msg_port_descriptor_t src_task
;
7464 /* end of the kernel processed data */
7466 mach_vm_address_t target_address
;
7467 mach_vm_size_t size
;
7468 mach_vm_offset_t mask
;
7470 mach_vm_address_t src_address
;
7472 vm_inherit_t inheritance
;
7476 Request
*req
= (Request
*)ARG1
;
7478 // GrP fixme check these
7479 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7480 name_for_port(MACH_REMOTE
),
7481 req
->target_address
, req
->size
,
7482 name_for_port(req
->src_task
.name
));
7484 MACH_ARG(mach_vm_remap
.size
) = req
->size
;
7485 MACH_ARG(mach_vm_remap
.copy
) = req
->copy
;
7487 AFTER
= POST_FN(mach_vm_remap
);
7494 mach_msg_header_t Head
;
7496 kern_return_t RetCode
;
7497 mach_vm_address_t target_address
;
7498 vm_prot_t cur_protection
;
7499 vm_prot_t max_protection
;
7503 Reply
*reply
= (Reply
*)ARG1
;
7505 if (!reply
->RetCode
) {
7506 // GrP fixme check src and dest tasks
7507 PRINT("mapped at 0x%llx", reply
->target_address
);
7508 // GrP fixme max prot
7509 ML_(notify_core_and_tool_of_mmap
)(
7510 reply
->target_address
, VG_PGROUNDUP(MACH_ARG(mach_vm_remap
.size
)),
7511 reply
->cur_protection
, VKI_MAP_SHARED
, -1, 0);
7512 // GrP fixme VKI_MAP_PRIVATE if !copy?
7514 PRINT("mig return %d", reply
->RetCode
);
7519 PRE(mach_vm_region_recurse
)
7523 mach_msg_header_t Head
;
7525 mach_vm_address_t address
;
7526 natural_t nesting_depth
;
7527 mach_msg_type_number_t infoCnt
;
7531 Request
*req
= (Request
*)ARG1
;
7533 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7534 name_for_port(MACH_REMOTE
),
7535 req
->address
, req
->nesting_depth
, req
->infoCnt
);
7537 AFTER
= POST_FN(mach_vm_region_recurse
);
7540 POST(mach_vm_region_recurse
)
7544 mach_msg_header_t Head
;
7546 kern_return_t RetCode
;
7547 mach_vm_address_t address
;
7548 mach_vm_size_t size
;
7549 natural_t nesting_depth
;
7550 mach_msg_type_number_t infoCnt
;
7555 Reply
*reply
= (Reply
*)ARG1
;
7557 if (!reply
->RetCode
) {
7558 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7559 reply
->address
, reply
->size
,
7560 reply
->nesting_depth
, reply
->infoCnt
);
7561 // GrP fixme mark info contents beyond infoCnt as bogus
7563 PRINT("mig return %d", reply
->RetCode
);
7568 /* ---------------------------------------------------------------------
7569 mach_msg: messages to thread
7570 ------------------------------------------------------------------ */
7574 POST(thread_terminate
)
7579 PRE(thread_terminate
)
7581 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7582 Bool self_terminate
= (mh
->msgh_request_port
== MACH_THREAD
);
7584 PRINT("thread_terminate(%s)", name_for_port(mh
->msgh_request_port
));
7586 AFTER
= POST_FN(thread_terminate
);
7588 if (self_terminate
) {
7589 // Terminating this thread.
7590 // Copied from sys_exit.
7591 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
7592 tst
->exitreason
= VgSrc_ExitThread
;
7593 tst
->os_state
.exitcode
= 0; // GrP fixme anything better?
7594 // What we would like to do is:
7595 // SET_STATUS_Success(0);
7596 // but that doesn't work, because this is a MACH-class syscall,
7597 // and SET_STATUS_Success creates a UNIX-class syscall result.
7598 // Hence we have to laboriously construct the full SysRes "by hand"
7599 // and use that to set the syscall return status.
7600 #if defined(VGA_x86)
7601 SET_STATUS_from_SysRes(
7602 VG_(mk_SysRes_x86_darwin
)(
7603 VG_DARWIN_SYSCALL_CLASS_MACH
,
7604 False
/*success*/, 0, 0
7607 #elif defined(VGA_amd64)
7608 SET_STATUS_from_SysRes(
7609 VG_(mk_SysRes_amd64_darwin
)(
7610 VG_DARWIN_SYSCALL_CLASS_MACH
,
7611 False
/*success*/, 0, 0
7615 #error unknown architecture
7617 *flags
&= ~SfMayBlock
; // clear flag set by PRE(mach_msg)
7619 // Terminating some other thread.
7620 // Do keep the scheduler lock while terminating any other thread.
7621 // Otherwise we might halt the other thread while it holds the lock,
7622 // which would deadlock the process.
7623 // GrP fixme good enough?
7624 // GrP fixme need to clean up other thread's valgrind data?
7636 PRINT("thread_create(mach_task_self(), ...)");
7638 AFTER
= POST_FN(thread_create
);
7641 VG_(core_panic
)("thread_create() unimplemented");
7645 PRE(thread_create_running
)
7649 mach_msg_header_t Head
;
7651 thread_state_flavor_t flavor
;
7652 mach_msg_type_number_t new_stateCnt
;
7653 natural_t new_state
[144];
7658 thread_state_t regs
;
7659 ThreadState
*new_thread
;
7661 PRINT("thread_create_running(mach_task_self(), ...)");
7663 // The new thread will immediately begin execution,
7664 // so we need to hijack the register state here.
7666 req
= (Request
*)ARG1
;
7667 regs
= (thread_state_t
)req
->new_state
;
7669 // Build virtual thread.
7670 new_thread
= build_thread(regs
, req
->flavor
, req
->new_stateCnt
);
7672 // Edit the thread state to send to the real kernel.
7673 hijack_thread_state(regs
, req
->flavor
, req
->new_stateCnt
, new_thread
);
7675 AFTER
= POST_FN(thread_create_running
);
7679 POST(thread_create_running
)
7683 mach_msg_header_t Head
;
7684 /* start of the kernel processed data */
7685 mach_msg_body_t msgh_body
;
7686 mach_msg_port_descriptor_t child_act
;
7687 /* end of the kernel processed data */
7691 Reply
*reply
= (Reply
*)ARG1
;
7693 assign_port_name(reply
->child_act
.name
, "thread-%p");
7694 PRINT("%s", name_for_port(reply
->child_act
.name
));
7698 PRE(bsdthread_create
)
7702 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7703 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
7704 PRE_REG_READ5(pthread_t
,"bsdthread_create",
7705 void *,"func", void *,"func_arg", void *,"stack",
7706 pthread_t
,"thread", unsigned int,"flags");
7708 // The kernel will call V's pthread_hijack() to launch the thread.
7709 // Here we allocate the thread state and pass it to pthread_hijack()
7710 // via the func_arg parameter.
7712 tst
= VG_(get_ThreadState
)(VG_(alloc_ThreadState
)());
7713 allocstack(tst
->tid
);
7715 tst
->os_state
.func_arg
= (Addr
)ARG2
;
7718 // Create a semaphore that pthread_hijack will signal once it starts
7719 // POST(bsdthread_create) needs to wait for the new memory map to appear
7720 semaphore_create(mach_task_self(), &tst
->os_state
.child_go
,
7721 SYNC_POLICY_FIFO
, 0);
7722 semaphore_create(mach_task_self(), &tst
->os_state
.child_done
,
7723 SYNC_POLICY_FIFO
, 0);
7726 POST(bsdthread_create
)
7728 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7729 // We hold V's lock on the child's behalf.
7730 // If we return before letting pthread_hijack do its thing, V thinks
7731 // the new pthread struct is still unmapped when we return to libc,
7732 // causing false errors.
7734 ThreadState
*tst
= (ThreadState
*)ARG2
;
7735 semaphore_signal(tst
->os_state
.child_go
);
7736 semaphore_wait(tst
->os_state
.child_done
);
7737 semaphore_destroy(mach_task_self(), tst
->os_state
.child_go
);
7738 semaphore_destroy(mach_task_self(), tst
->os_state
.child_done
);
7740 // GrP fixme semaphore destroy needed when thread creation fails
7741 // GrP fixme probably other cleanup too
7742 // GrP fixme spinlocks might be good enough?
7744 // DDD: I'm not at all sure this is the right spot for this. It probably
7745 // should be in pthread_hijack instead, just before the call to
7746 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7747 // parent tid value there...
7748 vg_assert(VG_(owns_BigLock_LL
)(tid
));
7749 VG_TRACK ( pre_thread_ll_create
, tid
, tst
->tid
);
7753 PRE(bsdthread_terminate
)
7757 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7758 ARG1
, ARG2
, name_for_port(ARG3
), name_for_port(ARG4
));
7759 PRE_REG_READ4(int,"bsdthread_terminate",
7760 void *,"freeaddr", size_t,"freesize",
7761 mach_port_t
,"kport", mach_port_t
,"joinsem");
7763 // Free memory and signal semaphore.
7764 // GrP fixme errors?
7765 if (ARG4
) semaphore_signal((semaphore_t
)ARG4
);
7767 ML_(notify_core_and_tool_of_munmap
)(ARG1
, ARG2
);
7768 # if DARWIN_VERS >= DARWIN_10_8
7769 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7770 the mig output. Work around it for the time being. */
7771 VG_(do_syscall2
)(__NR_munmap
, ARG1
, ARG2
);
7773 vm_deallocate(mach_task_self(), (vm_address_t
)ARG1
, (vm_size_t
)ARG2
);
7777 // Tell V to terminate the thread.
7778 // Copied from sys_exit.
7779 tst
= VG_(get_ThreadState
)(tid
);
7780 tst
->exitreason
= VgSrc_ExitThread
;
7781 tst
->os_state
.exitcode
= 0; // GrP fixme anything better?
7782 SET_STATUS_Success(0);
7786 POST(thread_suspend
)
7792 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7793 Bool self_suspend
= (mh
->msgh_request_port
== MACH_THREAD
);
7795 PRINT("thread_suspend(%s)", name_for_port(mh
->msgh_request_port
));
7797 AFTER
= POST_FN(thread_suspend
);
7800 // Don't keep the scheduler lock while self-suspending.
7801 // Otherwise we might halt while still holding the lock,
7802 // which would deadlock the process.
7803 *flags
|= SfMayBlock
;
7805 // Do keep the scheduler lock while suspending any other thread.
7806 // Otherwise we might halt the other thread while it holds the lock,
7807 // which would deadlock the process.
7808 *flags
&= ~SfMayBlock
;
7819 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7820 Bool self_resume
= (mh
->msgh_request_port
== MACH_THREAD
);
7822 PRINT("thread_resume(%s)", name_for_port(mh
->msgh_request_port
));
7824 AFTER
= POST_FN(thread_resume
);
7827 // This doesn't make much sense. If we are resuming ourself, we can't
7828 // already be running. So I don't see how we can ever get here.
7831 // Resuming some other thread. It might not yet come back to life
7832 // (if the suspend count is still above zero) so make sure we keep
7833 // holding the lock.
7834 *flags
&= ~SfMayBlock
;
7839 POST(thread_get_state
)
7843 mach_msg_header_t Head
;
7845 kern_return_t RetCode
;
7846 mach_msg_type_number_t old_stateCnt
;
7847 natural_t old_state
[144];
7848 mach_msg_trailer_t trailer
;
7852 Reply
*reply
= (Reply
*)ARG1
;
7853 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7854 thread_state_flavor_t flavor
= MACH_ARG(thread_get_state
.flavor
);
7856 if (!reply
->RetCode
) {
7857 thread_state_from_vex((thread_state_t
)reply
->old_state
,
7858 flavor
, reply
->old_stateCnt
,
7859 &VG_(get_ThreadState
)(tid
)->arch
.vex
);
7861 PRINT("mig return %d", reply
->RetCode
);
7865 PRE(thread_get_state
)
7869 mach_msg_header_t Head
;
7871 thread_state_flavor_t flavor
;
7872 mach_msg_type_number_t old_stateCnt
;
7876 Request
*req
= (Request
*)ARG1
;
7877 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7879 // GrP fixme if (self) {
7880 PRINT("thread_get_state(%s, %d)",
7881 name_for_port(req
->Head
.msgh_request_port
), req
->flavor
);
7883 PRINT("thread_get_state(0x%x, %d)",
7884 req->Head.msgh_request_port, req->flavor);
7887 // Hack the thread state after making the real call.
7888 MACH_ARG(thread_get_state
.thread
) = req
->Head
.msgh_request_port
;
7889 MACH_ARG(thread_get_state
.flavor
) = req
->flavor
;
7891 AFTER
= POST_FN(thread_get_state
);
7897 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7898 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7900 // GrP fixme if (self) {
7901 PRINT("thread_policy(%s, ...)", name_for_port(mh
->msgh_request_port
));
7903 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7906 AFTER
= POST_FN(thread_policy
);
7914 PRE(thread_policy_set
)
7916 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7918 PRINT("thread_policy_set(%s, ...)", name_for_port(mh
->msgh_request_port
));
7920 AFTER
= POST_FN(thread_policy_set
);
7923 POST(thread_policy_set
)
7930 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
7932 PRINT("thread_info(%s, ...)", name_for_port(mh
->msgh_request_port
));
7933 // GrP fixme does any thread info need to be hijacked?
7935 AFTER
= POST_FN(thread_info
);
7940 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7945 /* ---------------------------------------------------------------------
7946 mach_msg: messages to bootstrap port
7947 ------------------------------------------------------------------ */
7950 POST(bootstrap_register
)
7954 mach_msg_header_t Head
;
7956 kern_return_t RetCode
;
7957 mach_msg_trailer_t trailer
;
7961 Reply
*reply
= (Reply
*)ARG1
;
7963 if (reply
->RetCode
) PRINT("mig return %d", reply
->RetCode
);
7966 PRE(bootstrap_register
)
7970 mach_msg_header_t Head
;
7971 /* start of the kernel processed data */
7972 mach_msg_body_t msgh_body
;
7973 mach_msg_port_descriptor_t service_port
;
7974 /* end of the kernel processed data */
7976 name_t service_name
;
7980 Request
*req
= (Request
*)ARG1
;
7982 PRINT("bootstrap_register(port 0x%x, \"%s\")",
7983 req
->service_port
.name
, req
->service_name
);
7985 /* The required entry in the allocated_ports list (mapping) might
7986 not exist, due perhaps to broken syscall wrappers (mach__N etc).
7987 Create a minimal entry so that assign_port_name below doesn't
7988 cause an assertion. */
7989 if (!port_exists(req
->service_port
.name
)) {
7990 port_create_vanilla(req
->service_port
.name
);
7993 assign_port_name(req
->service_port
.name
, req
->service_name
);
7995 AFTER
= POST_FN(bootstrap_register
);
7999 POST(bootstrap_look_up
)
8003 mach_msg_header_t Head
;
8004 /* start of the kernel processed data */
8005 mach_msg_body_t msgh_body
;
8006 mach_msg_port_descriptor_t service_port
;
8007 /* end of the kernel processed data */
8008 mach_msg_trailer_t trailer
;
8012 Reply
*reply
= (Reply
*)ARG1
;
8014 if ((reply
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
) &&
8015 reply
->service_port
.name
)
8017 assign_port_name(reply
->service_port
.name
,
8018 MACH_ARG(bootstrap_look_up
.service_name
));
8019 PRINT("%s", name_for_port(reply
->service_port
.name
));
8023 VG_(free
)(MACH_ARG(bootstrap_look_up
.service_name
));
8026 PRE(bootstrap_look_up
)
8030 mach_msg_header_t Head
;
8032 name_t service_name
;
8036 Request
*req
= (Request
*)ARG1
;
8038 PRINT("bootstrap_look_up(\"%s\")", req
->service_name
);
8040 MACH_ARG(bootstrap_look_up
.service_name
) =
8041 VG_(strdup
)("syswrap-darwin.bootstrap-name", req
->service_name
);
8043 AFTER
= POST_FN(bootstrap_look_up
);
8047 /* ---------------------------------------------------------------------
8048 mach_msg: receiver-specific handlers
8049 ------------------------------------------------------------------ */
8052 POST(mach_msg_receive
)
8054 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8056 // GrP fixme don't know of anything interesting here currently
8057 // import_complex_message handles everything
8058 // PRINT("UNHANDLED reply %d", mh->msgh_id);
8060 // Assume the call may have mapped or unmapped memory
8061 ML_(sync_mappings
)("after", "mach_msg_receive", mh
->msgh_id
);
8064 PRE(mach_msg_receive
)
8066 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8068 PRINT("mach_msg_receive(port %s)", name_for_port(mh
->msgh_reply_port
));
8070 AFTER
= POST_FN(mach_msg_receive
);
8072 // no message sent, only listening for a reply
8073 // assume message may block
8074 *flags
|= SfMayBlock
;
8078 PRE(mach_msg_bootstrap
)
8080 // message to bootstrap port
8082 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8084 switch (mh
->msgh_id
) {
8086 CALL_PRE(bootstrap_register
);
8089 CALL_PRE(bootstrap_look_up
);
8093 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
8094 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8095 mh
->msgh_reply_port
);
8103 // message to host self - check for host-level kernel calls
8105 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8107 switch (mh
->msgh_id
) {
8109 CALL_PRE(host_info
);
8112 CALL_PRE(host_page_size
);
8115 CALL_PRE(host_get_io_master
);
8118 CALL_PRE(host_get_clock_service
);
8121 CALL_PRE(host_request_notification
);
8124 CALL_PRE(host_create_mach_voucher
);
8128 CALL_PRE(host_get_special_port
);
8132 // unknown message to host self
8133 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
8134 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8135 mh
->msgh_reply_port
);
8140 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
8141 // /usr/include/mach/mach_port.h et al (grep in /usr/include
8145 // message to a task port
8147 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8149 switch (mh
->msgh_id
) {
8151 CALL_PRE(mach_port_type
);
8154 CALL_PRE(mach_port_allocate
);
8157 CALL_PRE(mach_port_destroy
);
8160 CALL_PRE(mach_port_deallocate
);
8163 CALL_PRE(mach_port_get_refs
);
8166 CALL_PRE(mach_port_mod_refs
);
8169 CALL_PRE(mach_port_get_set_status
);
8172 CALL_PRE(mach_port_move_member
);
8175 CALL_PRE(mach_port_request_notification
);
8178 CALL_PRE(mach_port_insert_right
);
8181 CALL_PRE(mach_port_extract_right
);
8184 CALL_PRE(mach_port_get_attributes
);
8187 CALL_PRE(mach_port_set_attributes
);
8190 CALL_PRE(mach_port_insert_member
);
8193 CALL_PRE(mach_port_extract_member
);
8197 CALL_PRE(mach_port_set_context
);
8201 CALL_PRE(task_threads
);
8204 CALL_PRE(mach_ports_register
);
8207 CALL_PRE(mach_ports_lookup
);
8210 CALL_PRE(task_info
);
8213 CALL_PRE(task_set_info
);
8216 CALL_PRE(task_suspend
);
8219 CALL_PRE(task_resume
);
8222 CALL_PRE(task_get_special_port
);
8225 CALL_PRE(task_set_special_port
);
8228 CALL_PRE(thread_create
);
8231 CALL_PRE(thread_create_running
);
8235 CALL_PRE(task_get_exception_ports
);
8239 CALL_PRE(semaphore_create
);
8242 CALL_PRE(semaphore_destroy
);
8245 CALL_PRE(task_policy_set
);
8248 #if DARWIN_VERS >= DARWIN_10_12
8250 CALL_PRE(task_register_dyld_image_infos
);
8254 CALL_PRE(task_register_dyld_shared_cache_image_info
);
8256 #endif /* DARWIN_VERS >= DARWIN_10_12 */
8259 CALL_PRE(vm_allocate
);
8262 CALL_PRE(vm_deallocate
);
8265 CALL_PRE(vm_protect
);
8268 CALL_PRE(vm_inherit
);
8277 CALL_PRE(vm_read_overwrite
);
8286 CALL_PRE(mach_make_memory_entry_64
);
8289 CALL_PRE(vm_purgable_control
);
8293 CALL_PRE(mach_vm_allocate
);
8296 CALL_PRE(mach_vm_deallocate
);
8299 CALL_PRE(mach_vm_protect
);
8302 CALL_PRE(mach_vm_inherit
);
8305 CALL_PRE(mach_vm_read
);
8308 CALL_PRE(mach_vm_copy
);
8311 CALL_PRE(mach_vm_read_overwrite
);
8314 CALL_PRE(mach_vm_map
);
8317 CALL_PRE(mach_vm_remap
);
8320 CALL_PRE(mach_vm_region_recurse
);
8323 CALL_PRE(mach_make_memory_entry_64
);
8326 CALL_PRE(mach_vm_purgable_control
);
8330 // unknown message to task self
8331 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
8332 mh
->msgh_id
, name_for_port(mh
->msgh_remote_port
),
8333 mh
->msgh_reply_port
);
8339 PRE(mach_msg_thread
)
8341 // message to local thread - check for thread-level kernel calls
8343 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8345 switch (mh
->msgh_id
) {
8347 CALL_PRE(thread_terminate
);
8350 CALL_PRE(thread_get_state
);
8353 CALL_PRE(thread_suspend
);
8356 CALL_PRE(thread_resume
);
8359 CALL_PRE(thread_info
);
8362 CALL_PRE(thread_policy
);
8365 CALL_PRE(thread_policy_set
);
8368 // unknown message to a thread
8369 VG_(printf
)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
8370 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8371 mh
->msgh_reply_port
);
8377 static int is_thread_port(mach_port_t port
)
8379 if (port
== 0) return False
;
8381 return VG_(lwpid_to_vgtid
)(port
) != VG_INVALID_THREADID
;
8385 static int is_task_port(mach_port_t port
)
8387 if (port
== 0) return False
;
8389 if (port
== vg_task_port
) return True
;
8391 return (0 == VG_(strncmp
)("task-", name_for_port(port
), 5));
8395 /* ---------------------------------------------------------------------
8396 mach_msg: base handlers
8397 ------------------------------------------------------------------ */
8401 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8402 mach_msg_option_t option
= (mach_msg_option_t
)ARG2
;
8403 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8404 mach_msg_size_t rcv_size
= (mach_msg_size_t
)ARG4
;
8405 // mach_port_t rcv_name = (mach_port_t)ARG5;
8406 size_t complex_header_size
= 0;
8408 PRE_REG_READ7(long, "mach_msg",
8409 mach_msg_header_t
*,"msg", mach_msg_option_t
,"option",
8410 mach_msg_size_t
,"send_size", mach_msg_size_t
,"rcv_size",
8411 mach_port_t
,"rcv_name", mach_msg_timeout_t
,"timeout",
8412 mach_port_t
,"notify");
8414 // Assume default POST handler until specified otherwise
8417 // Assume call may block unless specified otherwise
8418 *flags
|= SfMayBlock
;
8420 if (option
& MACH_SEND_MSG
) {
8421 // Validate outgoing message header
8422 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8423 (Addr
)&mh
->msgh_bits
, sizeof(mh
->msgh_bits
));
8424 // msgh_size not required, use parameter instead
8425 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8426 (Addr
)&mh
->msgh_remote_port
, sizeof(mh
->msgh_remote_port
));
8427 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8428 (Addr
)&mh
->msgh_local_port
, sizeof(mh
->msgh_local_port
));
8429 // msgh_reserved not required
8430 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8431 (Addr
)&mh
->msgh_id
, sizeof(mh
->msgh_id
));
8433 if (mh
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
8434 // Validate typed message data and handle memory map changes.
8435 complex_header_size
= export_complex_message(tid
, mh
);
8438 // GrP fixme handle sender-specified message trailer
8439 // (but is this only for too-secure processes?)
8440 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8441 # if DARWIN_VERS >= DARWIN_10_10
8442 if (mh
->msgh_bits
& MACH_SEND_TRAILER
) {
8443 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8446 vg_assert(! (mh
->msgh_bits
& MACH_SEND_TRAILER
));
8449 MACH_REMOTE
= mh
->msgh_remote_port
;
8450 MACH_MSGH_ID
= mh
->msgh_id
;
8453 if (option
& MACH_RCV_MSG
) {
8454 // Pre-validate receive buffer
8455 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr
)mh
, rcv_size
);
8458 // Call a PRE handler. The PRE handler may set an AFTER handler.
8460 if (!(option
& MACH_SEND_MSG
)) {
8461 // no message sent, receive only
8462 CALL_PRE(mach_msg_receive
);
8465 else if (mh
->msgh_request_port
== vg_host_port
) {
8466 // message sent to mach_host_self()
8467 CALL_PRE(mach_msg_host
);
8470 else if (is_task_port(mh
->msgh_request_port
)) {
8471 // message sent to a task
8472 CALL_PRE(mach_msg_task
);
8475 else if (mh
->msgh_request_port
== vg_bootstrap_port
) {
8476 // message sent to bootstrap port
8477 CALL_PRE(mach_msg_bootstrap
);
8480 else if (is_thread_port(mh
->msgh_request_port
)) {
8481 // message sent to one of this process's threads
8482 CALL_PRE(mach_msg_thread
);
8486 // this is an attempt to optimize mapping sync
8487 // but there are always some cases hard to find
8489 Bool do_mapping_update
= False
;
8490 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8491 // which is obviously not true...
8492 switch (mh
->msgh_id
) {
8493 // com.apple.windowserver.active
8494 case 29008: // this one opens a port type 'a'
8496 // com.apple.windowserver.active 'a' port
8499 case 29820: // adds a vm mapping
8500 case 29809: // contains a ool mem
8501 case 29800: // opens a port type 'b'
8503 case 29876: // adds a vm mapping
8505 // com.apple.windowserver.active 'b' port
8515 case 29237: // contains a ool mem
8520 case 29570: // contains a ool mem
8522 case 29569: // contains a ool mem
8527 if (mh
->msgh_id
== 29820 ||
8528 mh
->msgh_id
== 29876)
8529 do_mapping_update
= True
;
8531 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8532 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8533 mh
->msgh_reply_port
);
8536 // com.apple.FontServer
8538 PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
8539 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8540 mh
->msgh_reply_port
);
8543 // com.apple.system.notification_center
8546 case 78945695: // contains a ool mem
8549 if (mh
->msgh_id
== 78945695)
8550 do_mapping_update
= False
;
8551 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8552 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8553 mh
->msgh_reply_port
);
8556 // com.apple.CoreServices.coreservicesd
8559 case 10002: // adds vm mappings
8560 case 10003: // adds vm mappings
8565 case 13016: // contains a ool mem
8566 if (mh
->msgh_id
== 10002||
8567 mh
->msgh_id
== 10003)
8568 do_mapping_update
= True
;
8569 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8570 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8571 mh
->msgh_reply_port
);
8574 // com.apple.system.logger
8576 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8577 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8578 mh
->msgh_reply_port
);
8581 // com.apple.coreservices.launchservicesd, and others
8582 case 1999646836: // might adds vm mapping
8583 if (mh
->msgh_id
== 1999646836)
8584 do_mapping_update
= True
;
8585 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8586 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8587 mh
->msgh_reply_port
);
8592 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8593 mh
->msgh_id
, name_for_port(mh
->msgh_request_port
),
8594 mh
->msgh_reply_port
);
8597 // arbitrary message to arbitrary port
8598 do_mapping_update
= True
;
8599 PRINT("UNHANDLED 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
);
8604 // this is an optimization, don't check mapping on known mach_msg
8605 if (do_mapping_update
)
8606 AFTER
= POST_FN(mach_msg_unhandled
);
8608 AFTER
= POST_FN(mach_msg_unhandled_check
);
8610 AFTER
= POST_FN(mach_msg_unhandled
);
8613 // Assume the entire message body may be read.
8614 // GrP fixme generates false positives for unknown protocols
8616 PRE_MEM_READ("mach_msg(payload)",
8617 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8618 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8626 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8627 mach_msg_option_t option
= (mach_msg_option_t
)ARG2
;
8629 if (option
& MACH_RCV_MSG
) {
8631 // error during send or receive
8632 // GrP fixme need to clean up port rights?
8634 mach_msg_trailer_t
*mt
=
8635 (mach_msg_trailer_t
*)((Addr
)mh
+ round_msg(mh
->msgh_size
));
8637 // Assume the entire received message and trailer is initialized
8638 // GrP fixme would being more specific catch any bugs?
8639 POST_MEM_WRITE((Addr
)mh
,
8640 round_msg(mh
->msgh_size
) + mt
->msgh_trailer_size
);
8642 if (mh
->msgh_bits
& MACH_MSGH_BITS_COMPLEX
) {
8643 // Update memory map for out-of-line message data
8644 import_complex_message(tid
, mh
);
8649 // Call handler chosen by PRE(mach_msg)
8651 (*AFTER
)(tid
, arrghs
, status
);
8656 POST(mach_msg_unhandled
)
8658 mach_msg_header_t
*mh
= (mach_msg_header_t
*)ARG1
;
8659 ML_(sync_mappings
)("after", "mach_msg_receive-UNHANDLED", mh
->msgh_id
);
8662 POST(mach_msg_unhandled_check
)
8664 if (ML_(sync_mappings
)("after", "mach_msg_receive (unhandled_check)", 0))
8665 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid
);
8669 /* ---------------------------------------------------------------------
8671 ------------------------------------------------------------------ */
8673 PRE(mach_reply_port
)
8675 PRINT("mach_reply_port()");
8678 POST(mach_reply_port
)
8680 record_named_port(tid
, RES
, MACH_PORT_RIGHT_RECEIVE
, "reply-%p");
8681 PRINT("reply port %s", name_for_port(RES
));
8685 PRE(mach_thread_self
)
8687 PRINT("mach_thread_self()");
8690 POST(mach_thread_self
)
8692 record_named_port(tid
, RES
, MACH_PORT_RIGHT_SEND
, "thread-%p");
8693 PRINT("thread %#lx", RES
);
8699 PRINT("mach_host_self()");
8702 POST(mach_host_self
)
8705 record_named_port(tid
, RES
, MACH_PORT_RIGHT_SEND
, "mach_host_self()");
8706 PRINT("host %#lx", RES
);
8712 PRINT("mach_task_self()");
8715 POST(mach_task_self
)
8718 record_named_port(tid
, RES
, MACH_PORT_RIGHT_SEND
, "mach_task_self()");
8719 PRINT("task %#lx", RES
);
8723 PRE(syscall_thread_switch
)
8725 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8726 name_for_port(ARG1
), SARG2
, SARG3
);
8727 PRE_REG_READ3(long, "syscall_thread_switch",
8728 mach_port_t
,"thread", int,"option", natural_t
,"timeout");
8730 *flags
|= SfMayBlock
;
8734 PRE(semaphore_signal
)
8736 PRINT("semaphore_signal(%s)", name_for_port(ARG1
));
8737 PRE_REG_READ1(long, "semaphore_signal", semaphore_t
,"semaphore");
8741 PRE(semaphore_signal_all
)
8743 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1
));
8744 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t
,"semaphore");
8748 PRE(semaphore_signal_thread
)
8750 PRINT("semaphore_signal_thread(%s, %s)",
8751 name_for_port(ARG1
), name_for_port(ARG2
));
8752 PRE_REG_READ2(long, "semaphore_signal_thread",
8753 semaphore_t
,"semaphore", mach_port_t
,"thread");
8759 PRINT("semaphore_wait(%s)", name_for_port(ARG1
));
8760 PRE_REG_READ1(long, "semaphore_signal", semaphore_t
,"semaphore");
8762 *flags
|= SfMayBlock
;
8766 PRE(semaphore_wait_signal
)
8768 PRINT("semaphore_wait_signal(%s, %s)",
8769 name_for_port(ARG1
), name_for_port(ARG2
));
8770 PRE_REG_READ2(long, "semaphore_wait_signal",
8771 semaphore_t
,"wait_semaphore",
8772 semaphore_t
,"signal_semaphore");
8774 *flags
|= SfMayBlock
;
8778 PRE(semaphore_timedwait
)
8780 PRINT("semaphore_timedwait(%s, %g seconds)",
8781 name_for_port(ARG1
), ARG2
+ARG3
/1000000000.0);
8782 PRE_REG_READ3(long, "semaphore_wait_signal",
8783 semaphore_t
,"semaphore",
8785 int,"wait_time_lo");
8787 *flags
|= SfMayBlock
;
8791 PRE(semaphore_timedwait_signal
)
8793 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8794 name_for_port(ARG1
), name_for_port(ARG2
), ARG3
+ARG4
/1000000000.0);
8795 PRE_REG_READ4(long, "semaphore_wait_signal",
8796 semaphore_t
,"wait_semaphore",
8797 semaphore_t
,"signal_semaphore",
8799 int,"wait_time_lo");
8801 *flags
|= SfMayBlock
;
8805 PRE(__semwait_signal
)
8807 /* 10.5 args: int cond_sem, int mutex_sem,
8808 int timeout, int relative,
8809 time_t tv_sec, time_t tv_nsec */
8810 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8811 name_for_port(ARG1
), name_for_port(ARG2
), SARG3
, SARG4
, SARG5
, SARG6
);
8812 PRE_REG_READ6(long, "__semwait_signal",
8813 int,"cond_sem", int,"mutex_sem",
8814 int,"timeout", int,"relative",
8815 vki_time_t
,"tv_sec", int,"tv_nsec");
8817 *flags
|= SfMayBlock
;
8819 // GrP provided this alternative version for 10.6, but NjN
8820 // reckons the 10.5 is is still correct for 10.6. So, retaining
8821 // Greg's version as a comment just in case we need it later.
8822 //PRE(__old_semwait_signal)
8824 // /* 10.5 args: int cond_sem, int mutex_sem,
8825 // int timeout, int relative,
8826 // const timespec *ts */
8827 // PRINT("__old_semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8828 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8829 // PRE_REG_READ5(int, "__old_semwait_signal",
8830 // int,cond_sem, int,mutex_sem,
8831 // int,timeout, int,relative,
8832 // const struct vki_timespec *,ts);
8834 // if (ARG5) PRE_MEM_READ ("__old_semwait_signal(ts)",
8835 // ARG5, sizeof(struct vki_timespec));
8837 // *flags |= SfMayBlock;
8843 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1
), SARG2
, ARG3
);
8844 PRE_REG_READ3(long, "task_for_pid",
8845 mach_port_t
,"target",
8846 vki_pid_t
, "pid", mach_port_t
*,"task");
8847 PRE_MEM_WRITE("task_for_pid(task)", ARG3
, sizeof(mach_port_t
));
8854 POST_MEM_WRITE(ARG3
, sizeof(mach_port_t
));
8856 task
= *(mach_port_t
*)ARG3
;
8857 record_named_port(tid
, task
, MACH_PORT_RIGHT_SEND
, "task-%p");
8858 PRINT("task 0x%x", task
);
8864 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1
), ARG2
);
8865 PRE_REG_READ2(long, "task_for_pid", mach_port_t
,"task", vki_pid_t
*,"pid");
8866 PRE_MEM_WRITE("task_for_pid(pid)", ARG2
, sizeof(vki_pid_t
));
8873 POST_MEM_WRITE(ARG2
, sizeof(vki_pid_t
));
8875 pid
= *(vki_pid_t
*)ARG2
;
8876 PRINT("pid %u", pid
);
8880 PRE(mach_timebase_info
)
8882 PRINT("mach_timebase_info(%#lx)", ARG1
);
8883 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8884 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1
, sizeof(struct vki_mach_timebase_info
));
8887 POST(mach_timebase_info
)
8889 POST_MEM_WRITE(ARG1
, sizeof(struct vki_mach_timebase_info
));
8893 PRE(mach_wait_until
)
8895 #if VG_WORDSIZE == 8
8896 PRINT("mach_wait_until(%lu)", ARG1
);
8897 PRE_REG_READ1(long, "mach_wait_until",
8898 unsigned long long,"deadline");
8900 PRINT("mach_wait_until(%llu)", LOHI64(ARG1
, ARG2
));
8901 PRE_REG_READ2(long, "mach_wait_until",
8902 int,"deadline_hi", int,"deadline_lo");
8904 *flags
|= SfMayBlock
;
8908 PRE(mk_timer_create
)
8910 PRINT("mk_timer_create()");
8911 PRE_REG_READ0(long, "mk_timer_create");
8914 POST(mk_timer_create
)
8916 record_named_port(tid
, RES
, MACH_PORT_RIGHT_SEND
, "mk_timer-%p");
8920 PRE(mk_timer_destroy
)
8922 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1
));
8923 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t
,"name");
8925 // Must block to prevent race (other thread allocates and
8926 // notifies after we deallocate but before we notify)
8927 *flags
&= ~SfMayBlock
;
8930 POST(mk_timer_destroy
)
8932 // Must have cleared SfMayBlock in PRE to prevent race
8933 record_port_destroy(ARG1
);
8939 #if VG_WORDSIZE == 8
8940 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1
), ARG2
);
8941 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t
,"name",
8942 unsigned long,"expire_time");
8944 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1
), LOHI64(ARG2
, ARG3
));
8945 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t
,"name",
8946 int,"expire_time_hi", int,"expire_time_lo");
8951 PRE(mk_timer_cancel
)
8953 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1
), ARG2
);
8954 PRE_REG_READ2(long, "mk_timer_cancel",
8955 mach_port_t
,"name", Addr
,"result_time");
8957 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2
,sizeof(vki_uint64_t
));
8961 POST(mk_timer_cancel
)
8964 POST_MEM_WRITE(ARG2
, sizeof(vki_uint64_t
));
8969 PRE(iokit_user_client_trap
)
8971 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
8972 name_for_port(ARG1
), ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
, ARG8
);
8973 PRE_REG_READ8(kern_return_t
, "iokit_user_client_trap",
8974 mach_port_t
,connect
, unsigned int,index
,
8975 uintptr_t,p1
, uintptr_t,p2
, uintptr_t,p3
,
8976 uintptr_t,p4
, uintptr_t,p5
, uintptr_t,p6
);
8978 // can't do anything else with this in general
8979 // might be able to use connect+index to choose something sometimes
8982 POST(iokit_user_client_trap
)
8984 ML_(sync_mappings
)("after", "iokit_user_client_trap", ARG2
);
8991 PRE_REG_READ0(long, "swtch");
8993 *flags
|= SfMayBlock
;
8999 PRINT("swtch_pri ( %ld )", SARG1
);
9000 PRE_REG_READ1(long, "swtch_pri", int,"pri");
9002 *flags
|= SfMayBlock
;
9008 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
9009 an explanation of what follows. */
9010 /* This handles the fake signal-return system call created by
9011 sigframe-x86-darwin.c. */
9012 /* See also comments just below on PRE(sigreturn). */
9014 PRINT("FAKE_SIGRETURN ( )");
9016 vg_assert(VG_(is_valid_tid
)(tid
));
9017 vg_assert(tid
>= 1 && tid
< VG_N_THREADS
);
9018 vg_assert(VG_(is_running_thread
)(tid
));
9020 /* Remove the signal frame from this thread's (guest) stack,
9021 in the process restoring the pre-signal guest state. */
9022 VG_(sigframe_destroy
)(tid
, True
);
9024 /* Tell the driver not to update the guest state with the "result",
9025 and set a bogus result to keep it happy. */
9026 *flags
|= SfNoWriteResult
;
9027 SET_STATUS_Success(0);
9029 /* Check to see if any signals arose as a result of this. */
9030 *flags
|= SfPollAfter
;
9036 /* This is the "real" sigreturn. But because we construct all the
9037 signal frames ourselves (of course, in m_sigframe), this cannot
9038 happen as a result of normal signal delivery. I think it
9039 happens only when doing siglongjmp, in which case Darwin's Libc
9040 appears to use it for two different purposes: to mess with the
9041 per-thread sigaltstack flags (as per arg 2), or to restore the
9042 thread's state from a ucontext* (as per arg 1). */
9044 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1
, ARG2
);
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 if (ARG2
== VKI_UC_SET_ALT_STACK
) {
9051 /* This is confusing .. the darwin kernel sources imply there is
9052 a per-thread on-altstack/not-on-altstack flag, which is set
9053 by this flag. Just ignore it and claim success for the time
9055 VG_(debugLog
)(0, "syswrap-darwin",
9056 "WARNING: Ignoring sigreturn( ..., "
9057 "UC_SET_ALT_STACK );\n");
9058 SET_STATUS_Success(0);
9061 if (ARG2
== VKI_UC_RESET_ALT_STACK
) {
9063 VG_(debugLog
)(0, "syswrap-darwin",
9064 "WARNING: Ignoring sigreturn( ..., "
9065 "UC_RESET_ALT_STACK );\n");
9066 SET_STATUS_Success(0);
9070 /* Otherwise claim this isn't supported. (Could be
9073 What do we have to do if we do need to support it?
9075 1. Change the second argument of VG_(sigframe_destroy) from
9076 "Bool isRT" to "UInt sysno", so we can pass the syscall
9077 number, so it can distinguish this case from the
9078 __NR_DARWIN_FAKE_SIGRETURN case.
9080 2. In VG_(sigframe_destroy), look at sysno to distinguish the
9081 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
9082 For this case, restore the thread's CPU state (or at least
9083 the integer regs) from the ucontext in ARG1 (and do all the
9084 other "signal-returns" stuff too).
9086 3. For (2), how do we know where the ucontext is? One way is to
9087 temporarily copy ARG1 into this thread's guest_EBX (or any
9088 other int reg), and have VG_(sigframe_destroy) read
9089 guest_EBX. Why is it ok to trash guest_EBX (or any other int
9090 reg)? Because VG_(sigframe_destroy) is just about to
9091 overwrite all the regs anyway -- since the primary purpose of
9092 calling it is to restore the register state from the ucontext
9095 Hey, it's uggerly. But at least it's documented.
9097 /* But in the meantime ... */
9098 VG_(debugLog
)(0, "syswrap-darwin",
9099 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
9100 VG_(debugLog
)(0, "syswrap-darwin",
9101 "WARNING: Thread/program/Valgrind "
9102 "will likely segfault now.\n");
9103 VG_(debugLog
)(0, "syswrap-darwin",
9104 "WARNING: Please file a bug report at "
9105 "http://www.valgrind.org.\n");
9106 SET_STATUS_Failure( VKI_ENOSYS
);
9110 /* ---------------------------------------------------------------------
9111 machine-dependent traps
9112 ------------------------------------------------------------------ */
9114 #if defined(VGA_x86)
9115 static VexGuestX86SegDescr
* alloc_zeroed_x86_LDT ( void )
9117 Int nbytes
= VEX_GUEST_X86_LDT_NENT
* sizeof(VexGuestX86SegDescr
);
9118 return VG_(calloc
)("syswrap-darwin.ldt", nbytes
, 1);
9122 PRE(thread_fast_set_cthread_self
)
9124 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1
);
9125 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t
*, self
);
9127 #if defined(VGA_x86)
9128 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
9130 VexGuestX86SegDescr
*ldt
;
9131 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
9132 ldt
= (VexGuestX86SegDescr
*)tst
->arch
.vex
.guest_LDT
;
9134 ldt
= alloc_zeroed_x86_LDT();
9135 tst
->arch
.vex
.guest_LDT
= (HWord
)ldt
;
9137 VG_(memset
)(&ldt
[6], 0, sizeof(ldt
[6]));
9138 ldt
[6].LdtEnt
.Bits
.LimitLow
= 1;
9139 ldt
[6].LdtEnt
.Bits
.LimitHi
= 0;
9140 ldt
[6].LdtEnt
.Bits
.BaseLow
= ARG1
& 0xffff;
9141 ldt
[6].LdtEnt
.Bits
.BaseMid
= (ARG1
>> 16) & 0xff;
9142 ldt
[6].LdtEnt
.Bits
.BaseHi
= (ARG1
>> 24) & 0xff;
9143 ldt
[6].LdtEnt
.Bits
.Pres
= 1; // ACC_P
9144 ldt
[6].LdtEnt
.Bits
.Dpl
= 3; // ACC_PL_U
9145 ldt
[6].LdtEnt
.Bits
.Type
= 0x12; // ACC_DATA_W
9146 ldt
[6].LdtEnt
.Bits
.Granularity
= 1; // SZ_G
9147 ldt
[6].LdtEnt
.Bits
.Default_Big
= 1; // SZ_32
9149 tst
->os_state
.pthread
= ARG1
;
9150 tst
->arch
.vex
.guest_GS
= 0x37;
9152 // What we would like to do is:
9153 // SET_STATUS_Success(0x37);
9154 // but that doesn't work, because this is a MDEP-class syscall,
9155 // and SET_STATUS_Success creates a UNIX-class syscall result.
9156 // Hence we have to laboriously construct the full SysRes "by hand"
9157 // and use that to set the syscall return status.
9158 SET_STATUS_from_SysRes(
9159 VG_(mk_SysRes_x86_darwin
)(
9160 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self
),
9166 #elif defined(VGA_amd64)
9167 // GrP fixme bigger hack than x86
9169 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
9170 tst
->os_state
.pthread
= ARG1
;
9171 tst
->arch
.vex
.guest_GS_CONST
= ARG1
;
9172 // SET_STATUS_Success(0x60);
9173 // see comments on x86 case just above
9174 SET_STATUS_from_SysRes(
9175 VG_(mk_SysRes_amd64_darwin
)(
9176 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self
),
9183 #error unknown architecture
9188 /* ---------------------------------------------------------------------
9189 Added for OSX 10.6 (Snow Leopard)
9190 ------------------------------------------------------------------ */
9192 #if DARWIN_VERS >= DARWIN_10_6
9194 PRE(psynch_mutexwait
)
9196 PRINT("psynch_mutexwait(BOGUS)");
9197 *flags
|= SfMayBlock
;
9199 POST(psynch_mutexwait
)
9203 PRE(psynch_mutexdrop
)
9205 PRINT("psynch_mutexdrop(BOGUS)");
9206 *flags
|= SfMayBlock
;
9208 POST(psynch_mutexdrop
)
9214 PRINT("psynch_cvbroad(BOGUS)");
9216 POST(psynch_cvbroad
)
9220 PRE(psynch_cvsignal
)
9222 PRINT("psynch_cvsignal(BOGUS)");
9224 POST(psynch_cvsignal
)
9230 PRINT("psynch_cvwait(BOGUS)");
9231 *flags
|= SfMayBlock
;
9237 PRE(psynch_rw_rdlock
)
9239 PRINT("psynch_rw_rdlock(BOGUS)");
9240 *flags
|= SfMayBlock
;
9242 POST(psynch_rw_rdlock
)
9246 PRE(psynch_rw_wrlock
)
9248 PRINT("psynch_rw_wrlock(BOGUS)");
9249 *flags
|= SfMayBlock
;
9251 POST(psynch_rw_wrlock
)
9255 PRE(psynch_rw_unlock
)
9257 PRINT("psynch_rw_unlock(BOGUS)");
9259 POST(psynch_rw_unlock
)
9263 PRE(__thread_selfid
)
9265 PRINT("__thread_selfid ()");
9266 PRE_REG_READ0(vki_uint64_t
, "__thread_selfid");
9271 #if VG_WORDSIZE == 4
9272 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
9274 ((unsigned int *)ARG3
)[0], ((unsigned int *)ARG3
)[1],
9275 LOHI64(ARG4
, ARG5
));
9276 PRE_REG_READ5(ssize_t
, "fsgetpath",
9277 void*,"buf", size_t,"bufsize",
9279 vki_uint32_t
, "objid_low32", vki_uint32_t
, "objid_high32");
9281 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
9283 ((unsigned int *)ARG3
)[0],
9284 ((unsigned int *)ARG3
)[1], ARG4
);
9285 PRE_REG_READ4(ssize_t
, "fsgetpath",
9286 void*,"buf", size_t,"bufsize",
9287 fsid_t
*,"fsid", uint64_t,"objid");
9289 PRE_MEM_READ("fsgetpath(fsid)", ARG3
, sizeof(fsid_t
));
9290 PRE_MEM_WRITE("fsgetpath(buf)", ARG1
, ARG2
);
9295 POST_MEM_WRITE(ARG1
, RES
);
9298 PRE(audit_session_self
)
9300 PRINT("audit_session_self()");
9302 POST(audit_session_self
)
9304 record_named_port(tid
, RES
, MACH_PORT_RIGHT_SEND
, "audit-session-%p");
9305 PRINT("audit-session %#lx", RES
);
9308 #endif /* DARWIN_VERS >= DARWIN_10_6 */
9311 /* ---------------------------------------------------------------------
9312 Added for OSX 10.7 (Lion)
9313 ------------------------------------------------------------------ */
9315 #if DARWIN_VERS >= DARWIN_10_7
9317 PRE(psynch_cvclrprepost
)
9319 PRINT("psynch_cvclrprepost(BOGUS)");
9320 *flags
|= SfMayBlock
;
9322 POST(psynch_cvclrprepost
)
9326 #endif /* DARWIN_VERS >= DARWIN_10_7 */
9329 /* ---------------------------------------------------------------------
9330 Added for OSX 10.8 (Mountain Lion)
9331 ------------------------------------------------------------------ */
9333 /* About munge tags, eg munge_wllww.
9335 Means the syscall takes 5 args. For a 64 bit process each arg
9336 occupies one 64-bit value and so the mapping to ARGn macros is
9337 direct. For a 32 bit process, this is more complex: 'w' denotes a
9338 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
9339 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
9340 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
9341 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
9342 in order to get sane values for the arguments in 32-bit
9345 static void munge_wwl(UWord
* a1
, UWord
* a2
, ULong
* a3
,
9346 UWord aRG1
, UWord aRG2
, UWord aRG3
, UWord aRG4
)
9348 # if defined(VGA_x86)
9349 *a1
= aRG1
; *a2
= aRG2
; *a3
= LOHI64(aRG3
,aRG4
);
9351 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
;
9355 static void munge_wll(UWord
* a1
, ULong
* a2
, ULong
* a3
,
9356 UWord aRG1
, UWord aRG2
, UWord aRG3
,
9357 UWord aRG4
, UWord aRG5
)
9359 # if defined(VGA_x86)
9360 *a1
= aRG1
; *a2
= LOHI64(aRG2
,aRG3
); *a3
= LOHI64(aRG4
,aRG5
);
9362 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
;
9366 static void munge_wwlw(UWord
* a1
, UWord
* a2
, ULong
* a3
, UWord
* a4
,
9367 UWord aRG1
, UWord aRG2
, UWord aRG3
,
9368 UWord aRG4
, UWord aRG5
)
9370 # if defined(VGA_x86)
9371 *a1
= aRG1
; *a2
= aRG2
; *a3
= LOHI64(aRG3
,aRG4
); *a4
= aRG5
;
9373 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
; *a4
= aRG4
;
9377 static void munge_wwwl(UWord
* a1
, UWord
* a2
, UWord
* a3
, ULong
* a4
,
9378 UWord aRG1
, UWord aRG2
, UWord aRG3
,
9379 UWord aRG4
, UWord aRG5
)
9381 # if defined(VGA_x86)
9382 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
; *a4
= LOHI64(aRG4
,aRG5
);
9384 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
; *a4
= aRG4
;
9388 static void munge_wllww(UWord
* a1
, ULong
* a2
, ULong
* a3
, UWord
* a4
, UWord
* a5
,
9389 UWord aRG1
, UWord aRG2
, UWord aRG3
,
9390 UWord aRG4
, UWord aRG5
, UWord aRG6
, UWord aRG7
)
9392 # if defined(VGA_x86)
9393 *a1
= aRG1
; *a2
= LOHI64(aRG2
,aRG3
); *a3
= LOHI64(aRG4
,aRG5
);
9394 *a4
= aRG6
; *a5
= aRG7
;
9396 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
; *a4
= aRG4
; *a5
= aRG5
;
9400 static void munge_wwllww(UWord
* a1
, UWord
* a2
, ULong
* a3
,
9401 ULong
* a4
, UWord
* a5
, UWord
* a6
,
9402 UWord aRG1
, UWord aRG2
, UWord aRG3
, UWord aRG4
,
9403 UWord aRG5
, UWord aRG6
, UWord aRG7
, UWord aRG8
)
9405 # if defined(VGA_x86)
9406 *a1
= aRG1
; *a2
= aRG2
;
9407 *a3
= LOHI64(aRG3
,aRG4
); *a4
= LOHI64(aRG5
,aRG6
);
9408 *a5
= aRG7
; *a6
= aRG8
;
9410 *a1
= aRG1
; *a2
= aRG2
; *a3
= aRG3
; *a4
= aRG4
; *a5
= aRG5
; *a6
= aRG6
;
9414 #if DARWIN_VERS >= DARWIN_10_8
9416 PRE(kernelrpc_mach_vm_allocate_trap
)
9418 UWord a1
; UWord a2
; ULong a3
; UWord a4
;
9419 munge_wwlw(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9420 PRINT("kernelrpc_mach_vm_allocate_trap"
9421 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
9422 name_for_port(a1
), *(void**)a2
, a3
, a4
);
9423 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
9426 POST(kernelrpc_mach_vm_allocate_trap
)
9428 UWord a1
; UWord a2
; ULong a3
; UWord a4
;
9429 munge_wwlw(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9430 PRINT("address:%p size:%#llx", *(void**)a2
, a3
);
9431 if (ML_(safe_to_deref
)((void*)a2
, sizeof(void*))) {
9432 POST_MEM_WRITE(a2
, sizeof(void*));
9434 if (a1
== mach_task_self()) {
9436 ML_(sync_mappings
)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
9438 /* This is nearly right, but not always -- sometimes the mapping
9439 appears to be r--, for some reason. Hence resync. */
9440 ML_(notify_core_and_tool_of_mmap
)(
9442 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_ANON
, -1, 0);
9447 PRE(kernelrpc_mach_vm_deallocate_trap
)
9449 UWord a1
; ULong a2
; ULong a3
;
9450 munge_wll(&a1
, &a2
, &a3
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9451 PRINT("kernelrpc_mach_vm_deallocate_trap"
9452 "(target:%#lx, address:%#llx, size:%#llx)", a1
, a2
, a3
);
9454 POST(kernelrpc_mach_vm_deallocate_trap
)
9456 UWord a1
; ULong a2
; ULong a3
;
9457 munge_wll(&a1
, &a2
, &a3
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9458 // kernelrpc_mach_vm_deallocate_trap could be call with
9459 // address ==0 && size == 0,
9460 // we shall not notify any unmap then
9462 ML_(notify_core_and_tool_of_munmap
)(a2
, a3
);
9465 PRE(kernelrpc_mach_vm_protect_trap
)
9467 UWord a1
; ULong a2
; ULong a3
; UWord a4
; UWord a5
;
9468 munge_wllww(&a1
, &a2
, &a3
, &a4
, &a5
,
9469 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
);
9470 PRINT("kernelrpc_mach_vm_protect_trap"
9471 "(task:%#lx, address:%#llx, size:%#llx,"
9472 " set_maximum:%#lx, new_prot:%#lx)", a1
, a2
, a3
, a4
, a5
);
9474 POST(kernelrpc_mach_vm_protect_trap
)
9476 UWord a1
; ULong a2
; ULong a3
; UWord a4
; UWord a5
;
9477 munge_wllww(&a1
, &a2
, &a3
, &a4
, &a5
,
9478 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
);
9479 if (/*a4 set_maximum == 0 && */a1
== mach_task_self()) {
9480 ML_(notify_core_and_tool_of_mprotect
)((Addr
)a2
, (SizeT
)a3
, (Int
)a5
);
9481 VG_(di_notify_vm_protect
)((Addr
)a2
, (SizeT
)a3
, (UInt
)a5
);
9485 PRE(kernelrpc_mach_port_allocate_trap
)
9487 // munge_www -- no need to call helper
9488 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9490 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9491 ARG3
, sizeof(mach_port_name_t
));
9493 POST(kernelrpc_mach_port_allocate_trap
)
9495 // munge_www -- no need to call helper
9496 POST_MEM_WRITE(ARG3
, sizeof(mach_port_name_t
));
9497 PRINT(", name:%#x", *(mach_port_name_t
*)ARG3
);
9498 record_unnamed_port(tid
, *(mach_port_name_t
*)ARG3
, ARG2
);
9501 PRE(kernelrpc_mach_port_destroy_trap
)
9503 // munge_ww -- no need to call helper
9504 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1
, ARG2
);
9505 record_port_destroy(ARG2
);
9508 PRE(kernelrpc_mach_port_deallocate_trap
)
9510 // munge_ww -- no need to call helper
9511 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9514 POST(kernelrpc_mach_port_deallocate_trap
)
9516 // munge_ww -- no need to call helper
9519 PRE(kernelrpc_mach_port_mod_refs_trap
)
9521 // munge_wwww -- no need to call helper
9522 PRINT("kernelrpc_mach_port_mod_refs_trap"
9523 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9524 ARG1
, ARG2
, ARG3
, ARG4
);
9527 PRE(kernelrpc_mach_port_move_member_trap
)
9529 // munge_www -- no need to call helper
9530 PRINT("kernelrpc_mach_port_move_member_trap"
9531 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9535 PRE(kernelrpc_mach_port_insert_right_trap
)
9537 //munge_wwww -- no need to call helper
9538 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9539 "(%lx,%lx,%lx,%lx)", ARG1
, ARG2
, ARG3
, ARG4
);
9542 PRE(kernelrpc_mach_port_insert_member_trap
)
9544 // munge_www -- no need to call helper
9545 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9546 "(%lx,%lx,%lx)", ARG1
, ARG2
, ARG3
);
9549 PRE(kernelrpc_mach_port_extract_member_trap
)
9551 // munge_www -- no need to call helper
9552 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9553 "(%lx,%lx,%lx)", ARG1
, ARG2
, ARG3
);
9559 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1
, ARG2
, ARG3
);
9560 /* mem effects unknown */
9570 PRINT("process_policy(FIXME)("
9571 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9572 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9573 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
);
9574 /* mem effects unknown */
9576 POST(process_policy
)
9581 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9584 /* ---------------------------------------------------------------------
9585 Added for OSX 10.9 (Mavericks)
9586 ------------------------------------------------------------------ */
9588 #if DARWIN_VERS >= DARWIN_10_9
9590 PRE(kernelrpc_mach_vm_map_trap
)
9592 UWord a1
; UWord a2
; ULong a3
; ULong a4
; UWord a5
; UWord a6
;
9593 munge_wwllww(&a1
, &a2
, &a3
, &a4
, &a5
, &a6
,
9594 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
, ARG8
);
9595 PRINT("kernelrpc_mach_vm_map_trap"
9596 "(target:%#lx, address:%p, size:%#llx,"
9597 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9598 a1
, *(void**)a2
, a3
, a4
, a5
, a6
);
9599 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2
, sizeof(void*));
9601 POST(kernelrpc_mach_vm_map_trap
)
9603 UWord a1
; UWord a2
; ULong a3
; ULong a4
; UWord a5
; UWord a6
;
9604 munge_wwllww(&a1
, &a2
, &a3
, &a4
, &a5
, &a6
,
9605 ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
, ARG7
, ARG8
);
9606 PRINT("-> address:%p", *(void**)a2
);
9607 if (ML_(safe_to_deref
)((void*)a2
, sizeof(void*))) {
9608 POST_MEM_WRITE(a2
, sizeof(void*));
9610 ML_(notify_core_and_tool_of_mmap
)(
9611 *(mach_vm_address_t
*)a2
, a3
,
9612 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_ANON
, -1, 0);
9613 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9616 PRE(kernelrpc_mach_port_construct_trap
)
9618 UWord a1
; UWord a2
; ULong a3
; UWord a4
;
9619 munge_wwlw(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9620 PRINT("kernelrpc_mach_port_construct_trap"
9621 "(target: %s, options: %#lx, content: %llx, name: %p)",
9622 name_for_port(a1
), a2
, a3
, *(mach_port_name_t
**)a4
);
9623 PRE_MEM_WRITE("kernelrpc_mach_port_construct_trap(name)", a4
,
9624 sizeof(mach_port_name_t
*));
9626 POST(kernelrpc_mach_port_construct_trap
)
9628 UWord a1
; UWord a2
; ULong a3
; UWord a4
;
9629 munge_wwlw(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9630 PRINT("-> name:%p", *(mach_port_name_t
**)a4
);
9631 if (ML_(safe_to_deref
)((mach_port_name_t
*)a4
, sizeof(mach_port_name_t
*))) {
9632 POST_MEM_WRITE(a4
, sizeof(mach_port_name_t
*));
9636 PRE(kernelrpc_mach_port_destruct_trap
)
9638 UWord a1
; UWord a2
; UWord a3
; ULong a4
;
9639 munge_wwwl(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9640 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9641 "(%lx,%lx,%lx,%llx)", a1
, a2
, a3
, a4
);
9644 PRE(kernelrpc_mach_port_guard_trap
)
9646 UWord a1
; UWord a2
; ULong a3
; UWord a4
;
9647 munge_wwlw(&a1
, &a2
, &a3
, &a4
, ARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9648 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9649 "(%lx,%lx,%llx,%lx)", a1
, a2
, a3
, a4
);
9652 PRE(kernelrpc_mach_port_unguard_trap
)
9655 UWord a1
; UWord a2
; ULong a3
;
9656 munge_wwl(&a1
, &a2
, &a3
, ARG1
, ARG2
, ARG3
, ARG4
);
9657 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9658 "(%lx,%lx,%llx)", a1
, a2
, a3
);
9661 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9664 /* ---------------------------------------------------------------------
9665 Added for OSX 10.10 (Yosemite)
9666 ------------------------------------------------------------------ */
9668 #if DARWIN_VERS >= DARWIN_10_10
9670 PRE(necp_match_policy
)
9672 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9673 // struct necp_aggregate_result *returned_result)
9674 PRINT("necp_match_policy(FIXME)(%lx,%lu, %lx)", ARG1
, ARG2
, ARG3
);
9675 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters
,
9676 size_t, parameters_size
, struct necp_aggregate_result
*,
9678 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1
, ARG2
);
9680 POST(necp_match_policy
)
9682 POST_MEM_WRITE(ARG3
, sizeof(struct vki_necp_aggregate_result
));
9688 UWord namelen
= ARG2
;
9690 UWord oldlenp
= ARG4
;
9692 UWord newlen
= ARG6
; // FIXME: or newlenp ??
9694 PRINT( "sysctlbyname ( %#lx,%lu, %#lx,%#lx, %#lx,%lu )",
9695 name
, namelen
, oldp
, oldlenp
, newp
, newlen
);
9697 PRE_REG_READ6(int, "sysctlbyname", char*, name
, size_t, namelen
,
9698 void*, oldp
, vki_size_t
*, oldlenp
,
9699 void*, newp
, vki_size_t
*, newlenp
); // <---<<
9701 // reads name[0..namelen-1]
9702 PRE_MEM_READ("sysctlbyname(name)", name
, namelen
);
9704 if (VG_(clo_trace_syscalls
)) {
9706 const HChar
* t_name
= (const HChar
*)name
;
9707 VG_(printf
)(" name: ");
9708 for (i
= 0; i
< namelen
; i
++) {
9709 VG_(printf
)("%c", t_name
[i
]);
9714 Bool is_kern_dot_userstack
9717 common_PRE_sysctl( /*IMPLICIT ARGS*/tid
,status
,flags
,/*!IMPLICIT_ARGS*/
9718 is_kern_dot_userstack
, oldp
, oldlenp
, newp
, newlen
);
9723 UWord oldlenp
= ARG4
;
9725 if (SUCCESS
|| ERR
== VKI_ENOMEM
) {
9726 // sysctl can write truncated data and return VKI_ENOMEM
9728 POST_MEM_WRITE(oldlenp
, sizeof(size_t));
9730 if (oldp
&& oldlenp
) {
9731 POST_MEM_WRITE(oldp
, *(size_t*)oldlenp
);
9736 PRE(getattrlistbulk
)
9738 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9739 // void *attributeBuffer, size_t bufferSize,
9740 // uint64_t options);
9741 // Presumably the last arg is value-pair in the 32 bit case.
9742 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9743 SARG1
, ARG2
, ARG3
, ARG4
, ARG5
);
9744 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd
, void*, list
,
9745 void*, attributeBuffer
, size_t, bufferSize
,
9746 uint32_t, options_lo32
);
9747 PRE_MEM_READ("getattrlistbulk(alist)", ARG2
, sizeof(struct vki_attrlist
));
9748 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3
, ARG4
);
9750 POST(getattrlistbulk
)
9752 // FIXME: this isn't right. It seems as if what is returned is a
9753 // set of variable-length records -- see complication in
9754 // POST(getattrlist). For now, just paint the entire result buffer
9755 // as defined. Sigh.
9757 if (ARG3
&& /* "at least one output element was written" */RES
> 0)
9758 POST_MEM_WRITE(ARG3
, ARG4
);
9763 PRINT("faccessat(FIXME)(fd:%ld, path:%#lx(%s), amode:%#lx, flag:%#lx)",
9764 ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
);
9765 PRE_REG_READ4(int, "faccessat",
9766 int, fd
, user_addr_t
, path
, int, amode
, int, flag
);
9771 PRINT("fstatat64(FIXME)(fd:%ld, path:%#lx(%s), ub:%#lx, flag:%#lx)",
9772 ARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, ARG4
);
9773 PRE_REG_READ4(int, "fstatat64",
9774 int, fd
, user_addr_t
, path
, user_addr_t
, ub
, int, flag
);
9781 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %ld )",
9782 SARG1
, ARG2
, (HChar
*)ARG2
, ARG3
, SARG4
);
9783 PRE_REG_READ4(long, "readlinkat",
9784 int, dfd
, const char *, path
, char *, buf
, int, bufsiz
);
9785 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2
);
9786 PRE_MEM_WRITE( "readlinkat(buf)", ARG3
,ARG4
);
9789 * Refer to coregrind/m_syswrap/syswrap-linux.c
9793 SET_STATUS_from_SysRes( VG_(do_syscall4
)(saved
, ARG1
, ARG2
, ARG3
, ARG4
));
9796 if (SUCCESS
&& RES
> 0)
9797 POST_MEM_WRITE( ARG3
, RES
);
9802 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9803 // user_addr_t arg2, user_addr_t arg3)
9804 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1
, ARG2
, ARG3
, ARG4
);
9805 PRE_REG_READ4(int, "bsdthreadctl",
9806 void*, cmd
, void*, arg1
, void*, arg2
, void*, arg3
);
9811 PRINT("csrctl(op:%ld, useraddr:%#lx, usersize:%#lx) FIXME", ARG1
, ARG2
, ARG3
);
9812 PRE_REG_READ3(int, "csrctl",
9813 uint32_t, op
, user_addr_t
, useraddr
, user_addr_t
, usersize
);
9816 PRE(guarded_open_dprotected_np
)
9818 PRINT("guarded_open_dprotected_np("
9819 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9820 "dpclass:%#lx, dpflags: %#lx) FIXME",
9821 ARG1
, (HChar
*)ARG1
, ARG2
, ARG3
, ARG4
, ARG5
, ARG6
);
9824 PRE(guarded_write_np
)
9826 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9827 ARG1
, ARG2
, ARG3
, (ULong
)ARG4
);
9830 PRE(guarded_pwrite_np
)
9832 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9833 ARG1
, ARG2
, ARG3
, (ULong
)ARG4
, (Long
)ARG5
);
9836 PRE(guarded_writev_np
)
9838 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9839 ARG1
, ARG2
, ARG3
, (ULong
)ARG4
);
9842 #endif /* DARWIN_VERS >= DARWIN_10_10 */
9845 /* ---------------------------------------------------------------------
9846 Added for OSX 10.11 (El Capitan)
9847 ------------------------------------------------------------------ */
9849 #if DARWIN_VERS >= DARWIN_10_11
9853 *flags
|= SfMayBlock
;
9854 PRINT("pselect ( %ld, %#lx, %#lx, %#lx, %#lx, %#lx )", SARG1
, ARG2
, ARG3
,
9856 PRE_REG_READ5(long, "pselect",
9857 int, n
, vki_fd_set
*, readfds
, vki_fd_set
*, writefds
,
9858 vki_fd_set
*, exceptfds
, struct vki_timeval
*, timeout
);
9859 // XXX: this possibly understates how much memory is read.
9861 PRE_MEM_READ( "pselect(readfds)",
9862 ARG2
, ARG1
/8 /* __FD_SETSIZE/8 */ );
9864 PRE_MEM_READ( "pselect(writefds)",
9865 ARG3
, ARG1
/8 /* __FD_SETSIZE/8 */ );
9867 PRE_MEM_READ( "pselect(exceptfds)",
9868 ARG4
, ARG1
/8 /* __FD_SETSIZE/8 */ );
9870 PRE_timeval_READ( "pselect(timeout)", ARG5
);
9872 PRE_MEM_READ( "pselect(sigmask)", ARG6
, sizeof(vki_sigset_t
) );
9875 #endif /* DARWIN_VERS >= DARWIN_10_11 */
9878 /* ---------------------------------------------------------------------
9879 Added for macOS 10.12 (Sierra)
9880 ------------------------------------------------------------------ */
9882 #if DARWIN_VERS >= DARWIN_10_12
9886 PRINT("getentropy(buffer:%#lx, size:%ld) FIXME", ARG1
, ARG2
);
9887 PRE_REG_READ2(int, "getentropy",
9888 void*, buffer
, size_t, size
);
9893 PRINT("ulock_wake(operation:%ld, addr:%#lx, wake_value:%ld) FIXME",
9895 PRE_REG_READ3(int, "ulock_wake",
9896 uint32_t, operation
, void*, addr
, uint64_t, wake_value
);
9899 PRE(host_create_mach_voucher_trap
)
9901 // munge_wwww -- no need to call helper
9902 PRINT("host_create_mach_voucher_trap"
9903 "(host:%#lx, recipes:%#lx, recipes_size:%ld, voucher:%#lx) FIXME",
9904 ARG1
, ARG2
, ARG3
, ARG4
);
9907 PRE(task_register_dyld_image_infos
)
9911 mach_msg_header_t Head
;
9912 /* start of the kernel processed data */
9913 mach_msg_body_t msgh_body
;
9914 mach_msg_ool_descriptor_t dyld_images
;
9915 /* end of the kernel processed data */
9917 mach_msg_type_number_t dyld_imagesCnt
;
9921 // Request *req = (Request *)ARG1;
9923 PRINT("task_register_dyld_image_infos(%s)", name_for_port(MACH_REMOTE
));
9925 AFTER
= POST_FN(task_register_dyld_image_infos
);
9928 POST(task_register_dyld_image_infos
)
9932 mach_msg_header_t Head
;
9934 kern_return_t RetCode
;
9938 Reply
*reply
= (Reply
*)ARG1
;
9939 if (!reply
->RetCode
) {
9941 PRINT("mig return %d", reply
->RetCode
);
9945 PRE(task_register_dyld_shared_cache_image_info
)
9949 mach_msg_header_t Head
;
9951 dyld_kernel_image_info_t dyld_cache_image
;
9953 boolean_t private_cache
;
9957 // Request *req = (Request *)ARG1;
9959 PRINT("task_register_dyld_shared_cache_image_info(%s)",
9960 name_for_port(MACH_REMOTE
));
9962 AFTER
= POST_FN(task_register_dyld_shared_cache_image_info
);
9965 POST(task_register_dyld_shared_cache_image_info
)
9969 mach_msg_header_t Head
;
9971 kern_return_t RetCode
;
9975 Reply
*reply
= (Reply
*)ARG1
;
9976 if (!reply
->RetCode
) {
9978 PRINT("mig return %d", reply
->RetCode
);
9982 PRE(mach_generate_activity_id
)
9984 // munge_www -- no need to call helper
9985 PRINT("mach_generate_activity_id"
9986 "(target:%s, count:%ld)",
9987 name_for_port(ARG1
), ARG2
);
9988 PRE_REG_READ3(long, "mach_generate_activity_id",
9989 mach_port_name_t
, target
, int, count
, uint64_t *, activity_id
);
9990 if (ARG2
<= 0 || ARG2
> MACH_ACTIVITY_ID_COUNT_MAX
) {
9991 SET_STATUS_Failure( VKI_EINVAL
);
9993 if (ML_(safe_to_deref
)( (void*)ARG3
, sizeof(vki_uint64_t
*) )) {
9994 PRE_MEM_WRITE( "mach_generate_activity_id(activity_id)", ARG3
, sizeof(vki_uint64_t
) );
9996 SET_STATUS_Failure( VKI_EFAULT
);
10000 POST(mach_generate_activity_id
)
10002 if (ML_(safe_to_deref
)( (void*)ARG3
, sizeof(vki_uint64_t
*) )) {
10003 POST_MEM_WRITE( ARG3
, sizeof(vki_uint64_t
) );
10004 PRINT("-> activity_id:%#llx", *(uint64_t*)ARG3
);
10008 #endif /* DARWIN_VERS >= DARWIN_10_12 */
10011 /* ---------------------------------------------------------------------
10013 ------------------------------------------------------------------ */
10015 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
10017 #define MACX_(sysno, name) \
10018 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10020 #define MACXY(sysno, name) \
10021 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
10023 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
10026 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
10027 unfortunately misused for Mach too, causing assertion failures
10028 // _____ : unimplemented in valgrind
10029 GEN : handlers are in syswrap-generic.c
10030 MAC : handlers are in this file
10031 X_ : PRE handler only
10032 XY : PRE and POST handlers
10034 const SyscallTableEntry
ML_(syscall_table
)[] = {
10035 // _____(__NR_syscall), // 0
10036 MACX_(__NR_exit
, exit
),
10037 GENX_(__NR_fork
, sys_fork
),
10038 GENXY(__NR_read
, sys_read
),
10039 GENX_(__NR_write
, sys_write
),
10040 GENXY(__NR_open
, sys_open
),
10041 GENXY(__NR_close
, sys_close
),
10042 GENXY(__NR_wait4
, sys_wait4
),
10043 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
10044 GENX_(__NR_link
, sys_link
),
10045 GENX_(__NR_unlink
, sys_unlink
),
10046 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
10047 GENX_(__NR_chdir
, sys_chdir
),
10048 GENX_(__NR_fchdir
, sys_fchdir
),
10049 GENX_(__NR_mknod
, sys_mknod
),
10050 GENX_(__NR_chmod
, sys_chmod
),
10051 GENX_(__NR_chown
, sys_chown
),
10052 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
10053 MACXY(__NR_getfsstat
, getfsstat
),
10054 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
10055 GENX_(__NR_getpid
, sys_getpid
), // 20
10056 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
10057 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
10058 GENX_(__NR_setuid
, sys_setuid
),
10059 GENX_(__NR_getuid
, sys_getuid
),
10060 GENX_(__NR_geteuid
, sys_geteuid
),
10061 MACX_(__NR_ptrace
, ptrace
),
10062 MACXY(__NR_recvmsg
, recvmsg
),
10063 MACX_(__NR_sendmsg
, sendmsg
),
10064 MACXY(__NR_recvfrom
, recvfrom
),
10065 MACXY(__NR_accept
, accept
),
10066 MACXY(__NR_getpeername
, getpeername
),
10067 MACXY(__NR_getsockname
, getsockname
),
10068 GENX_(__NR_access
, sys_access
),
10069 MACX_(__NR_chflags
, chflags
),
10070 MACX_(__NR_fchflags
, fchflags
),
10071 GENX_(__NR_sync
, sys_sync
),
10072 GENX_(__NR_kill
, sys_kill
),
10073 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
10074 GENX_(__NR_getppid
, sys_getppid
),
10075 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
10076 GENXY(__NR_dup
, sys_dup
),
10077 MACXY(__NR_pipe
, pipe
),
10078 GENX_(__NR_getegid
, sys_getegid
),
10079 #if DARWIN_VERS >= DARWIN_10_7
10080 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
10082 // _____(__NR_profil),
10084 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
10085 MACXY(__NR_sigaction
, sigaction
),
10086 GENX_(__NR_getgid
, sys_getgid
),
10087 MACXY(__NR_sigprocmask
, sigprocmask
),
10088 MACXY(__NR_getlogin
, getlogin
),
10089 // _____(__NR_setlogin),
10090 // _____(__NR_acct),
10091 MACXY(__NR_sigpending
, sigpending
),
10092 GENXY(__NR_sigaltstack
, sys_sigaltstack
),
10093 MACXY(__NR_ioctl
, ioctl
),
10094 // _____(__NR_reboot),
10095 // _____(__NR_revoke),
10096 GENX_(__NR_symlink
, sys_symlink
), // 57
10097 GENX_(__NR_readlink
, sys_readlink
),
10098 GENX_(__NR_execve
, sys_execve
),
10099 GENX_(__NR_umask
, sys_umask
), // 60
10100 GENX_(__NR_chroot
, sys_chroot
),
10101 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
10102 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
10103 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
10104 GENX_(__NR_msync
, sys_msync
),
10105 GENX_(__NR_vfork
, sys_fork
), // (We treat vfork as fork.)
10106 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
10107 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
10108 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
10109 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
10110 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
10111 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
10112 GENXY(__NR_munmap
, sys_munmap
),
10113 GENXY(__NR_mprotect
, sys_mprotect
),
10114 GENX_(__NR_madvise
, sys_madvise
),
10115 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
10116 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
10117 GENXY(__NR_mincore
, sys_mincore
),
10118 GENXY(__NR_getgroups
, sys_getgroups
),
10119 // _____(__NR_setgroups), // 80
10120 GENX_(__NR_getpgrp
, sys_getpgrp
),
10121 GENX_(__NR_setpgid
, sys_setpgid
),
10122 GENXY(__NR_setitimer
, sys_setitimer
),
10123 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
10124 // _____(__NR_swapon),
10125 GENXY(__NR_getitimer
, sys_getitimer
),
10126 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
10127 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
10128 MACXY(__NR_getdtablesize
, getdtablesize
),
10129 GENXY(__NR_dup2
, sys_dup2
),
10130 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
10131 MACXY(__NR_fcntl
, fcntl
),
10132 GENX_(__NR_select
, sys_select
),
10133 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
10134 GENX_(__NR_fsync
, sys_fsync
),
10135 GENX_(__NR_setpriority
, sys_setpriority
),
10136 MACXY(__NR_socket
, socket
),
10137 MACX_(__NR_connect
, connect
),
10138 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
10139 GENX_(__NR_getpriority
, sys_getpriority
), // 100
10140 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
10141 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
10142 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
10143 MACX_(__NR_bind
, bind
),
10144 MACX_(__NR_setsockopt
, setsockopt
),
10145 MACX_(__NR_listen
, listen
),
10146 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
10147 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
10148 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
10149 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
10150 MACX_(__NR_sigsuspend
, sigsuspend
), // old sigsuspend
10151 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
10152 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
10153 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
10154 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
10155 GENXY(__NR_gettimeofday
, sys_gettimeofday
),
10156 GENXY(__NR_getrusage
, sys_getrusage
),
10157 MACXY(__NR_getsockopt
, getsockopt
),
10158 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
10159 GENXY(__NR_readv
, sys_readv
), // 120
10160 GENX_(__NR_writev
, sys_writev
),
10161 // _____(__NR_settimeofday),
10162 GENX_(__NR_fchown
, sys_fchown
),
10163 GENX_(__NR_fchmod
, sys_fchmod
),
10164 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
10165 // _____(__NR_setreuid),
10166 // _____(__NR_setregid),
10167 GENX_(__NR_rename
, sys_rename
),
10168 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
10169 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
10170 GENX_(__NR_flock
, sys_flock
),
10171 MACXY(__NR_mkfifo
, mkfifo
),
10172 MACX_(__NR_sendto
, sendto
),
10173 MACX_(__NR_shutdown
, shutdown
),
10174 MACXY(__NR_socketpair
, socketpair
),
10175 GENX_(__NR_mkdir
, sys_mkdir
),
10176 GENX_(__NR_rmdir
, sys_rmdir
),
10177 GENX_(__NR_utimes
, sys_utimes
),
10178 MACX_(__NR_futimes
, futimes
),
10179 // _____(__NR_adjtime), // 140
10180 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
10181 MACXY(__NR_gethostuuid
, gethostuuid
),
10182 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
10183 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
10184 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
10185 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
10186 GENX_(__NR_setsid
, sys_setsid
),
10187 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
10188 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
10189 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
10190 // _____(__NR_getpgid),
10191 // _____(__NR_setprivexec),
10192 GENXY(__NR_pread
, sys_pread64
),
10193 GENX_(__NR_pwrite
, sys_pwrite64
),
10194 // _____(__NR_nfssvc),
10195 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
10196 GENXY(__NR_statfs
, sys_statfs
),
10197 GENXY(__NR_fstatfs
, sys_fstatfs
),
10198 // _____(__NR_unmount),
10199 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
10200 // _____(__NR_getfh),
10201 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
10202 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
10203 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
10204 // _____(__NR_quotactl),
10205 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
10206 MACX_(__NR_mount
, mount
),
10207 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
10208 MACXY(__NR_csops
, csops
), // code-signing ops
10209 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
10210 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
10211 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
10212 // _____(__NR_waitid),
10213 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
10214 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
10215 // _____(__NR_add_profil),
10216 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
10217 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
10218 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
10219 MACX_(__NR_kdebug_trace
, kdebug_trace
), // 180
10220 GENX_(__NR_setgid
, sys_setgid
),
10221 MACX_(__NR_setegid
, setegid
),
10222 MACX_(__NR_seteuid
, seteuid
),
10223 MACX_(__NR_sigreturn
, sigreturn
),
10224 // _____(__NR_chud),
10225 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
10226 #if DARWIN_VERS >= DARWIN_10_6
10227 // _____(__NR_fdatasync),
10229 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
10231 GENXY(__NR_stat
, sys_newstat
),
10232 GENXY(__NR_fstat
, sys_newfstat
),
10233 GENXY(__NR_lstat
, sys_newlstat
),
10234 MACX_(__NR_pathconf
, pathconf
),
10235 MACX_(__NR_fpathconf
, fpathconf
),
10236 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
10237 GENXY(__NR_getrlimit
, sys_getrlimit
),
10238 GENX_(__NR_setrlimit
, sys_setrlimit
),
10239 MACXY(__NR_getdirentries
, getdirentries
),
10240 MACXY(__NR_mmap
, mmap
),
10241 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
10242 MACX_(__NR_lseek
, lseek
),
10243 GENX_(__NR_truncate
, sys_truncate64
), // 200
10244 GENX_(__NR_ftruncate
, sys_ftruncate64
),
10245 MACXY(__NR___sysctl
, __sysctl
),
10246 GENX_(__NR_mlock
, sys_mlock
),
10247 GENX_(__NR_munlock
, sys_munlock
),
10248 // _____(__NR_undelete),
10249 // _____(__NR_ATsocket),
10250 // _____(__NR_ATgetmsg),
10251 // _____(__NR_ATputmsg),
10252 // _____(__NR_ATPsndreq),
10253 // _____(__NR_ATPsndrsp),
10254 // _____(__NR_ATPgetreq),
10255 // _____(__NR_ATPgetrsp),
10256 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
10257 #if DARWIN_VERS >= DARWIN_10_6
10258 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
10259 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
10261 // _____(__NR_kqueue_from_portset_np),
10262 // _____(__NR_kqueue_portset_np),
10264 // _____(__NR_mkcomplex),
10265 // _____(__NR_statv),
10266 // _____(__NR_lstatv),
10267 // _____(__NR_fstatv),
10268 MACXY(__NR_getattrlist
, getattrlist
), // 220
10269 MACX_(__NR_setattrlist
, setattrlist
),
10270 MACXY(__NR_getdirentriesattr
, getdirentriesattr
),
10271 MACX_(__NR_exchangedata
, exchangedata
),
10272 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
10273 // _____(__NR_searchfs),
10274 GENX_(__NR_delete
, sys_unlink
),
10275 // _____(__NR_copyfile),
10276 #if DARWIN_VERS >= DARWIN_10_6
10277 // _____(__NR_fgetattrlist),
10278 // _____(__NR_fsetattrlist),
10280 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
10281 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
10283 GENXY(__NR_poll
, sys_poll
),
10284 MACX_(__NR_watchevent
, watchevent
),
10285 MACXY(__NR_waitevent
, waitevent
),
10286 MACX_(__NR_modwatch
, modwatch
),
10287 MACXY(__NR_getxattr
, getxattr
),
10288 MACXY(__NR_fgetxattr
, fgetxattr
),
10289 MACX_(__NR_setxattr
, setxattr
),
10290 MACX_(__NR_fsetxattr
, fsetxattr
),
10291 MACX_(__NR_removexattr
, removexattr
),
10292 MACX_(__NR_fremovexattr
, fremovexattr
),
10293 MACXY(__NR_listxattr
, listxattr
), // 240
10294 MACXY(__NR_flistxattr
, flistxattr
),
10295 MACXY(__NR_fsctl
, fsctl
),
10296 MACX_(__NR_initgroups
, initgroups
),
10297 MACXY(__NR_posix_spawn
, posix_spawn
),
10298 #if DARWIN_VERS >= DARWIN_10_6
10299 // _____(__NR_ffsctl),
10301 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
10303 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
10304 // _____(__NR_nfsclnt),
10305 // _____(__NR_fhopen),
10306 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
10307 // _____(__NR_minherit),
10308 // _____(__NR_semsys),
10309 // _____(__NR_msgsys),
10310 // _____(__NR_shmsys),
10311 MACXY(__NR_semctl
, semctl
),
10312 MACX_(__NR_semget
, semget
),
10313 MACX_(__NR_semop
, semop
),
10314 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
10315 // _____(__NR_msgctl),
10316 // _____(__NR_msgget),
10317 // _____(__NR_msgsnd), // 260
10318 // _____(__NR_msgrcv),
10319 MACXY(__NR_shmat
, shmat
),
10320 MACXY(__NR_shmctl
, shmctl
),
10321 MACXY(__NR_shmdt
, shmdt
),
10322 MACX_(__NR_shmget
, shmget
),
10323 MACXY(__NR_shm_open
, shm_open
),
10324 MACXY(__NR_shm_unlink
, shm_unlink
),
10325 MACX_(__NR_sem_open
, sem_open
),
10326 MACX_(__NR_sem_close
, sem_close
),
10327 MACX_(__NR_sem_unlink
, sem_unlink
),
10328 MACX_(__NR_sem_wait
, sem_wait
),
10329 MACX_(__NR_sem_trywait
, sem_trywait
),
10330 MACX_(__NR_sem_post
, sem_post
),
10331 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
10332 // has become sysctlbyname. See below.
10333 MACXY(__NR_sem_init
, sem_init
),
10334 MACX_(__NR_sem_destroy
, sem_destroy
),
10335 MACX_(__NR_open_extended
, open_extended
), // 277
10336 // _____(__NR_umask_extended),
10337 MACXY(__NR_stat_extended
, stat_extended
),
10338 MACXY(__NR_lstat_extended
, lstat_extended
), // 280
10339 MACXY(__NR_fstat_extended
, fstat_extended
),
10340 MACX_(__NR_chmod_extended
, chmod_extended
),
10341 MACX_(__NR_fchmod_extended
,fchmod_extended
),
10342 MACXY(__NR_access_extended
,access_extended
),
10343 MACX_(__NR_settid
, settid
),
10344 #if DARWIN_VERS >= DARWIN_10_8
10345 MACX_(__NR_gettid
, gettid
), // 286
10347 // _____(__NR_setsgroups),
10348 // _____(__NR_getsgroups),
10349 // _____(__NR_setwgroups),
10350 // _____(__NR_getwgroups),
10351 // _____(__NR_mkfifo_extended),
10352 // _____(__NR_mkdir_extended),
10353 // _____(__NR_identitysvc),
10354 // _____(__NR_shared_region_check_np),
10355 // _____(__NR_shared_region_map_np),
10356 #if DARWIN_VERS >= DARWIN_10_6
10357 // _____(__NR_vm_pressure_monitor),
10358 // _____(__NR_psynch_rw_longrdlock),
10359 // _____(__NR_psynch_rw_yieldwrlock),
10360 // _____(__NR_psynch_rw_downgrade),
10361 // _____(__NR_psynch_rw_upgrade),
10362 MACXY(__NR_psynch_mutexwait
, psynch_mutexwait
), // 301
10363 MACXY(__NR_psynch_mutexdrop
, psynch_mutexdrop
), // 302
10364 MACXY(__NR_psynch_cvbroad
, psynch_cvbroad
), // 303
10365 MACXY(__NR_psynch_cvsignal
, psynch_cvsignal
), // 304
10366 MACXY(__NR_psynch_cvwait
, psynch_cvwait
), // 305
10367 MACXY(__NR_psynch_rw_rdlock
, psynch_rw_rdlock
), // 306
10368 MACXY(__NR_psynch_rw_wrlock
, psynch_rw_wrlock
), // 307
10369 MACXY(__NR_psynch_rw_unlock
, psynch_rw_unlock
), // 308
10370 // _____(__NR_psynch_rw_unlock2),
10372 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
10373 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
10374 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
10375 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
10376 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
10377 // _____(__NR___pthread_mutex_destroy),
10378 // _____(__NR___pthread_mutex_init),
10379 // _____(__NR___pthread_mutex_lock),
10380 // _____(__NR___pthread_mutex_trylock),
10381 // _____(__NR___pthread_mutex_unlock),
10382 // _____(__NR___pthread_cond_init),
10383 // _____(__NR___pthread_cond_destroy),
10384 // _____(__NR___pthread_cond_broadcast),
10385 // _____(__NR___pthread_cond_signal),
10387 // _____(__NR_getsid),
10388 // _____(__NR_settid_with_pid),
10389 #if DARWIN_VERS >= DARWIN_10_7
10390 MACXY(__NR_psynch_cvclrprepost
, psynch_cvclrprepost
), // 312
10392 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(308)), // old __pthread_cond_timedwait
10394 // _____(__NR_aio_fsync),
10395 MACXY(__NR_aio_return
, aio_return
),
10396 MACX_(__NR_aio_suspend
, aio_suspend
),
10397 // _____(__NR_aio_cancel),
10398 MACX_(__NR_aio_error
, aio_error
),
10399 MACXY(__NR_aio_read
, aio_read
),
10400 MACX_(__NR_aio_write
, aio_write
),
10401 // _____(__NR_lio_listio), // 320
10402 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
10404 #if DARWIN_VERS >= DARWIN_10_8
10405 MACXY(__NR_iopolicysys
, iopolicysys
),
10406 MACXY(__NR_process_policy
, process_policy
),
10408 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
10409 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
10411 // _____(__NR_mlockall),
10412 // _____(__NR_munlockall),
10413 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
10414 MACX_(__NR_issetugid
, issetugid
),
10415 MACX_(__NR___pthread_kill
, __pthread_kill
),
10416 MACX_(__NR___pthread_sigmask
, __pthread_sigmask
),
10417 // _____(__NR___sigwait),
10418 MACX_(__NR___disable_threadsignal
, __disable_threadsignal
),
10419 MACX_(__NR___pthread_markcancel
, __pthread_markcancel
),
10420 MACX_(__NR___pthread_canceled
, __pthread_canceled
),
10421 MACX_(__NR___semwait_signal
, __semwait_signal
),
10422 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
10423 MACXY(__NR_proc_info
, proc_info
), // 336
10424 MACXY(__NR_sendfile
, sendfile
),
10425 MACXY(__NR_stat64
, stat64
),
10426 MACXY(__NR_fstat64
, fstat64
),
10427 MACXY(__NR_lstat64
, lstat64
), // 340
10428 MACXY(__NR_stat64_extended
, stat64_extended
),
10429 MACXY(__NR_lstat64_extended
, lstat64_extended
),
10430 MACXY(__NR_fstat64_extended
, fstat64_extended
),
10431 MACXY(__NR_getdirentries64
, getdirentries64
),
10432 MACXY(__NR_statfs64
, statfs64
),
10433 MACXY(__NR_fstatfs64
, fstatfs64
),
10434 MACXY(__NR_getfsstat64
, getfsstat64
),
10435 MACX_(__NR___pthread_chdir
, __pthread_chdir
),
10436 MACX_(__NR___pthread_fchdir
, __pthread_fchdir
),
10437 // _____(__NR_audit),
10438 MACXY(__NR_auditon
, auditon
),
10439 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
10440 // _____(__NR_getauid),
10441 // _____(__NR_setauid),
10442 // _____(__NR_getaudit),
10443 // _____(__NR_setaudit),
10444 MACXY(__NR_getaudit_addr
, getaudit_addr
),
10445 // _____(__NR_setaudit_addr),
10446 // _____(__NR_auditctl),
10447 MACXY(__NR_bsdthread_create
, bsdthread_create
), // 360
10448 MACX_(__NR_bsdthread_terminate
, bsdthread_terminate
),
10449 MACXY(__NR_kqueue
, kqueue
),
10450 MACXY(__NR_kevent
, kevent
),
10451 GENX_(__NR_lchown
, sys_lchown
),
10452 // _____(__NR_stack_snapshot),
10453 MACX_(__NR_bsdthread_register
, bsdthread_register
),
10454 MACX_(__NR_workq_open
, workq_open
),
10455 MACXY(__NR_workq_ops
, workq_ops
),
10456 #if DARWIN_VERS >= DARWIN_10_6
10457 MACXY(__NR_kevent64
, kevent64
),
10459 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
10461 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // old semwait_signal
10462 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // old semwait_signal_nocancel
10463 #if DARWIN_VERS >= DARWIN_10_6
10464 MACX_(__NR___thread_selfid
, __thread_selfid
),
10466 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
10468 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
10469 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
10470 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
10471 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
10472 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
10473 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
10474 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
10475 // _____(__NR___mac_execve), // 380
10476 MACX_(__NR___mac_syscall
, __mac_syscall
),
10477 // _____(__NR___mac_get_file),
10478 // _____(__NR___mac_set_file),
10479 // _____(__NR___mac_get_link),
10480 // _____(__NR___mac_set_link),
10481 // _____(__NR___mac_get_proc),
10482 // _____(__NR___mac_set_proc),
10483 // _____(__NR___mac_get_fd),
10484 // _____(__NR___mac_set_fd),
10485 // _____(__NR___mac_get_pid),
10486 // _____(__NR___mac_get_lcid),
10487 // _____(__NR___mac_get_lctx),
10488 // _____(__NR___mac_set_lctx),
10489 // _____(__NR_setlcid),
10490 // _____(__NR_getlcid),
10491 // GrP fixme need any special nocancel handling?
10492 GENXY(__NR_read_nocancel
, sys_read
),
10493 GENX_(__NR_write_nocancel
, sys_write
),
10494 GENXY(__NR_open_nocancel
, sys_open
),
10495 GENXY(__NR_close_nocancel
, sys_close
),
10496 GENXY(__NR_wait4_nocancel
, sys_wait4
), // 400
10497 MACXY(__NR_recvmsg_nocancel
, recvmsg
),
10498 MACX_(__NR_sendmsg_nocancel
, sendmsg
),
10499 MACXY(__NR_recvfrom_nocancel
, recvfrom
),
10500 MACXY(__NR_accept_nocancel
, accept
),
10501 GENX_(__NR_msync_nocancel
, sys_msync
),
10502 MACXY(__NR_fcntl_nocancel
, fcntl
),
10503 GENX_(__NR_select_nocancel
, sys_select
),
10504 GENX_(__NR_fsync_nocancel
, sys_fsync
),
10505 MACX_(__NR_connect_nocancel
, connect
),
10506 MACX_(__NR_sigsuspend_nocancel
, sigsuspend
),
10507 GENXY(__NR_readv_nocancel
, sys_readv
),
10508 GENX_(__NR_writev_nocancel
, sys_writev
),
10509 MACX_(__NR_sendto_nocancel
, sendto
),
10510 GENXY(__NR_pread_nocancel
, sys_pread64
),
10511 GENX_(__NR_pwrite_nocancel
, sys_pwrite64
),
10512 // _____(__NR_waitid_nocancel),
10513 GENXY(__NR_poll_nocancel
, sys_poll
),
10514 // _____(__NR_msgsnd_nocancel),
10515 // _____(__NR_msgrcv_nocancel),
10516 MACX_(__NR_sem_wait_nocancel
, sem_wait
), // 420
10517 // _____(__NR_aio_suspend_nocancel),
10518 // _____(__NR___sigwait_nocancel),
10519 MACX_(__NR___semwait_signal_nocancel
, __semwait_signal
),
10520 // _____(__NR___mac_mount),
10521 // _____(__NR___mac_get_mount),
10522 // _____(__NR___mac_getfsstat),
10523 #if DARWIN_VERS >= DARWIN_10_6
10524 MACXY(__NR_fsgetpath
, fsgetpath
),
10525 MACXY(__NR_audit_session_self
, audit_session_self
),
10526 // _____(__NR_audit_session_join),
10528 #if DARWIN_VERS >= DARWIN_10_9
10529 MACX_(__NR_fileport_makeport
, fileport_makeport
),
10530 // _____(__NR_fileport_makefd), // 431
10531 // _____(__NR_audit_session_port), // 432
10532 // _____(__NR_pid_suspend), // 433
10533 // _____(__NR_pid_resume), // 434
10534 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(435)), // ???
10535 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(436)), // ???
10536 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(437)), // ???
10537 // _____(__NR_shared_region_map_and_slide_np), // 438
10538 // _____(__NR_kas_info), // 439
10539 // _____(__NR_memorystatus_control), // 440
10540 MACX_(__NR_guarded_open_np
, guarded_open_np
),
10541 MACX_(__NR_guarded_close_np
, guarded_close_np
),
10542 MACX_(__NR_guarded_kqueue_np
, guarded_kqueue_np
),
10543 MACX_(__NR_change_fdguard_np
, change_fdguard_np
),
10544 MACX_(__NR_connectx
, connectx
),
10545 MACX_(__NR_disconnectx
, disconnectx
),
10547 #if DARWIN_VERS >= DARWIN_10_10
10548 MACXY(__NR_sysctlbyname
, sysctlbyname
), // 274
10549 MACXY(__NR_necp_match_policy
, necp_match_policy
), // 460
10550 MACXY(__NR_getattrlistbulk
, getattrlistbulk
), // 461
10551 MACX_(__NR_faccessat
, faccessat
), // 466
10552 MACX_(__NR_fstatat64
, fstatat64
), // 470
10553 MACX_(__NR_readlinkat
, readlinkat
), // 473
10554 MACX_(__NR_bsdthread_ctl
, bsdthread_ctl
), // 478
10555 MACX_(__NR_csrctl
, csrctl
), // 483
10556 MACX_(__NR_guarded_open_dprotected_np
, guarded_open_dprotected_np
), // 484
10557 MACX_(__NR_guarded_write_np
, guarded_write_np
), // 485
10558 MACX_(__NR_guarded_pwrite_np
, guarded_pwrite_np
), // 486
10559 MACX_(__NR_guarded_writev_np
, guarded_writev_np
), // 487
10560 // _____(__NR___mremap_encrypted), // 489
10562 #if DARWIN_VERS >= DARWIN_10_11
10563 // _____(__NR_kdebug_trace_string), // 178
10564 // _____(__NR_kevent_qos), // 374
10565 MACX_(__NR_pselect
, pselect
), // 394
10566 // _____(__NR_netagent_trigger), // 490
10567 // _____(__NR_stack_snapshot_with_config), // 491
10568 // _____(__NR_microstackshot), // 492
10569 // _____(__NR_grab_pgo_data), // 493
10570 // _____(__NR_persona), // 494
10571 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(495)), // ???
10572 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(496)), // ???
10573 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(497)), // ???
10574 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(498)), // ???
10575 // _____(__NR_work_interval_ctl), // 499
10577 #if DARWIN_VERS >= DARWIN_10_12
10578 // _____(__NR_kdebug_typefilter), // 177
10579 // _____(__NR_clonefileat), // 462
10580 // _____(__NR_renameatx_np), // 488
10581 MACX_(__NR_getentropy
, getentropy
), // 500
10582 // _____(__NR_necp_open), // 501
10583 // _____(__NR_necp_client_action), // 502
10584 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(503)), // ???
10585 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(504)), // ???
10586 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(505)), // ???
10587 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(506)), // ???
10588 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(507)), // ???
10589 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(508)), // ???
10590 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(509)), // ???
10591 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(510)), // ???
10592 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(511)), // ???
10593 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(512)), // ???
10594 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(513)), // ???
10595 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(514)), // ???
10596 // _____(__NR_ulock_wait), // 515
10597 MACX_(__NR_ulock_wake
, ulock_wake
), // 516
10598 // _____(__NR_fclonefileat), // 517
10599 // _____(__NR_fs_snapshot), // 518
10600 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(519)), // ???
10601 // _____(__NR_terminate_with_payload), // 520
10602 // _____(__NR_abort_with_payload), // 521
10604 #if DARWIN_VERS >= DARWIN_10_13
10605 // _____(__NR_thread_selfcounts), // 186
10606 // _____(__NR_kevent_id, // 375
10607 // _____(__NR_necp_session_open), // 522
10608 // _____(__NR_necp_session_action), // 523
10609 // _____(__NR_setattrlistat), // 524
10610 // _____(__NR_net_qos_guideline), // 525
10611 // _____(__NR_fmount), // 526
10612 // _____(__NR_ntp_adjtime), // 527
10613 // _____(__NR_ntp_gettime), // 528
10614 // _____(__NR_os_fault_with_payload), // 529
10616 // _____(__NR_MAXSYSCALL)
10617 MACX_(__NR_DARWIN_FAKE_SIGRETURN
, FAKE_SIGRETURN
)
10621 // Mach traps use negative syscall numbers.
10622 // Use ML_(mach_trap_table)[-mach_trap_number] .
10623 // cf xnu sources osfmk/kern/syscall_sw.c
10625 const SyscallTableEntry
ML_(mach_trap_table
)[] = {
10626 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
10627 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
10628 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
10629 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
10630 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
10631 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
10632 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
10633 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
10634 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
10635 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
10637 # if DARWIN_VERS >= DARWIN_10_8
10638 MACXY(__NR_kernelrpc_mach_vm_allocate_trap
, kernelrpc_mach_vm_allocate_trap
),
10640 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
10643 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
10645 # if DARWIN_VERS >= DARWIN_10_8
10646 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap
),
10648 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
10651 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
10653 # if DARWIN_VERS >= DARWIN_10_8
10654 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap
),
10657 # if DARWIN_VERS >= DARWIN_10_9
10658 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap
),
10661 # if DARWIN_VERS < DARWIN_10_8
10662 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
10663 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
10666 # if DARWIN_VERS >= DARWIN_10_8
10667 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap
),
10668 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap
),
10669 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap
),
10670 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap
),
10671 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap
),
10672 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap
),
10673 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap
),
10674 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap
),
10676 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
10677 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
10678 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
10679 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
10680 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
10681 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
10682 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
10683 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
10686 # if DARWIN_VERS >= DARWIN_10_9
10687 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap
),
10688 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap
),
10690 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
10691 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
10694 MACXY(__NR_mach_reply_port
, mach_reply_port
),
10695 MACXY(__NR_thread_self_trap
, mach_thread_self
),
10696 MACXY(__NR_task_self_trap
, mach_task_self
),
10697 MACXY(__NR_host_self_trap
, mach_host_self
),
10698 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
10699 MACXY(__NR_mach_msg_trap
, mach_msg
),
10700 // _____(__NR_mach_msg_overwrite_trap),
10701 MACX_(__NR_semaphore_signal_trap
, semaphore_signal
),
10702 MACX_(__NR_semaphore_signal_all_trap
, semaphore_signal_all
),
10703 MACX_(__NR_semaphore_signal_thread_trap
, semaphore_signal_thread
),
10704 MACX_(__NR_semaphore_wait_trap
, semaphore_wait
),
10705 MACX_(__NR_semaphore_wait_signal_trap
, semaphore_wait_signal
),
10706 MACX_(__NR_semaphore_timedwait_trap
, semaphore_timedwait
),
10707 MACX_(__NR_semaphore_timedwait_signal_trap
, semaphore_timedwait_signal
),
10708 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
10710 # if DARWIN_VERS >= DARWIN_10_9
10711 MACX_(__NR_kernelrpc_mach_port_guard_trap
, kernelrpc_mach_port_guard_trap
),
10712 MACX_(__NR_kernelrpc_mach_port_unguard_trap
, kernelrpc_mach_port_unguard_trap
),
10714 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(41)),
10715 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
10718 # if DARWIN_VERS >= DARWIN_10_12
10719 MACXY(__NR_mach_generate_activity_id
, mach_generate_activity_id
),
10720 # elif DARWIN_VERS >= DARWIN_10_10
10721 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10722 # elif defined(VGA_x86) || DARWIN_VERS == DARWIN_10_9
10723 // _____(__NR_map_fd),
10725 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
10728 // _____(__NR_task_name_for_pid),
10729 MACXY(__NR_task_for_pid
, task_for_pid
),
10730 MACXY(__NR_pid_for_task
, pid_for_task
),
10731 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
10732 #if defined(VGA_x86)
10733 // _____(__NR_macx_swapon),
10734 // _____(__NR_macx_swapoff),
10736 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
10737 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
10739 #if DARWIN_VERS >= DARWIN_10_13
10740 // _____(__NR_thread_get_special_reply_port, // 50
10742 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10743 #endif /* DARWIN_VERS >= DARWIN_10_13 */
10744 #if defined(VGA_x86)
10745 // _____(__NR_macx_triggers),
10746 // _____(__NR_macx_backing_store_suspend),
10747 // _____(__NR_macx_backing_store_recovery),
10749 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
10750 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
10751 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
10753 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
10754 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
10755 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
10756 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
10757 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
10758 MACX_(__NR_swtch_pri
, swtch_pri
),
10759 MACX_(__NR_swtch
, swtch
), // -60
10760 MACX_(__NR_syscall_thread_switch
, syscall_thread_switch
),
10761 // _____(__NR_clock_sleep_trap),
10762 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
10763 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
10764 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
10765 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
10766 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
10767 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
10768 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
10769 #if DARWIN_VERS >= DARWIN_10_12
10770 MACX_(__NR_host_create_mach_voucher_trap
, host_create_mach_voucher_trap
),
10772 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
10774 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
10775 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
10776 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
10777 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
10778 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
10779 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
10780 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
10781 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
10782 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
10783 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
10784 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
10785 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
10786 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
10787 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
10788 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
10789 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
10790 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
10791 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
10792 MACXY(__NR_mach_timebase_info
, mach_timebase_info
),
10793 MACX_(__NR_mach_wait_until
, mach_wait_until
),
10794 MACXY(__NR_mk_timer_create
, mk_timer_create
),
10795 MACXY(__NR_mk_timer_destroy
, mk_timer_destroy
),
10796 MACX_(__NR_mk_timer_arm
, mk_timer_arm
),
10797 MACXY(__NR_mk_timer_cancel
, mk_timer_cancel
),
10798 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
10799 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
10800 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
10801 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
10802 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
10803 MACXY(__NR_iokit_user_client_trap
, iokit_user_client_trap
), // -100
10807 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
10808 // calling convention instead of the syscall convention.
10809 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
10811 #if defined(VGA_x86)
10812 const SyscallTableEntry
ML_(mdep_trap_table
)[] = {
10813 MACX_(__NR_thread_fast_set_cthread_self
, thread_fast_set_cthread_self
),
10815 #elif defined(VGA_amd64)
10816 const SyscallTableEntry
ML_(mdep_trap_table
)[] = {
10817 MACX_(__NR_thread_fast_set_cthread_self
, thread_fast_set_cthread_self
),
10820 #error unknown architecture
10823 const UInt
ML_(syscall_table_size
) =
10824 sizeof(ML_(syscall_table
)) / sizeof(ML_(syscall_table
)[0]);
10826 const UInt
ML_(mach_trap_table_size
) =
10827 sizeof(ML_(mach_trap_table
)) / sizeof(ML_(mach_trap_table
)[0]);
10829 const UInt
ML_(mdep_trap_table_size
) =
10830 sizeof(ML_(mdep_trap_table
)) / sizeof(ML_(mdep_trap_table
)[0]);
10832 #endif // defined(VGO_darwin)
10834 /*--------------------------------------------------------------------*/
10836 /*--------------------------------------------------------------------*/