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