1
2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2005-2013 Apple Inc.
11 Greg Parker gparker@apple.com
12
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.
17
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.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #if defined(VGO_darwin)
32
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"
60
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"
65
66 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
67 #include <mach/mach.h>
68 #include <mach/mach_vm.h>
69 #include <semaphore.h>
70 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
71
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];
76
77 typedef uint64_t mig_addr_t;
78
79
80 // Saved ports
81 static mach_port_t vg_host_port = 0;
82 static mach_port_t vg_task_port = 0;
83 static mach_port_t vg_bootstrap_port = 0;
84
85 // Run a thread from beginning to end and return the thread's
86 // scheduler-return-code.
thread_wrapper(Word tidW)87 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
88 {
89 VgSchedReturnCode ret;
90 ThreadId tid = (ThreadId)tidW;
91 ThreadState* tst = VG_(get_ThreadState)(tid);
92
93 VG_(debugLog)(1, "syswrap-darwin",
94 "thread_wrapper(tid=%lld): entry\n",
95 (ULong)tidW);
96
97 vg_assert(tst->status == VgTs_Init);
98
99 /* make sure we get the CPU lock before doing anything significant */
100 VG_(acquire_BigLock)(tid, "thread_wrapper");
101
102 if (0)
103 VG_(printf)("thread tid %d started: stack = %p\n",
104 tid, &tid);
105
106 /* Make sure error reporting is enabled in the new thread. */
107 tst->err_disablement_level = 0;
108
109 VG_TRACK(pre_thread_first_insn, tid);
110
111 tst->os_state.lwpid = VG_(gettid)();
112 tst->os_state.threadgroup = VG_(getpid)();
113
114 /* Thread created with all signals blocked; scheduler will set the
115 appropriate mask */
116
117 ret = VG_(scheduler)(tid);
118
119 vg_assert(VG_(is_exiting)(tid));
120
121 vg_assert(tst->status == VgTs_Runnable);
122 vg_assert(VG_(is_running_thread)(tid));
123
124 VG_(debugLog)(1, "syswrap-darwin",
125 "thread_wrapper(tid=%lld): done\n",
126 (ULong)tidW);
127
128 /* Return to caller, still holding the lock. */
129 return ret;
130 }
131
132
133
134 /* Allocate a stack for this thread, if it doesn't already have one.
135 Returns the initial stack pointer value to use, or 0 if allocation
136 failed. */
137
allocstack(ThreadId tid)138 Addr allocstack ( ThreadId tid )
139 {
140 ThreadState* tst = VG_(get_ThreadState)(tid);
141 VgStack* stack;
142 Addr initial_SP;
143
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. */
147
148 if (tst->os_state.valgrind_stack_base == 0)
149 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
150
151 if (tst->os_state.valgrind_stack_base != 0)
152 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
153
154 /* If no stack is present, allocate one. */
155
156 if (tst->os_state.valgrind_stack_base == 0) {
157 stack = VG_(am_alloc_VgStack)( &initial_SP );
158 if (stack) {
159 tst->os_state.valgrind_stack_base = (Addr)stack;
160 tst->os_state.valgrind_stack_init_SP = initial_SP;
161 }
162 }
163
164 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n",
165 tid,
166 (void*)tst->os_state.valgrind_stack_base,
167 (void*)tst->os_state.valgrind_stack_init_SP );
168
169 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP));
170
171 return tst->os_state.valgrind_stack_init_SP;
172 }
173
174
find_stack_segment(ThreadId tid,Addr sp)175 void find_stack_segment(ThreadId tid, Addr sp)
176 {
177 ML_(guess_and_register_stack) (sp, VG_(get_ThreadState)(tid));
178 }
179
180
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).
183 */
run_a_thread_NORETURN(Word tidW)184 static void run_a_thread_NORETURN ( Word tidW )
185 {
186 Int c;
187 VgSchedReturnCode src;
188 ThreadId tid = (ThreadId)tidW;
189 ThreadState* tst;
190
191 VG_(debugLog)(1, "syswrap-darwin",
192 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
193 (ULong)tidW);
194
195 tst = VG_(get_ThreadState)(tid);
196 vg_assert(tst);
197
198 /* Run the thread all the way through. */
199 src = thread_wrapper(tid);
200
201 VG_(debugLog)(1, "syswrap-darwin",
202 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
203 (ULong)tidW);
204
205 c = VG_(count_living_threads)();
206 vg_assert(c >= 1); /* stay sane */
207
208 // Tell the tool this thread is exiting
209 VG_TRACK( pre_thread_ll_exit, tid );
210
211 /* If the thread is exiting with errors disabled, complain loudly;
212 doing so is bad (does the user know this has happened?) Also,
213 in all cases, be paranoid and clear the flag anyway so that the
214 thread slot is safe in this respect if later reallocated. This
215 should be unnecessary since the flag should be cleared when the
216 slot is reallocated, in thread_wrapper(). */
217 if (tst->err_disablement_level > 0) {
218 VG_(umsg)(
219 "WARNING: exiting thread has error reporting disabled.\n"
220 "WARNING: possibly as a result of some mistake in the use\n"
221 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n"
222 );
223 VG_(debugLog)(
224 1, "syswrap-linux",
225 "run_a_thread_NORETURN(tid=%lld): "
226 "WARNING: exiting thread has err_disablement_level = %u\n",
227 (ULong)tidW, tst->err_disablement_level
228 );
229 }
230 tst->err_disablement_level = 0;
231
232 if (c == 1) {
233
234 VG_(debugLog)(1, "syswrap-darwin",
235 "run_a_thread_NORETURN(tid=%lld): "
236 "last one standing\n",
237 (ULong)tidW);
238
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);
243
244 } else {
245
246 mach_msg_header_t msg;
247
248 VG_(debugLog)(1, "syswrap-darwin",
249 "run_a_thread_NORETURN(tid=%lld): "
250 "not last one standing\n",
251 (ULong)tidW);
252
253 /* OK, thread is dead, but others still exist. Just exit. */
254
255 /* This releases the run lock */
256 VG_(exit_thread)(tid);
257 vg_assert(tst->status == VgTs_Zombie);
258
259 /* tid is now invalid. */
260
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
266
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);
273
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");
277 }
278
279 /*NOTREACHED*/
280 vg_assert(0);
281 }
282
283
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.
288 */
VG_(main_thread_wrapper_NORETURN)289 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
290 {
291 Addr sp;
292 VG_(debugLog)(1, "syswrap-darwin",
293 "entering VG_(main_thread_wrapper_NORETURN)\n");
294
295 sp = allocstack(tid);
296
297 /* If we can't even allocate the first thread's stack, we're hosed.
298 Give up. */
299 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
300
301 /* shouldn't be any other threads around yet */
302 vg_assert( VG_(count_living_threads)() == 1 );
303
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 */
309 );
310
311 /*NOTREACHED*/
312 vg_assert(0);
313 }
314
315
start_thread_NORETURN(Word arg)316 void start_thread_NORETURN ( Word arg )
317 {
318 ThreadState* tst = (ThreadState*)arg;
319 ThreadId tid = tst->tid;
320
321 run_a_thread_NORETURN ( (Word)tid );
322 /*NOTREACHED*/
323 vg_assert(0);
324 }
325
326
VG_(cleanup_thread)327 void VG_(cleanup_thread) ( ThreadArchState* arch )
328 {
329 }
330
331
332 /* ---------------------------------------------------------------------
333 Message reporting, with duplicate removal
334 ------------------------------------------------------------------ */
335
336 static WordFM* decaying_string_table = NULL; /* HChar* -> UWord */
337
decaying_string_table_cmp(UWord s1,UWord s2)338 static Word decaying_string_table_cmp ( UWord s1, UWord s2 ) {
339 return (Word)VG_(strcmp)( (HChar*)s1, (HChar*)s2 );
340 }
341
342 static void log_decaying ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
log_decaying(const HChar * format,...)343 static void log_decaying ( const HChar* format, ... )
344 {
345 // get the message into a stack-allocated string.
346 HChar buf[256];
347 VG_(memset)(buf, 0, sizeof(buf));
348 va_list vargs;
349 va_start(vargs,format);
350 (void) VG_(vsnprintf)(buf, sizeof(buf), format, vargs);
351 va_end(vargs);
352 buf[sizeof(buf)-1] = 0;
353
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 );
359 }
360
361 const HChar* key = NULL;
362 UWord val = 0;
363 if (!VG_(lookupFM)(decaying_string_table,
364 (UWord*)&key, &val, (UWord)&buf[0])) {
365 // We haven't seen this string before, so strdup it and add
366 // it to the table.
367 vg_assert(key == NULL && val == 0);
368 key = VG_(strdup)("syswrap-darwin.pd.2", buf);
369 VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)0);
370 }
371
372 vg_assert(key != NULL && key != &buf[0]);
373
374 // So, finally, |key| is in the tree, and |val| is what it is
375 // currently associated with. Increment that counter.
376 val++;
377 Bool b = VG_(addToFM)(decaying_string_table, (UWord)key, (UWord)val);
378 vg_assert(b);
379
380 if (-1 != VG_(log2)( (UInt)val )) {
381 if (val == 1)
382 VG_(dmsg)("%s\n", key);
383 else
384 VG_(dmsg)("%s (repeated %lu times)\n", key, val);
385 }
386 }
387
388
389 /* ---------------------------------------------------------------------
390 Mach port tracking (based on syswrap-generic's fd tracker)
391 ------------------------------------------------------------------ */
392
393 /* One of these is allocated for each open port. */
394 typedef struct OpenPort
395 {
396 mach_port_t port;
397 mach_port_type_t type; /* right type(s) */
398 Int send_count; /* number of send rights */
399 HChar *name; /* bootstrap name or NULL */
400 ExeContext *where; /* first allocation only */
401 struct OpenPort *next, *prev;
402 } OpenPort;
403
404 // strlen("0x12345678")
405 #define PORT_STRLEN (2+2*sizeof(mach_port_t))
406
407 /* List of allocated ports. */
408 static OpenPort *allocated_ports;
409
410 /* Count of open ports. */
411 static Int allocated_port_count = 0;
412
413 /* Create an entry for |port|, with no other info. Assumes it doesn't
414 already exist. */
port_create_vanilla(mach_port_t port)415 static void port_create_vanilla(mach_port_t port)
416 {
417 OpenPort* op
418 = VG_(calloc)("syswrap-darwin.port_create_vanilla", sizeof(OpenPort), 1);
419 op->port = port;
420 /* Add it to the list. */
421 op->next = allocated_ports;
422 if (allocated_ports) allocated_ports->prev = op;
423 allocated_ports = op;
424 allocated_port_count++;
425 }
426
427 __attribute__((unused))
port_exists(mach_port_t port)428 static Bool port_exists(mach_port_t port)
429 {
430 OpenPort *i;
431
432 /* Check to see if this port is already open. */
433 i = allocated_ports;
434 while (i) {
435 if (i->port == port) {
436 return True;
437 }
438 i = i->next;
439 }
440
441 return False;
442 }
443
info_for_port(mach_port_t port)444 static OpenPort *info_for_port(mach_port_t port)
445 {
446 OpenPort *i;
447 if (!port) return NULL;
448
449 i = allocated_ports;
450 while (i) {
451 if (i->port == port) {
452 return i;
453 }
454 i = i->next;
455 }
456
457 return NULL;
458 }
459
460
461 // Give a port a name, without changing its refcount
462 // GrP fixme don't override name if it already has a specific one
assign_port_name(mach_port_t port,const HChar * name)463 __private_extern__ void assign_port_name(mach_port_t port, const HChar *name)
464 {
465 OpenPort *i;
466 if (!port) return;
467 vg_assert(name);
468
469 i = info_for_port(port);
470 vg_assert(i);
471
472 if (i->name) VG_(free)(i->name);
473 i->name =
474 VG_(malloc)("syswrap-darwin.mach-port-name",
475 VG_(strlen)(name) + PORT_STRLEN + 1);
476 VG_(sprintf)(i->name, name, port);
477 }
478
479
480 // Return the name of the given port or "UNKNOWN 0x1234" if not known.
name_for_port(mach_port_t port)481 static const HChar *name_for_port(mach_port_t port)
482 {
483 static HChar buf[8 + PORT_STRLEN + 1];
484 OpenPort *i;
485
486 // hack
487 if (port == VG_(gettid)()) return "mach_thread_self()";
488 if (port == 0) return "NULL";
489
490 i = allocated_ports;
491 while (i) {
492 if (i->port == port) {
493 return i->name;
494 }
495 i = i->next;
496 }
497
498 VG_(sprintf)(buf, "NONPORT-%#x", port);
499 return buf;
500 }
501
502 /* Note the fact that a port was just deallocated. */
503
504 static
record_port_mod_refs(mach_port_t port,mach_port_type_t right,Int delta)505 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta)
506 {
507 OpenPort *i = allocated_ports;
508 if (!port) return;
509
510 while(i) {
511 if(i->port == port) {
512 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME);
513 if (right & MACH_PORT_TYPE_SEND) {
514 // send rights are refcounted
515 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy
516 i->send_count += delta;
517 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND;
518 else i->type &= ~MACH_PORT_TYPE_SEND;
519 }
520 right = right & ~MACH_PORT_TYPE_SEND;
521 if (right) {
522 // other rights are not refcounted
523 if (delta > 0) {
524 i->type |= right;
525 } else if (delta < 0) {
526 i->type &= ~right;
527 }
528 }
529
530 if (i->type != 0) return;
531
532 // Port has no rights left. Kill it.
533 // VG_(printf)("deleting port %p %s", i->port, i->name);
534 if(i->prev)
535 i->prev->next = i->next;
536 else
537 allocated_ports = i->next;
538 if(i->next)
539 i->next->prev = i->prev;
540 if(i->name)
541 VG_(free) (i->name);
542 VG_(free) (i);
543 allocated_port_count--;
544 return;
545 }
546 i = i->next;
547 }
548
549 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta);
550 }
551
552 static
record_port_insert_rights(mach_port_t port,mach_msg_type_name_t type)553 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type)
554 {
555 switch (type) {
556 case MACH_MSG_TYPE_PORT_NAME:
557 // this task has no rights for the name
558 break;
559 case MACH_MSG_TYPE_PORT_RECEIVE:
560 // this task gets receive rights
561 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1);
562 break;
563 case MACH_MSG_TYPE_PORT_SEND:
564 // this task gets a send right
565 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1);
566 break;
567 case MACH_MSG_TYPE_PORT_SEND_ONCE:
568 // this task gets send-once rights
569 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1);
570 break;
571 default:
572 vg_assert(0);
573 break;
574 }
575 }
576
577 static
record_port_dealloc(mach_port_t port)578 void record_port_dealloc(mach_port_t port)
579 {
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);
582 }
583
584 static
record_port_destroy(mach_port_t port)585 void record_port_destroy(mach_port_t port)
586 {
587 // deletes all rights to port
588 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN);
589 }
590
591
592 /* Note the fact that a Mach port was just allocated or transferred.
593 If the port is already known, increment its reference count. */
record_named_port(ThreadId tid,mach_port_t port,mach_port_right_t right,const HChar * name)594 void record_named_port(ThreadId tid, mach_port_t port,
595 mach_port_right_t right, const HChar *name)
596 {
597 OpenPort *i;
598 if (!port) return;
599
600 /* Check to see if this port is already open. */
601 i = allocated_ports;
602 while (i) {
603 if (i->port == port) {
604 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1);
605 return;
606 }
607 i = i->next;
608 }
609
610 /* Not already one: allocate an OpenPort */
611 if (i == NULL) {
612 i = VG_(malloc)("syswrap-darwin.mach-port", sizeof(OpenPort));
613
614 i->prev = NULL;
615 i->next = allocated_ports;
616 if(allocated_ports) allocated_ports->prev = i;
617 allocated_ports = i;
618 allocated_port_count++;
619
620 i->port = port;
621 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0);
622 i->name = NULL;
623 if (right != -1) {
624 i->type = MACH_PORT_TYPE(right);
625 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0;
626 } else {
627 i->type = 0;
628 i->send_count = 0;
629 }
630
631 assign_port_name(port, name);
632 }
633 }
634
635
636 // Record opening of a nameless port.
record_unnamed_port(ThreadId tid,mach_port_t port,mach_port_right_t right)637 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right)
638 {
639 record_named_port(tid, port, right, "unnamed-%p");
640 }
641
642
643 /* Dump summary of open Mach ports, like VG_(show_open_fds) */
VG_(show_open_ports)644 void VG_(show_open_ports)(void)
645 {
646 OpenPort *i;
647
648 VG_(message)(Vg_UserMsg,
649 "MACH PORTS: %d open at exit.\n", allocated_port_count);
650
651 for (i = allocated_ports; i; i = i->next) {
652 if (i->name) {
653 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s\n", i->port,
654 i->name);
655 } else {
656 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x\n", i->port);
657 }
658
659 if (i->where) {
660 VG_(pp_ExeContext)(i->where);
661 VG_(message)(Vg_UserMsg, "\n");
662 }
663 }
664
665 VG_(message)(Vg_UserMsg, "\n");
666 }
667
668
669 /* ---------------------------------------------------------------------
670 sync_mappings
671 ------------------------------------------------------------------ */
672
673 typedef
674 enum { CheckAlways=1, CheckEvery20, CheckNever }
675 CheckHowOften;
676
show_CheckHowOften(CheckHowOften cho)677 static const HChar* show_CheckHowOften ( CheckHowOften cho ) {
678 switch (cho) {
679 case CheckAlways: return "Always ";
680 case CheckEvery20: return "Every20";
681 case CheckNever: return "Never ";
682 default: vg_assert(0);
683 }
684 }
685
686 /* Statistics for one particular resync-call set of arguments,
687 as specified by key1, key2 and key3. */
688 typedef
689 struct {
690 CheckHowOften cho;
691 const HChar* key1;
692 const HChar* key2;
693 UWord key3;
694 ULong n_checks;
695 ULong n_mappings_added;
696 ULong n_mappings_removed;
697 }
698 SyncStats;
699
cmp_eqkeys_SyncStats(SyncStats * ss1,SyncStats * ss2)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);
704 }
705
706 /* The filter data. */
707 #define N_SYNCSTATS 1000
708 static Int syncstats_used = 0;
709 static SyncStats syncstats[N_SYNCSTATS];
710
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)
714
715
716 static
update_syncstats(CheckHowOften cho,const HChar * key1,const HChar * key2,UWord key3,UInt n_mappings_added,UInt n_mappings_removed)717 void update_syncstats ( CheckHowOften cho,
718 const HChar* key1, const HChar* key2,
719 UWord key3,
720 UInt n_mappings_added, UInt n_mappings_removed )
721 {
722 SyncStats dummy = { CheckAlways, key1, key2, key3, 0, 0, 0 };
723 Int i;
724 for (i = 0; i < syncstats_used; i++) {
725 if (cmp_eqkeys_SyncStats(&syncstats[i], &dummy))
726 break;
727 }
728 vg_assert(i >= 0 && i <= syncstats_used);
729 if (i == syncstats_used) {
730 // alloc new
731 vg_assert(syncstats_used < N_SYNCSTATS);
732 syncstats_used++;
733 syncstats[i] = dummy;
734 syncstats[i].cho = cho;
735 }
736 vg_assert(cmp_eqkeys_SyncStats(&syncstats[i], &dummy));
737 syncstats[i].n_checks++;
738 syncstats[i].n_mappings_added += (ULong)n_mappings_added;
739 syncstats[i].n_mappings_removed += (ULong)n_mappings_removed;
740 // reorder
741 static UInt reorder_ctr = 0;
742 if (i > 0 && 0 == (1 & reorder_ctr++)) {
743 SyncStats tmp = syncstats[i-1];
744 syncstats[i-1] = syncstats[i];
745 syncstats[i] = tmp;
746 }
747 }
748
749
maybe_show_syncstats(void)750 static void maybe_show_syncstats ( void )
751 {
752 Int i;
753
754 // display
755 if (0 == (n_syncsRequested & 0xFF)) {
756 VG_(printf)("Resync filter: %'llu requested, %'llu performed (%llu%%)\n",
757 n_syncsRequested, n_syncsPerformed,
758 (100 * n_syncsPerformed) /
759 (n_syncsRequested == 0 ? 1 : n_syncsRequested));
760 for (i = 0; i < syncstats_used; i++) {
761 if (i >= 40) break; // just show the top 40
762 VG_(printf)(" [%3d] (%s) upd %6llu diff %4llu+,%3llu-"
763 " %s %s 0x%08llx\n",
764 i, show_CheckHowOften(syncstats[i].cho),
765 syncstats[i].n_checks,
766 syncstats[i].n_mappings_added,
767 syncstats[i].n_mappings_removed,
768 syncstats[i].key1, syncstats[i].key2,
769 (ULong)syncstats[i].key3);
770 }
771 if (i < syncstats_used) {
772 VG_(printf)(" and %d more entries not shown.\n", syncstats_used - i);
773 }
774 VG_(printf)("\n");
775 }
776 }
777
778
ML_(sync_mappings)779 Bool ML_(sync_mappings)(const HChar* when, const HChar* where, UWord num)
780 {
781 // If VG(clo_resync_filter) == 0, the filter is disabled, and
782 // we must always honour the resync request.
783 //
784 // If VG(clo_resync_filter) == 1, the filter is enabled,
785 // so we try to avoid doing the sync if possible, but keep
786 // quiet.
787 //
788 // If VG(clo_resync_filter) == 2, the filter is enabled,
789 // so we try to avoid doing the sync if possible, and also
790 // periodically show stats, so that the filter can be updated.
791 // (by hand).
792
793 if (VG_(clo_resync_filter) >= 2)
794 maybe_show_syncstats();
795
796 n_syncsRequested++;
797
798 // Usually the number of segments added/removed in a single call is very
799 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for
800 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model,
801 // because we can't do dynamic allocation within VG_(get_changed_segments),
802 // because it's in m_aspacemgr.
803 ChangedSeg* css = NULL;
804 Int css_size;
805 Int css_used;
806 Int i;
807 Bool ok;
808
809 // -------------- BEGIN resync-filter-kludge --------------
810 //
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).
818 //
819 // Assume this is kernel-version and word-size specific, so develop
820 // filters accordingly. This might be overly conservative --
821 // I don't know.
822
823 # define STREQ(_s1, _s2) (0 == VG_(strcmp)((_s1),(_s2)))
824 Bool when_in = STREQ(when, "in");
825 Bool when_after = STREQ(when, "after");
826 Bool where_mmr = STREQ(where, "mach_msg_receive");
827 Bool where_mmrU = STREQ(where, "mach_msg_receive-UNHANDLED");
828 Bool where_iuct = STREQ(where, "iokit_user_client_trap");
829 Bool where_MwcN = STREQ(where, "ML_(wqthread_continue_NORETURN)");
830 Bool where_woQR = STREQ(where, "workq_ops(QUEUE_REQTHREADS)");
831 Bool where_woTR = STREQ(where, "workq_ops(THREAD_RETURN)");
832 Bool where_ke64 = STREQ(where, "kevent64");
833 # undef STREQ
834
835 vg_assert(
836 1 >= ( (where_mmr ? 1 : 0) + (where_mmrU ? 1 : 0)
837 + (where_iuct ? 1 : 0) + (where_MwcN ? 1 : 0)
838 + (where_woQR ? 1 : 0) + (where_woTR ? 1 : 0)
839 + (where_ke64 ? 1 : 0)
840 ));
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);
845
846 CheckHowOften check = CheckAlways;
847
848 # if DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8
849 /* ---------- BEGIN filter for 64-bit 10.9.x ---------- */
850 if (when_after && where_mmr) {
851 // "after mach_msg_receive <number>"
852 switch (num) {
853 case 0x00000000: // upd 12414 diff 36+,0-
854 check = CheckEvery20;
855 break;
856 default:
857 break;
858 }
859 }
860 else
861 if (when_after && where_mmrU) {
862 // "after mach_msg_receive-UNHANDLED <number>"
863 switch (num) {
864 case 0x00000000: // upd 16687 diff 73+,0-
865 case 0x00000001: // upd 5106 diff 89+,0-
866 case 0x00000002: // upd 1609 diff 1+,0-
867 case 0x00000003: // upd 1987 diff 6+,0-
868 // case 0x00000b95: // upd 2894 diff 57+,1- <==dangerous
869 case 0x000072d9: // upd 2616 diff 11+,0-
870 case 0x000072cb: // upd 2616 diff 9+,0-
871 case 0x000074d5: // upd 172 diff 0+,0-
872 check = CheckEvery20;
873 break;
874 default:
875 break;
876 }
877 }
878 else
879 if (when_in && where_MwcN && num == 0x00000000) {
880 // in ML_(wqthread_continue_NORETURN) 0x00000000
881 // upd 4346 diff 0+,0-
882 check = CheckEvery20;
883 }
884 else
885 if (when_after && where_woQR && num == 0x00000000) {
886 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
887 // upd 14434 diff 102+,0-
888 check = CheckEvery20;
889 }
890 else
891 if (when_after && where_woTR && num == 0x00000000) {
892 // after workq_ops(THREAD_RETURN) 0x00000000
893 // upd 14434 diff 102+,0-
894 check = CheckEvery20;
895 }
896 else
897 if (when_after && where_ke64 && num == 0x00000000) {
898 // after kevent64 0x00000000
899 // upd 1736 diff 78+,0-
900 check = CheckEvery20;
901 }
902 /* ----------- END filter for 64-bit 10.9.x ----------- */
903 # endif /* DARWIN_VERS == DARWIN_10_9 && VG_WORDSIZE == 8 */
904
905 # if DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8
906 /* ---------- BEGIN filter for 64-bit 10.10.x ---------- */
907 if (when_after && where_mmr) {
908 // "after mach_msg_receive <number>"
909 switch (num) {
910 case 0x00000000: // upd 2380 diff 23+,0-
911 check = CheckEvery20;
912 break;
913 default:
914 break;
915 }
916 }
917 else
918 if (when_after && where_mmrU) {
919 // "after mach_msg_receive-UNHANDLED <number>"
920 switch (num) {
921 case 0x00000000: // upd 2370 diff 93+,1- <==dangerous
922 case 0x0000004f: // upd 212 diff 2+,0-
923 case 0x00000b95: // upd 9826 diff 163+,1- diff scale, dangerous
924 case 0x00000ba5: // upd 304 diff 0+,0-
925 case 0x0000157f: // upd 201 diff 2+,0-
926 case 0x0000157d: // upd 197 diff 1+,0-
927 case 0x0000333d: // upd 112 diff 0+,0-
928 case 0x0000333f: // upd 223 diff 10+,0-
929 case 0x000072cd: // upd 8286 diff 98+,0- diff scale
930 case 0x000072ae: // upd 193 diff 10+,0-
931 case 0x000072ec: // upd 319 diff 7+,0-
932 case 0x77303074: // upd 113 diff 3+,0-
933 case 0x10000000: // upd 314 diff 6+,0-
934 check = CheckEvery20;
935 break;
936 default:
937 break;
938 }
939 }
940 else
941 if (when_in && where_MwcN && num == 0x00000000) {
942 // in ML_(wqthread_continue_NORETURN) 0x00000000
943 // upd 1110 diff 37+,0-
944 check = CheckEvery20;
945 }
946 else
947 if (when_after && where_woQR && num == 0x00000000) {
948 // after workq_ops(QUEUE_REQTHREADS) 0x00000000
949 // upd 1099 diff 37+,0-
950 check = CheckEvery20;
951 }
952 else
953 if (when_after && where_woTR && num == 0x00000000) {
954 // after workq_ops(THREAD_RETURN) 0x00000000
955 // 1239 diff 53+,0-
956 check = CheckEvery20;
957 }
958 else
959 if (when_after && where_ke64 && num == 0x00000000) {
960 // after kevent64 0x00000000
961 // upd 1463 diff 15+,0-
962 check = CheckEvery20;
963 }
964 /* ----------- END filter for 64-bit 10.10.x ----------- */
965 # endif /* DARWIN_VERS == DARWIN_10_10 && VG_WORDSIZE == 8 */
966
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. */
969 {
970 static UInt ctr1k = 0;
971 ctr1k++;
972 if ((ctr1k % 1000) == 0)
973 check = CheckAlways;
974 }
975
976 /* If the filter is disabled, we must always check. */
977 if (VG_(clo_resync_filter) == 0)
978 check = CheckAlways;
979
980 switch (check) {
981 case CheckAlways:
982 break;
983 case CheckEvery20: {
984 // only resync once every 20th time
985 static UInt ctr10 = 0;
986 ctr10++;
987 if ((ctr10 % 20) != 0) return False;
988 break;
989 }
990 case CheckNever:
991 return False;
992 default:
993 vg_assert(0);
994 }
995 //
996 // --------------- END resync-filter-kludge ---------------
997
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);
1002 }
1003
1004 // 16 is enough for most cases, but small enough that overflow happens
1005 // occasionally and thus the overflow path gets some test coverage.
1006 css_size = 16;
1007 ok = False;
1008 while (!ok) {
1009 VG_(free)(css); // css is NULL on first iteration; that's ok.
1010 css = VG_(calloc)("sys_wrap.sync_mappings",
1011 css_size, sizeof(ChangedSeg));
1012 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used);
1013 css_size *= 2;
1014 }
1015
1016 UInt css_added = 0, css_removed = 0;
1017
1018 // Now add/remove them.
1019 for (i = 0; i < css_used; i++) {
1020 ChangedSeg* cs = &css[i];
1021 if (cs->is_added) {
1022 css_added++;
1023 ML_(notify_core_and_tool_of_mmap)(
1024 cs->start, cs->end - cs->start + 1,
1025 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset);
1026 // should this call VG_(di_notify_mmap) also?
1027 } else {
1028 css_removed++;
1029 ML_(notify_core_and_tool_of_munmap)(
1030 cs->start, cs->end - cs->start + 1);
1031 }
1032 if (VG_(clo_trace_syscalls)) {
1033 if (cs->is_added) {
1034 VG_(debugLog)(0, "syswrap-darwin",
1035 " added region 0x%010lx..0x%010lx prot %u at %s (%s)\n",
1036 cs->start, cs->end + 1, (UInt)cs->prot, where, when);
1037 } else {
1038 VG_(debugLog)(0, "syswrap-darwin",
1039 " removed region 0x%010lx..0x%010lx at %s (%s)\n",
1040 cs->start, cs->end + 1, where, when);
1041 }
1042 }
1043 }
1044
1045 VG_(free)(css);
1046
1047 if (0)
1048 VG_(debugLog)(0, "syswrap-darwin", "SYNC: %d %s %s\n",
1049 css_used, when, where);
1050
1051 // Update the stats, so we can derive the filter above.
1052 n_syncsPerformed++;
1053 update_syncstats(check, when, where, num, css_added, css_removed);
1054
1055 return css_used > 0;
1056 }
1057
1058 /* ---------------------------------------------------------------------
1059 wrappers
1060 ------------------------------------------------------------------ */
1061
1062 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name)
1063 #define POST(name) DEFN_POST_TEMPLATE(darwin, name)
1064
1065 #define PRE_FN(name) vgSysWrap_darwin_##name##_before
1066 #define POST_FN(name) vgSysWrap_darwin_##name##_after
1067
1068 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags)
1069 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status)
1070
1071 #if VG_WORDSIZE == 4
1072 // Combine two 32-bit values into a 64-bit value
1073 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) )
1074 # if defined(VGA_x86)
1075 # define LOHI64(lo,hi) ( ((ULong)(UInt)(lo)) | (((ULong)(UInt)(hi)) << 32) )
1076 # else
1077 # error unknown architecture
1078 # endif
1079 #endif
1080
1081 // Retrieve the current Mach thread
1082 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid)
1083
1084 // Set the POST handler for a mach_msg derivative
1085 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn
1086
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
1091
1092 /* ---------------------------------------------------------------------
1093 darwin ioctl wrapper
1094 ------------------------------------------------------------------ */
1095
PRE(ioctl)1096 PRE(ioctl)
1097 {
1098 *flags |= SfMayBlock;
1099
1100 /* Handle ioctls that don't take an arg first */
1101 switch (ARG2 /* request */) {
1102 case VKI_TIOCSCTTY:
1103 case VKI_TIOCEXCL:
1104 case VKI_TIOCSBRK:
1105 case VKI_TIOCCBRK:
1106 case VKI_TIOCPTYGRANT:
1107 case VKI_TIOCPTYUNLK:
1108 case VKI_DTRACEHIOC_REMOVE:
1109 PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2);
1110 PRE_REG_READ2(long, "ioctl",
1111 unsigned int, fd, unsigned int, request);
1112 return;
1113 default:
1114 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3);
1115 PRE_REG_READ3(long, "ioctl",
1116 unsigned int, fd, unsigned int, request, unsigned long, arg);
1117 }
1118
1119 switch (ARG2 /* request */) {
1120 case VKI_TIOCGWINSZ:
1121 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
1122 break;
1123 case VKI_TIOCSWINSZ:
1124 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
1125 break;
1126 case VKI_TIOCMBIS:
1127 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
1128 break;
1129 case VKI_TIOCMBIC:
1130 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
1131 break;
1132 case VKI_TIOCMSET:
1133 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
1134 break;
1135 case VKI_TIOCMGET:
1136 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
1137 break;
1138 case VKI_TIOCGPGRP:
1139 /* Get process group ID for foreground processing group. */
1140 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1141 break;
1142 case VKI_TIOCSPGRP:
1143 /* Set a process group ID? */
1144 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
1145 break;
1146 case VKI_FIONBIO:
1147 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
1148 break;
1149 case VKI_FIOASYNC:
1150 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
1151 break;
1152 case VKI_FIONREAD: /* identical to SIOCINQ */
1153 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1154 break;
1155
1156
1157 /* These all use struct ifreq AFAIK */
1158 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */
1159 case VKI_SIOCGIFFLAGS: /* get flags */
1160 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
1161 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1162 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
1163 break;
1164 case VKI_SIOCGIFMTU: /* get MTU size */
1165 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
1166 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1167 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
1168 break;
1169 case VKI_SIOCGIFADDR: /* get PA address */
1170 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
1171 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1172 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
1173 break;
1174 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1175 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
1176 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1177 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
1178 break;
1179 case VKI_SIOCGIFMETRIC: /* get metric */
1180 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
1181 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1182 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
1183 break;
1184 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1185 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
1186 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1187 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
1188 break;
1189 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1190 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
1191 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1192 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
1193 break;
1194 case VKI_SIOCGIFCONF: /* get iface list */
1195 /* WAS:
1196 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1197 KERNEL_DO_SYSCALL(tid,RES);
1198 if (!VG_(is_kerror)(RES) && RES == 0)
1199 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1200 */
1201 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1202 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
1203 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
1204 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
1205 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
1206 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
1207 if ( ARG3 ) {
1208 // TODO len must be readable and writable
1209 // buf pointer only needs to be readable
1210 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
1211 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
1212 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
1213 }
1214 break;
1215
1216 case VKI_SIOCSIFFLAGS: /* set flags */
1217 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
1218 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1219 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
1220 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1221 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1222 break;
1223 case VKI_SIOCSIFADDR: /* set PA address */
1224 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1225 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1226 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1227 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
1228 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1229 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
1230 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1231 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1232 break;
1233 case VKI_SIOCSIFMETRIC: /* set metric */
1234 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
1235 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1236 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
1237 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1238 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1239 break;
1240 case VKI_SIOCSIFMTU: /* set MTU size */
1241 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
1242 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
1243 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
1244 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1245 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1246 break;
1247 /* Routing table calls. */
1248 #ifdef VKI_SIOCADDRT
1249 case VKI_SIOCADDRT: /* add routing table entry */
1250 case VKI_SIOCDELRT: /* delete routing table entry */
1251 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
1252 sizeof(struct vki_rtentry));
1253 break;
1254 #endif
1255
1256 case VKI_SIOCGPGRP:
1257 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
1258 break;
1259 case VKI_SIOCSPGRP:
1260 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
1261 //tst->sys_flags &= ~SfMayBlock;
1262 break;
1263
1264 case VKI_FIODTYPE:
1265 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
1266 break;
1267
1268 case VKI_DTRACEHIOC_ADDDOF:
1269 break;
1270
1271 // ttycom.h
1272 case VKI_TIOCGETA:
1273 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) );
1274 break;
1275 case VKI_TIOCSETA:
1276 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) );
1277 break;
1278 case VKI_TIOCGETD:
1279 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) );
1280 break;
1281 case VKI_TIOCSETD:
1282 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) );
1283 break;
1284 case VKI_TIOCPTYGNAME:
1285 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 );
1286 break;
1287
1288 // filio.h
1289 case VKI_FIOCLEX:
1290 break;
1291 case VKI_FIONCLEX:
1292 break;
1293
1294 default:
1295 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
1296 break;
1297 }
1298 }
1299
1300
POST(ioctl)1301 POST(ioctl)
1302 {
1303 vg_assert(SUCCESS);
1304 switch (ARG2 /* request */) {
1305 case VKI_TIOCGWINSZ:
1306 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
1307 break;
1308 case VKI_TIOCSWINSZ:
1309 case VKI_TIOCMBIS:
1310 case VKI_TIOCMBIC:
1311 case VKI_TIOCMSET:
1312 break;
1313 case VKI_TIOCMGET:
1314 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
1315 break;
1316 case VKI_TIOCGPGRP:
1317 /* Get process group ID for foreground processing group. */
1318 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1319 break;
1320 case VKI_TIOCSPGRP:
1321 /* Set a process group ID? */
1322 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
1323 break;
1324 case VKI_TIOCSCTTY:
1325 break;
1326 case VKI_FIONBIO:
1327 break;
1328 case VKI_FIOASYNC:
1329 break;
1330 case VKI_FIONREAD: /* identical to SIOCINQ */
1331 POST_MEM_WRITE( ARG3, sizeof(int) );
1332 break;
1333
1334 /* These all use struct ifreq AFAIK */
1335 case VKI_SIOCGIFFLAGS: /* get flags */
1336 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
1337 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
1338 break;
1339 case VKI_SIOCGIFMTU: /* get MTU size */
1340 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
1341 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
1342 break;
1343 case VKI_SIOCGIFADDR: /* get PA address */
1344 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
1345 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
1346 case VKI_SIOCGIFNETMASK: /* get network PA mask */
1347 POST_MEM_WRITE(
1348 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
1349 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
1350 break;
1351 case VKI_SIOCGIFMETRIC: /* get metric */
1352 POST_MEM_WRITE(
1353 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
1354 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
1355 break;
1356 case VKI_SIOCGIFCONF: /* get iface list */
1357 /* WAS:
1358 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
1359 KERNEL_DO_SYSCALL(tid,RES);
1360 if (!VG_(is_kerror)(RES) && RES == 0)
1361 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
1362 */
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 );
1367 }
1368 break;
1369
1370 case VKI_SIOCSIFFLAGS: /* set flags */
1371 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
1372 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
1373 case VKI_SIOCSIFNETMASK: /* set network PA mask */
1374 case VKI_SIOCSIFMETRIC: /* set metric */
1375 case VKI_SIOCSIFADDR: /* set PA address */
1376 case VKI_SIOCSIFMTU: /* set MTU size */
1377 break;
1378
1379 #ifdef VKI_SIOCADDRT
1380 /* Routing table calls. */
1381 case VKI_SIOCADDRT: /* add routing table entry */
1382 case VKI_SIOCDELRT: /* delete routing table entry */
1383 break;
1384 #endif
1385
1386 case VKI_SIOCGPGRP:
1387 POST_MEM_WRITE(ARG3, sizeof(int));
1388 break;
1389 case VKI_SIOCSPGRP:
1390 break;
1391
1392 case VKI_FIODTYPE:
1393 POST_MEM_WRITE( ARG3, sizeof(int) );
1394 break;
1395
1396 case VKI_DTRACEHIOC_REMOVE:
1397 case VKI_DTRACEHIOC_ADDDOF:
1398 break;
1399
1400 // ttycom.h
1401 case VKI_TIOCGETA:
1402 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios));
1403 break;
1404 case VKI_TIOCSETA:
1405 break;
1406 case VKI_TIOCGETD:
1407 POST_MEM_WRITE( ARG3, sizeof(int) );
1408 break;
1409 case VKI_TIOCSETD:
1410 break;
1411 case VKI_TIOCPTYGNAME:
1412 POST_MEM_WRITE( ARG3, 128);
1413 break;
1414 case VKI_TIOCSBRK: /* set break bit */
1415 case VKI_TIOCCBRK: /* clear break bit */
1416 case VKI_TIOCPTYGRANT:
1417 case VKI_TIOCPTYUNLK:
1418 break;
1419
1420 default:
1421 break;
1422 }
1423 }
1424
1425
1426 /* ---------------------------------------------------------------------
1427 darwin fcntl wrapper
1428 ------------------------------------------------------------------ */
name_for_fcntl(UWord cmd)1429 static const HChar *name_for_fcntl(UWord cmd) {
1430 #define F(n) case VKI_##n: return #n
1431 switch (cmd) {
1432 F(F_CHKCLEAN);
1433 F(F_RDAHEAD);
1434 F(F_NOCACHE);
1435 F(F_FULLFSYNC);
1436 F(F_FREEZE_FS);
1437 F(F_THAW_FS);
1438 F(F_GLOBAL_NOCACHE);
1439 F(F_PREALLOCATE);
1440 F(F_SETSIZE);
1441 F(F_RDADVISE);
1442 # if DARWIN_VERS < DARWIN_10_9
1443 F(F_READBOOTSTRAP);
1444 F(F_WRITEBOOTSTRAP);
1445 # endif
1446 F(F_LOG2PHYS);
1447 F(F_GETPATH);
1448 F(F_PATHPKG_CHECK);
1449 F(F_ADDSIGS);
1450 # if DARWIN_VERS >= DARWIN_10_9
1451 F(F_ADDFILESIGS);
1452 # endif
1453 default:
1454 return "UNKNOWN";
1455 }
1456 #undef F
1457 }
1458
PRE(fcntl)1459 PRE(fcntl)
1460 {
1461 switch (ARG2) {
1462 // These ones ignore ARG3.
1463 case VKI_F_GETFD:
1464 case VKI_F_GETFL:
1465 case VKI_F_GETOWN:
1466 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2);
1467 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1468 break;
1469
1470 // These ones use ARG3 as "arg".
1471 case VKI_F_DUPFD:
1472 case VKI_F_SETFD:
1473 case VKI_F_SETFL:
1474 case VKI_F_SETOWN:
1475 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
1476 PRE_REG_READ3(long, "fcntl",
1477 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
1478 break;
1479
1480 // These ones use ARG3 as "lock".
1481 case VKI_F_GETLK:
1482 case VKI_F_SETLK:
1483 case VKI_F_SETLKW:
1484 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1485 PRE_REG_READ3(long, "fcntl",
1486 unsigned int, fd, unsigned int, cmd,
1487 struct flock64 *, lock);
1488 // GrP fixme mem read sizeof(flock64)
1489 if (ARG2 == VKI_F_SETLKW)
1490 *flags |= SfMayBlock;
1491 break;
1492 # if DARWIN_VERS >= DARWIN_10_10
1493 case VKI_F_SETLKWTIMEOUT:
1494 PRINT("fcntl[ARG3=='locktimeout'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3);
1495 PRE_REG_READ3(long, "fcntl",
1496 unsigned int, fd, unsigned int, cmd,
1497 struct flocktimeout *, lock);
1498 *flags |= SfMayBlock;
1499 break;
1500 # endif
1501
1502 // none
1503 case VKI_F_CHKCLEAN:
1504 case VKI_F_RDAHEAD:
1505 case VKI_F_NOCACHE:
1506 case VKI_F_FULLFSYNC:
1507 case VKI_F_FREEZE_FS:
1508 case VKI_F_THAW_FS:
1509 case VKI_F_GLOBAL_NOCACHE:
1510 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1));
1511 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
1512 break;
1513
1514 // struct fstore
1515 case VKI_F_PREALLOCATE:
1516 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1517 PRE_REG_READ3(long, "fcntl",
1518 unsigned int, fd, unsigned int, cmd,
1519 struct fstore *, fstore);
1520 {
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);
1532 }
1533 break;
1534
1535 // off_t
1536 case VKI_F_SETSIZE:
1537 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1538 PRE_REG_READ3(long, "fcntl",
1539 unsigned int, fd, unsigned int, cmd,
1540 vki_off_t *, offset);
1541 break;
1542
1543 // struct radvisory
1544 case VKI_F_RDADVISE:
1545 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1546 PRE_REG_READ3(long, "fcntl",
1547 unsigned int, fd, unsigned int, cmd,
1548 struct vki_radvisory *, radvisory);
1549 {
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 );
1555 }
1556 break;
1557
1558 # if DARWIN_VERS < DARWIN_10_9
1559 // struct fbootstraptransfer
1560 case VKI_F_READBOOTSTRAP:
1561 case VKI_F_WRITEBOOTSTRAP:
1562 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1563 PRE_REG_READ3(long, "fcntl",
1564 unsigned int, fd, unsigned int, cmd,
1565 struct fbootstraptransfer *, bootstrap);
1566 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)",
1567 ARG3, sizeof(struct vki_fbootstraptransfer) );
1568 break;
1569 # endif
1570
1571 // struct log2phys (out)
1572 case VKI_F_LOG2PHYS:
1573 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1574 PRE_REG_READ3(long, "fcntl",
1575 unsigned int, fd, unsigned int, cmd,
1576 struct log2phys *, l2p);
1577 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)",
1578 ARG3, sizeof(struct vki_log2phys) );
1579 break;
1580
1581 // char[maxpathlen] (out)
1582 case VKI_F_GETPATH:
1583 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3);
1584 PRE_REG_READ3(long, "fcntl",
1585 unsigned int, fd, unsigned int, cmd,
1586 char *, pathbuf);
1587 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)",
1588 ARG3, VKI_MAXPATHLEN );
1589 break;
1590
1591 // char[maxpathlen] (in)
1592 case VKI_F_PATHPKG_CHECK:
1593 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3,
1594 (char *)ARG3);
1595 PRE_REG_READ3(long, "fcntl",
1596 unsigned int, fd, unsigned int, cmd,
1597 char *, pathbuf);
1598 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3);
1599 break;
1600
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);
1606
1607 {
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);
1613
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);
1617 }
1618 break;
1619
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);
1625
1626 {
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);
1632 }
1633 break;
1634
1635 default:
1636 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2);
1637 log_decaying("UNKNOWN fcntl %ld!", ARG2);
1638 break;
1639 }
1640 }
1641
POST(fcntl)1642 POST(fcntl)
1643 {
1644 vg_assert(SUCCESS);
1645 switch (ARG2) {
1646 case VKI_F_DUPFD:
1647 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
1648 VG_(close)(RES);
1649 SET_STATUS_Failure( VKI_EMFILE );
1650 } else {
1651 if (VG_(clo_track_fds))
1652 ML_(record_fd_open_named)(tid, RES);
1653 }
1654 break;
1655
1656 case VKI_F_GETFD:
1657 case VKI_F_GETFL:
1658 case VKI_F_GETOWN:
1659 case VKI_F_SETFD:
1660 case VKI_F_SETFL:
1661 case VKI_F_SETOWN:
1662 case VKI_F_GETLK:
1663 case VKI_F_SETLK:
1664 case VKI_F_SETLKW:
1665 # if DARWIN_VERS >= DARWIN_10_10
1666 case VKI_F_SETLKWTIMEOUT:
1667 break;
1668 # endif
1669
1670 case VKI_F_PREALLOCATE:
1671 {
1672 struct vki_fstore *fstore = (struct vki_fstore *)ARG3;
1673 POST_FIELD_WRITE( fstore->fst_bytesalloc );
1674 }
1675 break;
1676
1677 case VKI_F_LOG2PHYS:
1678 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) );
1679 break;
1680
1681 case VKI_F_GETPATH:
1682 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) );
1683 PRINT("\"%s\"", (char*)ARG3);
1684 break;
1685
1686 default:
1687 // DDD: ugh, missing lots of cases here, not nice
1688 break;
1689 }
1690 }
1691
1692 /* ---------------------------------------------------------------------
1693 unix syscalls
1694 ------------------------------------------------------------------ */
1695
PRE(futimes)1696 PRE(futimes)
1697 {
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) );
1705 }
1706 }
1707
PRE(semget)1708 PRE(semget)
1709 {
1710 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1711 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
1712 }
1713
PRE(semop)1714 PRE(semop)
1715 {
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);
1721 }
1722
PRE(semctl)1723 PRE(semctl)
1724 {
1725 switch (ARG3) {
1726 case VKI_IPC_STAT:
1727 case VKI_IPC_SET:
1728 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1729 PRE_REG_READ4(long, "semctl",
1730 int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
1731 break;
1732 case VKI_GETALL:
1733 case VKI_SETALL:
1734 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1735 PRE_REG_READ4(long, "semctl",
1736 int, semid, int, semnum, int, cmd, unsigned short *, arg);
1737 break;
1738 case VKI_SETVAL:
1739 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
1740 PRE_REG_READ4(long, "semctl",
1741 int, semid, int, semnum, int, cmd, int, arg);
1742 break;
1743 default:
1744 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
1745 PRE_REG_READ3(long, "semctl",
1746 int, semid, int, semnum, int, cmd);
1747 break;
1748 }
1749 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4);
1750 }
POST(semctl)1751 POST(semctl)
1752 {
1753 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4);
1754 }
1755
PRE(sem_open)1756 PRE(sem_open)
1757 {
1758 if (ARG2 & VKI_O_CREAT) {
1759 // 4-arg version
1760 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )",
1761 ARG1,(char*)ARG1,ARG2,ARG3,ARG4);
1762 PRE_REG_READ4(vki_sem_t *, "sem_open",
1763 const char *, name, int, oflag, vki_mode_t, mode,
1764 unsigned int, value);
1765 } else {
1766 // 2-arg version
1767 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2);
1768 PRE_REG_READ2(vki_sem_t *, "sem_open",
1769 const char *, name, int, oflag);
1770 }
1771 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 );
1772
1773 /* Otherwise handle normally */
1774 *flags |= SfMayBlock;
1775 }
1776
PRE(sem_close)1777 PRE(sem_close)
1778 {
1779 PRINT("sem_close( %#lx )", ARG1);
1780 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem);
1781 }
1782
PRE(sem_unlink)1783 PRE(sem_unlink)
1784 {
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 );
1788 }
1789
PRE(sem_post)1790 PRE(sem_post)
1791 {
1792 PRINT("sem_post( %#lx )", ARG1);
1793 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem);
1794 *flags |= SfMayBlock;
1795 }
1796
PRE(sem_destroy)1797 PRE(sem_destroy)
1798 {
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));
1802 }
1803
PRE(sem_init)1804 PRE(sem_init)
1805 {
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));
1810 }
1811
POST(sem_init)1812 POST(sem_init)
1813 {
1814 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t));
1815 }
1816
PRE(sem_wait)1817 PRE(sem_wait)
1818 {
1819 PRINT("sem_wait( %#lx )", ARG1);
1820 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem);
1821 *flags |= SfMayBlock;
1822 }
1823
PRE(sem_trywait)1824 PRE(sem_trywait)
1825 {
1826 PRINT("sem_trywait( %#lx )", ARG1);
1827 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem);
1828 *flags |= SfMayBlock;
1829 }
1830
PRE(kqueue)1831 PRE(kqueue)
1832 {
1833 PRINT("kqueue()");
1834 }
1835
POST(kqueue)1836 POST(kqueue)
1837 {
1838 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) {
1839 VG_(close)(RES);
1840 SET_STATUS_Failure( VKI_EMFILE );
1841 } else {
1842 if (VG_(clo_track_fds)) {
1843 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1844 }
1845 }
1846 }
1847
PRE(fileport_makeport)1848 PRE(fileport_makeport)
1849 {
1850 PRINT("fileport_makeport(fd:%#lx, portnamep:%#lx) FIXME",
1851 ARG1, ARG2);
1852 }
1853
PRE(guarded_open_np)1854 PRE(guarded_open_np)
1855 {
1856 PRINT("guarded_open_np(path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx) FIXME",
1857 ARG1, (char*)ARG1, ARG2, ARG3, ARG4);
1858 }
1859
PRE(guarded_kqueue_np)1860 PRE(guarded_kqueue_np)
1861 {
1862 PRINT("guarded_kqueue_np(guard:%#lx, guardflags:%#lx) FIXME",
1863 ARG1, ARG2);
1864 }
1865
POST(guarded_kqueue_np)1866 POST(guarded_kqueue_np)
1867 {
1868 if (!ML_(fd_allowed)(RES, "guarded_kqueue_np", tid, True)) {
1869 VG_(close)(RES);
1870 SET_STATUS_Failure( VKI_EMFILE );
1871 } else {
1872 if (VG_(clo_track_fds)) {
1873 ML_(record_fd_open_with_given_name)(tid, RES, NULL);
1874 }
1875 }
1876 }
1877
PRE(guarded_close_np)1878 PRE(guarded_close_np)
1879 {
1880 PRINT("guarded_close_np(fd:%#lx, guard:%#lx) FIXME",
1881 ARG1, ARG2);
1882 }
1883
PRE(change_fdguard_np)1884 PRE(change_fdguard_np)
1885 {
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);
1888 }
1889
PRE(connectx)1890 PRE(connectx)
1891 {
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);
1894 }
1895
PRE(disconnectx)1896 PRE(disconnectx)
1897 {
1898 PRINT("disconnectx(s:%#lx, aid:%#lx, cid:%#lx) FIXME",
1899 ARG1, ARG2, ARG3);
1900 }
1901
1902
PRE(kevent)1903 PRE(kevent)
1904 {
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);
1911
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));
1918
1919 *flags |= SfMayBlock;
1920 }
1921
POST(kevent)1922 POST(kevent)
1923 {
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));
1926 }
1927
1928
PRE(kevent64)1929 PRE(kevent64)
1930 {
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);
1937
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));
1944
1945 *flags |= SfMayBlock;
1946 }
1947
POST(kevent64)1948 POST(kevent64)
1949 {
1950 PRINT("kevent64 ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent64));
1951 if (RES > 0) {
1952 ML_(sync_mappings)("after", "kevent64", 0);
1953 POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent64));
1954 }
1955 }
1956
1957
1958 Addr pthread_starter = 0;
1959 Addr wqthread_starter = 0;
1960 SizeT pthread_structsize = 0;
1961
PRE(bsdthread_register)1962 PRE(bsdthread_register)
1963 {
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");
1967
1968 pthread_starter = ARG1;
1969 wqthread_starter = ARG2;
1970 pthread_structsize = ARG3;
1971 ARG1 = (Word)&pthread_hijack_asm;
1972 ARG2 = (Word)&wqthread_hijack_asm;
1973 }
1974
PRE(workq_open)1975 PRE(workq_open)
1976 {
1977 PRINT("workq_open()");
1978 PRE_REG_READ0(int, "workq_open");
1979
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.
1982 }
1983
workqop_name(int op)1984 static const HChar *workqop_name(int op)
1985 {
1986 switch (op) {
1987 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD";
1988 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE";
1989 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN";
1990 case VKI_WQOPS_THREAD_SETCONC: return "THREAD_SETCONC";
1991 case VKI_WQOPS_QUEUE_NEWSPISUPP: return "QUEUE_NEWSPISUPP";
1992 case VKI_WQOPS_QUEUE_REQTHREADS: return "QUEUE_REQTHREADS";
1993 default: return "?";
1994 }
1995 }
1996
1997
PRE(workq_ops)1998 PRE(workq_ops)
1999 {
2000 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2,
2001 ARG3);
2002 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item",
2003 int,"priority");
2004
2005 switch (ARG1) {
2006 case VKI_WQOPS_QUEUE_ADD:
2007 case VKI_WQOPS_QUEUE_REMOVE:
2008 // GrP fixme need anything here?
2009 // GrP fixme may block?
2010 break;
2011 case VKI_WQOPS_QUEUE_NEWSPISUPP:
2012 // JRS don't think we need to do anything here -- this just checks
2013 // whether some newer functionality is supported
2014 break;
2015 case VKI_WQOPS_QUEUE_REQTHREADS:
2016 // JRS uh, looks like it queues up a bunch of threads, or some such?
2017 *flags |= SfMayBlock; // the kernel sources take a spinlock, so play safe
2018 break;
2019 case VKI_WQOPS_THREAD_RETURN: {
2020 // The interesting case. The kernel will do one of two things:
2021 // 1. Return normally. We continue; libc proceeds to stop the thread.
2022 // V does nothing special here.
2023 // 2. Jump to wqthread_hijack. This wipes the stack and runs a
2024 // new work item, and never returns from workq_ops.
2025 // V handles this by longjmp() from wqthread_hijack back to the
2026 // scheduler, which continues at the new client SP/IP/state.
2027 // This works something like V's signal handling.
2028 // To the tool, this looks like workq_ops() sometimes returns
2029 // to a strange address.
2030 ThreadState *tst = VG_(get_ThreadState)(tid);
2031 tst->os_state.wq_jmpbuf_valid = True;
2032 *flags |= SfMayBlock; // GrP fixme true?
2033 break;
2034 }
2035 default:
2036 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1);
2037 break;
2038 }
2039 }
POST(workq_ops)2040 POST(workq_ops)
2041 {
2042 ThreadState *tst = VG_(get_ThreadState)(tid);
2043 tst->os_state.wq_jmpbuf_valid = False;
2044 switch (ARG1) {
2045 case VKI_WQOPS_THREAD_RETURN:
2046 ML_(sync_mappings)("after", "workq_ops(THREAD_RETURN)", 0);
2047 break;
2048 case VKI_WQOPS_QUEUE_REQTHREADS:
2049 ML_(sync_mappings)("after", "workq_ops(QUEUE_REQTHREADS)", 0);
2050 break;
2051 default:
2052 break;
2053 }
2054 }
2055
2056
2057
PRE(__mac_syscall)2058 PRE(__mac_syscall)
2059 {
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");
2064
2065 // GrP fixme check call's arg?
2066 // GrP fixme check policy?
2067 }
2068
2069
2070 /* Not like syswrap-generic's sys_exit, which exits only one thread.
2071 More like syswrap-generic's sys_exit_group. */
PRE(exit)2072 PRE(exit)
2073 {
2074 ThreadId t;
2075 ThreadState* tst;
2076
2077 PRINT("darwin exit( %ld )", ARG1);
2078 PRE_REG_READ1(void, "exit", int, status);
2079
2080 tst = VG_(get_ThreadState)(tid);
2081
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? */
2088 )
2089 continue;
2090
2091 VG_(threads)[t].exitreason = VgSrc_ExitProcess;
2092 VG_(threads)[t].os_state.exitcode = ARG1;
2093
2094 if (t != tid)
2095 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */
2096 }
2097
2098 /* We have to claim the syscall already succeeded. */
2099 SET_STATUS_Success(0);
2100 }
2101
2102
PRE(sigaction)2103 PRE(sigaction)
2104 {
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);
2109
2110 if (ARG2 != 0) {
2111 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2;
2112 PRE_MEM_READ( "sigaction(act->sa_handler)",
2113 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2114 PRE_MEM_READ( "sigaction(act->sa_mask)",
2115 (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2116 PRE_MEM_READ( "sigaction(act->sa_flags)",
2117 (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2118 }
2119 if (ARG3 != 0)
2120 PRE_MEM_WRITE( "sigaction(oldact)",
2121 ARG3, sizeof(vki_sigaction_fromK_t));
2122
2123 SET_STATUS_from_SysRes(
2124 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2,
2125 (vki_sigaction_fromK_t *)ARG3)
2126 );
2127 }
POST(sigaction)2128 POST(sigaction)
2129 {
2130 vg_assert(SUCCESS);
2131 if (RES == 0 && ARG3 != 0)
2132 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t));
2133 }
2134
2135
PRE(__pthread_kill)2136 PRE(__pthread_kill)
2137 {
2138 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2);
2139 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig);
2140 }
2141
2142
PRE(__pthread_sigmask)2143 PRE(__pthread_sigmask)
2144 {
2145 // GrP fixme
2146 // JRS: arguments are identical to sigprocmask
2147 // (how, sigset_t*, sigset_t*). Perhaps behave identically?
2148 log_decaying("UNKNOWN __pthread_sigmask is unsupported.");
2149 SET_STATUS_Success( 0 );
2150 }
2151
2152
PRE(__pthread_canceled)2153 PRE(__pthread_canceled)
2154 {
2155 *flags |= SfMayBlock; /* might kill this thread??? */
2156 /* I don't think so -- I think it just changes the cancellation
2157 state. But taking no chances. */
2158 PRINT("__pthread_canceled ( %ld )", ARG1);
2159 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1);
2160 }
2161
2162
PRE(__pthread_markcancel)2163 PRE(__pthread_markcancel)
2164 {
2165 *flags |= SfMayBlock; /* might kill this thread??? */
2166 PRINT("__pthread_markcancel ( %#lx )", ARG1);
2167 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1);
2168 /* Just let it go through. No idea if this is correct. */
2169 }
2170
2171
PRE(__disable_threadsignal)2172 PRE(__disable_threadsignal)
2173 {
2174 vki_sigset_t set;
2175 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3);
2176 /* I don't think this really looks at its arguments. So don't
2177 bother to check them. */
2178
2179 VG_(sigfillset)( &set );
2180 SET_STATUS_from_SysRes(
2181 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL )
2182 );
2183
2184 /* We don't expect that blocking all signals for this thread could
2185 cause any more to be delivered (how could it?), but just in case
2186 .. */
2187 if (SUCCESS)
2188 *flags |= SfPollAfter;
2189 }
2190
2191
PRE(__pthread_chdir)2192 PRE(__pthread_chdir)
2193 {
2194 PRINT("__pthread_chdir ( %#lx(%s) )", ARG1, (char*)ARG1);
2195 PRE_REG_READ1(long, "__pthread_chdir", const char *, path);
2196 PRE_MEM_RASCIIZ( "__pthread_chdir(path)", ARG1 );
2197 }
2198
2199
2200
PRE(__pthread_fchdir)2201 PRE(__pthread_fchdir)
2202 {
2203 PRINT("__pthread_fchdir ( %ld )", ARG1);
2204 PRE_REG_READ1(long, "__pthread_fchdir", unsigned int, fd);
2205 }
2206
2207
PRE(kdebug_trace)2208 PRE(kdebug_trace)
2209 {
2210 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)",
2211 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
2212 /*
2213 Don't check anything - some clients pass fewer arguments.
2214 PRE_REG_READ6(long, "kdebug_trace",
2215 int,"code", int,"arg1", int,"arg2",
2216 int,"arg3", int,"arg4", int,"arg5");
2217 */
2218 }
2219
2220
PRE(seteuid)2221 PRE(seteuid)
2222 {
2223 PRINT("seteuid(%ld)", ARG1);
2224 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid");
2225 }
2226
2227
PRE(setegid)2228 PRE(setegid)
2229 {
2230 PRINT("setegid(%ld)", ARG1);
2231 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid");
2232 }
2233
PRE(settid)2234 PRE(settid)
2235 {
2236 PRINT("settid(%ld, %ld)", ARG1, ARG2);
2237 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid");
2238 }
2239
PRE(gettid)2240 PRE(gettid)
2241 {
2242 PRINT("gettid()");
2243 PRE_REG_READ0(long, gettid);
2244 }
2245
2246 /* XXX need to check whether we need POST operations for
2247 * waitevent, watchevent, modwatch -- jpeach
2248 */
PRE(watchevent)2249 PRE(watchevent)
2250 {
2251 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2);
2252 PRE_REG_READ2(long, "watchevent",
2253 vki_eventreq *, "event", unsigned int, "eventmask");
2254
2255 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq));
2256 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int));
2257 *flags |= SfMayBlock;
2258 }
2259
2260 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1)
PRE(waitevent)2261 PRE(waitevent)
2262 {
2263 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2);
2264 PRE_REG_READ2(long, "waitevent",
2265 vki_eventreq *, "event", struct timeval *, "timeout");
2266 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq));
2267
2268 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) {
2269 PRE_timeval_READ("waitevent(timeout)", ARG2);
2270 }
2271
2272 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */
2273 *flags |= SfMayBlock;
2274 }
2275
POST(waitevent)2276 POST(waitevent)
2277 {
2278 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq));
2279 }
2280
PRE(modwatch)2281 PRE(modwatch)
2282 {
2283 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2);
2284 PRE_REG_READ2(long, "modwatch",
2285 vki_eventreq *, "event", unsigned int, "eventmask");
2286
2287 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq));
2288 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int));
2289 }
2290
PRE(getxattr)2291 PRE(getxattr)
2292 {
2293 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)",
2294 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
2295
2296 PRE_REG_READ6(vki_ssize_t, "getxattr",
2297 const char *, path, char *, name, void *, value,
2298 vki_size_t, size, uint32_t, position, int, options);
2299 PRE_MEM_RASCIIZ("getxattr(path)", ARG1);
2300 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2301 if (ARG3)
2302 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2303 }
2304
POST(getxattr)2305 POST(getxattr)
2306 {
2307 vg_assert((vki_ssize_t)RES >= 0);
2308 if (ARG3)
2309 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2310 }
2311
PRE(fgetxattr)2312 PRE(fgetxattr)
2313 {
2314 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)",
2315 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6);
2316
2317 PRE_REG_READ6(vki_ssize_t, "fgetxattr",
2318 int, fd, char *, name, void *, value,
2319 vki_size_t, size, uint32_t, position, int, options);
2320 PRE_MEM_RASCIIZ("getxattr(name)", ARG2);
2321 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4);
2322 }
2323
POST(fgetxattr)2324 POST(fgetxattr)
2325 {
2326 vg_assert((vki_ssize_t)RES >= 0);
2327 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES);
2328 }
2329
PRE(setxattr)2330 PRE(setxattr)
2331 {
2332 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )",
2333 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
2334 PRE_REG_READ6(int, "setxattr",
2335 const char *,"path", char *,"name", void *,"value",
2336 vki_size_t,"size", uint32_t,"position", int,"options" );
2337
2338 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
2339 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
2340 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
2341 }
2342
2343
PRE(fsetxattr)2344 PRE(fsetxattr)
2345 {
2346 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )",
2347 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 );
2348 PRE_REG_READ6(int, "fsetxattr",
2349 int,"fd", char *,"name", void *,"value",
2350 vki_size_t,"size", uint32_t,"position", int,"options" );
2351
2352 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
2353 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
2354 }
2355
2356
PRE(removexattr)2357 PRE(removexattr)
2358 {
2359 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )",
2360 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 );
2361 PRE_REG_READ3(int, "removexattr",
2362 const char*, "path", char*, "attrname", int, "options");
2363 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
2364 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2365 }
2366
2367
PRE(fremovexattr)2368 PRE(fremovexattr)
2369 {
2370 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )",
2371 ARG1, ARG2, (HChar*)ARG2, ARG3 );
2372 PRE_REG_READ3(int, "fremovexattr",
2373 int, "fd", char*, "attrname", int, "options");
2374 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 );
2375 }
2376
2377
PRE(listxattr)2378 PRE(listxattr)
2379 {
2380 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )",
2381 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 );
2382 PRE_REG_READ4 (long, "listxattr",
2383 const char *,"path", char *,"namebuf",
2384 vki_size_t,"size", int,"options" );
2385
2386 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
2387 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 );
2388 *flags |= SfMayBlock;
2389 }
POST(listxattr)2390 POST(listxattr)
2391 {
2392 vg_assert(SUCCESS);
2393 vg_assert((vki_ssize_t)RES >= 0);
2394 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2395 }
2396
2397
PRE(flistxattr)2398 PRE(flistxattr)
2399 {
2400 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )",
2401 ARG1, ARG2, ARG3, ARG4 );
2402 PRE_REG_READ4 (long, "flistxattr",
2403 int, "fd", char *,"namebuf",
2404 vki_size_t,"size", int,"options" );
2405 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 );
2406 *flags |= SfMayBlock;
2407 }
POST(flistxattr)2408 POST(flistxattr)
2409 {
2410 vg_assert(SUCCESS);
2411 vg_assert((vki_ssize_t)RES >= 0);
2412 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES );
2413 }
2414
2415
PRE(shmat)2416 PRE(shmat)
2417 {
2418 UWord arg2tmp;
2419 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
2420 PRE_REG_READ3(long, "shmat",
2421 int, shmid, const void *, shmaddr, int, shmflg);
2422 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
2423 if (arg2tmp == 0)
2424 SET_STATUS_Failure( VKI_EINVAL );
2425 else
2426 ARG2 = arg2tmp; // used in POST
2427 }
POST(shmat)2428 POST(shmat)
2429 {
2430 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
2431 }
2432
PRE(shmctl)2433 PRE(shmctl)
2434 {
2435 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
2436 PRE_REG_READ3(long, "shmctl",
2437 int, shmid, int, cmd, struct vki_shmid_ds *, buf);
2438 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
2439 }
POST(shmctl)2440 POST(shmctl)
2441 {
2442 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
2443 }
2444
PRE(shmdt)2445 PRE(shmdt)
2446 {
2447 PRINT("shmdt ( %#lx )",ARG1);
2448 PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
2449 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
2450 SET_STATUS_Failure( VKI_EINVAL );
2451 }
POST(shmdt)2452 POST(shmdt)
2453 {
2454 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
2455 }
2456
PRE(shmget)2457 PRE(shmget)
2458 {
2459 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
2460 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
2461 }
2462
PRE(shm_open)2463 PRE(shm_open)
2464 {
2465 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3);
2466 PRE_REG_READ3(long, "shm_open",
2467 const char *,"name", int,"flags", vki_mode_t,"mode");
2468
2469 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 );
2470
2471 *flags |= SfMayBlock;
2472 }
POST(shm_open)2473 POST(shm_open)
2474 {
2475 vg_assert(SUCCESS);
2476 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) {
2477 VG_(close)(RES);
2478 SET_STATUS_Failure( VKI_EMFILE );
2479 } else {
2480 if (VG_(clo_track_fds))
2481 ML_(record_fd_open_with_given_name)(tid, RES, (char*)ARG1);
2482 }
2483 }
2484
PRE(shm_unlink)2485 PRE(shm_unlink)
2486 {
2487 *flags |= SfMayBlock;
2488 PRINT("shm_unlink ( %#lx(%s) )", ARG1,(char*)ARG1);
2489 PRE_REG_READ1(long, "shm_unlink", const char *, pathname);
2490 PRE_MEM_RASCIIZ( "shm_unlink(pathname)", ARG1 );
2491 }
POST(shm_unlink)2492 POST(shm_unlink)
2493 {
2494 /* My reading of the man page suggests that a call may cause memory
2495 mappings to change: "if no references exist at the time of the
2496 call to shm_unlink(), the resources are reclaimed immediately".
2497 So we need to resync here, sigh. */
2498 ML_(sync_mappings)("after", "shm_unlink", 0);
2499 }
2500
PRE(stat_extended)2501 PRE(stat_extended)
2502 {
2503 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2504 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2505 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf,
2506 void *, fsacl, vki_size_t *, fsacl_size);
2507 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 );
2508 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2509 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2510 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2511 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2512 }
POST(stat_extended)2513 POST(stat_extended)
2514 {
2515 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2516 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2517 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2518 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2519 }
2520
2521
PRE(lstat_extended)2522 PRE(lstat_extended)
2523 {
2524 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2525 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2526 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf,
2527 void *, fsacl, vki_size_t *, fsacl_size);
2528 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 );
2529 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2530 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2531 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2532 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2533 }
POST(lstat_extended)2534 POST(lstat_extended)
2535 {
2536 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2537 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2538 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2539 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2540 }
2541
2542
PRE(fstat_extended)2543 PRE(fstat_extended)
2544 {
2545 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )",
2546 ARG1, ARG2, ARG3, ARG4);
2547 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf,
2548 void *, fsacl, vki_size_t *, fsacl_size);
2549 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) );
2550 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2551 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2552 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2553 }
POST(fstat_extended)2554 POST(fstat_extended)
2555 {
2556 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2557 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2558 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2559 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2560 }
2561
2562
PRE(stat64_extended)2563 PRE(stat64_extended)
2564 {
2565 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2566 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2567 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf,
2568 void *, fsacl, vki_size_t *, fsacl_size);
2569 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 );
2570 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2571 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2572 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2573 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2574 }
POST(stat64_extended)2575 POST(stat64_extended)
2576 {
2577 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2578 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2579 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2580 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2581 }
2582
2583
PRE(lstat64_extended)2584 PRE(lstat64_extended)
2585 {
2586 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )",
2587 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2588 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf,
2589 void *, fsacl, vki_size_t *, fsacl_size);
2590 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 );
2591 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2592 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2593 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2594 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2595 }
POST(lstat64_extended)2596 POST(lstat64_extended)
2597 {
2598 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2599 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2600 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2601 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2602 }
2603
2604
PRE(fstat64_extended)2605 PRE(fstat64_extended)
2606 {
2607 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )",
2608 ARG1, ARG2, ARG3, ARG4);
2609 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf,
2610 void *, fsacl, vki_size_t *, fsacl_size);
2611 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) );
2612 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2613 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 );
2614 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) );
2615 }
POST(fstat64_extended)2616 POST(fstat64_extended)
2617 {
2618 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2619 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) ))
2620 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 );
2621 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) );
2622 }
2623
2624
PRE(fchmod_extended)2625 PRE(fchmod_extended)
2626 {
2627 /* DDD: Note: this is not really correct. Handling of
2628 chmod_extended is broken in the same way. */
2629 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )",
2630 ARG1, ARG2, ARG3, ARG4, ARG5);
2631 PRE_REG_READ5(long, "fchmod_extended",
2632 unsigned int, fildes,
2633 uid_t, uid,
2634 gid_t, gid,
2635 vki_mode_t, mode,
2636 void* /*really,user_addr_t*/, xsecurity);
2637 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2638 is just way wrong. [The trouble is with the size, which depends on a
2639 non-trival kernel computation] */
2640 if (ARG5) {
2641 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5,
2642 sizeof(struct vki_kauth_filesec) );
2643 }
2644 }
2645
PRE(chmod_extended)2646 PRE(chmod_extended)
2647 {
2648 /* DDD: Note: this is not really correct. Handling of
2649 fchmod_extended is broken in the same way. */
2650 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )",
2651 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5);
2652 PRE_REG_READ5(long, "chmod_extended",
2653 unsigned int, fildes,
2654 uid_t, uid,
2655 gid_t, gid,
2656 vki_mode_t, mode,
2657 void* /*really,user_addr_t*/, xsecurity);
2658 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1);
2659 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2660 is just way wrong. [The trouble is with the size, which depends on a
2661 non-trival kernel computation] */
2662 if (ARG5) {
2663 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5,
2664 sizeof(struct vki_kauth_filesec) );
2665 }
2666 }
2667
PRE(open_extended)2668 PRE(open_extended)
2669 {
2670 /* DDD: Note: this is not really correct. Handling of
2671 {,f}chmod_extended is broken in the same way. */
2672 PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )",
2673 ARG1, ARG1 ? (HChar*)ARG1 : "(null)",
2674 ARG2, ARG3, ARG4, ARG5, ARG6);
2675 PRE_REG_READ6(long, "open_extended",
2676 char*, path,
2677 int, flags,
2678 uid_t, uid,
2679 gid_t, gid,
2680 vki_mode_t, mode,
2681 void* /*really,user_addr_t*/, xsecurity);
2682 PRE_MEM_RASCIIZ("open_extended(path)", ARG1);
2683 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this
2684 is just way wrong. [The trouble is with the size, which depends on a
2685 non-trival kernel computation] */
2686 if (ARG6)
2687 PRE_MEM_READ( "open_extended(xsecurity)", ARG6,
2688 sizeof(struct vki_kauth_filesec) );
2689 }
2690
2691 // This is a ridiculous syscall. Specifically, the 'entries' argument points
2692 // to a buffer that contains one or more 'accessx_descriptor' structs followed
2693 // by one or more strings. Each accessx_descriptor contains a field,
2694 // 'ad_name_offset', which points to one of the strings (or it can contain
2695 // zero which means "reuse the string from the previous accessx_descriptor").
2696 //
2697 // What's really ridiculous is that we are only given the size of the overall
2698 // buffer, not the number of accessx_descriptors, nor the number of strings.
2699 // The kernel determines the number of accessx_descriptors by walking through
2700 // them one by one, checking that the ad_name_offset points within the buffer,
2701 // past the current point (or that it's a zero, unless its the first
2702 // descriptor); if so, we assume that this really is an accessx_descriptor,
2703 // if not, we assume we've hit the strings section. Gah.
2704 //
2705 // This affects us here because number of entries in the 'results' buffer is
2706 // determined by the number of accessx_descriptors. So we have to know that
2707 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In
2708 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the
2709 // computation after the syscall has succeeded, because the kernel will have
2710 // checked for all the zillion different ways this syscall can fail, and we'll
2711 // know we have a well-formed 'entries' buffer. This means we might miss some
2712 // uses of unaddressable memory but oh well.
2713 //
PRE(access_extended)2714 PRE(access_extended)
2715 {
2716 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
2717 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
2718 // XXX: the accessx_descriptor struct contains padding, so this can cause
2719 // unnecessary undefined value errors. But you arguably shouldn't be
2720 // passing undefined values to the kernel anyway...
2721 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
2722 vki_errno_t *, results, vki_uid_t *, uid);
2723 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
2724
2725 // XXX: as mentioned above, this check is too hard to do before the
2726 // syscall.
2727 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? );
2728 }
POST(access_extended)2729 POST(access_extended)
2730 {
2731 // 'n_descs' is the number of descriptors we think are in the buffer. We
2732 // start with the maximum possible value, which occurs if we have the
2733 // shortest possible string section. The shortest string section allowed
2734 // consists of a single one-char string (plus the NUL char). Hence the
2735 // '2'.
2736 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
2737 SizeT size = ARG2;
2738 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
2739 Int i; // Current position in the descriptors section array.
2740 Int u; // Upper bound on the length of the descriptors array
2741 // (recomputed each time around the loop)
2742 vg_assert(n_descs > 0);
2743
2744 // Step through the descriptors, lowering 'n_descs' until we know we've
2745 // reached the string section.
2746 for (i = 0; True; i++) {
2747 // If we're past our estimate, we must be one past the end of the
2748 // descriptors section (ie. at the start of the string section). Stop.
2749 if (i >= n_descs)
2750 break;
2751
2752 // Get the array index for the string, but pretend momentarily that it
2753 // is actually another accessx_descriptor. That gives us an upper bound
2754 // on the length of the descriptors section. (Unless the index is zero,
2755 // in which case we have no new info.)
2756 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor);
2757 if (u == 0) {
2758 vg_assert(i != 0);
2759 continue;
2760 }
2761
2762 // If the upper bound is below our current estimate, revise that
2763 // estimate downwards.
2764 if (u < n_descs)
2765 n_descs = u;
2766 }
2767
2768 // Sanity check.
2769 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS);
2770
2771 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) );
2772 }
2773
2774
PRE(chflags)2775 PRE(chflags)
2776 {
2777 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2);
2778 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags);
2779 PRE_MEM_RASCIIZ("chflags(path)", ARG1);
2780
2781 // GrP fixme sanity-check flags value?
2782 }
2783
PRE(fchflags)2784 PRE(fchflags)
2785 {
2786 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2);
2787 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags);
2788
2789 // GrP fixme sanity-check flags value?
2790 }
2791
PRE(stat64)2792 PRE(stat64)
2793 {
2794 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2795 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2796 PRE_MEM_RASCIIZ("stat64(path)", ARG1);
2797 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
2798 }
POST(stat64)2799 POST(stat64)
2800 {
2801 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2802 }
2803
PRE(lstat64)2804 PRE(lstat64)
2805 {
2806 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2);
2807 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf);
2808 PRE_MEM_RASCIIZ("lstat64(path)", ARG1);
2809 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2810 }
POST(lstat64)2811 POST(lstat64)
2812 {
2813 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2814 }
2815
PRE(fstat64)2816 PRE(fstat64)
2817 {
2818 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2);
2819 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf);
2820 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
2821 }
POST(fstat64)2822 POST(fstat64)
2823 {
2824 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
2825 }
2826
PRE(getfsstat)2827 PRE(getfsstat)
2828 {
2829 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2830 PRE_REG_READ3(int, "getfsstat",
2831 struct vki_statfs *, buf, int, bufsize, int, flags);
2832 if (ARG1) {
2833 // ARG2 is a BYTE SIZE
2834 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2);
2835 }
2836 }
POST(getfsstat)2837 POST(getfsstat)
2838 {
2839 if (ARG1) {
2840 // RES is a STRUCT COUNT
2841 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs));
2842 }
2843 }
2844
PRE(getfsstat64)2845 PRE(getfsstat64)
2846 {
2847 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3);
2848 PRE_REG_READ3(int, "getfsstat64",
2849 struct vki_statfs64 *, buf, int, bufsize, int, flags);
2850 if (ARG1) {
2851 // ARG2 is a BYTE SIZE
2852 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2);
2853 }
2854 }
POST(getfsstat64)2855 POST(getfsstat64)
2856 {
2857 if (ARG1) {
2858 // RES is a STRUCT COUNT
2859 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64));
2860 }
2861 }
2862
PRE(mount)2863 PRE(mount)
2864 {
2865 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
2866 // We are conservative and check everything, except the memory pointed to
2867 // by 'data'.
2868 *flags |= SfMayBlock;
2869 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )",
2870 ARG1,(char*)ARG1, ARG2,(char*)ARG2, ARG3, ARG4);
2871 PRE_REG_READ4(long, "mount",
2872 const char *, type, const char *, dir,
2873 int, flags, void *, data);
2874 PRE_MEM_RASCIIZ( "mount(type)", ARG1);
2875 PRE_MEM_RASCIIZ( "mount(dir)", ARG2);
2876 }
2877
2878
scan_attrlist(ThreadId tid,struct vki_attrlist * attrList,void * attrBuf,SizeT attrBufSize,void (* fn)(ThreadId,void * attrData,SizeT size))2879 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList,
2880 void *attrBuf, SizeT attrBufSize,
2881 void (*fn)(ThreadId, void *attrData, SizeT size)
2882 )
2883 {
2884 typedef struct {
2885 uint32_t attrBit;
2886 int32_t attrSize;
2887 } attrspec;
2888 static const attrspec commonattr[] = {
2889 // This order is important.
2890 #if DARWIN_VERS >= DARWIN_10_6
2891 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) },
2892 #endif
2893 { ATTR_CMN_NAME, -1 },
2894 { ATTR_CMN_DEVID, sizeof(dev_t) },
2895 { ATTR_CMN_FSID, sizeof(fsid_t) },
2896 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) },
2897 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) },
2898 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) },
2899 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) },
2900 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) },
2901 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) },
2902 { ATTR_CMN_CRTIME, sizeof(struct timespec) },
2903 { ATTR_CMN_MODTIME, sizeof(struct timespec) },
2904 { ATTR_CMN_CHGTIME, sizeof(struct timespec) },
2905 { ATTR_CMN_ACCTIME, sizeof(struct timespec) },
2906 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) },
2907 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ },
2908 { ATTR_CMN_OWNERID, sizeof(uid_t) },
2909 { ATTR_CMN_GRPID, sizeof(gid_t) },
2910 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) },
2911 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) },
2912 { ATTR_CMN_NAMEDATTRLIST, -1 },
2913 { ATTR_CMN_FLAGS, sizeof(uint32_t) },
2914 { ATTR_CMN_USERACCESS, sizeof(uint32_t) },
2915 { ATTR_CMN_EXTENDED_SECURITY, -1 },
2916 { ATTR_CMN_UUID, sizeof(guid_t) },
2917 { ATTR_CMN_GRPUUID, sizeof(guid_t) },
2918 { ATTR_CMN_FILEID, sizeof(uint64_t) },
2919 { ATTR_CMN_PARENTID, sizeof(uint64_t) },
2920 #if DARWIN_VERS >= DARWIN_10_6
2921 { ATTR_CMN_FULLPATH, -1 },
2922 #endif
2923 #if DARWIN_VERS >= DARWIN_10_8
2924 { ATTR_CMN_ADDEDTIME, -1 },
2925 #endif
2926 { 0, 0 }
2927 };
2928 static const attrspec volattr[] = {
2929 // This order is important.
2930 { ATTR_VOL_INFO, 0 },
2931 { ATTR_VOL_FSTYPE, sizeof(uint32_t) },
2932 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) },
2933 { ATTR_VOL_SIZE, sizeof(off_t) },
2934 { ATTR_VOL_SPACEFREE, sizeof(off_t) },
2935 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) },
2936 { ATTR_VOL_MINALLOCATION, sizeof(off_t) },
2937 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) },
2938 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) },
2939 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) },
2940 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) },
2941 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) },
2942 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) },
2943 { ATTR_VOL_MOUNTPOINT, -1 },
2944 { ATTR_VOL_NAME, -1 },
2945 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) },
2946 { ATTR_VOL_MOUNTEDDEVICE, -1 },
2947 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) },
2948 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) },
2949 #if DARWIN_VERS >= DARWIN_10_6
2950 { ATTR_VOL_UUID, sizeof(uuid_t) },
2951 #endif
2952 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) },
2953 { 0, 0 }
2954 };
2955 static const attrspec dirattr[] = {
2956 // This order is important.
2957 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) },
2958 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) },
2959 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) },
2960 { 0, 0 }
2961 };
2962 static const attrspec fileattr[] = {
2963 // This order is important.
2964 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) },
2965 { ATTR_FILE_TOTALSIZE, sizeof(off_t) },
2966 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) },
2967 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) },
2968 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) },
2969 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) },
2970 { ATTR_FILE_FILETYPE, sizeof(uint32_t) },
2971 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) },
2972 { ATTR_FILE_FORKLIST, -1 },
2973 { ATTR_FILE_DATALENGTH, sizeof(off_t) },
2974 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) },
2975 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) },
2976 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) },
2977 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) },
2978 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) },
2979 { 0, 0 }
2980 };
2981 static const attrspec forkattr[] = {
2982 // This order is important.
2983 { ATTR_FORK_TOTALSIZE, sizeof(off_t) },
2984 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) },
2985 { 0, 0 }
2986 };
2987
2988 static const attrspec *attrdefs[5] = {
2989 commonattr, volattr, dirattr, fileattr, forkattr
2990 };
2991 attrgroup_t a[5];
2992 uint8_t *d, *dend;
2993 int g, i;
2994
2995 vg_assert(attrList->bitmapcount == 5);
2996 VG_(memcpy)(a, &attrList->commonattr, sizeof(a));
2997 d = attrBuf;
2998 dend = d + attrBufSize;
2999
3000 #if DARWIN_VERS >= DARWIN_10_6
3001 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set
3002 if (a[0] & ATTR_CMN_RETURNED_ATTRS) {
3003 // fixme range check this?
3004 a[0] &= ~ATTR_CMN_RETURNED_ATTRS;
3005 fn(tid, d, sizeof(attribute_set_t));
3006 VG_(memcpy)(a, d, sizeof(a));
3007 }
3008 #endif
3009
3010 for (g = 0; g < 5; g++) {
3011 for (i = 0; attrdefs[g][i].attrBit; i++) {
3012 uint32_t bit = attrdefs[g][i].attrBit;
3013 int32_t size = attrdefs[g][i].attrSize;
3014
3015 if (a[g] & bit) {
3016 a[g] &= ~bit; // clear bit for error check later
3017 if (size == -1) {
3018 attrreference_t *ref = (attrreference_t *)d;
3019 size = MIN(sizeof(attrreference_t), dend - d);
3020 fn(tid, d, size);
3021 if (size >= sizeof(attrreference_t) &&
3022 d + ref->attr_dataoffset < dend)
3023 {
3024 fn(tid, d + ref->attr_dataoffset,
3025 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset)));
3026 }
3027 d += size;
3028 }
3029 else {
3030 size = MIN(size, dend - d);
3031 fn(tid, d, size);
3032 d += size;
3033 }
3034
3035 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4);
3036 if (d > dend) d = dend;
3037 }
3038 }
3039
3040 // Known bits are cleared. Die if any bits are left.
3041 if (a[g] != 0) {
3042 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]);
3043 }
3044 }
3045 }
3046
get1attr(ThreadId tid,void * attrData,SizeT attrDataSize)3047 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3048 {
3049 POST_MEM_WRITE((Addr)attrData, attrDataSize);
3050 }
3051
set1attr(ThreadId tid,void * attrData,SizeT attrDataSize)3052 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize)
3053 {
3054 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize);
3055 }
3056
PRE(getattrlist)3057 PRE(getattrlist)
3058 {
3059 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3060 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
3061 PRE_REG_READ5(int, "getattrlist",
3062 const char *,path, struct vki_attrlist *,attrList,
3063 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3064 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1);
3065 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3066 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4);
3067 }
3068
POST(getattrlist)3069 POST(getattrlist)
3070 {
3071 if (ARG4 > sizeof(vki_uint32_t)) {
3072 // attrBuf is uint32_t size followed by attr data
3073 vki_uint32_t *sizep = (vki_uint32_t *)ARG3;
3074 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t));
3075 if (ARG5 & FSOPT_REPORT_FULLSIZE) {
3076 // *sizep is bytes required for return value, including *sizep
3077 } else {
3078 // *sizep is actual bytes returned, including *sizep
3079 }
3080 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr);
3081 }
3082 }
3083
3084
PRE(setattrlist)3085 PRE(setattrlist)
3086 {
3087 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)",
3088 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5);
3089 PRE_REG_READ5(int, "setattrlist",
3090 const char *,path, struct vki_attrlist *,attrList,
3091 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options);
3092 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1);
3093 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist));
3094 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr);
3095 }
3096
3097
PRE(getdirentriesattr)3098 PRE(getdirentriesattr)
3099 {
3100 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)",
3101 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
3102 PRE_REG_READ8(int, "getdirentriesattr",
3103 int,fd, struct vki_attrlist *,attrList,
3104 void *,attrBuf, size_t,attrBufSize,
3105 unsigned int *,count, unsigned int *,basep,
3106 unsigned int *,newState, unsigned int,options);
3107 PRE_MEM_READ("getdirentriesattr(attrList)",
3108 ARG2, sizeof(struct vki_attrlist));
3109 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4);
3110 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3111 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int));
3112 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int));
3113 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int));
3114 }
POST(getdirentriesattr)3115 POST(getdirentriesattr)
3116 {
3117 char *p, *end;
3118 unsigned int count;
3119 unsigned int i;
3120
3121 POST_MEM_WRITE(ARG5, sizeof(unsigned int));
3122 POST_MEM_WRITE(ARG6, sizeof(unsigned int));
3123 POST_MEM_WRITE(ARG7, sizeof(unsigned int));
3124
3125 // return buffer is concatenation of variable-size structs
3126 count = *(unsigned int *)ARG5;
3127 p = (char *)ARG3;
3128 end = (char *)ARG3 + ARG4;
3129 for (i = 0; i < count; i++) {
3130 vg_assert(p < end); // failure is kernel bug or Valgrind bug
3131 p += *(unsigned int *)p;
3132 }
3133
3134 POST_MEM_WRITE(ARG3, p - (char *)ARG3);
3135
3136 PRINT("got %d records, %ld/%lu bytes\n",
3137 count, (Addr)p-(Addr)ARG3, ARG4);
3138 }
3139
3140
PRE(fsgetpath)3141 PRE(fsgetpath)
3142 {
3143 #if VG_WORDSIZE == 4
3144 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)",
3145 ARG1, ARG2, ARG3,
3146 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1],
3147 LOHI64(ARG4, ARG5));
3148 PRE_REG_READ5(ssize_t, "fsgetpath",
3149 void*,"buf", size_t,"bufsize",
3150 fsid_t *,"fsid",
3151 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32");
3152 #else
3153 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)",
3154 ARG1, ARG2, ARG3,
3155 ((unsigned int *)ARG3)[0],
3156 ((unsigned int *)ARG3)[1], ARG4);
3157 PRE_REG_READ4(ssize_t, "fsgetpath",
3158 void*,"buf", size_t,"bufsize",
3159 fsid_t *,"fsid", uint64_t,"objid");
3160 #endif
3161 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t));
3162 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2);
3163 }
3164
POST(fsgetpath)3165 POST(fsgetpath)
3166 {
3167 POST_MEM_WRITE(ARG1, RES);
3168 }
3169
PRE(audit_session_self)3170 PRE(audit_session_self)
3171 {
3172 PRINT("audit_session_self()");
3173 }
3174
POST(audit_session_self)3175 POST(audit_session_self)
3176 {
3177 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p");
3178 PRINT("audit-session %#lx", RES);
3179 }
3180
PRE(exchangedata)3181 PRE(exchangedata)
3182 {
3183 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)",
3184 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3);
3185 PRE_REG_READ3(int, "exchangedata",
3186 char *, path1, char *, path2, unsigned long, options);
3187 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 );
3188 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 );
3189 }
3190
PRE(fsctl)3191 PRE(fsctl)
3192 {
3193 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )",
3194 ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
3195 PRE_REG_READ4( long, "fsctl",
3196 char *,"path", unsigned int,"request",
3197 void *,"data", unsigned int,"options");
3198
3199 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 );
3200
3201 switch (ARG2) {
3202 case VKI_afpfsByteRangeLock2FSCTL: {
3203 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3204 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)",
3205 pb->offset);
3206 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)",
3207 pb->length);
3208 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)",
3209 pb->unLockFlag);
3210 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)",
3211 pb->startEndFlag);
3212 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)",
3213 pb->fd);
3214
3215 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)",
3216 pb->retRangeStart);
3217
3218 // GrP fixme check fd
3219 break;
3220 }
3221 case VKI_FSIOC_SYNC_VOLUME:
3222 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) );
3223 break;
3224
3225 default:
3226 // fsctl requests use ioctl encoding
3227 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
3228 break;
3229 }
3230 }
3231
POST(fsctl)3232 POST(fsctl)
3233 {
3234 switch (ARG2) {
3235 case VKI_afpfsByteRangeLock2FSCTL: {
3236 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3;
3237 POST_FIELD_WRITE(pb->retRangeStart);
3238 break;
3239 }
3240 case VKI_FSIOC_SYNC_VOLUME:
3241 break;
3242
3243 default:
3244 // fsctl requests use ioctl encoding
3245 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
3246 break;
3247 }
3248 }
3249
PRE(initgroups)3250 PRE(initgroups)
3251 {
3252 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3);
3253 PRE_REG_READ3(long, "initgroups",
3254 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid);
3255 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t));
3256 }
3257
3258
3259 //--------- posix_spawn ---------//
3260 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from
3261 the simpler AIX equivalent (syswrap-aix5.c). */
3262 // Pre_read a char** argument.
pre_argv_envp(Addr a,ThreadId tid,const HChar * s1,const HChar * s2)3263 static void pre_argv_envp(Addr a, ThreadId tid, const HChar* s1, const HChar* s2)
3264 {
3265 while (True) {
3266 Addr a_deref;
3267 Addr* a_p = (Addr*)a;
3268 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
3269 a_deref = *a_p;
3270 if (0 == a_deref)
3271 break;
3272 PRE_MEM_RASCIIZ( s2, a_deref );
3273 a += sizeof(char*);
3274 }
3275 }
simple_pre_exec_check(const HChar * exe_name,Bool trace_this_child)3276 static SysRes simple_pre_exec_check ( const HChar* exe_name,
3277 Bool trace_this_child )
3278 {
3279 Int fd, ret;
3280 SysRes res;
3281 Bool setuid_allowed;
3282
3283 // Check it's readable
3284 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
3285 if (sr_isError(res)) {
3286 return res;
3287 }
3288 fd = sr_Res(res);
3289 VG_(close)(fd);
3290
3291 // Check we have execute permissions. We allow setuid executables
3292 // to be run only in the case when we are not simulating them, that
3293 // is, they to be run natively.
3294 setuid_allowed = trace_this_child ? False : True;
3295 ret = VG_(check_executable)(NULL/*&is_setuid*/,
3296 exe_name, setuid_allowed);
3297 if (0 != ret) {
3298 return VG_(mk_SysRes_Error)(ret);
3299 }
3300 return VG_(mk_SysRes_Success)(0);
3301 }
PRE(posix_spawn)3302 PRE(posix_spawn)
3303 {
3304 HChar* path = NULL; /* path to executable */
3305 HChar** envp = NULL;
3306 HChar** argv = NULL;
3307 HChar** arg2copy;
3308 HChar* launcher_basename = NULL;
3309 Int i, j, tot_args;
3310 SysRes res;
3311 Bool trace_this_child;
3312
3313 /* args: pid_t* pid
3314 char* path
3315 posix_spawn_file_actions_t* file_actions
3316 char** argv
3317 char** envp
3318 */
3319 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )",
3320 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3321
3322 /* Standard pre-syscall checks */
3323
3324 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path,
3325 void*, file_actions, char**, argv, char**, envp );
3326 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) );
3327 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2);
3328 // DDD: check file_actions
3329 if (ARG4 != 0)
3330 pre_argv_envp( ARG4, tid, "posix_spawn(argv)",
3331 "posix_spawn(argv[i])" );
3332 if (ARG5 != 0)
3333 pre_argv_envp( ARG5, tid, "posix_spawn(envp)",
3334 "posix_spawn(envp[i])" );
3335
3336 if (0)
3337 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n",
3338 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 );
3339
3340 /* Now follows a bunch of logic copied from PRE(sys_execve) in
3341 syswrap-generic.c. */
3342
3343 /* Check that the name at least begins in client-accessible storage. */
3344 if (ARG2 == 0 /* obviously bogus */
3345 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) {
3346 SET_STATUS_Failure( VKI_EFAULT );
3347 return;
3348 }
3349
3350 // Decide whether or not we want to follow along
3351 { // Make 'child_argv' be a pointer to the child's arg vector
3352 // (skipping the exe name)
3353 const HChar** child_argv = (const HChar**)ARG4;
3354 if (child_argv && child_argv[0] == NULL)
3355 child_argv = NULL;
3356 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv );
3357 }
3358
3359 // Do the important checks: it is a file, is executable, permissions are
3360 // ok, etc. We allow setuid executables to run only in the case when
3361 // we are not simulating them, that is, they to be run natively.
3362 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child );
3363 if (sr_isError(res)) {
3364 SET_STATUS_Failure( sr_Err(res) );
3365 return;
3366 }
3367
3368 /* If we're tracing the child, and the launcher name looks bogus
3369 (possibly because launcher.c couldn't figure it out, see
3370 comments therein) then we have no option but to fail. */
3371 if (trace_this_child
3372 && (VG_(name_of_launcher) == NULL
3373 || VG_(name_of_launcher)[0] != '/')) {
3374 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
3375 return;
3376 }
3377
3378 /* Ok. So let's give it a try. */
3379 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (HChar*)ARG2);
3380
3381 /* posix_spawn on Darwin is combining the fork and exec in one syscall.
3382 So, we should not terminate gdbserver : this is still the parent
3383 running, which will terminate its gdbserver when exiting.
3384 If the child process is traced, it will start a fresh gdbserver
3385 after posix_spawn. */
3386
3387 // Set up the child's exe path.
3388 //
3389 if (trace_this_child) {
3390
3391 // We want to exec the launcher. Get its pre-remembered path.
3392 path = VG_(name_of_launcher);
3393 // VG_(name_of_launcher) should have been acquired by m_main at
3394 // startup. The following two assertions should be assured by
3395 // the "If we're tracking the child .." test just above here.
3396 vg_assert(path);
3397 vg_assert(path[0] == '/');
3398 launcher_basename = path;
3399
3400 } else {
3401 path = (HChar*)ARG2;
3402 }
3403
3404 // Set up the child's environment.
3405 //
3406 // Remove the valgrind-specific stuff from the environment so the
3407 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
3408 // This is done unconditionally, since if we are tracing the child,
3409 // the child valgrind will set up the appropriate client environment.
3410 // Nb: we make a copy of the environment before trying to mangle it
3411 // as it might be in read-only memory (this was bug #101881).
3412 //
3413 // Then, if tracing the child, set VALGRIND_LIB for it.
3414 //
3415 if (ARG5 == 0) {
3416 envp = NULL;
3417 } else {
3418 envp = VG_(env_clone)( (HChar**)ARG5 );
3419 vg_assert(envp);
3420 VG_(env_remove_valgrind_env_stuff)( envp );
3421 }
3422
3423 if (trace_this_child) {
3424 // Set VALGRIND_LIB in ARG5 (the environment)
3425 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
3426 }
3427
3428 // Set up the child's args. If not tracing it, they are
3429 // simply ARG4. Otherwise, they are
3430 //
3431 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..]
3432 //
3433 // except that the first VG_(args_for_valgrind_noexecpass) args
3434 // are omitted.
3435 //
3436 if (!trace_this_child) {
3437 argv = (HChar**)ARG4;
3438 } else {
3439 vg_assert( VG_(args_for_valgrind) );
3440 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
3441 vg_assert( VG_(args_for_valgrind_noexecpass)
3442 <= VG_(sizeXA)( VG_(args_for_valgrind) ) );
3443 /* how many args in total will there be? */
3444 // launcher basename
3445 tot_args = 1;
3446 // V's args
3447 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) );
3448 tot_args -= VG_(args_for_valgrind_noexecpass);
3449 // name of client exe
3450 tot_args++;
3451 // args for client exe, skipping [0]
3452 arg2copy = (HChar**)ARG4;
3453 if (arg2copy && arg2copy[0]) {
3454 for (i = 1; arg2copy[i]; i++)
3455 tot_args++;
3456 }
3457 // allocate
3458 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1",
3459 (tot_args+1) * sizeof(HChar*) );
3460 // copy
3461 j = 0;
3462 argv[j++] = launcher_basename;
3463 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) {
3464 if (i < VG_(args_for_valgrind_noexecpass))
3465 continue;
3466 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i );
3467 }
3468 argv[j++] = (HChar*)ARG2;
3469 if (arg2copy && arg2copy[0])
3470 for (i = 1; arg2copy[i]; i++)
3471 argv[j++] = arg2copy[i];
3472 argv[j++] = NULL;
3473 // check
3474 vg_assert(j == tot_args+1);
3475 }
3476
3477 /* DDD: sort out the signal state. What signal
3478 state does the child inherit from the parent? */
3479
3480 if (0) {
3481 HChar **cpp;
3482 VG_(printf)("posix_spawn: %s\n", path);
3483 for (cpp = argv; cpp && *cpp; cpp++)
3484 VG_(printf)("argv: %s\n", *cpp);
3485 if (1)
3486 for (cpp = envp; cpp && *cpp; cpp++)
3487 VG_(printf)("env: %s\n", *cpp);
3488 }
3489
3490 /* Let the call go through as usual. However, we have to poke
3491 the altered arguments back into the argument slots. */
3492 ARG2 = (UWord)path;
3493 ARG4 = (UWord)argv;
3494 ARG5 = (UWord)envp;
3495
3496 /* not to mention .. */
3497 *flags |= SfMayBlock;
3498 }
POST(posix_spawn)3499 POST(posix_spawn)
3500 {
3501 vg_assert(SUCCESS);
3502 if (ARG1 != 0) {
3503 POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) );
3504 }
3505 }
3506
3507
PRE(socket)3508 PRE(socket)
3509 {
3510 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
3511 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
3512 }
3513
POST(socket)3514 POST(socket)
3515 {
3516 SysRes r;
3517 vg_assert(SUCCESS);
3518 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
3519 SET_STATUS_from_SysRes(r);
3520 }
3521
3522
PRE(setsockopt)3523 PRE(setsockopt)
3524 {
3525 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )",
3526 ARG1,ARG2,ARG3,ARG4,ARG5);
3527 PRE_REG_READ5(long, "setsockopt",
3528 int, s, int, level, int, optname,
3529 const void *, optval, vki_socklen_t, optlen);
3530 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
3531 }
3532
3533
PRE(getsockopt)3534 PRE(getsockopt)
3535 {
3536 Addr optval_p = ARG4;
3537 Addr optlen_p = ARG5;
3538 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",
3539 ARG1,ARG2,ARG3,ARG4,ARG5);
3540 PRE_REG_READ5(long, "getsockopt",
3541 int, s, int, level, int, optname,
3542 void *, optval, vki_socklen_t *, optlen);
3543 /* int getsockopt(int socket, int level, int option_name,
3544 void *restrict option_value,
3545 socklen_t *restrict option_len); */
3546 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3547 if (optval_p != (Addr)NULL) {
3548 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p,
3549 "socketcall.getsockopt(optval)",
3550 "socketcall.getsockopt(optlen)" );
3551 }
3552 // DDD: #warning GrP fixme darwin-specific sockopts
3553 }
3554
POST(getsockopt)3555 POST(getsockopt)
3556 {
3557 Addr optval_p = ARG4;
3558 Addr optlen_p = ARG5;
3559 vg_assert(SUCCESS);
3560 if (optval_p != (Addr)NULL) {
3561 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES),
3562 optval_p, optlen_p,
3563 "socketcall.getsockopt(optlen_out)" );
3564 // DDD: #warning GrP fixme darwin-specific sockopts
3565 }
3566 }
3567
3568
PRE(connect)3569 PRE(connect)
3570 {
3571 *flags |= SfMayBlock;
3572 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3573 PRE_REG_READ3(long, "connect",
3574 int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
3575 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
3576 }
3577
3578
PRE(accept)3579 PRE(accept)
3580 {
3581 *flags |= SfMayBlock;
3582 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3583 PRE_REG_READ3(long, "accept",
3584 int, s, struct sockaddr *, addr, int, *addrlen);
3585 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
3586 }
3587
POST(accept)3588 POST(accept)
3589 {
3590 SysRes r;
3591 vg_assert(SUCCESS);
3592 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
3593 ARG1,ARG2,ARG3);
3594 SET_STATUS_from_SysRes(r);
3595 }
3596
PRE(mkfifo)3597 PRE(mkfifo)
3598 {
3599 *flags |= SfMayBlock;
3600 PRINT("mkfifo ( %#lx(%s), %lld )",ARG1,(char *)ARG1,(ULong)ARG2);
3601 PRE_REG_READ2(long, "mkfifo", const char *, path, vki_mode_t, mode);
3602 PRE_MEM_RASCIIZ( "mkfifo(path)", ARG1 );
3603 }
3604
POST(mkfifo)3605 POST(mkfifo)
3606 {
3607 vg_assert(SUCCESS);
3608 if (!ML_(fd_allowed)(RES, "mkfifo", tid, True)) {
3609 VG_(close)(RES);
3610 SET_STATUS_Failure( VKI_EMFILE );
3611 } else {
3612 if (VG_(clo_track_fds))
3613 ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)ARG1);
3614 }
3615 }
3616
PRE(sendto)3617 PRE(sendto)
3618 {
3619 *flags |= SfMayBlock;
3620 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )",
3621 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6);
3622 PRE_REG_READ6(long, "sendto",
3623 int, s, const void *, msg, int, len,
3624 unsigned int, flags,
3625 const struct sockaddr *, to, int, tolen);
3626 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3627 }
3628
PRE(sendfile)3629 PRE(sendfile)
3630 {
3631 #if VG_WORDSIZE == 4
3632 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)",
3633 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7);
3634
3635 PRE_REG_READ7(long, "sendfile",
3636 int, fromfd, int, tofd,
3637 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32,
3638 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3639 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t));
3640 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr));
3641 #else
3642 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)",
3643 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
3644
3645 PRE_REG_READ6(long, "sendfile",
3646 int, fromfd, int, tofd,
3647 vki_uint64_t, offset,
3648 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags);
3649 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t));
3650 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr));
3651 #endif
3652
3653 *flags |= SfMayBlock;
3654 }
POST(sendfile)3655 POST(sendfile)
3656 {
3657 #if VG_WORDSIZE == 4
3658 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t));
3659 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr));
3660 #else
3661 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t));
3662 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr));
3663 #endif
3664 }
3665
PRE(recvfrom)3666 PRE(recvfrom)
3667 {
3668 *flags |= SfMayBlock;
3669 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",
3670 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3671 PRE_REG_READ6(long, "recvfrom",
3672 int, s, void *, buf, int, len, unsigned int, flags,
3673 struct sockaddr *, from, int *, fromlen);
3674 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3675 }
3676
POST(recvfrom)3677 POST(recvfrom)
3678 {
3679 vg_assert(SUCCESS);
3680 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
3681 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
3682 }
3683
3684
PRE(sendmsg)3685 PRE(sendmsg)
3686 {
3687 *flags |= SfMayBlock;
3688 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3689 PRE_REG_READ3(long, "sendmsg",
3690 int, s, const struct msghdr *, msg, int, flags);
3691 ML_(generic_PRE_sys_sendmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3692 }
3693
3694
PRE(recvmsg)3695 PRE(recvmsg)
3696 {
3697 *flags |= SfMayBlock;
3698 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3699 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
3700 ML_(generic_PRE_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2);
3701 }
3702
POST(recvmsg)3703 POST(recvmsg)
3704 {
3705 ML_(generic_POST_sys_recvmsg)(tid, "msg", (struct vki_msghdr *)ARG2, RES);
3706 }
3707
3708
PRE(shutdown)3709 PRE(shutdown)
3710 {
3711 *flags |= SfMayBlock;
3712 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2);
3713 PRE_REG_READ2(int, "shutdown", int, s, int, how);
3714 }
3715
3716
PRE(bind)3717 PRE(bind)
3718 {
3719 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
3720 PRE_REG_READ3(long, "bind",
3721 int, sockfd, struct sockaddr *, my_addr, int, addrlen);
3722 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
3723 }
3724
3725
PRE(listen)3726 PRE(listen)
3727 {
3728 PRINT("listen ( %ld, %ld )",ARG1,ARG2);
3729 PRE_REG_READ2(long, "listen", int, s, int, backlog);
3730 }
3731
3732
PRE(getsockname)3733 PRE(getsockname)
3734 {
3735 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3736 PRE_REG_READ3(long, "getsockname",
3737 int, s, struct sockaddr *, name, int *, namelen);
3738 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
3739 }
3740
POST(getsockname)3741 POST(getsockname)
3742 {
3743 vg_assert(SUCCESS);
3744 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
3745 ARG1,ARG2,ARG3);
3746 }
3747
3748
PRE(getpeername)3749 PRE(getpeername)
3750 {
3751 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
3752 PRE_REG_READ3(long, "getpeername",
3753 int, s, struct sockaddr *, name, int *, namelen);
3754 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
3755 }
3756
POST(getpeername)3757 POST(getpeername)
3758 {
3759 vg_assert(SUCCESS);
3760 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
3761 ARG1,ARG2,ARG3);
3762 }
3763
3764
PRE(socketpair)3765 PRE(socketpair)
3766 {
3767 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
3768 PRE_REG_READ4(long, "socketpair",
3769 int, d, int, type, int, protocol, int *, sv);
3770 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
3771 }
3772
POST(socketpair)3773 POST(socketpair)
3774 {
3775 vg_assert(SUCCESS);
3776 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
3777 ARG1,ARG2,ARG3,ARG4);
3778 }
3779
3780
PRE(gethostuuid)3781 PRE(gethostuuid)
3782 {
3783 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2);
3784 PRE_REG_READ2(int,"gethostuuid",
3785 char *,"uuid_buf",
3786 const struct vki_timespec *,"timeout");
3787
3788 PRE_MEM_WRITE("uuid_buf", ARG1, 16);
3789 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec));
3790
3791 *flags |= SfMayBlock;
3792 }
3793
3794
POST(gethostuuid)3795 POST(gethostuuid)
3796 {
3797 POST_MEM_WRITE(ARG1, 16);
3798 }
3799
3800 /* Darwin pipe() returns the two descriptors in two registers. */
PRE(pipe)3801 PRE(pipe)
3802 {
3803 PRINT("pipe ( )");
3804 PRE_REG_READ0(int, "pipe");
3805 }
3806
POST(pipe)3807 POST(pipe)
3808 {
3809 Int p0, p1;
3810 vg_assert(SUCCESS);
3811 p0 = RES;
3812 p1 = RESHI;
3813
3814 if (!ML_(fd_allowed)(p0, "pipe", tid, True) ||
3815 !ML_(fd_allowed)(p1, "pipe", tid, True)) {
3816 VG_(close)(p0);
3817 VG_(close)(p1);
3818 SET_STATUS_Failure( VKI_EMFILE );
3819 } else {
3820 if (VG_(clo_track_fds)) {
3821 ML_(record_fd_open_nameless)(tid, p0);
3822 ML_(record_fd_open_nameless)(tid, p1);
3823 }
3824 }
3825 }
3826
3827
PRE(getlogin)3828 PRE(getlogin)
3829 {
3830 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2);
3831 PRE_REG_READ2(long, "getlogin",
3832 char *,"namebuf", unsigned int,"namelen");
3833
3834 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2);
3835 }
3836
POST(getlogin)3837 POST(getlogin)
3838 {
3839 POST_MEM_WRITE(ARG1, ARG2);
3840 }
3841
3842
PRE(ptrace)3843 PRE(ptrace)
3844 {
3845 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4);
3846 PRE_REG_READ4(long, "ptrace",
3847 int,"request", vki_pid_t,"pid",
3848 vki_caddr_t,"addr", int,"data");
3849
3850 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism.
3851
3852 // GrP fixme anything needed?
3853 }
3854
3855
PRE(issetugid)3856 PRE(issetugid)
3857 {
3858 PRINT("issetugid ( )");
3859 PRE_REG_READ0(long, "issetugid");
3860 }
3861
3862
PRE(getdtablesize)3863 PRE(getdtablesize)
3864 {
3865 PRINT("getdtablesize ( )");
3866 PRE_REG_READ0(long, "getdtablesize");
3867 }
3868
POST(getdtablesize)3869 POST(getdtablesize)
3870 {
3871 // Subtract Valgrind's fd range from client's dtable
3872 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit));
3873 }
3874
PRE(lseek)3875 PRE(lseek)
3876 {
3877 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3);
3878 PRE_REG_READ4(vki_off_t, "lseek",
3879 unsigned int,fd, int,offset_hi, int,offset_lo,
3880 unsigned int,whence);
3881 }
3882
3883
PRE(pathconf)3884 PRE(pathconf)
3885 {
3886 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2);
3887 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name");
3888 PRE_MEM_RASCIIZ("pathconf(path)", ARG1);
3889 }
3890
3891
PRE(fpathconf)3892 PRE(fpathconf)
3893 {
3894 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2);
3895 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name");
3896
3897 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False))
3898 SET_STATUS_Failure( VKI_EBADF );
3899 }
3900
3901
PRE(getdirentries)3902 PRE(getdirentries)
3903 {
3904 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4);
3905 PRE_REG_READ4(int, "getdirentries",
3906 int, fd, char *, buf, int, nbytes, long *, basep);
3907 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long));
3908 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3);
3909 }
3910
POST(getdirentries)3911 POST(getdirentries)
3912 {
3913 POST_MEM_WRITE(ARG4, sizeof(long));
3914 // GrP fixme be specific about d_name?
3915 POST_MEM_WRITE(ARG2, RES);
3916 }
3917
3918
PRE(getdirentries64)3919 PRE(getdirentries64)
3920 {
3921 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4);
3922 PRE_REG_READ4(vki_ssize_t, "getdirentries",
3923 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep);
3924 /* JRS 18-Nov-2014: it appears that sometimes |basep| doesn't point
3925 to valid memory and the kernel doesn't modify it. I can't
3926 determine the conditions under which that happens. But it
3927 causes Memcheck to complain, confusingly. So disable this check
3928 for the time being.
3929
3930 PRE_MEM_WRITE("getdirentries64(position)", ARG4, sizeof(vki_off_t));
3931 */
3932 PRE_MEM_WRITE("getdirentries64(buf)", ARG2, ARG3);
3933 }
POST(getdirentries64)3934 POST(getdirentries64)
3935 {
3936 /* Disabled; see coments in the PRE wrapper.
3937 POST_MEM_WRITE(ARG4, sizeof(vki_off_t));
3938 */
3939 // GrP fixme be specific about d_name? (fixme copied from 32 bit version)
3940 POST_MEM_WRITE(ARG2, RES);
3941 }
3942
3943
PRE(statfs64)3944 PRE(statfs64)
3945 {
3946 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2);
3947 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf);
3948 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
3949 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3950 }
POST(statfs64)3951 POST(statfs64)
3952 {
3953 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3954 }
3955
3956
PRE(fstatfs64)3957 PRE(fstatfs64)
3958 {
3959 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2);
3960 PRE_REG_READ2(long, "fstatfs64",
3961 unsigned int, fd, struct statfs *, buf);
3962 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) );
3963 }
POST(fstatfs64)3964 POST(fstatfs64)
3965 {
3966 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) );
3967 }
3968
PRE(csops)3969 PRE(csops)
3970 {
3971 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4);
3972 PRE_REG_READ4(int, "csops",
3973 vki_pid_t, pid, uint32_t, ops,
3974 void *, useraddr, vki_size_t, usersize);
3975
3976 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 );
3977
3978 // If the pid is ours, don't mark the program as KILL or HARD
3979 // Maybe we should keep track of this for later calls to STATUS
3980 if (!ARG1 || VG_(getpid)() == ARG1) {
3981 switch (ARG2) {
3982 case VKI_CS_OPS_MARKINVALID:
3983 case VKI_CS_OPS_MARKHARD:
3984 case VKI_CS_OPS_MARKKILL:
3985 SET_STATUS_Success(0);
3986 }
3987 }
3988 }
POST(csops)3989 POST(csops)
3990 {
3991 POST_MEM_WRITE( ARG3, ARG4 );
3992 }
3993
PRE(auditon)3994 PRE(auditon)
3995 {
3996 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3);
3997 PRE_REG_READ3(int,"auditon",
3998 int,"cmd", void*,"data", unsigned int,"length");
3999
4000 switch (ARG1) {
4001
4002 case VKI_A_SETPOLICY:
4003 case VKI_A_SETKMASK:
4004 case VKI_A_SETQCTRL:
4005 case VKI_A_SETCOND:
4006 case VKI_A_SETCLASS:
4007 case VKI_A_SETPMASK:
4008 case VKI_A_SETFSIZE:
4009 #if DARWIN_VERS >= DARWIN_10_6
4010 case VKI_A_SENDTRIGGER:
4011 #endif
4012 // kernel reads data..data+length
4013 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4014 break;
4015
4016 case VKI_A_GETKMASK:
4017 case VKI_A_GETPOLICY:
4018 case VKI_A_GETQCTRL:
4019 case VKI_A_GETFSIZE:
4020 case VKI_A_GETCOND:
4021 // kernel writes data..data+length
4022 // GrP fixme be precise about what gets written
4023 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4024 break;
4025
4026
4027 case VKI_A_GETCLASS:
4028 case VKI_A_GETPINFO:
4029 case VKI_A_GETPINFO_ADDR:
4030 #if DARWIN_VERS >= DARWIN_10_6
4031 case VKI_A_GETSINFO_ADDR:
4032 #endif
4033 // kernel reads and writes data..data+length
4034 // GrP fixme be precise about what gets read and written
4035 PRE_MEM_READ("auditon(data)", ARG2, ARG3);
4036 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3);
4037 break;
4038
4039 case VKI_A_SETKAUDIT:
4040 case VKI_A_SETSTAT:
4041 case VKI_A_SETUMASK:
4042 case VKI_A_SETSMASK:
4043 case VKI_A_GETKAUDIT:
4044 case VKI_A_GETCWD:
4045 case VKI_A_GETCAR:
4046 case VKI_A_GETSTAT:
4047 // unimplemented on darwin
4048 break;
4049
4050 default:
4051 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld\n", ARG1);
4052 break;
4053 }
4054 }
POST(auditon)4055 POST(auditon)
4056 {
4057 switch (ARG1) {
4058
4059 case VKI_A_SETPOLICY:
4060 case VKI_A_SETKMASK:
4061 case VKI_A_SETQCTRL:
4062 case VKI_A_SETCOND:
4063 case VKI_A_SETCLASS:
4064 case VKI_A_SETPMASK:
4065 case VKI_A_SETFSIZE:
4066 #if DARWIN_VERS >= DARWIN_10_6
4067 case VKI_A_SENDTRIGGER:
4068 #endif
4069 // kernel reads data..data+length
4070 break;
4071
4072 case VKI_A_GETKMASK:
4073 case VKI_A_GETPOLICY:
4074 case VKI_A_GETQCTRL:
4075 case VKI_A_GETFSIZE:
4076 case VKI_A_GETCOND:
4077 // kernel writes data..data+length
4078 // GrP fixme be precise about what gets written
4079 POST_MEM_WRITE(ARG2, ARG3);
4080 break;
4081
4082
4083 case VKI_A_GETCLASS:
4084 case VKI_A_GETPINFO:
4085 case VKI_A_GETPINFO_ADDR:
4086 #if DARWIN_VERS >= DARWIN_10_6
4087 case VKI_A_GETSINFO_ADDR:
4088 #endif
4089 // kernel reads and writes data..data+length
4090 // GrP fixme be precise about what gets read and written
4091 POST_MEM_WRITE(ARG2, ARG3);
4092 break;
4093
4094 case VKI_A_SETKAUDIT:
4095 case VKI_A_SETSTAT:
4096 case VKI_A_SETUMASK:
4097 case VKI_A_SETSMASK:
4098 case VKI_A_GETKAUDIT:
4099 case VKI_A_GETCWD:
4100 case VKI_A_GETCAR:
4101 case VKI_A_GETSTAT:
4102 // unimplemented on darwin
4103 break;
4104
4105 default:
4106 break;
4107 }
4108 }
4109
4110
PRE(mmap)4111 PRE(mmap)
4112 {
4113 // SysRes r;
4114 if (0) VG_(am_do_sync_check)("(PRE_MMAP)",__FILE__,__LINE__);
4115
4116 #if VG_WORDSIZE == 4
4117 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )",
4118 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) );
4119 PRE_REG_READ7(Addr, "mmap",
4120 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4121 unsigned long,offset_hi, unsigned long,offset_lo);
4122 // GrP fixme V mmap and kernel mach_msg collided once - don't use
4123 // V's mechanism for now
4124 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
4125 // (Off64T)LOHI64(ARG6, ARG7) );
4126 #else
4127 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )",
4128 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4129 PRE_REG_READ6(long, "mmap",
4130 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd,
4131 Off64T,offset);
4132 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
4133
4134 #endif
4135
4136 // SET_STATUS_from_SysRes(r);
4137 }
4138
POST(mmap)4139 POST(mmap)
4140 {
4141 if (RES != -1) {
4142 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6);
4143 // Try to load symbols from the region
4144 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/,
4145 -1/*don't use_fd*/ );
4146 ML_(sync_mappings)("after", "mmap", 0);
4147 }
4148 }
4149
4150
4151 /* This function holds common elements of PRE(__sysctl) and
4152 PRE(sysctlbyname). */
common_PRE_sysctl(ThreadId tid,SyscallStatus * status,UWord * flags,Bool is_kern_dot_userstack,UWord oldp,UWord oldlenp,UWord newp,UWord newlen)4153 static void common_PRE_sysctl (
4154 /*IMPLICIT ARGS*/
4155 ThreadId tid, /*OUT*/SyscallStatus* status, /*OUT*/UWord* flags,
4156 /*!IMPLICIT ARGS*/
4157 Bool is_kern_dot_userstack,
4158 UWord oldp, UWord oldlenp,
4159 UWord newp, UWord newlen )
4160 {
4161 if (oldlenp) {
4162 // writes *oldlenp
4163 PRE_MEM_WRITE("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4164 if (oldp) {
4165 // also reads *oldlenp, and writes up to oldp[0..(*oldlenp)-1]
4166 PRE_MEM_READ("sysctl(oldlenp)", oldlenp, sizeof(size_t));
4167 PRE_MEM_WRITE("sysctl(oldp)", oldp, *(size_t*)oldlenp);
4168 }
4169 }
4170 if (newp) {
4171 PRE_MEM_READ("sysctl(newp)", newp, newlen);
4172 }
4173
4174 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid
4175 // (executable path and arguments and environment
4176
4177 if (is_kern_dot_userstack) {
4178 // Intercept sysctl(kern.usrstack). The kernel's reply
4179 // would be Valgrind's stack, not the client's stack.
4180 // GrP fixme kern_usrstack64 */
4181 if (newp || newlen) {
4182 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only */
4183 } else {
4184 Addr* t_oldp = (Addr*)oldp;
4185 size_t* t_oldlenp = (size_t*)oldlenp;
4186 if (t_oldlenp) {
4187 // According to some searches on the net, it looks like
4188 // USRSTACK gives the address of the byte following the
4189 // highest byte of the stack. As VG_(clstk_end) is the
4190 // address of the highest addressable byte, we add 1.
4191 Addr stack_end = VG_(clstk_end)+1;
4192 size_t oldlen = *t_oldlenp;
4193 // always return actual size
4194 *t_oldlenp = sizeof(Addr);
4195 if (t_oldp && oldlen >= sizeof(Addr)) {
4196 // oldp is big enough. copy value and return 0
4197 *t_oldp = stack_end;
4198 SET_STATUS_Success(0);
4199 } else {
4200 // oldp isn't big enough. copy as much as possible
4201 // and return ENOMEM
4202 if (t_oldp) VG_(memcpy)(t_oldp, &stack_end, oldlen);
4203 SET_STATUS_Failure(VKI_ENOMEM);
4204 }
4205 }
4206 }
4207 }
4208
4209 if (!SUCCESS && !FAILURE) {
4210 // Don't set SfPostOnFail if we've already handled it locally.
4211 *flags |= SfPostOnFail;
4212 }
4213 }
4214
4215
PRE(__sysctl)4216 PRE(__sysctl)
4217 {
4218 UWord name = ARG1;
4219 UWord namelen = ARG2;
4220 UWord oldp = ARG3;
4221 UWord oldlenp = ARG4;
4222 UWord newp = ARG5;
4223 UWord newlen = ARG6;
4224
4225 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )",
4226 name, namelen, oldp, oldlenp, newp, newlen );
4227
4228 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen,
4229 void*, oldp, vki_size_t *, oldlenp,
4230 void*, newp, vki_size_t *, newlenp);
4231
4232 PRE_MEM_READ("sysctl(name)", name, namelen); // reads name[0..namelen-1]
4233
4234 if (VG_(clo_trace_syscalls)) {
4235 UInt i;
4236 Int* t_name = (Int*)name;
4237 VG_(printf)(" mib: [ ");
4238 for (i = 0; i < namelen; i++) {
4239 VG_(printf)("%d ", t_name[i]);
4240 }
4241 VG_(printf)("]");
4242 }
4243
4244 Int vKI_KERN_USRSTACKXX
4245 = VG_WORDSIZE == 4 ? VKI_KERN_USRSTACK32 : VKI_KERN_USRSTACK64;
4246 Bool is_kern_dot_userstack
4247 = name && namelen == 2
4248 && ((Int*)name)[0] == VKI_CTL_KERN
4249 && ((Int*)name)[1] == vKI_KERN_USRSTACKXX;
4250
4251 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
4252 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
4253 }
4254
POST(__sysctl)4255 POST(__sysctl)
4256 {
4257 UWord oldp = ARG3;
4258 UWord oldlenp = ARG4;
4259
4260 if (SUCCESS || ERR == VKI_ENOMEM) {
4261 // sysctl can write truncated data and return VKI_ENOMEM
4262 if (oldlenp) {
4263 POST_MEM_WRITE(oldlenp, sizeof(size_t));
4264 }
4265 if (oldp && oldlenp) {
4266 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
4267 }
4268 }
4269 }
4270
4271
PRE(sigpending)4272 PRE(sigpending)
4273 {
4274 PRINT( "sigpending ( %#lx )", ARG1 );
4275 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set);
4276 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t));
4277 }
POST(sigpending)4278 POST(sigpending)
4279 {
4280 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
4281 }
4282
4283
PRE(sigprocmask)4284 PRE(sigprocmask)
4285 {
4286 UWord arg1;
4287 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3);
4288 PRE_REG_READ3(long, "sigprocmask",
4289 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset);
4290 if (ARG2 != 0)
4291 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
4292 if (ARG3 != 0)
4293 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
4294
4295 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the
4296 value of 'how' is irrelevant, and it appears that Darwin's libc
4297 passes zero, which is not equal to any of
4298 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes
4299 VG_(do_sys_sigprocmask) to complain, since it checks the 'how'
4300 value independently of the other args. Solution: in this case,
4301 simply pass a valid (but irrelevant) value for 'how'. */
4302 /* Also, in this case the new set is passed to the kernel by
4303 reference, not value, as in some other sigmask related Darwin
4304 syscalls. */
4305 arg1 = ARG1;
4306 if (ARG2 == 0 /* the new-set is NULL */
4307 && ARG1 != VKI_SIG_BLOCK
4308 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) {
4309 arg1 = VKI_SIG_SETMASK;
4310 }
4311 SET_STATUS_from_SysRes(
4312 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2,
4313 (vki_sigset_t*)ARG3 )
4314 );
4315
4316 if (SUCCESS)
4317 *flags |= SfPollAfter;
4318 }
4319
POST(sigprocmask)4320 POST(sigprocmask)
4321 {
4322 vg_assert(SUCCESS);
4323 if (RES == 0 && ARG3 != 0)
4324 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
4325 }
4326
4327
PRE(sigsuspend)4328 PRE(sigsuspend)
4329 {
4330 /* Just hand this off to the kernel. Is that really correct? And
4331 shouldn't we at least set SfPollAfter? These questions apply to
4332 all the Linux versions too. */
4333 /* I think the first arg is the 32-bit signal mask (by value), and
4334 the other two args are ignored. */
4335 *flags |= SfMayBlock;
4336 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 );
4337 PRE_REG_READ1(int, "sigsuspend", int, sigmask);
4338 }
4339
4340
4341 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64-
4342 and 32-bit wrappers are different.
4343
4344 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and
4345 length in the usual way. I have seen values NULL, 0 passed in some
4346 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the
4347 basis that they don't do anything if the length is zero, so it's OK
4348 for the buffer pointer to be NULL in that case (meaning they don't
4349 complain).
4350
4351 int proc_info(int32_t callnum, int32_t pid,
4352 uint32_t flavor, uint64_t arg,
4353 user_addr_t buffer, int32_t buffersize)
4354 */
4355 #if DARWIN_VERS >= DARWIN_10_6
PRE(proc_info)4356 PRE(proc_info)
4357 {
4358 #if VG_WORDSIZE == 4
4359 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4360 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7);
4361 PRE_REG_READ7(int, "proc_info",
4362 int, callnum, int, pid, unsigned int, flavor,
4363 vki_uint32_t, arg_low32,
4364 vki_uint32_t, arg_high32,
4365 void*, buffer, int, buffersize);
4366 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7);
4367 #else
4368 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)",
4369 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6);
4370 PRE_REG_READ6(int, "proc_info",
4371 int, callnum, int, pid, unsigned int, flavor,
4372 unsigned long long int, arg,
4373 void*, buffer, int, buffersize);
4374 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6);
4375 #endif
4376 }
4377
POST(proc_info)4378 POST(proc_info)
4379 {
4380 #if VG_WORDSIZE == 4
4381 vg_assert(SUCCESS);
4382
4383 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4384 if (ARG1 == 5 && ARG3 == 2 && LOHI64(ARG4,ARG5) == 0 )
4385 {
4386 const HChar* new_name = (const HChar*) ARG6;
4387 if (new_name) { // Paranoia
4388 ThreadState* tst = VG_(get_ThreadState)(tid);
4389 SizeT new_len = VG_(strlen)(new_name);
4390
4391 /* Don't bother reusing the memory. This is a rare event. */
4392 tst->thread_name =
4393 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4394 VG_(strcpy)(tst->thread_name, new_name);
4395 }
4396 }
4397
4398 POST_MEM_WRITE(ARG6, ARG7);
4399 #else
4400 vg_assert(SUCCESS);
4401
4402 // Intercept internal call to proc_setcontrol() where flavor = 2, arg = 0
4403 if (ARG1 == 5 && ARG3 == 2 && ARG4 == 0 )
4404 {
4405 const HChar* new_name = (const HChar*) ARG5;
4406 if (new_name) { // Paranoia
4407 ThreadState* tst = VG_(get_ThreadState)(tid);
4408 SizeT new_len = VG_(strlen)(new_name);
4409
4410 /* Don't bother reusing the memory. This is a rare event. */
4411 tst->thread_name =
4412 VG_(realloc)("syscall(proc_info)", tst->thread_name, new_len + 1);
4413 VG_(strcpy)(tst->thread_name, new_name);
4414 }
4415 }
4416
4417 POST_MEM_WRITE(ARG5, ARG6);
4418 #endif
4419 }
4420
4421 #endif /* DARWIN_VERS >= DARWIN_10_6 */
4422
4423 /* ---------------------------------------------------------------------
4424 aio_*
4425 ------------------------------------------------------------------ */
4426
4427 // We must record the aiocbp for each aio_read() in a table so that when
4428 // aio_return() is called we can mark the memory written asynchronously by
4429 // aio_read() as having been written. We don't have to do this for
4430 // aio_write(). See bug 197227 for more details.
4431 static OSet* aiocbp_table = NULL;
4432 static Bool aio_init_done = False;
4433
aio_init(void)4434 static void aio_init(void)
4435 {
4436 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free));
4437 aio_init_done = True;
4438 }
4439
4440 static Bool was_a_successful_aio_read = False;
4441
PRE(aio_return)4442 PRE(aio_return)
4443 {
4444 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4445 // This assumes that the kernel looks at the struct pointer, but not the
4446 // contents of the struct.
4447 PRINT( "aio_return ( %#lx )", ARG1 );
4448 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp);
4449
4450 if (!aio_init_done) aio_init();
4451 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp);
4452 }
POST(aio_return)4453 POST(aio_return)
4454 {
4455 // If we found the aiocbp in our own table it must have been an aio_read(),
4456 // so mark the buffer as written. If we didn't find it, it must have been
4457 // an aio_write() or a bogus aio_return() (eg. a second one on the same
4458 // aiocbp). Either way, the buffer won't have been written so we don't
4459 // have to mark the buffer as written.
4460 if (was_a_successful_aio_read) {
4461 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4462 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4463 was_a_successful_aio_read = False;
4464 }
4465 }
4466
PRE(aio_suspend)4467 PRE(aio_suspend)
4468 {
4469 // This assumes that the kernel looks at the struct pointers in the list,
4470 // but not the contents of the structs.
4471 PRINT( "aio_suspend ( %#lx )", ARG1 );
4472 PRE_REG_READ3(long, "aio_suspend",
4473 const struct vki_aiocb *, aiocbp, int, nent,
4474 const struct vki_timespec *, timeout);
4475 if (ARG2 > 0)
4476 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *));
4477 if (ARG3)
4478 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec));
4479 }
4480
PRE(aio_error)4481 PRE(aio_error)
4482 {
4483 // This assumes that the kernel looks at the struct pointer, but not the
4484 // contents of the struct.
4485 PRINT( "aio_error ( %#lx )", ARG1 );
4486 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp);
4487 }
4488
PRE(aio_read)4489 PRE(aio_read)
4490 {
4491 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4492
4493 PRINT( "aio_read ( %#lx )", ARG1 );
4494 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp);
4495 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4496
4497 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4498 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) {
4499 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)",
4500 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4501 } else {
4502 SET_STATUS_Failure( VKI_EBADF );
4503 }
4504 } else {
4505 SET_STATUS_Failure( VKI_EINVAL );
4506 }
4507 }
POST(aio_read)4508 POST(aio_read)
4509 {
4510 // We have to record the fact that there is an asynchronous read request
4511 // pending. When a successful aio_return() occurs for this aiocb, then we
4512 // will mark the memory as having been defined.
4513 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4514 if (!aio_init_done) aio_init();
4515 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel
4516 // should have caused the aio_read() to fail and we shouldn't have reached
4517 // here.
4518 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp);
4519 }
4520
PRE(aio_write)4521 PRE(aio_write)
4522 {
4523 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1;
4524
4525 PRINT( "aio_write ( %#lx )", ARG1 );
4526 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp);
4527 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb));
4528
4529 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) {
4530 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) {
4531 PRE_MEM_READ("aio_write(aiocbp->aio_buf)",
4532 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes);
4533 } else {
4534 SET_STATUS_Failure( VKI_EBADF );
4535 }
4536 } else {
4537 SET_STATUS_Failure( VKI_EINVAL );
4538 }
4539 }
4540
4541 /* ---------------------------------------------------------------------
4542 mach_msg: formatted messages
4543 ------------------------------------------------------------------ */
4544
desc_size(mach_msg_descriptor_t * desc)4545 static size_t desc_size(mach_msg_descriptor_t *desc)
4546 {
4547 switch (desc->type.type) {
4548 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port);
4549 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line);
4550 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line);
4551 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports);
4552 default:
4553 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type);
4554 return sizeof(desc->type); // guess
4555 }
4556 }
4557
4558
assign_port_names(mach_msg_ool_ports_descriptor_t * desc,const char * name)4559 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc,
4560 const char *name)
4561 {
4562 mach_msg_size_t i;
4563 mach_port_t *ports = (mach_port_t *)desc->address;
4564 for (i = 0; i < desc->count; i++) {
4565 assign_port_name(ports[i], name);
4566 }
4567 }
4568
4569
import_complex_message(ThreadId tid,mach_msg_header_t * mh)4570 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh)
4571 {
4572 mach_msg_body_t *body;
4573 mach_msg_size_t count, i;
4574 uint8_t *p;
4575 mach_msg_descriptor_t *desc;
4576
4577 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4578
4579 body = (mach_msg_body_t *)(mh+1);
4580 count = body->msgh_descriptor_count;
4581 p = (uint8_t *)(body+1);
4582
4583 for (i = 0; i < count; i++) {
4584 desc = (mach_msg_descriptor_t *)p;
4585 p += desc_size(desc);
4586
4587 switch (desc->type.type) {
4588 case MACH_MSG_PORT_DESCRIPTOR:
4589 // single port
4590 record_unnamed_port(tid, desc->port.name, -1);
4591 record_port_insert_rights(desc->port.name, desc->port.disposition);
4592 PRINT("got port %s;\n", name_for_port(desc->port.name));
4593 break;
4594
4595 case MACH_MSG_OOL_DESCRIPTOR:
4596 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4597 // out-of-line memory - map it
4598 // GrP fixme how is VOLATILE different? do we care?
4599 // GrP fixme do other flags tell us anything? assume shared for now
4600 // GrP fixme more SF_ flags marking mach_msg memory might be nice
4601 // GrP fixme protection
4602 if (desc->out_of_line.size > 0) {
4603 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4604 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address +
4605 (Addr)desc->out_of_line.size);
4606 PRINT("got ool mem %p..%p;\n", desc->out_of_line.address,
4607 (char*)desc->out_of_line.address+desc->out_of_line.size);
4608
4609 ML_(notify_core_and_tool_of_mmap)(
4610 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4611 VKI_MAP_PRIVATE, -1, 0);
4612 }
4613 // GrP fixme mark only un-rounded part as initialized
4614 break;
4615
4616 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4617 // out-of-line array of ports - map it
4618 // GrP fixme see fixmes above
4619 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));
4620
4621 if (desc->ool_ports.count > 0) {
4622 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4623 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t));
4624 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address;
4625
4626 ML_(notify_core_and_tool_of_mmap)(
4627 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE,
4628 VKI_MAP_PRIVATE, -1, 0);
4629
4630 PRINT(":");
4631 for (i = 0; i < desc->ool_ports.count; i++) {
4632 record_unnamed_port(tid, ports[i], -1);
4633 record_port_insert_rights(ports[i], desc->port.disposition);
4634 PRINT(" %s", name_for_port(ports[i]));
4635 }
4636 }
4637 PRINT(";\n");
4638 break;
4639
4640 default:
4641 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4642 break;
4643 }
4644 }
4645 }
4646
4647
pre_port_desc_read(ThreadId tid,mach_msg_port_descriptor_t * desc2)4648 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2)
4649 {
4650 #pragma pack(4)
4651 struct {
4652 mach_port_t name;
4653 mach_msg_size_t pad1;
4654 uint16_t pad2;
4655 uint8_t disposition;
4656 uint8_t type;
4657 } *desc = (void*)desc2;
4658 #pragma pack()
4659
4660 PRE_FIELD_READ("msg->desc.port.name", desc->name);
4661 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition);
4662 PRE_FIELD_READ("msg->desc.port.type", desc->type);
4663 }
4664
4665
pre_ool_desc_read(ThreadId tid,mach_msg_ool_descriptor_t * desc2)4666 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2)
4667 {
4668 #pragma pack(4)
4669 struct {
4670 Addr address;
4671 #if VG_WORDSIZE != 8
4672 mach_msg_size_t size;
4673 #endif
4674 uint8_t deallocate;
4675 uint8_t copy;
4676 uint8_t pad1;
4677 uint8_t type;
4678 #if VG_WORDSIZE == 8
4679 mach_msg_size_t size;
4680 #endif
4681 } *desc = (void*)desc2;
4682 #pragma pack()
4683
4684 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address);
4685 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size);
4686 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate);
4687 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy);
4688 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type);
4689 }
4690
pre_oolports_desc_read(ThreadId tid,mach_msg_ool_ports_descriptor_t * desc2)4691 static void pre_oolports_desc_read(ThreadId tid,
4692 mach_msg_ool_ports_descriptor_t *desc2)
4693 {
4694 #pragma pack(4)
4695 struct {
4696 Addr address;
4697 #if VG_WORDSIZE != 8
4698 mach_msg_size_t size;
4699 #endif
4700 uint8_t deallocate;
4701 uint8_t copy;
4702 uint8_t disposition;
4703 uint8_t type;
4704 #if VG_WORDSIZE == 8
4705 mach_msg_size_t size;
4706 #endif
4707 } *desc = (void*)desc2;
4708 #pragma pack()
4709
4710 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address);
4711 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size);
4712 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate);
4713 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy);
4714 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition);
4715 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type);
4716 }
4717
4718
4719 // Returns the size of the descriptor area
4720 // (mach_msg_body_t + any mach_msg_descriptor_t)
export_complex_message(ThreadId tid,mach_msg_header_t * mh)4721 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh)
4722 {
4723 mach_msg_body_t *body;
4724 mach_msg_size_t count, i;
4725 uint8_t *p;
4726 mach_msg_descriptor_t *desc;
4727
4728 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX);
4729
4730 body = (mach_msg_body_t *)(mh+1);
4731 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body));
4732
4733 count = body->msgh_descriptor_count;
4734 p = (uint8_t *)(body+1);
4735
4736 for (i = 0; i < count; i++) {
4737 desc = (mach_msg_descriptor_t *)p;
4738 p += desc_size(desc);
4739
4740 switch (desc->type.type) {
4741 case MACH_MSG_PORT_DESCRIPTOR:
4742 // single port; no memory map effects
4743 pre_port_desc_read(tid, &desc->port);
4744 break;
4745
4746 case MACH_MSG_OOL_DESCRIPTOR:
4747 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR:
4748 // out-of-line memory - unmap it if it's marked dealloc
4749 // GrP fixme need to remap if message fails?
4750 // GrP fixme how is VOLATILE different? do we care?
4751 // GrP fixme struct is different for lp64
4752 pre_ool_desc_read(tid, &desc->out_of_line);
4753
4754 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) {
4755 vm_size_t size = desc->out_of_line.size;
4756 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address);
4757 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size);
4758 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address,
4759 (Addr)desc->out_of_line.address + size);
4760 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4761 }
4762 break;
4763
4764 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
4765 // out-of-line array of ports - unmap it if it's marked dealloc
4766 // GrP fixme need to remap if message fails?
4767 // GrP fixme struct different for lp64
4768 pre_oolports_desc_read(tid, &desc->ool_ports);
4769
4770 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) {
4771 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t);
4772 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address);
4773 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size);
4774 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address,
4775 (Addr)desc->ool_ports.address + size);
4776 ML_(notify_core_and_tool_of_munmap)(start, end - start);
4777 }
4778 break;
4779 default:
4780 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type);
4781 break;
4782 }
4783 }
4784
4785 return (size_t)((Addr)p - (Addr)body);
4786 }
4787
4788
4789 /* ---------------------------------------------------------------------
4790 mach_msg: host-related messages
4791 ------------------------------------------------------------------ */
4792
4793
POST(host_info)4794 POST(host_info)
4795 {
4796 #pragma pack(4)
4797 typedef struct {
4798 mach_msg_header_t Head;
4799 NDR_record_t NDR;
4800 kern_return_t RetCode;
4801 mach_msg_type_number_t host_info_outCnt;
4802 integer_t host_info_out[14];
4803 } Reply;
4804 #pragma pack()
4805
4806 Reply *reply = (Reply *)ARG1;
4807
4808 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
4809 }
4810
PRE(host_info)4811 PRE(host_info)
4812 {
4813 #pragma pack(4)
4814 typedef struct {
4815 mach_msg_header_t Head;
4816 NDR_record_t NDR;
4817 host_flavor_t flavor;
4818 mach_msg_type_number_t host_info_outCnt;
4819 } Request;
4820 #pragma pack()
4821
4822 Request *req = (Request *)ARG1;
4823
4824 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor);
4825
4826 AFTER = POST_FN(host_info);
4827 }
4828
4829
POST(host_page_size)4830 POST(host_page_size)
4831 {
4832 #pragma pack(4)
4833 typedef struct {
4834 mach_msg_header_t Head;
4835 NDR_record_t NDR;
4836 kern_return_t RetCode;
4837 vm_size_t out_page_size;
4838 } Reply;
4839 #pragma pack()
4840
4841 Reply *reply = (Reply *)ARG1;
4842
4843 if (!reply->RetCode) {
4844 PRINT("page size %llu", (ULong)reply->out_page_size);
4845 } else {
4846 PRINT("mig return %d", reply->RetCode);
4847 }
4848 }
4849
PRE(host_page_size)4850 PRE(host_page_size)
4851 {
4852 PRINT("host_page_size(mach_host_self(), ...)");
4853
4854 AFTER = POST_FN(host_page_size);
4855 }
4856
4857
POST(host_get_io_master)4858 POST(host_get_io_master)
4859 {
4860 #pragma pack(4)
4861 typedef struct {
4862 mach_msg_header_t Head;
4863 /* start of the kernel processed data */
4864 mach_msg_body_t msgh_body;
4865 mach_msg_port_descriptor_t io_master;
4866 /* end of the kernel processed data */
4867 } Reply;
4868 #pragma pack()
4869
4870 Reply *reply = (Reply *)ARG1;
4871
4872 assign_port_name(reply->io_master.name, "io_master-%p");
4873 PRINT("%s", name_for_port(reply->io_master.name));
4874 }
4875
PRE(host_get_io_master)4876 PRE(host_get_io_master)
4877 {
4878 #pragma pack(4)
4879 typedef struct {
4880 mach_msg_header_t Head;
4881 } Request;
4882 #pragma pack()
4883
4884 // Request *req = (Request *)ARG1;
4885
4886 PRINT("host_get_io_master(mach_host_self())");
4887
4888 AFTER = POST_FN(host_get_io_master);
4889 }
4890
4891
POST(host_get_clock_service)4892 POST(host_get_clock_service)
4893 {
4894 #pragma pack(4)
4895 typedef struct {
4896 mach_msg_header_t Head;
4897 /* start of the kernel processed data */
4898 mach_msg_body_t msgh_body;
4899 mach_msg_port_descriptor_t clock_serv;
4900 /* end of the kernel processed data */
4901 } Reply;
4902 #pragma pack()
4903
4904 Reply *reply = (Reply *)ARG1;
4905
4906 assign_port_name(reply->clock_serv.name, "clock-%p");
4907 PRINT("%s", name_for_port(reply->clock_serv.name));
4908 }
4909
PRE(host_get_clock_service)4910 PRE(host_get_clock_service)
4911 {
4912 #pragma pack(4)
4913 typedef struct {
4914 mach_msg_header_t Head;
4915 NDR_record_t NDR;
4916 clock_id_t clock_id;
4917 } Request;
4918 #pragma pack()
4919
4920 Request *req = (Request *)ARG1;
4921
4922 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id);
4923
4924 AFTER = POST_FN(host_get_clock_service);
4925 }
4926
4927
PRE(host_request_notification)4928 PRE(host_request_notification)
4929 {
4930 #pragma pack(4)
4931 typedef struct {
4932 mach_msg_header_t Head;
4933 /* start of the kernel processed data */
4934 mach_msg_body_t msgh_body;
4935 mach_msg_port_descriptor_t notify_port;
4936 /* end of the kernel processed data */
4937 NDR_record_t NDR;
4938 host_flavor_t notify_type;
4939 } Request;
4940 #pragma pack()
4941
4942 Request *req = (Request *)ARG1;
4943
4944 if (MACH_REMOTE == mach_task_self()) {
4945 if (req->notify_type == 0) {
4946 PRINT("host_request_notification(mach_host_self(), %s, %s)",
4947 "HOST_NOTIFY_CALENDAR_CHANGE",
4948 name_for_port(req->notify_port.name));
4949 } else {
4950 PRINT("host_request_notification(mach_host_self(), %d, %s)",
4951 req->notify_type,
4952 name_for_port(req->notify_port.name));
4953 }
4954 } else {
4955 PRINT("host_request_notification(%s, %d, %s)",
4956 name_for_port(MACH_REMOTE),
4957 req->notify_type,
4958 name_for_port(req->notify_port.name));
4959 }
4960
4961 // GrP fixme only do this on success
4962 assign_port_name(req->notify_port.name, "host_notify-%p");
4963 }
4964
4965
4966 /* ---------------------------------------------------------------------
4967 mach_msg: messages to a task
4968 ------------------------------------------------------------------ */
4969
4970 // JRS 2011-Aug-25: just guessing here. I have no clear idea how
4971 // these structs are derived. They obviously relate to the various
4972 // .def files in the xnu sources, and can also be found in some
4973 // form in /usr/include/mach/*.h, but not sure how these all
4974 // relate to each other.
4975
PRE(mach_port_set_context)4976 PRE(mach_port_set_context)
4977 {
4978 #pragma pack(4)
4979 typedef struct {
4980 mach_msg_header_t Head;
4981 NDR_record_t NDR;
4982 mach_port_name_t name;
4983 mach_vm_address_t context;
4984 } Request;
4985 #pragma pack()
4986
4987 Request *req = (Request *)ARG1;
4988
4989 PRINT("mach_port_set_context(%s, %s, 0x%llx)",
4990 name_for_port(MACH_REMOTE),
4991 name_for_port(req->name), req->context);
4992
4993 AFTER = POST_FN(mach_port_set_context);
4994 }
4995
POST(mach_port_set_context)4996 POST(mach_port_set_context)
4997 {
4998 #pragma pack(4)
4999 typedef struct {
5000 mach_msg_header_t Head;
5001 NDR_record_t NDR;
5002 kern_return_t RetCode;
5003 } Reply;
5004 #pragma pack()
5005 }
5006
5007
5008 // JRS 2011-Aug-25 FIXME completely bogus
PRE(task_get_exception_ports)5009 PRE(task_get_exception_ports)
5010 {
5011 #pragma pack(4)
5012 typedef struct {
5013 mach_msg_header_t Head;
5014 NDR_record_t NDR;
5015 exception_mask_t exception_mask;
5016 } Request;
5017 #pragma pack()
5018
5019 PRINT("task_get_exception_ports(BOGUS)");
5020 AFTER = POST_FN(task_get_exception_ports);
5021 }
5022
POST(task_get_exception_ports)5023 POST(task_get_exception_ports)
5024 {
5025 #pragma pack(4)
5026 typedef struct {
5027 mach_msg_header_t Head;
5028 /* start of the kernel processed data */
5029 mach_msg_body_t msgh_body;
5030 mach_msg_port_descriptor_t old_handlers[32];
5031 /* end of the kernel processed data */
5032 NDR_record_t NDR;
5033 mach_msg_type_number_t masksCnt;
5034 exception_mask_t masks[32];
5035 exception_behavior_t old_behaviors[32];
5036 thread_state_flavor_t old_flavors[32];
5037 } Reply;
5038 #pragma pack()
5039 }
5040
5041
5042 ///////////////////////////////////////////////////
5043
PRE(mach_port_type)5044 PRE(mach_port_type)
5045 {
5046 #pragma pack(4)
5047 typedef struct {
5048 mach_msg_header_t Head;
5049 NDR_record_t NDR;
5050 mach_port_name_t name;
5051 } Request;
5052 #pragma pack()
5053
5054 Request *req = (Request *)ARG1;
5055
5056 PRINT("mach_port_type(%s, %s, ...)",
5057 name_for_port(MACH_REMOTE), name_for_port(req->name));
5058
5059 AFTER = POST_FN(mach_port_type);
5060 }
5061
POST(mach_port_type)5062 POST(mach_port_type)
5063 {
5064 }
5065
5066
PRE(mach_port_extract_member)5067 PRE(mach_port_extract_member)
5068 {
5069 #pragma pack(4)
5070 typedef struct {
5071 mach_msg_header_t Head;
5072 NDR_record_t NDR;
5073 mach_port_name_t name;
5074 mach_port_name_t pset;
5075 } Request;
5076 #pragma pack()
5077
5078 Request *req = (Request *)ARG1;
5079
5080 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)",
5081 name_for_port(MACH_REMOTE),
5082 req->name, req->pset);
5083
5084 AFTER = POST_FN(mach_port_extract_member);
5085
5086 // GrP fixme port tracker?
5087 }
5088
POST(mach_port_extract_member)5089 POST(mach_port_extract_member)
5090 {
5091 #pragma pack(4)
5092 typedef struct {
5093 mach_msg_header_t Head;
5094 NDR_record_t NDR;
5095 kern_return_t RetCode;
5096 } Reply;
5097 #pragma pack()
5098
5099 Reply *reply = (Reply *)ARG1;
5100
5101 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
5102 }
5103
5104
PRE(mach_port_allocate)5105 PRE(mach_port_allocate)
5106 {
5107 #pragma pack(4)
5108 typedef struct {
5109 mach_msg_header_t Head;
5110 NDR_record_t NDR;
5111 mach_port_right_t right;
5112 } Request;
5113 #pragma pack()
5114
5115 Request *req = (Request *)ARG1;
5116
5117 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right);
5118
5119 MACH_ARG(mach_port_allocate.right) = req->right;
5120
5121 AFTER = POST_FN(mach_port_allocate);
5122 }
5123
POST(mach_port_allocate)5124 POST(mach_port_allocate)
5125 {
5126 #pragma pack(4)
5127 typedef struct {
5128 mach_msg_header_t Head;
5129 NDR_record_t NDR;
5130 kern_return_t RetCode;
5131 mach_port_name_t name;
5132 } Reply;
5133 #pragma pack()
5134
5135 Reply *reply = (Reply *)ARG1;
5136
5137 if (!reply->RetCode) {
5138 if (MACH_REMOTE == vg_task_port) {
5139 // GrP fixme port tracking is too imprecise
5140 // vg_assert(!port_exists(reply->name));
5141 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right));
5142 PRINT("got port 0x%x", reply->name);
5143 } else {
5144 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name);
5145 }
5146 } else {
5147 PRINT("mig return %d", reply->RetCode);
5148 }
5149 }
5150
5151
PRE(mach_port_deallocate)5152 PRE(mach_port_deallocate)
5153 {
5154 #pragma pack(4)
5155 typedef struct {
5156 mach_msg_header_t Head;
5157 NDR_record_t NDR;
5158 mach_port_name_t name;
5159 } Request;
5160 #pragma pack()
5161
5162 Request *req = (Request *)ARG1;
5163
5164 PRINT("mach_port_deallocate(%s, %s)",
5165 name_for_port(MACH_REMOTE),
5166 name_for_port(req->name));
5167
5168 MACH_ARG(mach_port.port) = req->name;
5169
5170 AFTER = POST_FN(mach_port_deallocate);
5171
5172 // Must block to prevent race (other thread allocates and
5173 // notifies after we deallocate but before we notify)
5174 *flags &= ~SfMayBlock;
5175 }
5176
POST(mach_port_deallocate)5177 POST(mach_port_deallocate)
5178 {
5179 #pragma pack(4)
5180 typedef struct {
5181 mach_msg_header_t Head;
5182 NDR_record_t NDR;
5183 kern_return_t RetCode;
5184 } Reply;
5185 #pragma pack()
5186
5187 Reply *reply = (Reply *)ARG1;
5188
5189 if (!reply->RetCode) {
5190 if (MACH_REMOTE == vg_task_port) {
5191 // Must have cleared SfMayBlock in PRE to prevent race
5192 record_port_dealloc(MACH_ARG(mach_port.port));
5193 } else {
5194 VG_(printf)("UNKNOWN remote port dealloc\n");
5195 }
5196 } else {
5197 PRINT("mig return %d", reply->RetCode);
5198 }
5199 }
5200
5201
PRE(mach_port_get_refs)5202 PRE(mach_port_get_refs)
5203 {
5204 #pragma pack(4)
5205 typedef struct {
5206 mach_msg_header_t Head;
5207 NDR_record_t NDR;
5208 mach_port_name_t name;
5209 mach_port_right_t right;
5210 } Request;
5211 #pragma pack()
5212
5213 Request *req = (Request *)ARG1;
5214
5215 PRINT("mach_port_get_refs(%s, %s, 0x%x)",
5216 name_for_port(MACH_REMOTE),
5217 name_for_port(req->name), req->right);
5218
5219 MACH_ARG(mach_port_mod_refs.port) = req->name;
5220 MACH_ARG(mach_port_mod_refs.right) = req->right;
5221
5222 AFTER = POST_FN(mach_port_get_refs);
5223 }
5224
POST(mach_port_get_refs)5225 POST(mach_port_get_refs)
5226 {
5227 #pragma pack(4)
5228 typedef struct {
5229 mach_msg_header_t Head;
5230 NDR_record_t NDR;
5231 kern_return_t RetCode;
5232 mach_port_urefs_t refs;
5233 } Reply;
5234 #pragma pack()
5235
5236 Reply *reply = (Reply *)ARG1;
5237
5238 if (!reply->RetCode) {
5239 PRINT("got refs=%d", reply->refs);
5240 } else {
5241 PRINT("mig return %d", reply->RetCode);
5242 }
5243 }
5244
5245
PRE(mach_port_mod_refs)5246 PRE(mach_port_mod_refs)
5247 {
5248 #pragma pack(4)
5249 typedef struct {
5250 mach_msg_header_t Head;
5251 NDR_record_t NDR;
5252 mach_port_name_t name;
5253 mach_port_right_t right;
5254 mach_port_delta_t delta;
5255 } Request;
5256 #pragma pack()
5257
5258 Request *req = (Request *)ARG1;
5259
5260 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)",
5261 name_for_port(MACH_REMOTE),
5262 name_for_port(req->name), req->right, req->delta);
5263
5264 MACH_ARG(mach_port_mod_refs.port) = req->name;
5265 MACH_ARG(mach_port_mod_refs.right) = req->right;
5266 MACH_ARG(mach_port_mod_refs.delta) = req->delta;
5267
5268 AFTER = POST_FN(mach_port_mod_refs);
5269
5270 // Must block to prevent race (other thread allocates and
5271 // notifies after we deallocate but before we notify)
5272 *flags &= ~SfMayBlock;
5273 }
5274
POST(mach_port_mod_refs)5275 POST(mach_port_mod_refs)
5276 {
5277 #pragma pack(4)
5278 typedef struct {
5279 mach_msg_header_t Head;
5280 NDR_record_t NDR;
5281 kern_return_t RetCode;
5282 } Reply;
5283 #pragma pack()
5284
5285 Reply *reply = (Reply *)ARG1;
5286
5287 if (!reply->RetCode) {
5288 if (MACH_REMOTE == vg_task_port) {
5289 // Must have cleared SfMayBlock in PRE to prevent race
5290 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port),
5291 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)),
5292 MACH_ARG(mach_port_mod_refs.delta));
5293 } else {
5294 VG_(printf)("UNKNOWN remote port mod refs\n");
5295 }
5296 } else {
5297 PRINT("mig return %d", reply->RetCode);
5298 }
5299 }
5300
5301
PRE(mach_port_get_set_status)5302 PRE(mach_port_get_set_status)
5303 {
5304 #pragma pack(4)
5305 typedef struct {
5306 mach_msg_header_t Head;
5307 NDR_record_t NDR;
5308 mach_port_name_t name;
5309 } Request;
5310 #pragma pack()
5311
5312 Request *req = (Request *)ARG1;
5313
5314 PRINT("mach_port_get_set_status(%s, %s)",
5315 name_for_port(MACH_REMOTE),
5316 name_for_port(req->name));
5317
5318 AFTER = POST_FN(mach_port_get_set_status);
5319 }
5320
POST(mach_port_get_set_status)5321 POST(mach_port_get_set_status)
5322 {
5323 #pragma pack(4)
5324 typedef struct {
5325 mach_msg_header_t Head;
5326 /* start of the kernel processed data */
5327 mach_msg_body_t msgh_body;
5328 mach_msg_ool_descriptor_t members;
5329 /* end of the kernel processed data */
5330 NDR_record_t NDR;
5331 mach_msg_type_number_t membersCnt;
5332 mach_msg_trailer_t trailer;
5333 } Reply;
5334 #pragma pack()
5335
5336 // Reply *reply = (Reply *)ARG1;
5337
5338 // GrP fixme nothing to do?
5339 }
5340
5341
PRE(mach_port_move_member)5342 PRE(mach_port_move_member)
5343 {
5344 #pragma pack(4)
5345 typedef struct {
5346 mach_msg_header_t Head;
5347 NDR_record_t NDR;
5348 mach_port_name_t member;
5349 mach_port_name_t after;
5350 } Request;
5351 #pragma pack()
5352
5353 Request *req = (Request *)ARG1;
5354
5355 PRINT("mach_port_move_member(%s, %s, %s)",
5356 name_for_port(MACH_REMOTE),
5357 name_for_port(req->member),
5358 name_for_port(req->after));
5359 /*
5360 MACH_ARG(mach_port_move_member.member) = req->member;
5361 MACH_ARG(mach_port_move_member.after) = req->after;
5362 */
5363 AFTER = POST_FN(mach_port_move_member);
5364 }
5365
POST(mach_port_move_member)5366 POST(mach_port_move_member)
5367 {
5368 #pragma pack(4)
5369 typedef struct {
5370 mach_msg_header_t Head;
5371 NDR_record_t NDR;
5372 kern_return_t RetCode;
5373 mach_msg_trailer_t trailer;
5374 } Reply;
5375 #pragma pack()
5376
5377 Reply *reply = (Reply *)ARG1;
5378
5379 if (!reply->RetCode) {
5380 // fixme port set tracker?
5381 } else {
5382 PRINT("mig return %d", reply->RetCode);
5383 }
5384 }
5385
5386
PRE(mach_port_destroy)5387 PRE(mach_port_destroy)
5388 {
5389 #pragma pack(4)
5390 typedef struct {
5391 mach_msg_header_t Head;
5392 NDR_record_t NDR;
5393 mach_port_name_t name;
5394 } Request;
5395 #pragma pack()
5396
5397 Request *req = (Request *)ARG1;
5398
5399 PRINT("mach_port_destroy(%s, %s)",
5400 name_for_port(MACH_REMOTE),
5401 name_for_port(req->name));
5402
5403 MACH_ARG(mach_port.port) = req->name;
5404
5405 AFTER = POST_FN(mach_port_destroy);
5406
5407 // Must block to prevent race (other thread allocates and
5408 // notifies after we deallocate but before we notify)
5409 *flags &= ~SfMayBlock;
5410 }
5411
POST(mach_port_destroy)5412 POST(mach_port_destroy)
5413 {
5414 #pragma pack(4)
5415 typedef struct {
5416 mach_msg_header_t Head;
5417 NDR_record_t NDR;
5418 kern_return_t RetCode;
5419 } Reply;
5420 #pragma pack()
5421
5422 Reply *reply = (Reply *)ARG1;
5423
5424 if (!reply->RetCode) {
5425 if (MACH_REMOTE == vg_task_port) {
5426 // Must have cleared SfMayBlock in PRE to prevent race
5427 record_port_destroy(MACH_ARG(mach_port.port));
5428 } else {
5429 VG_(printf)("UNKNOWN remote port destroy\n");
5430 }
5431 } else {
5432 PRINT("mig return %d", reply->RetCode);
5433 }
5434 }
5435
5436
PRE(mach_port_request_notification)5437 PRE(mach_port_request_notification)
5438 {
5439 #pragma pack(4)
5440 typedef struct {
5441 mach_msg_header_t Head;
5442 /* start of the kernel processed data */
5443 mach_msg_body_t msgh_body;
5444 mach_msg_port_descriptor_t notify;
5445 /* end of the kernel processed data */
5446 NDR_record_t NDR;
5447 mach_port_name_t name;
5448 mach_msg_id_t msgid;
5449 mach_port_mscount_t sync;
5450 } Request;
5451 #pragma pack()
5452
5453 Request *req = (Request *)ARG1;
5454
5455 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)",
5456 name_for_port(MACH_REMOTE),
5457 name_for_port(req->name), req->msgid, req->sync,
5458 req->notify.name, req->notify.disposition);
5459
5460 AFTER = POST_FN(mach_port_request_notification);
5461 }
5462
POST(mach_port_request_notification)5463 POST(mach_port_request_notification)
5464 {
5465 // GrP fixme port tracker? not sure
5466 }
5467
5468
PRE(mach_port_insert_right)5469 PRE(mach_port_insert_right)
5470 {
5471 #pragma pack(4)
5472 typedef struct {
5473 mach_msg_header_t Head;
5474 /* start of the kernel processed data */
5475 mach_msg_body_t msgh_body;
5476 mach_msg_port_descriptor_t poly;
5477 /* end of the kernel processed data */
5478 NDR_record_t NDR;
5479 mach_port_name_t name;
5480 } Request;
5481 #pragma pack()
5482
5483 Request *req = (Request *)ARG1;
5484
5485 PRINT("mach_port_insert_right(%s, %s, %d, %d)",
5486 name_for_port(MACH_REMOTE),
5487 name_for_port(req->name), req->poly.name, req->poly.disposition);
5488
5489 AFTER = POST_FN(mach_port_insert_right);
5490
5491 if (MACH_REMOTE == mach_task_self()) {
5492 // GrP fixme import_complex_message handles everything?
5493 // what about export_complex_message for MOVE variants?
5494 } else {
5495 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n");
5496 // GrP fixme also may remove rights from this task?
5497 }
5498
5499 // GrP fixme port tracker?
5500 }
5501
POST(mach_port_insert_right)5502 POST(mach_port_insert_right)
5503 {
5504 }
5505
5506
PRE(mach_port_extract_right)5507 PRE(mach_port_extract_right)
5508 {
5509 #pragma pack(4)
5510 typedef struct {
5511 mach_msg_header_t Head;
5512 NDR_record_t NDR;
5513 mach_port_name_t name;
5514 mach_msg_type_name_t msgt_name;
5515 } Request;
5516 #pragma pack()
5517
5518 Request *req = (Request *)ARG1;
5519
5520 PRINT("mach_port_extract_right(%s, %s, %d)",
5521 name_for_port(MACH_REMOTE),
5522 name_for_port(req->name), req->msgt_name);
5523
5524 AFTER = POST_FN(mach_port_extract_right);
5525
5526 // fixme port tracker?
5527 }
5528
POST(mach_port_extract_right)5529 POST(mach_port_extract_right)
5530 {
5531 // fixme import_complex_message handles the returned result, right?
5532 }
5533
5534
PRE(mach_port_get_attributes)5535 PRE(mach_port_get_attributes)
5536 {
5537 #pragma pack(4)
5538 typedef struct {
5539 mach_msg_header_t Head;
5540 NDR_record_t NDR;
5541 mach_port_name_t name;
5542 mach_port_flavor_t flavor;
5543 mach_msg_type_number_t port_info_outCnt;
5544 } Request;
5545 #pragma pack()
5546
5547 Request *req = (Request *)ARG1;
5548
5549 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)",
5550 name_for_port(MACH_REMOTE),
5551 name_for_port(req->name), req->flavor, req->port_info_outCnt);
5552
5553 AFTER = POST_FN(mach_port_get_attributes);
5554 }
5555
POST(mach_port_get_attributes)5556 POST(mach_port_get_attributes)
5557 {
5558 }
5559
5560
PRE(mach_port_set_attributes)5561 PRE(mach_port_set_attributes)
5562 {
5563 #pragma pack(4)
5564 typedef struct {
5565 mach_msg_header_t Head;
5566 NDR_record_t NDR;
5567 mach_port_name_t name;
5568 mach_port_flavor_t flavor;
5569 mach_msg_type_number_t port_infoCnt;
5570 integer_t port_info[10];
5571 } Request;
5572 #pragma pack()
5573
5574 Request *req = (Request *)ARG1;
5575
5576 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)",
5577 name_for_port(MACH_REMOTE),
5578 name_for_port(req->name), req->flavor, req->port_infoCnt);
5579
5580 AFTER = POST_FN(mach_port_set_attributes);
5581 }
5582
POST(mach_port_set_attributes)5583 POST(mach_port_set_attributes)
5584 {
5585 }
5586
5587
PRE(mach_port_insert_member)5588 PRE(mach_port_insert_member)
5589 {
5590 #pragma pack(4)
5591 typedef struct {
5592 mach_msg_header_t Head;
5593 NDR_record_t NDR;
5594 mach_port_name_t name;
5595 mach_port_name_t pset;
5596 } Request;
5597 #pragma pack()
5598
5599 Request *req = (Request *)ARG1;
5600
5601 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)",
5602 name_for_port(MACH_REMOTE), req->name, req->pset);
5603
5604 AFTER = POST_FN(mach_port_insert_member);
5605
5606 // GrP fixme port tracker?
5607 }
5608
POST(mach_port_insert_member)5609 POST(mach_port_insert_member)
5610 {
5611 }
5612
5613
PRE(task_get_special_port)5614 PRE(task_get_special_port)
5615 {
5616 #pragma pack(4)
5617 typedef struct {
5618 mach_msg_header_t Head;
5619 NDR_record_t NDR;
5620 int which_port;
5621 } Request;
5622 #pragma pack()
5623
5624 Request *req = (Request *)ARG1;
5625
5626 switch (req->which_port) {
5627 case TASK_KERNEL_PORT:
5628 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)",
5629 name_for_port(MACH_REMOTE));
5630 break;
5631 case TASK_HOST_PORT:
5632 PRINT("task_get_special_port(%s, TASK_HOST_PORT)",
5633 name_for_port(MACH_REMOTE));
5634 break;
5635 case TASK_BOOTSTRAP_PORT:
5636 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)",
5637 name_for_port(MACH_REMOTE));
5638 break;
5639 #if DARWIN_VERS < DARWIN_10_8
5640 /* These disappeared in 10.8 */
5641 case TASK_WIRED_LEDGER_PORT:
5642 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)",
5643 name_for_port(MACH_REMOTE));
5644 break;
5645 case TASK_PAGED_LEDGER_PORT:
5646 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)",
5647 name_for_port(MACH_REMOTE));
5648 break;
5649 #endif
5650 default:
5651 PRINT("task_get_special_port(%s, %d)",
5652 name_for_port(MACH_REMOTE), req->which_port);
5653 break;
5654 }
5655
5656 MACH_ARG(task_get_special_port.which_port) = req->which_port;
5657
5658 AFTER = POST_FN(task_get_special_port);
5659 }
5660
POST(task_get_special_port)5661 POST(task_get_special_port)
5662 {
5663 #pragma pack(4)
5664 typedef struct {
5665 mach_msg_header_t Head;
5666 /* start of the kernel processed data */
5667 mach_msg_body_t msgh_body;
5668 mach_msg_port_descriptor_t special_port;
5669 /* end of the kernel processed data */
5670 } Reply;
5671 #pragma pack()
5672
5673 Reply *reply = (Reply *)ARG1;
5674
5675 PRINT("got port %#x ", reply->special_port.name);
5676
5677 switch (MACH_ARG(task_get_special_port.which_port)) {
5678 case TASK_BOOTSTRAP_PORT:
5679 vg_bootstrap_port = reply->special_port.name;
5680 assign_port_name(reply->special_port.name, "bootstrap");
5681 break;
5682 case TASK_KERNEL_PORT:
5683 assign_port_name(reply->special_port.name, "kernel");
5684 break;
5685 case TASK_HOST_PORT:
5686 assign_port_name(reply->special_port.name, "host");
5687 break;
5688 #if DARWIN_VERS < DARWIN_10_8
5689 /* These disappeared in 10.8 */
5690 case TASK_WIRED_LEDGER_PORT:
5691 assign_port_name(reply->special_port.name, "wired-ledger");
5692 break;
5693 case TASK_PAGED_LEDGER_PORT:
5694 assign_port_name(reply->special_port.name, "paged-ledger");
5695 break;
5696 #endif
5697 default:
5698 assign_port_name(reply->special_port.name, "special-%p");
5699 break;
5700 }
5701
5702 PRINT("%s", name_for_port(reply->special_port.name));
5703 }
5704
5705
PRE(semaphore_create)5706 PRE(semaphore_create)
5707 {
5708 #pragma pack(4)
5709 typedef struct {
5710 mach_msg_header_t Head;
5711 NDR_record_t NDR;
5712 int policy;
5713 int value;
5714 } Request;
5715 #pragma pack()
5716
5717 Request *req = (Request *)ARG1;
5718
5719 PRINT("semaphore_create(%s, ..., %d, %d)",
5720 name_for_port(MACH_REMOTE), req->policy, req->value);
5721
5722 AFTER = POST_FN(semaphore_create);
5723 }
5724
POST(semaphore_create)5725 POST(semaphore_create)
5726 {
5727 #pragma pack(4)
5728 typedef struct {
5729 mach_msg_header_t Head;
5730 /* start of the kernel processed data */
5731 mach_msg_body_t msgh_body;
5732 mach_msg_port_descriptor_t semaphore;
5733 /* end of the kernel processed data */
5734 mach_msg_trailer_t trailer;
5735 } Reply;
5736 #pragma pack()
5737
5738 Reply *reply = (Reply *)ARG1;
5739
5740 assign_port_name(reply->semaphore.name, "semaphore-%p");
5741 PRINT("%s", name_for_port(reply->semaphore.name));
5742 }
5743
5744
PRE(semaphore_destroy)5745 PRE(semaphore_destroy)
5746 {
5747 #pragma pack(4)
5748 typedef struct {
5749 mach_msg_header_t Head;
5750 /* start of the kernel processed data */
5751 mach_msg_body_t msgh_body;
5752 mach_msg_port_descriptor_t semaphore;
5753 /* end of the kernel processed data */
5754 mach_msg_trailer_t trailer;
5755 } Request;
5756 #pragma pack()
5757
5758 Request *req = (Request *)ARG1;
5759
5760 PRINT("semaphore_destroy(%s, %s)",
5761 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name));
5762
5763 record_port_destroy(req->semaphore.name);
5764
5765 AFTER = POST_FN(semaphore_destroy);
5766 }
5767
POST(semaphore_destroy)5768 POST(semaphore_destroy)
5769 {
5770 #pragma pack(4)
5771 typedef struct {
5772 mach_msg_header_t Head;
5773 NDR_record_t NDR;
5774 kern_return_t RetCode;
5775 mach_msg_trailer_t trailer;
5776 } Reply;
5777 #pragma pack()
5778
5779 Reply *reply = (Reply *)ARG1;
5780 if (!reply->RetCode) {
5781 } else {
5782 PRINT("mig return %d", reply->RetCode);
5783 }
5784 }
5785
PRE(task_policy_set)5786 PRE(task_policy_set)
5787 {
5788 #pragma pack(4)
5789 typedef struct {
5790 mach_msg_header_t Head;
5791 NDR_record_t NDR;
5792 task_policy_flavor_t flavor;
5793 mach_msg_type_number_t policy_infoCnt;
5794 integer_t policy_info[16];
5795 } Request;
5796 #pragma pack()
5797
5798 Request *req = (Request *)ARG1;
5799
5800 PRINT("task_policy_set(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
5801
5802 AFTER = POST_FN(task_policy_set);
5803 }
5804
POST(task_policy_set)5805 POST(task_policy_set)
5806 {
5807 #pragma pack(4)
5808 typedef struct {
5809 mach_msg_header_t Head;
5810 NDR_record_t NDR;
5811 kern_return_t RetCode;
5812 } Reply;
5813 #pragma pack()
5814
5815 Reply *reply = (Reply *)ARG1;
5816 if (!reply->RetCode) {
5817 } else {
5818 PRINT("mig return %d", reply->RetCode);
5819 }
5820 }
5821
5822
PRE(mach_ports_register)5823 PRE(mach_ports_register)
5824 {
5825 #pragma pack(4)
5826 typedef struct {
5827 mach_msg_header_t Head;
5828 /* start of the kernel processed data */
5829 mach_msg_body_t msgh_body;
5830 mach_msg_ool_ports_descriptor_t init_port_set;
5831 /* end of the kernel processed data */
5832 NDR_record_t NDR;
5833 mach_msg_type_number_t init_port_setCnt;
5834 } Request;
5835 #pragma pack()
5836
5837 // Request *req = (Request *)ARG1;
5838
5839 PRINT("mach_ports_register(%s)", name_for_port(MACH_REMOTE));
5840
5841 AFTER = POST_FN(mach_ports_register);
5842 }
5843
POST(mach_ports_register)5844 POST(mach_ports_register)
5845 {
5846 #pragma pack(4)
5847 typedef struct {
5848 mach_msg_header_t Head;
5849 NDR_record_t NDR;
5850 kern_return_t RetCode;
5851 } Reply;
5852 #pragma pack()
5853
5854 Reply *reply = (Reply *)ARG1;
5855 if (!reply->RetCode) {
5856 } else {
5857 PRINT("mig return %d", reply->RetCode);
5858 }
5859 }
5860
5861
PRE(mach_ports_lookup)5862 PRE(mach_ports_lookup)
5863 {
5864 #pragma pack(4)
5865 typedef struct {
5866 mach_msg_header_t Head;
5867 } Request;
5868 #pragma pack()
5869
5870 // Request *req = (Request *)ARG1;
5871
5872 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE));
5873
5874 AFTER = POST_FN(mach_ports_lookup);
5875 }
5876
POST(mach_ports_lookup)5877 POST(mach_ports_lookup)
5878 {
5879 #pragma pack(4)
5880 typedef struct {
5881 mach_msg_header_t Head;
5882 /* start of the kernel processed data */
5883 mach_msg_body_t msgh_body;
5884 mach_msg_ool_ports_descriptor_t init_port_set;
5885 /* end of the kernel processed data */
5886 NDR_record_t NDR;
5887 mach_msg_type_number_t init_port_setCnt;
5888 } Reply;
5889 #pragma pack()
5890
5891 // Reply *reply = (Reply *)ARG1;
5892 }
5893
5894
PRE(task_info)5895 PRE(task_info)
5896 {
5897 #pragma pack(4)
5898 typedef struct {
5899 mach_msg_header_t Head;
5900 NDR_record_t NDR;
5901 task_flavor_t flavor;
5902 mach_msg_type_number_t task_info_outCnt;
5903 } Request;
5904 #pragma pack()
5905
5906 Request *req = (Request *)ARG1;
5907
5908 PRINT("task_info(%s) flavor:%d", name_for_port(MACH_REMOTE), req->flavor);
5909
5910 AFTER = POST_FN(task_info);
5911 }
5912
POST(task_info)5913 POST(task_info)
5914 {
5915 #pragma pack(4)
5916 typedef struct {
5917 mach_msg_header_t Head;
5918 NDR_record_t NDR;
5919 kern_return_t RetCode;
5920 mach_msg_type_number_t task_info_outCnt;
5921 integer_t task_info_out[52];
5922 } Reply;
5923 #pragma pack()
5924
5925 Reply *reply = (Reply *)ARG1;
5926 if (!reply->RetCode) {
5927 } else {
5928 PRINT("mig return %d", reply->RetCode);
5929 }
5930 }
5931
5932
PRE(task_threads)5933 PRE(task_threads)
5934 {
5935 #pragma pack(4)
5936 typedef struct {
5937 mach_msg_header_t Head;
5938 } Request;
5939 #pragma pack()
5940
5941 // Request *req = (Request *)ARG1;
5942
5943 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE));
5944
5945 AFTER = POST_FN(task_threads);
5946 }
5947
POST(task_threads)5948 POST(task_threads)
5949 {
5950 #pragma pack(4)
5951 typedef struct {
5952 mach_msg_header_t Head;
5953 /* start of the kernel processed data */
5954 mach_msg_body_t msgh_body;
5955 mach_msg_ool_ports_descriptor_t act_list;
5956 /* end of the kernel processed data */
5957 NDR_record_t NDR;
5958 mach_msg_type_number_t act_listCnt;
5959 mach_msg_trailer_t trailer;
5960 } Reply;
5961 #pragma pack()
5962
5963 Reply *reply = (Reply *)ARG1;
5964
5965 if (MACH_REMOTE == vg_task_port) {
5966 assign_port_names(&reply->act_list, "thread-%p");
5967 } else {
5968 assign_port_names(&reply->act_list, "remote-thread-%p");
5969 }
5970 }
5971
5972
PRE(task_suspend)5973 PRE(task_suspend)
5974 {
5975 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE));
5976
5977 if (MACH_REMOTE == vg_task_port) {
5978 // GrP fixme self-suspend
5979 vg_assert(0);
5980 } else {
5981 // suspend other - no problem
5982 }
5983
5984 AFTER = POST_FN(task_suspend);
5985 }
5986
POST(task_suspend)5987 POST(task_suspend)
5988 {
5989 }
5990
5991
PRE(task_resume)5992 PRE(task_resume)
5993 {
5994 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE));
5995
5996 if (MACH_REMOTE == vg_task_port) {
5997 // GrP fixme self-resume
5998 vg_assert(0);
5999 } else {
6000 // resume other - no problem
6001 }
6002
6003 AFTER = POST_FN(task_resume);
6004 }
6005
POST(task_resume)6006 POST(task_resume)
6007 {
6008 }
6009
6010
PRE(vm_allocate)6011 PRE(vm_allocate)
6012 {
6013 #pragma pack(4)
6014 typedef struct {
6015 mach_msg_header_t Head;
6016 NDR_record_t NDR;
6017 vm_address_t address;
6018 vm_size_t size;
6019 int flags;
6020 } Request;
6021 #pragma pack()
6022
6023 Request *req = (Request *)ARG1;
6024
6025 PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)",
6026 name_for_port(MACH_REMOTE),
6027 (ULong)req->address, (ULong)req->size, req->flags);
6028
6029 MACH_ARG(vm_allocate.size) = req->size;
6030 MACH_ARG(vm_allocate.flags) = req->flags;
6031
6032 AFTER = POST_FN(vm_allocate);
6033 }
6034
POST(vm_allocate)6035 POST(vm_allocate)
6036 {
6037 #pragma pack(4)
6038 typedef struct {
6039 mach_msg_header_t Head;
6040 NDR_record_t NDR;
6041 kern_return_t RetCode;
6042 vm_address_t address;
6043 mach_msg_trailer_t trailer;
6044 } Reply;
6045 #pragma pack()
6046
6047 Reply *reply = (Reply *)ARG1;
6048
6049 if (!reply->RetCode) {
6050 if (MACH_REMOTE == vg_task_port) {
6051 PRINT("allocated at %#llx", (ULong)reply->address);
6052 // requesting 0 bytes returns address 0 with no error
6053 if (MACH_ARG(vm_allocate.size)) {
6054 ML_(notify_core_and_tool_of_mmap)(
6055 reply->address, MACH_ARG(vm_allocate.size),
6056 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6057 }
6058 } else {
6059 PRINT("allocated at %#llx in remote task %s",
6060 (ULong)reply->address,
6061 name_for_port(MACH_REMOTE));
6062 }
6063 } else {
6064 PRINT("mig return %d", reply->RetCode);
6065 }
6066 }
6067
6068
PRE(vm_deallocate)6069 PRE(vm_deallocate)
6070 {
6071 #pragma pack(4)
6072 typedef struct {
6073 mach_msg_header_t Head;
6074 NDR_record_t NDR;
6075 vm_address_t address;
6076 vm_size_t size;
6077 } Request;
6078 #pragma pack()
6079
6080 Request *req = (Request *)ARG1;
6081
6082 PRINT("vm_deallocate(%s, at %#llx, size %lld)",
6083 name_for_port(MACH_REMOTE),
6084 (ULong)req->address, (ULong)req->size);
6085
6086 MACH_ARG(vm_deallocate.address) = req->address;
6087 MACH_ARG(vm_deallocate.size) = req->size;
6088
6089 AFTER = POST_FN(vm_deallocate);
6090
6091 // Must block to prevent race (other thread allocates and
6092 // notifies after we deallocate but before we notify)
6093 *flags &= ~SfMayBlock;
6094 }
6095
POST(vm_deallocate)6096 POST(vm_deallocate)
6097 {
6098 #pragma pack(4)
6099 typedef struct {
6100 mach_msg_header_t Head;
6101 NDR_record_t NDR;
6102 kern_return_t RetCode;
6103 mach_msg_trailer_t trailer;
6104 } Reply;
6105 #pragma pack()
6106
6107 Reply *reply = (Reply *)ARG1;
6108
6109 if (!reply->RetCode) {
6110 if (MACH_REMOTE == vg_task_port) {
6111 if (MACH_ARG(vm_deallocate.size)) {
6112 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address));
6113 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) +
6114 MACH_ARG(vm_deallocate.size));
6115 // Must have cleared SfMayBlock in PRE to prevent race
6116 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6117 }
6118 }
6119 } else {
6120 PRINT("mig return %d", reply->RetCode);
6121 }
6122 }
6123
6124
PRE(vm_protect)6125 PRE(vm_protect)
6126 {
6127 #pragma pack(4)
6128 typedef struct {
6129 mach_msg_header_t Head;
6130 NDR_record_t NDR;
6131 vm_address_t address;
6132 vm_size_t size;
6133 boolean_t set_maximum;
6134 vm_prot_t new_protection;
6135 } Request;
6136 #pragma pack()
6137
6138 Request *req = (Request *)ARG1;
6139
6140 PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)",
6141 name_for_port(MACH_REMOTE),
6142 (ULong)req->address, (ULong)req->size,
6143 req->set_maximum, req->new_protection);
6144
6145 MACH_ARG(vm_protect.address) = req->address;
6146 MACH_ARG(vm_protect.size) = req->size;
6147 MACH_ARG(vm_protect.set_maximum) = req->set_maximum;
6148 MACH_ARG(vm_protect.new_protection) = req->new_protection;
6149
6150 AFTER = POST_FN(vm_protect);
6151 }
6152
POST(vm_protect)6153 POST(vm_protect)
6154 {
6155 #pragma pack(4)
6156 typedef struct {
6157 mach_msg_header_t Head;
6158 NDR_record_t NDR;
6159 kern_return_t RetCode;
6160 mach_msg_trailer_t trailer;
6161 } Reply;
6162 #pragma pack()
6163
6164 Reply *reply = (Reply *)ARG1;
6165
6166 if (!reply->RetCode) {
6167 if (MACH_REMOTE == vg_task_port) {
6168 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address));
6169 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) +
6170 MACH_ARG(vm_protect.size));
6171 UInt prot = MACH_ARG(vm_protect.new_protection);
6172 if (MACH_ARG(vm_protect.set_maximum)) {
6173 // GrP fixme mprotect max
6174 VG_(printf)("UNKNOWN vm_protect set maximum");
6175 //VG_(mprotect_max_range)(start, end-start, prot);
6176 } else {
6177 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6178 VG_(di_notify_vm_protect)(start, end-start, prot);
6179 }
6180 }
6181 } else {
6182 PRINT("mig return %d", reply->RetCode);
6183 }
6184 }
6185
6186
PRE(vm_inherit)6187 PRE(vm_inherit)
6188 {
6189 #pragma pack(4)
6190 typedef struct {
6191 mach_msg_header_t Head;
6192 NDR_record_t NDR;
6193 vm_address_t address;
6194 vm_size_t size;
6195 vm_inherit_t new_inheritance;
6196 } Request;
6197 #pragma pack()
6198
6199 Request *req = (Request *)ARG1;
6200
6201 PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)",
6202 name_for_port(MACH_REMOTE),
6203 (ULong)req->address, (ULong)req->size,
6204 req->new_inheritance);
6205
6206 AFTER = POST_FN(vm_inherit);
6207 }
6208
POST(vm_inherit)6209 POST(vm_inherit)
6210 {
6211 #pragma pack(4)
6212 typedef struct {
6213 mach_msg_header_t Head;
6214 NDR_record_t NDR;
6215 kern_return_t RetCode;
6216 mach_msg_trailer_t trailer;
6217 } Reply;
6218 #pragma pack()
6219
6220 Reply *reply = (Reply *)ARG1;
6221
6222 if (!reply->RetCode) {
6223 if (MACH_REMOTE == vg_task_port) {
6224 // GrP fixme do something?
6225 }
6226 } else {
6227 PRINT("mig return %d", reply->RetCode);
6228 }
6229 }
6230
6231
PRE(vm_read)6232 PRE(vm_read)
6233 {
6234 #pragma pack(4)
6235 typedef struct {
6236 mach_msg_header_t Head;
6237 NDR_record_t NDR;
6238 vm_address_t address;
6239 vm_size_t size;
6240 } Request;
6241 #pragma pack()
6242
6243 Request *req = (Request *)ARG1;
6244
6245 PRINT("vm_read(from %s at %#llx size %llu)",
6246 name_for_port(MACH_REMOTE),
6247 (ULong)req->address, (ULong)req->size);
6248
6249 MACH_ARG(vm_read.addr) = req->address;
6250 MACH_ARG(vm_read.size) = req->size;
6251
6252 AFTER = POST_FN(vm_read);
6253 }
6254
POST(vm_read)6255 POST(vm_read)
6256 {
6257 #pragma pack(4)
6258 typedef struct {
6259 mach_msg_header_t Head;
6260 /* start of the kernel processed data */
6261 mach_msg_body_t msgh_body;
6262 mach_msg_ool_descriptor_t data;
6263 /* end of the kernel processed data */
6264 NDR_record_t NDR;
6265 mach_msg_type_number_t dataCnt;
6266 } Reply;
6267 #pragma pack()
6268
6269 // Reply *reply = (Reply *)ARG1;
6270
6271 if (MACH_REMOTE == vg_task_port) {
6272 // vm_read from self
6273 // GrP fixme copy initialized state
6274 }
6275 }
6276
6277
6278
PRE(mach_vm_read)6279 PRE(mach_vm_read)
6280 {
6281 #pragma pack(4)
6282 typedef struct {
6283 mach_msg_header_t Head;
6284 NDR_record_t NDR;
6285 mach_vm_address_t address;
6286 mach_vm_size_t size;
6287 } Request;
6288 #pragma pack()
6289
6290 Request *req = (Request *)ARG1;
6291
6292 PRINT("mach_vm_read(from %s at 0x%llx size %llu)",
6293 name_for_port(MACH_REMOTE), req->address, req->size);
6294
6295 MACH_ARG(mach_vm_read.addr) = req->address;
6296 MACH_ARG(mach_vm_read.size) = req->size;
6297
6298 AFTER = POST_FN(mach_vm_read);
6299 }
6300
POST(mach_vm_read)6301 POST(mach_vm_read)
6302 {
6303 #pragma pack(4)
6304 typedef struct {
6305 mach_msg_header_t Head;
6306 /* start of the kernel processed data */
6307 mach_msg_body_t msgh_body;
6308 mach_msg_ool_descriptor_t data;
6309 /* end of the kernel processed data */
6310 NDR_record_t NDR;
6311 mach_msg_type_number_t dataCnt;
6312 } Reply;
6313 #pragma pack()
6314
6315 // Reply *reply = (Reply *)ARG1;
6316
6317 if (MACH_REMOTE == vg_task_port) {
6318 // vm_read from self
6319 // GrP fixme copy initialized state
6320 }
6321 }
6322
6323
PRE(vm_read_overwrite)6324 PRE(vm_read_overwrite)
6325 {
6326 #pragma pack(4)
6327 typedef struct {
6328 mach_msg_header_t Head;
6329 NDR_record_t NDR;
6330 vm_address_t address;
6331 vm_size_t size;
6332 vm_address_t data;
6333 } Request;
6334 #pragma pack()
6335
6336 Request *req = (Request *)ARG1;
6337
6338 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)",
6339 name_for_port(MACH_REMOTE),
6340 (ULong)req->address, (ULong)req->size, (ULong)req->data);
6341
6342 MACH_ARG(vm_read_overwrite.addr) = req->address;
6343 MACH_ARG(vm_read_overwrite.size) = req->size;
6344 MACH_ARG(vm_read_overwrite.data) = req->data;
6345
6346 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size);
6347
6348 AFTER = POST_FN(vm_read_overwrite);
6349 }
6350
POST(vm_read_overwrite)6351 POST(vm_read_overwrite)
6352 {
6353 #pragma pack(4)
6354 typedef struct {
6355 mach_msg_header_t Head;
6356 NDR_record_t NDR;
6357 kern_return_t RetCode;
6358 vm_size_t outsize;
6359 } Reply;
6360 #pragma pack()
6361
6362 Reply *reply = (Reply *)ARG1;
6363
6364 if (reply->RetCode) {
6365 PRINT("mig return %d", reply->RetCode);
6366 } else {
6367 PRINT("read %llu bytes", (unsigned long long)reply->outsize);
6368 if (MACH_REMOTE == vg_task_port) {
6369 // vm_read_overwrite from self
6370 // GrP fixme copy initialized state
6371 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6372 } else {
6373 // vm_read_overwrite from remote
6374 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize);
6375 }
6376 }
6377 }
6378
6379
PRE(vm_copy)6380 PRE(vm_copy)
6381 {
6382 #pragma pack(4)
6383 typedef struct {
6384 mach_msg_header_t Head;
6385 NDR_record_t NDR;
6386 vm_address_t source_address;
6387 vm_size_t size;
6388 vm_address_t dest_address;
6389 } Request;
6390 #pragma pack()
6391
6392 Request *req = (Request *)ARG1;
6393
6394 PRINT("vm_copy(%s, %#llx, %lld, %#llx)",
6395 name_for_port(MACH_REMOTE),
6396 (ULong)req->source_address,
6397 (ULong)req->size, (ULong)req->dest_address);
6398
6399 MACH_ARG(vm_copy.src) = req->source_address;
6400 MACH_ARG(vm_copy.dst) = req->dest_address;
6401 MACH_ARG(vm_copy.size) = req->size;
6402
6403 AFTER = POST_FN(vm_copy);
6404 }
6405
POST(vm_copy)6406 POST(vm_copy)
6407 {
6408 #pragma pack(4)
6409 typedef struct {
6410 mach_msg_header_t Head;
6411 NDR_record_t NDR;
6412 kern_return_t RetCode;
6413 mach_msg_trailer_t trailer;
6414 } Reply;
6415 #pragma pack()
6416
6417 Reply *reply = (Reply *)ARG1;
6418
6419 if (!reply->RetCode) {
6420 if (MACH_REMOTE == vg_task_port) {
6421 // GrP fixme set dst's initialization equal to src's
6422 // and wipe any symbols or translations in dst
6423 }
6424 } else {
6425 PRINT("mig return %d", reply->RetCode);
6426 }
6427 }
6428
6429
PRE(vm_map)6430 PRE(vm_map)
6431 {
6432 #pragma pack(4)
6433 typedef struct {
6434 mach_msg_header_t Head;
6435 /* start of the kernel processed data */
6436 mach_msg_body_t msgh_body;
6437 mach_msg_port_descriptor_t object;
6438 /* end of the kernel processed data */
6439 NDR_record_t NDR;
6440 vm_address_t address;
6441 vm_size_t size;
6442 vm_address_t mask;
6443 int flags;
6444 vm_offset_t offset;
6445 boolean_t copy;
6446 vm_prot_t cur_protection;
6447 vm_prot_t max_protection;
6448 vm_inherit_t inheritance;
6449 } Request;
6450 #pragma pack()
6451
6452 Request *req = (Request *)ARG1;
6453
6454 // GrP fixme check these
6455 PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)",
6456 name_for_port(MACH_REMOTE),
6457 (ULong)req->address, (ULong)req->size,
6458 name_for_port(req->object.name));
6459
6460 MACH_ARG(vm_map.size) = req->size;
6461 MACH_ARG(vm_map.copy) = req->copy;
6462 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection);
6463
6464 AFTER = POST_FN(vm_map);
6465 }
6466
POST(vm_map)6467 POST(vm_map)
6468 {
6469 #pragma pack(4)
6470 typedef struct {
6471 mach_msg_header_t Head;
6472 NDR_record_t NDR;
6473 kern_return_t RetCode;
6474 vm_address_t address;
6475 mach_msg_trailer_t trailer;
6476 } Reply;
6477 #pragma pack()
6478
6479 Reply *reply = (Reply *)ARG1;
6480
6481 if (!reply->RetCode) {
6482 // GrP fixme check src and dest tasks
6483 PRINT("mapped at %#llx", (ULong)reply->address);
6484 // GrP fixme max prot
6485 ML_(notify_core_and_tool_of_mmap)(
6486 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)),
6487 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0);
6488 // GrP fixme VKI_MAP_PRIVATE if !copy?
6489 } else {
6490 PRINT("mig return %d", reply->RetCode);
6491 }
6492 }
6493
6494
PRE(vm_remap)6495 PRE(vm_remap)
6496 {
6497 #pragma pack(4)
6498 typedef struct {
6499 mach_msg_header_t Head;
6500 /* start of the kernel processed data */
6501 mach_msg_body_t msgh_body;
6502 mach_msg_port_descriptor_t src_task;
6503 /* end of the kernel processed data */
6504 NDR_record_t NDR;
6505 vm_address_t target_address;
6506 vm_size_t size;
6507 vm_address_t mask;
6508 boolean_t anywhere;
6509 vm_address_t src_address;
6510 boolean_t copy;
6511 vm_inherit_t inheritance;
6512 } Request;
6513 #pragma pack()
6514
6515 Request *req = (Request *)ARG1;
6516
6517 // GrP fixme check src and dest tasks
6518
6519 if (VG_(clo_trace_syscalls)) {
6520 mach_port_name_t source_task = req->src_task.name;
6521 if (source_task == mach_task_self()) {
6522 PRINT("vm_remap(mach_task_self(), "
6523 "to %#llx size %lld, from mach_task_self() at %#llx, ...)",
6524 (ULong)req->target_address,
6525 (ULong)req->size, (ULong)req->src_address);
6526 } else {
6527 PRINT("vm_remap(mach_task_self(), "
6528 "to %#llx size %lld, from task %u at %#llx, ...)",
6529 (ULong)req->target_address, (ULong)req->size,
6530 source_task, (ULong)req->src_address);
6531 }
6532 }
6533
6534 // arg1 is task
6535 // vt->syscall_arg2 = req->target_address;
6536 MACH_ARG(vm_remap.size) = req->size;
6537 // vt->syscall_arg4 = req->copy;
6538
6539 AFTER = POST_FN(vm_remap);
6540 }
6541
POST(vm_remap)6542 POST(vm_remap)
6543 {
6544 #pragma pack(4)
6545 typedef struct {
6546 mach_msg_header_t Head;
6547 NDR_record_t NDR;
6548 kern_return_t RetCode;
6549 vm_address_t target_address;
6550 vm_prot_t cur_protection;
6551 vm_prot_t max_protection;
6552 mach_msg_trailer_t trailer;
6553 } Reply;
6554 #pragma pack()
6555
6556 Reply *reply = (Reply *)ARG1;
6557
6558 if (!reply->RetCode) {
6559 // GrP fixme check src and dest tasks
6560 UInt prot = reply->cur_protection & reply->max_protection;
6561 // GrP fixme max prot
6562 PRINT("mapped at %#llx", (ULong)reply->target_address);
6563 ML_(notify_core_and_tool_of_mmap)(
6564 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)),
6565 prot, VKI_MAP_SHARED, -1, 0);
6566 // GrP fixme VKI_MAP_FIXED if !copy?
6567 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self
6568 } else {
6569 PRINT("mig return %d", reply->RetCode);
6570 }
6571 }
6572
6573
PRE(mach_make_memory_entry_64)6574 PRE(mach_make_memory_entry_64)
6575 {
6576 #pragma pack(4)
6577 typedef struct {
6578 mach_msg_header_t Head;
6579 /* start of the kernel processed data */
6580 mach_msg_body_t msgh_body;
6581 mach_msg_port_descriptor_t parent_entry;
6582 /* end of the kernel processed data */
6583 NDR_record_t NDR;
6584 memory_object_size_t size;
6585 memory_object_offset_t offset;
6586 vm_prot_t permission;
6587 } Request;
6588 #pragma pack()
6589
6590 Request *req = (Request *)ARG1;
6591
6592 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)",
6593 name_for_port(MACH_REMOTE),
6594 req->size, req->offset, req->permission, req->parent_entry.type);
6595
6596 AFTER = POST_FN(mach_make_memory_entry_64);
6597 }
6598
POST(mach_make_memory_entry_64)6599 POST(mach_make_memory_entry_64)
6600 {
6601 #pragma pack(4)
6602 typedef struct {
6603 mach_msg_header_t Head;
6604 mach_msg_body_t msgh_body;
6605 mach_msg_port_descriptor_t object;
6606 NDR_record_t NDR;
6607 memory_object_size_t size;
6608 } Reply;
6609 #pragma pack()
6610
6611 Reply *reply = (Reply *)ARG1;
6612
6613 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
6614 assign_port_name(reply->object.name, "memory-%p");
6615 PRINT("%s", name_for_port(reply->object.name));
6616 }
6617 }
6618
6619
PRE(vm_purgable_control)6620 PRE(vm_purgable_control)
6621 {
6622 #pragma pack(4)
6623 typedef struct {
6624 mach_msg_header_t Head;
6625 NDR_record_t NDR;
6626 vm_address_t address;
6627 vm_purgable_t control;
6628 int state;
6629 } Request;
6630 #pragma pack()
6631
6632 Request *req = (Request *)ARG1;
6633
6634 PRINT("vm_purgable_control(%s, %#llx, %d, %d)",
6635 name_for_port(MACH_REMOTE),
6636 (ULong)req->address, req->control, req->state);
6637
6638 // GrP fixme verify address?
6639
6640 AFTER = POST_FN(vm_purgable_control);
6641 }
6642
POST(vm_purgable_control)6643 POST(vm_purgable_control)
6644 {
6645 #pragma pack(4)
6646 typedef struct {
6647 mach_msg_header_t Head;
6648 NDR_record_t NDR;
6649 kern_return_t RetCode;
6650 int state;
6651 } Reply;
6652 #pragma pack()
6653
6654 Reply *reply = (Reply *)ARG1;
6655
6656 if (!reply->RetCode) {
6657 } else {
6658 PRINT("mig return %d", reply->RetCode);
6659 }
6660 }
6661
6662
PRE(mach_vm_purgable_control)6663 PRE(mach_vm_purgable_control)
6664 {
6665 #pragma pack(4)
6666 typedef struct {
6667 mach_msg_header_t Head;
6668 NDR_record_t NDR;
6669 mach_vm_address_t address;
6670 vm_purgable_t control;
6671 int state;
6672 } Request;
6673 #pragma pack()
6674
6675 Request *req = (Request *)ARG1;
6676
6677 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)",
6678 name_for_port(MACH_REMOTE),
6679 (unsigned long long)req->address, req->control, req->state);
6680
6681 // GrP fixme verify address?
6682
6683 AFTER = POST_FN(mach_vm_purgable_control);
6684 }
6685
POST(mach_vm_purgable_control)6686 POST(mach_vm_purgable_control)
6687 {
6688 #pragma pack(4)
6689 typedef struct {
6690 mach_msg_header_t Head;
6691 NDR_record_t NDR;
6692 kern_return_t RetCode;
6693 int state;
6694 } Reply;
6695 #pragma pack()
6696
6697 Reply *reply = (Reply *)ARG1;
6698
6699 if (!reply->RetCode) {
6700 } else {
6701 PRINT("mig return %d", reply->RetCode);
6702 }
6703 }
6704
6705
PRE(mach_vm_allocate)6706 PRE(mach_vm_allocate)
6707 {
6708 #pragma pack(4)
6709 typedef struct {
6710 mach_msg_header_t Head;
6711 NDR_record_t NDR;
6712 mach_vm_address_t address;
6713 mach_vm_size_t size;
6714 int flags;
6715 } Request;
6716 #pragma pack()
6717
6718 Request *req = (Request *)ARG1;
6719
6720 PRINT("mach_vm_allocate (%s, at 0x%llx, size %lld, flags 0x%x)",
6721 name_for_port(MACH_REMOTE),
6722 req->address, req->size, req->flags);
6723
6724 MACH_ARG(mach_vm_allocate.size) = req->size;
6725 MACH_ARG(mach_vm_allocate.flags) = req->flags;
6726
6727 AFTER = POST_FN(mach_vm_allocate);
6728 }
6729
POST(mach_vm_allocate)6730 POST(mach_vm_allocate)
6731 {
6732 #pragma pack(4)
6733 typedef struct {
6734 mach_msg_header_t Head;
6735 NDR_record_t NDR;
6736 kern_return_t RetCode;
6737 mach_vm_address_t address;
6738 mach_msg_trailer_t trailer;
6739 } Reply;
6740 #pragma pack()
6741
6742 Reply *reply = (Reply *)ARG1;
6743
6744 if (!reply->RetCode) {
6745 if (MACH_REMOTE == vg_task_port) {
6746 PRINT("allocated at 0x%llx", reply->address);
6747 // requesting 0 bytes returns address 0 with no error
6748 if (MACH_ARG(mach_vm_allocate.size)) {
6749 ML_(notify_core_and_tool_of_mmap)(
6750 reply->address, MACH_ARG(mach_vm_allocate.size),
6751 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
6752 }
6753 } else {
6754 PRINT("allocated at 0x%llx in remote task %s", reply->address,
6755 name_for_port(MACH_REMOTE));
6756 }
6757 } else {
6758 PRINT("mig return %d", reply->RetCode);
6759 }
6760 }
6761
6762
PRE(mach_vm_deallocate)6763 PRE(mach_vm_deallocate)
6764 {
6765 #pragma pack(4)
6766 typedef struct {
6767 mach_msg_header_t Head;
6768 NDR_record_t NDR;
6769 mach_vm_address_t address;
6770 mach_vm_size_t size;
6771 } Request;
6772 #pragma pack()
6773
6774 Request *req = (Request *)ARG1;
6775
6776 PRINT("mach_vm_deallocate(%s, at 0x%llx, size %lld)",
6777 name_for_port(MACH_REMOTE),
6778 req->address, req->size);
6779
6780 MACH_ARG(mach_vm_deallocate.address) = req->address;
6781 MACH_ARG(mach_vm_deallocate.size) = req->size;
6782
6783 AFTER = POST_FN(mach_vm_deallocate);
6784
6785 // Must block to prevent race (other thread allocates and
6786 // notifies after we deallocate but before we notify)
6787 *flags &= ~SfMayBlock;
6788 }
6789
POST(mach_vm_deallocate)6790 POST(mach_vm_deallocate)
6791 {
6792 #pragma pack(4)
6793 typedef struct {
6794 mach_msg_header_t Head;
6795 NDR_record_t NDR;
6796 kern_return_t RetCode;
6797 mach_msg_trailer_t trailer;
6798 } Reply;
6799 #pragma pack()
6800
6801 Reply *reply = (Reply *)ARG1;
6802
6803 if (!reply->RetCode) {
6804 if (MACH_REMOTE == vg_task_port) {
6805 if (MACH_ARG(mach_vm_deallocate.size)) {
6806 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_deallocate.address));
6807 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_deallocate.address) +
6808 MACH_ARG(mach_vm_deallocate.size));
6809 // Must have cleared SfMayBlock in PRE to prevent race
6810 ML_(notify_core_and_tool_of_munmap)(start, end - start);
6811 }
6812 }
6813 } else {
6814 PRINT("mig return %d", reply->RetCode);
6815 }
6816 }
6817
6818
PRE(mach_vm_protect)6819 PRE(mach_vm_protect)
6820 {
6821 #pragma pack(4)
6822 typedef struct {
6823 mach_msg_header_t Head;
6824 NDR_record_t NDR;
6825 mach_vm_address_t address;
6826 mach_vm_size_t size;
6827 boolean_t set_maximum;
6828 vm_prot_t new_protection;
6829 } Request;
6830 #pragma pack()
6831
6832 Request *req = (Request *)ARG1;
6833
6834 PRINT("mach_vm_protect(%s, at 0x%llx, size %lld, set_max %d, prot %d)",
6835 name_for_port(MACH_REMOTE), req->address, req->size,
6836 req->set_maximum, req->new_protection);
6837
6838 MACH_ARG(mach_vm_protect.address) = req->address;
6839 MACH_ARG(mach_vm_protect.size) = req->size;
6840 MACH_ARG(mach_vm_protect.set_maximum) = req->set_maximum;
6841 MACH_ARG(mach_vm_protect.new_protection) = req->new_protection;
6842
6843 AFTER = POST_FN(mach_vm_protect);
6844 }
6845
POST(mach_vm_protect)6846 POST(mach_vm_protect)
6847 {
6848 #pragma pack(4)
6849 typedef struct {
6850 mach_msg_header_t Head;
6851 NDR_record_t NDR;
6852 kern_return_t RetCode;
6853 mach_msg_trailer_t trailer;
6854 } Reply;
6855 #pragma pack()
6856
6857 Reply *reply = (Reply *)ARG1;
6858
6859 if (!reply->RetCode) {
6860 if (MACH_REMOTE == vg_task_port) {
6861 Addr start = VG_PGROUNDDN(MACH_ARG(mach_vm_protect.address));
6862 Addr end = VG_PGROUNDUP(MACH_ARG(mach_vm_protect.address) +
6863 MACH_ARG(mach_vm_protect.size));
6864 UInt prot = MACH_ARG(mach_vm_protect.new_protection);
6865 if (MACH_ARG(mach_vm_protect.set_maximum)) {
6866 // DDD: #warning GrP fixme mprotect max
6867 //VG_(mprotect_max_range)(start, end-start, prot);
6868 } else {
6869 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot);
6870 }
6871 }
6872 } else {
6873 PRINT("mig return %d", reply->RetCode);
6874 }
6875 }
6876
6877
PRE(mach_vm_inherit)6878 PRE(mach_vm_inherit)
6879 {
6880 #pragma pack(4)
6881 typedef struct {
6882 mach_msg_header_t Head;
6883 NDR_record_t NDR;
6884 mach_vm_address_t address;
6885 mach_vm_size_t size;
6886 vm_inherit_t new_inheritance;
6887 } Request;
6888 #pragma pack()
6889
6890 Request *req = (Request *)ARG1;
6891
6892 PRINT("mach_vm_inherit(to %s, at 0x%llx, size %llu, value %u)",
6893 name_for_port(MACH_REMOTE),
6894 req->address, req->size, req->new_inheritance);
6895
6896 AFTER = POST_FN(mach_vm_inherit);
6897 }
6898
POST(mach_vm_inherit)6899 POST(mach_vm_inherit)
6900 {
6901 #pragma pack(4)
6902 typedef struct {
6903 mach_msg_header_t Head;
6904 NDR_record_t NDR;
6905 kern_return_t RetCode;
6906 mach_msg_trailer_t trailer;
6907 } Reply;
6908 #pragma pack()
6909
6910 Reply *reply = (Reply *)ARG1;
6911
6912 if (!reply->RetCode) {
6913 // no V-visible side effects
6914 // GrP fixme except maybe fork/exec
6915 } else {
6916 PRINT("mig return %d", reply->RetCode);
6917 }
6918 }
6919
6920
PRE(mach_vm_copy)6921 PRE(mach_vm_copy)
6922 {
6923 #pragma pack(4)
6924 typedef struct {
6925 mach_msg_header_t Head;
6926 NDR_record_t NDR;
6927 mach_vm_address_t source_address;
6928 mach_vm_size_t size;
6929 mach_vm_address_t dest_address;
6930 } Request;
6931 #pragma pack()
6932
6933 Request *req = (Request *)ARG1;
6934
6935 PRINT("mach_vm_copy(%s, 0x%llx, %llu, 0x%llx)",
6936 name_for_port(MACH_REMOTE),
6937 req->source_address, req->size, req->dest_address);
6938
6939 // arg1 is task
6940 // vt->syscall_arg2 = req->source_address;
6941 // vt->syscall_arg3 = req->size;
6942 // vt->syscall_arg4 = req->dest_address;
6943
6944 AFTER = POST_FN(mach_vm_copy);
6945 }
6946
POST(mach_vm_copy)6947 POST(mach_vm_copy)
6948 {
6949 #pragma pack(4)
6950 typedef struct {
6951 mach_msg_header_t Head;
6952 NDR_record_t NDR;
6953 kern_return_t RetCode;
6954 mach_msg_trailer_t trailer;
6955 } Reply;
6956 #pragma pack()
6957
6958 Reply *reply = (Reply *)ARG1;
6959
6960 if (!reply->RetCode) {
6961 if (MACH_REMOTE == vg_task_port) {
6962 // GrP fixme set dest's initialization equal to src's
6963 // BUT vm_copy allocates no memory
6964 }
6965 } else {
6966 PRINT("mig return %d", reply->RetCode);
6967 }
6968 }
6969
PRE(mach_vm_read_overwrite)6970 PRE(mach_vm_read_overwrite)
6971 {
6972 #pragma pack(4)
6973 typedef struct {
6974 mach_msg_header_t Head;
6975 NDR_record_t NDR;
6976 mach_vm_address_t address;
6977 mach_vm_size_t size;
6978 mach_vm_address_t data;
6979 } Request;
6980 #pragma pack()
6981
6982 Request *req = (Request *)ARG1;
6983
6984 PRINT("mach_vm_read_overwrite(%s, 0x%llx, %llu, 0x%llx)",
6985 name_for_port(MACH_REMOTE),
6986 req->address, req->size, req->data);
6987
6988 AFTER = POST_FN(mach_vm_read_overwrite);
6989 }
6990
POST(mach_vm_read_overwrite)6991 POST(mach_vm_read_overwrite)
6992 {
6993 #pragma pack(4)
6994 typedef struct {
6995 mach_msg_header_t Head;
6996 NDR_record_t NDR;
6997 kern_return_t RetCode;
6998 mach_vm_size_t outsize;
6999 } Reply;
7000 #pragma pack()
7001
7002 Reply *reply = (Reply *)ARG1;
7003
7004 if (!reply->RetCode) {
7005 if (MACH_REMOTE == vg_task_port) {
7006 // GrP fixme set dest's initialization equal to src's
7007 // BUT vm_copy allocates no memory
7008 }
7009 } else {
7010 PRINT("mig return %d", reply->RetCode);
7011 }
7012 }
7013
PRE(mach_vm_map)7014 PRE(mach_vm_map)
7015 {
7016 #pragma pack(4)
7017 typedef struct {
7018 mach_msg_header_t Head;
7019 /* start of the kernel processed data */
7020 mach_msg_body_t msgh_body;
7021 mach_msg_port_descriptor_t object;
7022 /* end of the kernel processed data */
7023 NDR_record_t NDR;
7024 mach_vm_address_t address;
7025 mach_vm_size_t size;
7026 mach_vm_address_t mask;
7027 int flags;
7028 memory_object_offset_t offset;
7029 boolean_t copy;
7030 vm_prot_t cur_protection;
7031 vm_prot_t max_protection;
7032 vm_inherit_t inheritance;
7033 } Request;
7034 #pragma pack()
7035
7036 Request *req = (Request *)ARG1;
7037
7038 // GrP fixme check these
7039 PRINT("mach_vm_map(in %s->%s at 0x%llx, size %llu, cur_prot:%x max_prot:%x ...)",
7040 name_for_port(req->Head.msgh_remote_port),
7041 name_for_port(req->object.name),
7042 req->address, req->size,
7043 req->cur_protection,
7044 req->max_protection);
7045
7046 MACH_ARG(mach_vm_map.size) = req->size;
7047 MACH_ARG(mach_vm_map.copy) = req->copy;
7048 MACH_ARG(mach_vm_map.protection) =
7049 (req->cur_protection & req->max_protection);
7050
7051 AFTER = POST_FN(mach_vm_map);
7052 }
7053
POST(mach_vm_map)7054 POST(mach_vm_map)
7055 {
7056 #pragma pack(4)
7057 typedef struct {
7058 mach_msg_header_t Head;
7059 NDR_record_t NDR;
7060 kern_return_t RetCode;
7061 mach_vm_address_t address;
7062 mach_msg_trailer_t trailer;
7063 } Reply;
7064 #pragma pack()
7065
7066 Reply *reply = (Reply *)ARG1;
7067
7068 if (!reply->RetCode) {
7069 // GrP fixme check src and dest tasks
7070 PRINT("mapped at 0x%llx", reply->address);
7071 # if 0
7072 // GrP fixme max prot
7073 ML_(notify_core_and_tool_of_mmap)(
7074 reply->address, VG_PGROUNDUP(MACH_ARG(mach_vm_map.size)),
7075 MACH_ARG(mach_vm_map.protection), VKI_MAP_SHARED, -1, 0);
7076 // GrP fixme VKI_MAP_PRIVATE if !copy?
7077 # else
7078 ML_(sync_mappings)("after", "mach_vm_map", 0);
7079 # endif
7080 } else {
7081 PRINT("mig return %d", reply->RetCode);
7082 }
7083 }
7084
7085
PRE(mach_vm_remap)7086 PRE(mach_vm_remap)
7087 {
7088 #pragma pack(4)
7089 typedef struct {
7090 mach_msg_header_t Head;
7091 /* start of the kernel processed data */
7092 mach_msg_body_t msgh_body;
7093 mach_msg_port_descriptor_t src_task;
7094 /* end of the kernel processed data */
7095 NDR_record_t NDR;
7096 mach_vm_address_t target_address;
7097 mach_vm_size_t size;
7098 mach_vm_offset_t mask;
7099 int flags;
7100 mach_vm_address_t src_address;
7101 boolean_t copy;
7102 vm_inherit_t inheritance;
7103 } Request;
7104 #pragma pack()
7105
7106 Request *req = (Request *)ARG1;
7107
7108 // GrP fixme check these
7109 PRINT("mach_vm_remap(in %s, at 0x%llx, size %llu, from %s ...)",
7110 name_for_port(MACH_REMOTE),
7111 req->target_address, req->size,
7112 name_for_port(req->src_task.name));
7113
7114 MACH_ARG(mach_vm_remap.size) = req->size;
7115 MACH_ARG(mach_vm_remap.copy) = req->copy;
7116
7117 AFTER = POST_FN(mach_vm_remap);
7118 }
7119
POST(mach_vm_remap)7120 POST(mach_vm_remap)
7121 {
7122 #pragma pack(4)
7123 typedef struct {
7124 mach_msg_header_t Head;
7125 NDR_record_t NDR;
7126 kern_return_t RetCode;
7127 mach_vm_address_t target_address;
7128 vm_prot_t cur_protection;
7129 vm_prot_t max_protection;
7130 } Reply;
7131 #pragma pack()
7132
7133 Reply *reply = (Reply *)ARG1;
7134
7135 if (!reply->RetCode) {
7136 // GrP fixme check src and dest tasks
7137 PRINT("mapped at 0x%llx", reply->target_address);
7138 // GrP fixme max prot
7139 ML_(notify_core_and_tool_of_mmap)(
7140 reply->target_address, VG_PGROUNDUP(MACH_ARG(mach_vm_remap.size)),
7141 reply->cur_protection, VKI_MAP_SHARED, -1, 0);
7142 // GrP fixme VKI_MAP_PRIVATE if !copy?
7143 } else {
7144 PRINT("mig return %d", reply->RetCode);
7145 }
7146 }
7147
7148
PRE(mach_vm_region_recurse)7149 PRE(mach_vm_region_recurse)
7150 {
7151 #pragma pack(4)
7152 typedef struct {
7153 mach_msg_header_t Head;
7154 NDR_record_t NDR;
7155 mach_vm_address_t address;
7156 natural_t nesting_depth;
7157 mach_msg_type_number_t infoCnt;
7158 } Request;
7159 #pragma pack()
7160
7161 Request *req = (Request *)ARG1;
7162
7163 PRINT("mach_vm_region_recurse(in %s, at 0x%llx, depth %u, count %u)",
7164 name_for_port(MACH_REMOTE),
7165 req->address, req->nesting_depth, req->infoCnt);
7166
7167 AFTER = POST_FN(mach_vm_region_recurse);
7168 }
7169
POST(mach_vm_region_recurse)7170 POST(mach_vm_region_recurse)
7171 {
7172 #pragma pack(4)
7173 typedef struct {
7174 mach_msg_header_t Head;
7175 NDR_record_t NDR;
7176 kern_return_t RetCode;
7177 mach_vm_address_t address;
7178 mach_vm_size_t size;
7179 natural_t nesting_depth;
7180 mach_msg_type_number_t infoCnt;
7181 int info[19];
7182 } Reply;
7183 #pragma pack()
7184
7185 Reply *reply = (Reply *)ARG1;
7186
7187 if (!reply->RetCode) {
7188 PRINT("got region at 0x%llx, size %llu, depth %u, count %u",
7189 reply->address, reply->size,
7190 reply->nesting_depth, reply->infoCnt);
7191 // GrP fixme mark info contents beyond infoCnt as bogus
7192 } else {
7193 PRINT("mig return %d", reply->RetCode);
7194 }
7195 }
7196
7197
7198 /* ---------------------------------------------------------------------
7199 mach_msg: messages to thread
7200 ------------------------------------------------------------------ */
7201
7202
7203
POST(thread_terminate)7204 POST(thread_terminate)
7205 {
7206 }
7207
7208
PRE(thread_terminate)7209 PRE(thread_terminate)
7210 {
7211 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7212 Bool self_terminate = (mh->msgh_request_port == MACH_THREAD);
7213
7214 PRINT("thread_terminate(%s)", name_for_port(mh->msgh_request_port));
7215
7216 AFTER = POST_FN(thread_terminate);
7217
7218 if (self_terminate) {
7219 // Terminating this thread.
7220 // Copied from sys_exit.
7221 ThreadState *tst = VG_(get_ThreadState)(tid);
7222 tst->exitreason = VgSrc_ExitThread;
7223 tst->os_state.exitcode = 0; // GrP fixme anything better?
7224 // What we would like to do is:
7225 // SET_STATUS_Success(0);
7226 // but that doesn't work, because this is a MACH-class syscall,
7227 // and SET_STATUS_Success creates a UNIX-class syscall result.
7228 // Hence we have to laboriously construct the full SysRes "by hand"
7229 // and use that to set the syscall return status.
7230 SET_STATUS_from_SysRes(
7231 VG_(mk_SysRes_x86_darwin)(
7232 VG_DARWIN_SYSCALL_CLASS_MACH,
7233 False/*success*/, 0, 0
7234 )
7235 );
7236 *flags &= ~SfMayBlock; // clear flag set by PRE(mach_msg)
7237 } else {
7238 // Terminating some other thread.
7239 // Do keep the scheduler lock while terminating any other thread.
7240 // Otherwise we might halt the other thread while it holds the lock,
7241 // which would deadlock the process.
7242 // GrP fixme good enough?
7243 // GrP fixme need to clean up other thread's valgrind data?
7244 }
7245 }
7246
7247
POST(thread_create)7248 POST(thread_create)
7249 {
7250 }
7251
7252
PRE(thread_create)7253 PRE(thread_create)
7254 {
7255 PRINT("thread_create(mach_task_self(), ...)");
7256
7257 AFTER = POST_FN(thread_create);
7258
7259 // GrP fixme
7260 VG_(core_panic)("thread_create() unimplemented");
7261 }
7262
7263
PRE(thread_create_running)7264 PRE(thread_create_running)
7265 {
7266 #pragma pack(4)
7267 typedef struct {
7268 mach_msg_header_t Head;
7269 NDR_record_t NDR;
7270 thread_state_flavor_t flavor;
7271 mach_msg_type_number_t new_stateCnt;
7272 natural_t new_state[144];
7273 } Request;
7274 #pragma pack()
7275
7276 Request *req;
7277 thread_state_t regs;
7278 ThreadState *new_thread;
7279
7280 PRINT("thread_create_running(mach_task_self(), ...)");
7281
7282 // The new thread will immediately begin execution,
7283 // so we need to hijack the register state here.
7284
7285 req = (Request *)ARG1;
7286 regs = (thread_state_t)req->new_state;
7287
7288 // Build virtual thread.
7289 new_thread = build_thread(regs, req->flavor, req->new_stateCnt);
7290
7291 // Edit the thread state to send to the real kernel.
7292 hijack_thread_state(regs, req->flavor, req->new_stateCnt, new_thread);
7293
7294 AFTER = POST_FN(thread_create_running);
7295 }
7296
7297
POST(thread_create_running)7298 POST(thread_create_running)
7299 {
7300 #pragma pack(4)
7301 typedef struct {
7302 mach_msg_header_t Head;
7303 /* start of the kernel processed data */
7304 mach_msg_body_t msgh_body;
7305 mach_msg_port_descriptor_t child_act;
7306 /* end of the kernel processed data */
7307 } Reply;
7308 #pragma pack()
7309
7310 Reply *reply = (Reply *)ARG1;
7311
7312 assign_port_name(reply->child_act.name, "thread-%p");
7313 PRINT("%s", name_for_port(reply->child_act.name));
7314 }
7315
7316
PRE(bsdthread_create)7317 PRE(bsdthread_create)
7318 {
7319 ThreadState *tst;
7320
7321 PRINT("bsdthread_create( %#lx, %#lx, %#lx, %#lx, %#lx )",
7322 ARG1, ARG2, ARG3, ARG4, ARG5);
7323 PRE_REG_READ5(pthread_t,"bsdthread_create",
7324 void *,"func", void *,"func_arg", void *,"stack",
7325 pthread_t,"thread", unsigned int,"flags");
7326
7327 // The kernel will call V's pthread_hijack() to launch the thread.
7328 // Here we allocate the thread state and pass it to pthread_hijack()
7329 // via the func_arg parameter.
7330
7331 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)());
7332 allocstack(tst->tid);
7333
7334 tst->os_state.func_arg = (Addr)ARG2;
7335 ARG2 = (Word)tst;
7336
7337 // Create a semaphore that pthread_hijack will signal once it starts
7338 // POST(bsdthread_create) needs to wait for the new memory map to appear
7339 semaphore_create(mach_task_self(), &tst->os_state.child_go,
7340 SYNC_POLICY_FIFO, 0);
7341 semaphore_create(mach_task_self(), &tst->os_state.child_done,
7342 SYNC_POLICY_FIFO, 0);
7343 }
7344
POST(bsdthread_create)7345 POST(bsdthread_create)
7346 {
7347 // Tell new thread's pthread_hijack to proceed, and wait for it to finish.
7348 // We hold V's lock on the child's behalf.
7349 // If we return before letting pthread_hijack do its thing, V thinks
7350 // the new pthread struct is still unmapped when we return to libc,
7351 // causing false errors.
7352
7353 ThreadState *tst = (ThreadState *)ARG2;
7354 semaphore_signal(tst->os_state.child_go);
7355 semaphore_wait(tst->os_state.child_done);
7356 semaphore_destroy(mach_task_self(), tst->os_state.child_go);
7357 semaphore_destroy(mach_task_self(), tst->os_state.child_done);
7358
7359 // GrP fixme semaphore destroy needed when thread creation fails
7360 // GrP fixme probably other cleanup too
7361 // GrP fixme spinlocks might be good enough?
7362
7363 // DDD: I'm not at all sure this is the right spot for this. It probably
7364 // should be in pthread_hijack instead, just before the call to
7365 // start_thread_NORETURN(), call_on_new_stack_0_1(), but we don't have the
7366 // parent tid value there...
7367 vg_assert(VG_(owns_BigLock_LL)(tid));
7368 VG_TRACK ( pre_thread_ll_create, tid, tst->tid );
7369 }
7370
7371
PRE(bsdthread_terminate)7372 PRE(bsdthread_terminate)
7373 {
7374 ThreadState *tst;
7375
7376 PRINT("bsdthread_terminate( %#lx, %lx, %s, %s )",
7377 ARG1, ARG2, name_for_port(ARG3), name_for_port(ARG4));
7378 PRE_REG_READ4(int,"bsdthread_terminate",
7379 void *,"freeaddr", size_t,"freesize",
7380 mach_port_t,"kport", mach_port_t,"joinsem");
7381
7382 // Free memory and signal semaphore.
7383 // GrP fixme errors?
7384 if (ARG4) semaphore_signal((semaphore_t)ARG4);
7385 if (ARG1 && ARG2) {
7386 ML_(notify_core_and_tool_of_munmap)(ARG1, ARG2);
7387 # if DARWIN_VERS >= DARWIN_10_8
7388 /* JRS 2012 Aug 02: ugly hack: vm_deallocate disappeared from
7389 the mig output. Work around it for the time being. */
7390 VG_(do_syscall2)(__NR_munmap, ARG1, ARG2);
7391 # else
7392 vm_deallocate(mach_task_self(), (vm_address_t)ARG1, (vm_size_t)ARG2);
7393 # endif
7394 }
7395
7396 // Tell V to terminate the thread.
7397 // Copied from sys_exit.
7398 tst = VG_(get_ThreadState)(tid);
7399 tst->exitreason = VgSrc_ExitThread;
7400 tst->os_state.exitcode = 0; // GrP fixme anything better?
7401 SET_STATUS_Success(0);
7402 }
7403
7404
POST(thread_suspend)7405 POST(thread_suspend)
7406 {
7407 }
7408
PRE(thread_suspend)7409 PRE(thread_suspend)
7410 {
7411 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7412 Bool self_suspend = (mh->msgh_request_port == MACH_THREAD);
7413
7414 PRINT("thread_suspend(%s)", name_for_port(mh->msgh_request_port));
7415
7416 AFTER = POST_FN(thread_suspend);
7417
7418 if (self_suspend) {
7419 // Don't keep the scheduler lock while self-suspending.
7420 // Otherwise we might halt while still holding the lock,
7421 // which would deadlock the process.
7422 *flags |= SfMayBlock;
7423 } else {
7424 // Do keep the scheduler lock while suspending any other thread.
7425 // Otherwise we might halt the other thread while it holds the lock,
7426 // which would deadlock the process.
7427 *flags &= ~SfMayBlock;
7428 }
7429 }
7430
7431
POST(thread_resume)7432 POST(thread_resume)
7433 {
7434 }
7435
PRE(thread_resume)7436 PRE(thread_resume)
7437 {
7438 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7439 Bool self_resume = (mh->msgh_request_port == MACH_THREAD);
7440
7441 PRINT("thread_resume(%s)", name_for_port(mh->msgh_request_port));
7442
7443 AFTER = POST_FN(thread_resume);
7444
7445 if (self_resume) {
7446 // This doesn't make much sense. If we are resuming ourself, we can't
7447 // already be running. So I don't see how we can ever get here.
7448 vg_assert(0);
7449 } else {
7450 // Resuming some other thread. It might not yet come back to life
7451 // (if the suspend count is still above zero) so make sure we keep
7452 // holding the lock.
7453 *flags &= ~SfMayBlock;
7454 }
7455 }
7456
7457
POST(thread_get_state)7458 POST(thread_get_state)
7459 {
7460 #pragma pack(4)
7461 typedef struct {
7462 mach_msg_header_t Head;
7463 NDR_record_t NDR;
7464 kern_return_t RetCode;
7465 mach_msg_type_number_t old_stateCnt;
7466 natural_t old_state[144];
7467 mach_msg_trailer_t trailer;
7468 } Reply;
7469 #pragma pack()
7470
7471 Reply *reply = (Reply *)ARG1;
7472 // mach_port_t thread = MACH_ARG(thread_get_state.thread);
7473 thread_state_flavor_t flavor = MACH_ARG(thread_get_state.flavor);
7474
7475 if (!reply->RetCode) {
7476 thread_state_from_vex((thread_state_t)reply->old_state,
7477 flavor, reply->old_stateCnt,
7478 &VG_(get_ThreadState)(tid)->arch.vex);
7479 } else {
7480 PRINT("mig return %d", reply->RetCode);
7481 }
7482 }
7483
PRE(thread_get_state)7484 PRE(thread_get_state)
7485 {
7486 #pragma pack(4)
7487 typedef struct {
7488 mach_msg_header_t Head;
7489 NDR_record_t NDR;
7490 thread_state_flavor_t flavor;
7491 mach_msg_type_number_t old_stateCnt;
7492 } Request;
7493 #pragma pack()
7494
7495 Request *req = (Request *)ARG1;
7496 // Bool self = (req->Head.msgh_request_port == MACH_THREAD);
7497
7498 // GrP fixme if (self) {
7499 PRINT("thread_get_state(%s, %d)",
7500 name_for_port(req->Head.msgh_request_port), req->flavor);
7501 /*} else {
7502 PRINT("thread_get_state(0x%x, %d)",
7503 req->Head.msgh_request_port, req->flavor);
7504 }*/
7505
7506 // Hack the thread state after making the real call.
7507 MACH_ARG(thread_get_state.thread) = req->Head.msgh_request_port;
7508 MACH_ARG(thread_get_state.flavor) = req->flavor;
7509
7510 AFTER = POST_FN(thread_get_state);
7511 }
7512
7513
PRE(thread_policy)7514 PRE(thread_policy)
7515 {
7516 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7517 // Bool self = (mh->msgh_request_port == MACH_THREAD);
7518
7519 // GrP fixme if (self) {
7520 PRINT("thread_policy(%s, ...)", name_for_port(mh->msgh_request_port));
7521 /*} else {
7522 PRINT("thread_policy(thread 0x%x, ...)", mh->msgh_request_port);
7523 }*/
7524
7525 AFTER = POST_FN(thread_policy);
7526 }
7527
POST(thread_policy)7528 POST(thread_policy)
7529 {
7530 }
7531
7532
PRE(thread_policy_set)7533 PRE(thread_policy_set)
7534 {
7535 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7536
7537 PRINT("thread_policy_set(%s, ...)", name_for_port(mh->msgh_request_port));
7538
7539 AFTER = POST_FN(thread_policy_set);
7540 }
7541
POST(thread_policy_set)7542 POST(thread_policy_set)
7543 {
7544 }
7545
7546
PRE(thread_info)7547 PRE(thread_info)
7548 {
7549 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7550
7551 PRINT("thread_info(%s, ...)", name_for_port(mh->msgh_request_port));
7552 // GrP fixme does any thread info need to be hijacked?
7553
7554 AFTER = POST_FN(thread_info);
7555 }
7556
POST(thread_info)7557 POST(thread_info)
7558 {
7559 // GrP fixme mark unused parts of thread_info_out as uninitialized?
7560 }
7561
7562
7563
7564 /* ---------------------------------------------------------------------
7565 mach_msg: messages to bootstrap port
7566 ------------------------------------------------------------------ */
7567
7568
POST(bootstrap_register)7569 POST(bootstrap_register)
7570 {
7571 #pragma pack(4)
7572 typedef struct {
7573 mach_msg_header_t Head;
7574 NDR_record_t NDR;
7575 kern_return_t RetCode;
7576 mach_msg_trailer_t trailer;
7577 } Reply;
7578 #pragma pack()
7579
7580 Reply *reply = (Reply *)ARG1;
7581
7582 if (reply->RetCode) PRINT("mig return %d", reply->RetCode);
7583 }
7584
PRE(bootstrap_register)7585 PRE(bootstrap_register)
7586 {
7587 #pragma pack(4)
7588 typedef struct {
7589 mach_msg_header_t Head;
7590 /* start of the kernel processed data */
7591 mach_msg_body_t msgh_body;
7592 mach_msg_port_descriptor_t service_port;
7593 /* end of the kernel processed data */
7594 NDR_record_t NDR;
7595 name_t service_name;
7596 } Request;
7597 #pragma pack()
7598
7599 Request *req = (Request *)ARG1;
7600
7601 PRINT("bootstrap_register(port 0x%x, \"%s\")",
7602 req->service_port.name, req->service_name);
7603
7604 /* The required entry in the allocated_ports list (mapping) might
7605 not exist, due perhaps to broken syscall wrappers (mach__N etc).
7606 Create a minimal entry so that assign_port_name below doesn't
7607 cause an assertion. */
7608 if (!port_exists(req->service_port.name)) {
7609 port_create_vanilla(req->service_port.name);
7610 }
7611
7612 assign_port_name(req->service_port.name, req->service_name);
7613
7614 AFTER = POST_FN(bootstrap_register);
7615 }
7616
7617
POST(bootstrap_look_up)7618 POST(bootstrap_look_up)
7619 {
7620 #pragma pack(4)
7621 typedef struct {
7622 mach_msg_header_t Head;
7623 /* start of the kernel processed data */
7624 mach_msg_body_t msgh_body;
7625 mach_msg_port_descriptor_t service_port;
7626 /* end of the kernel processed data */
7627 mach_msg_trailer_t trailer;
7628 } Reply;
7629 #pragma pack()
7630
7631 Reply *reply = (Reply *)ARG1;
7632
7633 if ((reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
7634 reply->service_port.name)
7635 {
7636 assign_port_name(reply->service_port.name,
7637 MACH_ARG(bootstrap_look_up.service_name));
7638 PRINT("%s", name_for_port(reply->service_port.name));
7639 } else {
7640 PRINT("not found");
7641 }
7642 VG_(free)(MACH_ARG(bootstrap_look_up.service_name));
7643 }
7644
PRE(bootstrap_look_up)7645 PRE(bootstrap_look_up)
7646 {
7647 #pragma pack(4)
7648 typedef struct {
7649 mach_msg_header_t Head;
7650 NDR_record_t NDR;
7651 name_t service_name;
7652 } Request;
7653 #pragma pack()
7654
7655 Request *req = (Request *)ARG1;
7656
7657 PRINT("bootstrap_look_up(\"%s\")", req->service_name);
7658
7659 MACH_ARG(bootstrap_look_up.service_name) =
7660 VG_(strdup)("syswrap-darwin.bootstrap-name", req->service_name);
7661
7662 AFTER = POST_FN(bootstrap_look_up);
7663 }
7664
7665
7666 /* ---------------------------------------------------------------------
7667 mach_msg: receiver-specific handlers
7668 ------------------------------------------------------------------ */
7669
7670
POST(mach_msg_receive)7671 POST(mach_msg_receive)
7672 {
7673 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7674
7675 // GrP fixme don't know of anything interesting here currently
7676 // import_complex_message handles everything
7677 // PRINT("UNHANDLED reply %d", mh->msgh_id);
7678
7679 // Assume the call may have mapped or unmapped memory
7680 ML_(sync_mappings)("after", "mach_msg_receive", mh->msgh_id);
7681 }
7682
PRE(mach_msg_receive)7683 PRE(mach_msg_receive)
7684 {
7685 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7686
7687 PRINT("mach_msg_receive(port %s)", name_for_port(mh->msgh_reply_port));
7688
7689 AFTER = POST_FN(mach_msg_receive);
7690
7691 // no message sent, only listening for a reply
7692 // assume message may block
7693 *flags |= SfMayBlock;
7694 }
7695
7696
PRE(mach_msg_bootstrap)7697 PRE(mach_msg_bootstrap)
7698 {
7699 // message to bootstrap port
7700
7701 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7702
7703 switch (mh->msgh_id) {
7704 case 403:
7705 CALL_PRE(bootstrap_register);
7706 return;
7707 case 404:
7708 CALL_PRE(bootstrap_look_up);
7709 return;
7710
7711 default:
7712 PRINT("UNHANDLED bootstrap message [id %d, to %s, reply 0x%x]\n",
7713 mh->msgh_id, name_for_port(mh->msgh_request_port),
7714 mh->msgh_reply_port);
7715 return;
7716 }
7717 }
7718
7719
PRE(mach_msg_host)7720 PRE(mach_msg_host)
7721 {
7722 // message to host self - check for host-level kernel calls
7723
7724 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7725
7726 switch (mh->msgh_id) {
7727 case 200:
7728 CALL_PRE(host_info);
7729 return;
7730 case 202:
7731 CALL_PRE(host_page_size);
7732 return;
7733 case 205:
7734 CALL_PRE(host_get_io_master);
7735 return;
7736 case 206:
7737 CALL_PRE(host_get_clock_service);
7738 return;
7739 case 217:
7740 CALL_PRE(host_request_notification);
7741 return;
7742
7743 default:
7744 // unknown message to host self
7745 log_decaying("UNKNOWN host message [id %d, to %s, reply 0x%x]",
7746 mh->msgh_id, name_for_port(mh->msgh_request_port),
7747 mh->msgh_reply_port);
7748 return;
7749 }
7750 }
7751
7752 // JRS 2011-Aug-25: these magic numbers (3201 etc) come from
7753 // /usr/include/mach/mach_port.h et al (grep in /usr/include
7754 // for them)
PRE(mach_msg_task)7755 PRE(mach_msg_task)
7756 {
7757 // message to a task port
7758
7759 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7760
7761 switch (mh->msgh_id) {
7762 case 3201:
7763 CALL_PRE(mach_port_type);
7764 return;
7765 case 3204:
7766 CALL_PRE(mach_port_allocate);
7767 return;
7768 case 3205:
7769 CALL_PRE(mach_port_destroy);
7770 return;
7771 case 3206:
7772 CALL_PRE(mach_port_deallocate);
7773 return;
7774 case 3207:
7775 CALL_PRE(mach_port_get_refs);
7776 return;
7777 case 3208:
7778 CALL_PRE(mach_port_mod_refs);
7779 return;
7780 case 3211:
7781 CALL_PRE(mach_port_get_set_status);
7782 return;
7783 case 3212:
7784 CALL_PRE(mach_port_move_member);
7785 return;
7786 case 3213:
7787 CALL_PRE(mach_port_request_notification);
7788 return;
7789 case 3214:
7790 CALL_PRE(mach_port_insert_right);
7791 return;
7792 case 3215:
7793 CALL_PRE(mach_port_extract_right);
7794 return;
7795 case 3217:
7796 CALL_PRE(mach_port_get_attributes);
7797 return;
7798 case 3218:
7799 CALL_PRE(mach_port_set_attributes);
7800 return;
7801 case 3226:
7802 CALL_PRE(mach_port_insert_member);
7803 return;
7804 case 3227:
7805 CALL_PRE(mach_port_extract_member);
7806 return;
7807
7808 case 3229:
7809 CALL_PRE(mach_port_set_context);
7810 return;
7811
7812 case 3402:
7813 CALL_PRE(task_threads);
7814 return;
7815 case 3403:
7816 CALL_PRE(mach_ports_register);
7817 return;
7818 case 3404:
7819 CALL_PRE(mach_ports_lookup);
7820 return;
7821
7822 case 3405:
7823 CALL_PRE(task_info);
7824 return;
7825
7826 case 3407:
7827 CALL_PRE(task_suspend);
7828 return;
7829 case 3408:
7830 CALL_PRE(task_resume);
7831 return;
7832
7833 case 3409:
7834 CALL_PRE(task_get_special_port);
7835 return;
7836 case 3411:
7837 CALL_PRE(thread_create);
7838 return;
7839 case 3412:
7840 CALL_PRE(thread_create_running);
7841 return;
7842
7843 case 3414:
7844 CALL_PRE(task_get_exception_ports);
7845 return;
7846
7847 case 3418:
7848 CALL_PRE(semaphore_create);
7849 return;
7850 case 3419:
7851 CALL_PRE(semaphore_destroy);
7852 return;
7853 case 3420:
7854 CALL_PRE(task_policy_set);
7855 return;
7856
7857 case 3801:
7858 CALL_PRE(vm_allocate);
7859 return;
7860 case 3802:
7861 CALL_PRE(vm_deallocate);
7862 return;
7863 case 3803:
7864 CALL_PRE(vm_protect);
7865 return;
7866 case 3804:
7867 CALL_PRE(vm_inherit);
7868 return;
7869 case 3805:
7870 CALL_PRE(vm_read);
7871 return;
7872 case 3808:
7873 CALL_PRE(vm_copy);
7874 return;
7875 case 3809:
7876 CALL_PRE(vm_read_overwrite);
7877 return;
7878 case 3812:
7879 CALL_PRE(vm_map);
7880 return;
7881 case 3814:
7882 CALL_PRE(vm_remap);
7883 return;
7884 case 3825:
7885 CALL_PRE(mach_make_memory_entry_64);
7886 return;
7887 case 3830:
7888 CALL_PRE(vm_purgable_control);
7889 return;
7890
7891 case 4800:
7892 CALL_PRE(mach_vm_allocate);
7893 return;
7894 case 4801:
7895 CALL_PRE(mach_vm_deallocate);
7896 return;
7897 case 4802:
7898 CALL_PRE(mach_vm_protect);
7899 return;
7900 case 4803:
7901 CALL_PRE(mach_vm_inherit);
7902 return;
7903 case 4804:
7904 CALL_PRE(mach_vm_read);
7905 return;
7906 case 4807:
7907 CALL_PRE(mach_vm_copy);
7908 return;
7909 case 4808:
7910 CALL_PRE(mach_vm_read_overwrite);
7911 return;
7912 case 4811:
7913 CALL_PRE(mach_vm_map);
7914 return;
7915 case 4813:
7916 CALL_PRE(mach_vm_remap);
7917 return;
7918 case 4815:
7919 CALL_PRE(mach_vm_region_recurse);
7920 return;
7921 case 4817:
7922 CALL_PRE(mach_make_memory_entry_64);
7923 return;
7924 case 4818:
7925 CALL_PRE(mach_vm_purgable_control);
7926 return;
7927
7928 default:
7929 // unknown message to task self
7930 log_decaying("UNKNOWN task message [id %d, to %s, reply 0x%x]",
7931 mh->msgh_id, name_for_port(mh->msgh_remote_port),
7932 mh->msgh_reply_port);
7933 return;
7934 }
7935 }
7936
7937
PRE(mach_msg_thread)7938 PRE(mach_msg_thread)
7939 {
7940 // message to local thread - check for thread-level kernel calls
7941
7942 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
7943
7944 switch (mh->msgh_id) {
7945 case 3600:
7946 CALL_PRE(thread_terminate);
7947 return;
7948 case 3603:
7949 CALL_PRE(thread_get_state);
7950 return;
7951 case 3605:
7952 CALL_PRE(thread_suspend);
7953 return;
7954 case 3606:
7955 CALL_PRE(thread_resume);
7956 return;
7957 case 3612:
7958 CALL_PRE(thread_info);
7959 return;
7960 case 3616:
7961 CALL_PRE(thread_policy);
7962 return;
7963 case 3617:
7964 CALL_PRE(thread_policy_set);
7965 return;
7966 default:
7967 // unknown message to a thread
7968 VG_(printf)("UNKNOWN thread message [id %d, to %s, reply 0x%x]\n",
7969 mh->msgh_id, name_for_port(mh->msgh_request_port),
7970 mh->msgh_reply_port);
7971 return;
7972 }
7973 }
7974
7975
is_thread_port(mach_port_t port)7976 static int is_thread_port(mach_port_t port)
7977 {
7978 if (port == 0) return False;
7979
7980 return VG_(lwpid_to_vgtid)(port) != VG_INVALID_THREADID;
7981 }
7982
7983
is_task_port(mach_port_t port)7984 static int is_task_port(mach_port_t port)
7985 {
7986 if (port == 0) return False;
7987
7988 if (port == vg_task_port) return True;
7989
7990 return (0 == VG_(strncmp)("task-", name_for_port(port), 5));
7991 }
7992
7993
7994 /* ---------------------------------------------------------------------
7995 mach_msg: base handlers
7996 ------------------------------------------------------------------ */
7997
PRE(mach_msg)7998 PRE(mach_msg)
7999 {
8000 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8001 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8002 // mach_msg_size_t send_size = (mach_msg_size_t)ARG3;
8003 mach_msg_size_t rcv_size = (mach_msg_size_t)ARG4;
8004 // mach_port_t rcv_name = (mach_port_t)ARG5;
8005 size_t complex_header_size = 0;
8006
8007 PRE_REG_READ7(long, "mach_msg",
8008 mach_msg_header_t*,"msg", mach_msg_option_t,"option",
8009 mach_msg_size_t,"send_size", mach_msg_size_t,"rcv_size",
8010 mach_port_t,"rcv_name", mach_msg_timeout_t,"timeout",
8011 mach_port_t,"notify");
8012
8013 // Assume default POST handler until specified otherwise
8014 AFTER = NULL;
8015
8016 // Assume call may block unless specified otherwise
8017 *flags |= SfMayBlock;
8018
8019 if (option & MACH_SEND_MSG) {
8020 // Validate outgoing message header
8021 PRE_MEM_READ("mach_msg(msg.msgh_bits)",
8022 (Addr)&mh->msgh_bits, sizeof(mh->msgh_bits));
8023 // msgh_size not required, use parameter instead
8024 PRE_MEM_READ("mach_msg(msg.msgh_remote_port)",
8025 (Addr)&mh->msgh_remote_port, sizeof(mh->msgh_remote_port));
8026 PRE_MEM_READ("mach_msg(msg.msgh_local_port)",
8027 (Addr)&mh->msgh_local_port, sizeof(mh->msgh_local_port));
8028 // msgh_reserved not required
8029 PRE_MEM_READ("mach_msg(msg.msgh_id)",
8030 (Addr)&mh->msgh_id, sizeof(mh->msgh_id));
8031
8032 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8033 // Validate typed message data and handle memory map changes.
8034 complex_header_size = export_complex_message(tid, mh);
8035 }
8036
8037 // GrP fixme handle sender-specified message trailer
8038 // (but is this only for too-secure processes?)
8039 // JRS 11 Nov 2014: this assertion is OK for <= 10.9 but fails on 10.10
8040 # if DARWIN_VERS == DARWIN_10_10
8041 if (mh->msgh_bits & MACH_SEND_TRAILER) {
8042 log_decaying("UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option");
8043 }
8044 # else
8045 vg_assert(! (mh->msgh_bits & MACH_SEND_TRAILER));
8046 # endif
8047
8048 MACH_REMOTE = mh->msgh_remote_port;
8049 MACH_MSGH_ID = mh->msgh_id;
8050 }
8051
8052 if (option & MACH_RCV_MSG) {
8053 // Pre-validate receive buffer
8054 PRE_MEM_WRITE("mach_msg(receive buffer)", (Addr)mh, rcv_size);
8055 }
8056
8057 // Call a PRE handler. The PRE handler may set an AFTER handler.
8058
8059 if (!(option & MACH_SEND_MSG)) {
8060 // no message sent, receive only
8061 CALL_PRE(mach_msg_receive);
8062 return;
8063 }
8064 else if (mh->msgh_request_port == vg_host_port) {
8065 // message sent to mach_host_self()
8066 CALL_PRE(mach_msg_host);
8067 return;
8068 }
8069 else if (is_task_port(mh->msgh_request_port)) {
8070 // message sent to a task
8071 CALL_PRE(mach_msg_task);
8072 return;
8073 }
8074 else if (mh->msgh_request_port == vg_bootstrap_port) {
8075 // message sent to bootstrap port
8076 CALL_PRE(mach_msg_bootstrap);
8077 return;
8078 }
8079 else if (is_thread_port(mh->msgh_request_port)) {
8080 // message sent to one of this process's threads
8081 CALL_PRE(mach_msg_thread);
8082 return;
8083 }
8084 else {
8085 // this is an attempt to optimize mapping sync
8086 // but there are always some cases hard to find
8087 #if 0
8088 Bool do_mapping_update = False;
8089 // sorted by msgh_id, we suppose that msgh_id are different for each service,
8090 // which is obviously not true...
8091 switch (mh->msgh_id) {
8092 // com.apple.windowserver.active
8093 case 29008: // this one opens a port type 'a'
8094
8095 // com.apple.windowserver.active 'a' port
8096 case 29000:
8097 case 29822:
8098 case 29820: // adds a vm mapping
8099 case 29809: // contains a ool mem
8100 case 29800: // opens a port type 'b'
8101 case 29873:
8102 case 29876: // adds a vm mapping
8103
8104 // com.apple.windowserver.active 'b' port
8105 case 29624:
8106 case 29625:
8107 case 29506:
8108 case 29504:
8109 case 29509:
8110 case 29315:
8111 case 29236:
8112 case 29473:
8113 case 29268:
8114 case 29237: // contains a ool mem
8115 case 29360:
8116 case 29301:
8117 case 29287:
8118 case 29568:
8119 case 29570: // contains a ool mem
8120 case 29211:
8121 case 29569: // contains a ool mem
8122 case 29374:
8123 case 29246:
8124 case 29239:
8125 case 29272:
8126 if (mh->msgh_id == 29820 ||
8127 mh->msgh_id == 29876)
8128 do_mapping_update = True;
8129
8130 PRINT("com.apple.windowserver.active service mach_msg [id %d, to %s, reply 0x%x]",
8131 mh->msgh_id, name_for_port(mh->msgh_request_port),
8132 mh->msgh_reply_port);
8133 break;
8134
8135 // com.apple.FontServer
8136 case 13024:
8137 PRINT("com.apple.FontServerservice mach_msg [id %d, to %s, reply 0x%x]",
8138 mh->msgh_id, name_for_port(mh->msgh_request_port),
8139 mh->msgh_reply_port);
8140 break;
8141
8142 // com.apple.system.notification_center
8143 case 78945698:
8144 case 78945701:
8145 case 78945695: // contains a ool mem
8146 case 78945694:
8147 case 78945700:
8148 if (mh->msgh_id == 78945695)
8149 do_mapping_update = False;
8150 PRINT("com.apple.system.notification_center mach_msg [id %d, to %s, reply 0x%x]",
8151 mh->msgh_id, name_for_port(mh->msgh_request_port),
8152 mh->msgh_reply_port);
8153 break;
8154
8155 // com.apple.CoreServices.coreservicesd
8156 case 10000:
8157 case 10019:
8158 case 10002: // adds vm mappings
8159 case 10003: // adds vm mappings
8160 case 14007:
8161 case 13000:
8162 case 13001:
8163 case 13011:
8164 case 13016: // contains a ool mem
8165 if (mh->msgh_id == 10002||
8166 mh->msgh_id == 10003)
8167 do_mapping_update = True;
8168 PRINT("com.apple.CoreServices.coreservicesd mach_msg [id %d, to %s, reply 0x%x]",
8169 mh->msgh_id, name_for_port(mh->msgh_request_port),
8170 mh->msgh_reply_port);
8171 break;
8172
8173 // com.apple.system.logger
8174 case 118:
8175 PRINT("com.apple.system.logger mach_msg [id %d, to %s, reply 0x%x]",
8176 mh->msgh_id, name_for_port(mh->msgh_request_port),
8177 mh->msgh_reply_port);
8178 break;
8179
8180 // com.apple.coreservices.launchservicesd, and others
8181 case 1999646836: // might adds vm mapping
8182 if (mh->msgh_id == 1999646836)
8183 do_mapping_update = True;
8184 PRINT("om.apple.coreservices.launchservicesd mach_msg [id %d, to %s, reply 0x%x]",
8185 mh->msgh_id, name_for_port(mh->msgh_request_port),
8186 mh->msgh_reply_port);
8187 break;
8188
8189 // com.apple.ocspd
8190 case 33012:
8191 PRINT("com.apple.ocspd mach_msg [id %d, to %s, reply 0x%x]",
8192 mh->msgh_id, name_for_port(mh->msgh_request_port),
8193 mh->msgh_reply_port);
8194
8195 default:
8196 // arbitrary message to arbitrary port
8197 do_mapping_update = True;
8198 PRINT("UNHANDLED mach_msg [id %d, to %s, reply 0x%x]",
8199 mh->msgh_id, name_for_port(mh->msgh_request_port),
8200 mh->msgh_reply_port);
8201 }
8202
8203 // this is an optimization, don't check mapping on known mach_msg
8204 if (do_mapping_update)
8205 AFTER = POST_FN(mach_msg_unhandled);
8206 else
8207 AFTER = POST_FN(mach_msg_unhandled_check);
8208 #else
8209 AFTER = POST_FN(mach_msg_unhandled);
8210 #endif
8211
8212 // Assume the entire message body may be read.
8213 // GrP fixme generates false positives for unknown protocols
8214 /*
8215 PRE_MEM_READ("mach_msg(payload)",
8216 (Addr)((char*)mh + sizeof(mach_msg_header_t) + complex_header_size),
8217 send_size - sizeof(mach_msg_header_t) - complex_header_size);
8218 */
8219 return;
8220 }
8221 }
8222
POST(mach_msg)8223 POST(mach_msg)
8224 {
8225 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8226 mach_msg_option_t option = (mach_msg_option_t)ARG2;
8227
8228 if (option & MACH_RCV_MSG) {
8229 if (RES != 0) {
8230 // error during send or receive
8231 // GrP fixme need to clean up port rights?
8232 } else {
8233 mach_msg_trailer_t *mt =
8234 (mach_msg_trailer_t *)((Addr)mh + round_msg(mh->msgh_size));
8235
8236 // Assume the entire received message and trailer is initialized
8237 // GrP fixme would being more specific catch any bugs?
8238 POST_MEM_WRITE((Addr)mh,
8239 round_msg(mh->msgh_size) + mt->msgh_trailer_size);
8240
8241 if (mh->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
8242 // Update memory map for out-of-line message data
8243 import_complex_message(tid, mh);
8244 }
8245 }
8246 }
8247
8248 // Call handler chosen by PRE(mach_msg)
8249 if (AFTER) {
8250 (*AFTER)(tid, arrghs, status);
8251 }
8252 }
8253
8254
POST(mach_msg_unhandled)8255 POST(mach_msg_unhandled)
8256 {
8257 mach_msg_header_t *mh = (mach_msg_header_t *)ARG1;
8258 ML_(sync_mappings)("after", "mach_msg_receive-UNHANDLED", mh->msgh_id);
8259 }
8260
POST(mach_msg_unhandled_check)8261 POST(mach_msg_unhandled_check)
8262 {
8263 if (ML_(sync_mappings)("after", "mach_msg_receive (unhandled_check)", 0))
8264 PRINT("mach_msg_unhandled_check tid:%d missed mapping change()", tid);
8265 }
8266
8267
8268 /* ---------------------------------------------------------------------
8269 other Mach traps
8270 ------------------------------------------------------------------ */
8271
PRE(mach_reply_port)8272 PRE(mach_reply_port)
8273 {
8274 PRINT("mach_reply_port()");
8275 }
8276
POST(mach_reply_port)8277 POST(mach_reply_port)
8278 {
8279 record_named_port(tid, RES, MACH_PORT_RIGHT_RECEIVE, "reply-%p");
8280 PRINT("reply port %s", name_for_port(RES));
8281 }
8282
8283
PRE(mach_thread_self)8284 PRE(mach_thread_self)
8285 {
8286 PRINT("mach_thread_self()");
8287 }
8288
POST(mach_thread_self)8289 POST(mach_thread_self)
8290 {
8291 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "thread-%p");
8292 PRINT("thread %#lx", RES);
8293 }
8294
8295
PRE(mach_host_self)8296 PRE(mach_host_self)
8297 {
8298 PRINT("mach_host_self()");
8299 }
8300
POST(mach_host_self)8301 POST(mach_host_self)
8302 {
8303 vg_host_port = RES;
8304 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_host_self()");
8305 PRINT("host %#lx", RES);
8306 }
8307
8308
PRE(mach_task_self)8309 PRE(mach_task_self)
8310 {
8311 PRINT("mach_task_self()");
8312 }
8313
POST(mach_task_self)8314 POST(mach_task_self)
8315 {
8316 vg_task_port = RES;
8317 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mach_task_self()");
8318 PRINT("task %#lx", RES);
8319 }
8320
8321
PRE(syscall_thread_switch)8322 PRE(syscall_thread_switch)
8323 {
8324 PRINT("syscall_thread_switch(%s, %ld, %ld)",
8325 name_for_port(ARG1), ARG2, ARG3);
8326 PRE_REG_READ3(long, "syscall_thread_switch",
8327 mach_port_t,"thread", int,"option", natural_t,"timeout");
8328
8329 *flags |= SfMayBlock;
8330 }
8331
8332
PRE(semaphore_signal)8333 PRE(semaphore_signal)
8334 {
8335 PRINT("semaphore_signal(%s)", name_for_port(ARG1));
8336 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8337 }
8338
8339
PRE(semaphore_signal_all)8340 PRE(semaphore_signal_all)
8341 {
8342 PRINT("semaphore_signal_all(%s)", name_for_port(ARG1));
8343 PRE_REG_READ1(long, "semaphore_signal_all", semaphore_t,"semaphore");
8344 }
8345
8346
PRE(semaphore_signal_thread)8347 PRE(semaphore_signal_thread)
8348 {
8349 PRINT("semaphore_signal_thread(%s, %s)",
8350 name_for_port(ARG1), name_for_port(ARG2));
8351 PRE_REG_READ2(long, "semaphore_signal_thread",
8352 semaphore_t,"semaphore", mach_port_t,"thread");
8353 }
8354
8355
PRE(semaphore_wait)8356 PRE(semaphore_wait)
8357 {
8358 PRINT("semaphore_wait(%s)", name_for_port(ARG1));
8359 PRE_REG_READ1(long, "semaphore_signal", semaphore_t,"semaphore");
8360
8361 *flags |= SfMayBlock;
8362 }
8363
8364
PRE(semaphore_wait_signal)8365 PRE(semaphore_wait_signal)
8366 {
8367 PRINT("semaphore_wait_signal(%s, %s)",
8368 name_for_port(ARG1), name_for_port(ARG2));
8369 PRE_REG_READ2(long, "semaphore_wait_signal",
8370 semaphore_t,"wait_semaphore",
8371 semaphore_t,"signal_semaphore");
8372
8373 *flags |= SfMayBlock;
8374 }
8375
8376
PRE(semaphore_timedwait)8377 PRE(semaphore_timedwait)
8378 {
8379 PRINT("semaphore_timedwait(%s, %g seconds)",
8380 name_for_port(ARG1), ARG2+ARG3/1000000000.0);
8381 PRE_REG_READ3(long, "semaphore_wait_signal",
8382 semaphore_t,"semaphore",
8383 int,"wait_time_hi",
8384 int,"wait_time_lo");
8385
8386 *flags |= SfMayBlock;
8387 }
8388
8389
PRE(semaphore_timedwait_signal)8390 PRE(semaphore_timedwait_signal)
8391 {
8392 PRINT("semaphore_wait_signal(wait %s, signal %s, %g seconds)",
8393 name_for_port(ARG1), name_for_port(ARG2), ARG3+ARG4/1000000000.0);
8394 PRE_REG_READ4(long, "semaphore_wait_signal",
8395 semaphore_t,"wait_semaphore",
8396 semaphore_t,"signal_semaphore",
8397 int,"wait_time_hi",
8398 int,"wait_time_lo");
8399
8400 *flags |= SfMayBlock;
8401 }
8402
8403
PRE(__semwait_signal)8404 PRE(__semwait_signal)
8405 {
8406 /* 10.5 args: int cond_sem, int mutex_sem,
8407 int timeout, int relative,
8408 time_t tv_sec, time_t tv_nsec */
8409 PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %lds:%ldns)",
8410 name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5, ARG6);
8411 PRE_REG_READ6(long, "__semwait_signal",
8412 int,"cond_sem", int,"mutex_sem",
8413 int,"timeout", int,"relative",
8414 vki_time_t,"tv_sec", int,"tv_nsec");
8415
8416 *flags |= SfMayBlock;
8417 }
8418 // GrP provided this alternative version for 10.6, but NjN
8419 // reckons the 10.5 is is still correct for 10.6. So, retaining
8420 // Greg's version as a comment just in case we need it later.
8421 //PRE(__semwait_signal)
8422 //{
8423 // /* 10.5 args: int cond_sem, int mutex_sem,
8424 // int timeout, int relative,
8425 // const timespec *ts */
8426 // PRINT("__semwait_signal(wait %s, signal %s, %ld, %ld, %#lx)",
8427 // name_for_port(ARG1), name_for_port(ARG2), ARG3, ARG4, ARG5);
8428 // PRE_REG_READ5(int, "__semwait_signal",
8429 // int,cond_sem, int,mutex_sem,
8430 // int,timeout, int,relative,
8431 // const struct vki_timespec *,ts);
8432 //
8433 // if (ARG5) PRE_MEM_READ ("__semwait_signal(ts)",
8434 // ARG5, sizeof(struct vki_timespec));
8435 //
8436 // *flags |= SfMayBlock;
8437 //}
8438
8439
PRE(__thread_selfid)8440 PRE(__thread_selfid)
8441 {
8442 PRINT("__thread_selfid ()");
8443 PRE_REG_READ0(vki_uint64_t, "__thread_selfid");
8444 }
8445
PRE(task_for_pid)8446 PRE(task_for_pid)
8447 {
8448 PRINT("task_for_pid(%s, %ld, %#lx)", name_for_port(ARG1), ARG2, ARG3);
8449 PRE_REG_READ3(long, "task_for_pid",
8450 mach_port_t,"target",
8451 vki_pid_t, "pid", mach_port_t *,"task");
8452 PRE_MEM_WRITE("task_for_pid(task)", ARG3, sizeof(mach_port_t));
8453 }
8454
POST(task_for_pid)8455 POST(task_for_pid)
8456 {
8457 mach_port_t task;
8458
8459 POST_MEM_WRITE(ARG3, sizeof(mach_port_t));
8460
8461 task = *(mach_port_t *)ARG3;
8462 record_named_port(tid, task, MACH_PORT_RIGHT_SEND, "task-%p");
8463 PRINT("task 0x%x", task);
8464 }
8465
8466
PRE(pid_for_task)8467 PRE(pid_for_task)
8468 {
8469 PRINT("pid_for_task(%s, %#lx)", name_for_port(ARG1), ARG2);
8470 PRE_REG_READ2(long, "task_for_pid", mach_port_t,"task", vki_pid_t *,"pid");
8471 PRE_MEM_WRITE("task_for_pid(pid)", ARG2, sizeof(vki_pid_t));
8472 }
8473
POST(pid_for_task)8474 POST(pid_for_task)
8475 {
8476 vki_pid_t pid;
8477
8478 POST_MEM_WRITE(ARG2, sizeof(vki_pid_t));
8479
8480 pid = *(vki_pid_t *)ARG2;
8481 PRINT("pid %u", pid);
8482 }
8483
8484
PRE(mach_timebase_info)8485 PRE(mach_timebase_info)
8486 {
8487 PRINT("mach_timebase_info(%#lx)", ARG1);
8488 PRE_REG_READ1(long, "mach_timebase_info", void *,"info");
8489 PRE_MEM_WRITE("mach_timebase_info(info)", ARG1, sizeof(struct vki_mach_timebase_info));
8490 }
8491
POST(mach_timebase_info)8492 POST(mach_timebase_info)
8493 {
8494 POST_MEM_WRITE(ARG1, sizeof(struct vki_mach_timebase_info));
8495 }
8496
8497
PRE(mach_wait_until)8498 PRE(mach_wait_until)
8499 {
8500 #if VG_WORDSIZE == 8
8501 PRINT("mach_wait_until(%lu)", ARG1);
8502 PRE_REG_READ1(long, "mach_wait_until",
8503 unsigned long long,"deadline");
8504 #else
8505 PRINT("mach_wait_until(%llu)", LOHI64(ARG1, ARG2));
8506 PRE_REG_READ2(long, "mach_wait_until",
8507 int,"deadline_hi", int,"deadline_lo");
8508 #endif
8509 *flags |= SfMayBlock;
8510 }
8511
8512
PRE(mk_timer_create)8513 PRE(mk_timer_create)
8514 {
8515 PRINT("mk_timer_create()");
8516 PRE_REG_READ0(long, "mk_timer_create");
8517 }
8518
POST(mk_timer_create)8519 POST(mk_timer_create)
8520 {
8521 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "mk_timer-%p");
8522 }
8523
8524
PRE(mk_timer_destroy)8525 PRE(mk_timer_destroy)
8526 {
8527 PRINT("mk_timer_destroy(%s)", name_for_port(ARG1));
8528 PRE_REG_READ1(long, "mk_timer_destroy", mach_port_t,"name");
8529
8530 // Must block to prevent race (other thread allocates and
8531 // notifies after we deallocate but before we notify)
8532 *flags &= ~SfMayBlock;
8533 }
8534
POST(mk_timer_destroy)8535 POST(mk_timer_destroy)
8536 {
8537 // Must have cleared SfMayBlock in PRE to prevent race
8538 record_port_destroy(ARG1);
8539 }
8540
8541
PRE(mk_timer_arm)8542 PRE(mk_timer_arm)
8543 {
8544 #if VG_WORDSIZE == 8
8545 PRINT("mk_timer_arm(%s, %lu)", name_for_port(ARG1), ARG2);
8546 PRE_REG_READ2(long, "mk_timer_arm", mach_port_t,"name",
8547 unsigned long,"expire_time");
8548 #else
8549 PRINT("mk_timer_arm(%s, %llu)", name_for_port(ARG1), LOHI64(ARG2, ARG3));
8550 PRE_REG_READ3(long, "mk_timer_arm", mach_port_t,"name",
8551 int,"expire_time_hi", int,"expire_time_lo");
8552 #endif
8553 }
8554
8555
PRE(mk_timer_cancel)8556 PRE(mk_timer_cancel)
8557 {
8558 PRINT("mk_timer_cancel(%s, %#lx)", name_for_port(ARG1), ARG2);
8559 PRE_REG_READ2(long, "mk_timer_cancel",
8560 mach_port_t,"name", Addr,"result_time");
8561 if (ARG2) {
8562 PRE_MEM_WRITE("mk_timer_cancel(result_time)", ARG2,sizeof(vki_uint64_t));
8563 }
8564 }
8565
POST(mk_timer_cancel)8566 POST(mk_timer_cancel)
8567 {
8568 if (ARG2) {
8569 POST_MEM_WRITE(ARG2, sizeof(vki_uint64_t));
8570 }
8571 }
8572
8573
PRE(iokit_user_client_trap)8574 PRE(iokit_user_client_trap)
8575 {
8576 PRINT("iokit_user_client_trap(%s, %ld, %lx, %lx, %lx, %lx, %lx, %lx)",
8577 name_for_port(ARG1), ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
8578 PRE_REG_READ8(kern_return_t, "iokit_user_client_trap",
8579 mach_port_t,connect, unsigned int,index,
8580 uintptr_t,p1, uintptr_t,p2, uintptr_t,p3,
8581 uintptr_t,p4, uintptr_t,p5, uintptr_t,p6);
8582
8583 // can't do anything else with this in general
8584 // might be able to use connect+index to choose something sometimes
8585 }
8586
POST(iokit_user_client_trap)8587 POST(iokit_user_client_trap)
8588 {
8589 ML_(sync_mappings)("after", "iokit_user_client_trap", ARG2);
8590 }
8591
8592
PRE(swtch)8593 PRE(swtch)
8594 {
8595 PRINT("swtch ( )");
8596 PRE_REG_READ0(long, "swtch");
8597
8598 *flags |= SfMayBlock;
8599 }
8600
8601
PRE(swtch_pri)8602 PRE(swtch_pri)
8603 {
8604 PRINT("swtch_pri ( %ld )", ARG1);
8605 PRE_REG_READ1(long, "swtch_pri", int,"pri");
8606
8607 *flags |= SfMayBlock;
8608 }
8609
8610
PRE(FAKE_SIGRETURN)8611 PRE(FAKE_SIGRETURN)
8612 {
8613 /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
8614 an explanation of what follows. */
8615 /* This handles the fake signal-return system call created by
8616 sigframe-x86-darwin.c. */
8617 /* See also comments just below on PRE(sigreturn). */
8618
8619 PRINT("FAKE_SIGRETURN ( )");
8620
8621 vg_assert(VG_(is_valid_tid)(tid));
8622 vg_assert(tid >= 1 && tid < VG_N_THREADS);
8623 vg_assert(VG_(is_running_thread)(tid));
8624
8625 /* Remove the signal frame from this thread's (guest) stack,
8626 in the process restoring the pre-signal guest state. */
8627 VG_(sigframe_destroy)(tid, True);
8628
8629 /* Tell the driver not to update the guest state with the "result",
8630 and set a bogus result to keep it happy. */
8631 *flags |= SfNoWriteResult;
8632 SET_STATUS_Success(0);
8633
8634 /* Check to see if any signals arose as a result of this. */
8635 *flags |= SfPollAfter;
8636 }
8637
8638
PRE(sigreturn)8639 PRE(sigreturn)
8640 {
8641 /* This is the "real" sigreturn. But because we construct all the
8642 signal frames ourselves (of course, in m_sigframe), this cannot
8643 happen as a result of normal signal delivery. I think it
8644 happens only when doing siglongjmp, in which case Darwin's Libc
8645 appears to use it for two different purposes: to mess with the
8646 per-thread sigaltstack flags (as per arg 2), or to restore the
8647 thread's state from a ucontext* (as per arg 1). */
8648
8649 PRINT("sigreturn ( uctx=%#lx, infostyle=%#lx )", ARG1, ARG2);
8650
8651 vg_assert(VG_(is_valid_tid)(tid));
8652 vg_assert(tid >= 1 && tid < VG_N_THREADS);
8653 vg_assert(VG_(is_running_thread)(tid));
8654
8655 if (ARG2 == VKI_UC_SET_ALT_STACK) {
8656 /* This is confusing .. the darwin kernel sources imply there is
8657 a per-thread on-altstack/not-on-altstack flag, which is set
8658 by this flag. Just ignore it and claim success for the time
8659 being. */
8660 VG_(debugLog)(0, "syswrap-darwin",
8661 "WARNING: Ignoring sigreturn( ..., "
8662 "UC_SET_ALT_STACK );\n");
8663 SET_STATUS_Success(0);
8664 return;
8665 }
8666 if (ARG2 == VKI_UC_RESET_ALT_STACK) {
8667 /* Ditto */
8668 VG_(debugLog)(0, "syswrap-darwin",
8669 "WARNING: Ignoring sigreturn( ..., "
8670 "UC_RESET_ALT_STACK );\n");
8671 SET_STATUS_Success(0);
8672 return;
8673 }
8674
8675 /* Otherwise claim this isn't supported. (Could be
8676 catastrophic).
8677
8678 What do we have to do if we do need to support it?
8679
8680 1. Change the second argument of VG_(sigframe_destroy) from
8681 "Bool isRT" to "UInt sysno", so we can pass the syscall
8682 number, so it can distinguish this case from the
8683 __NR_DARWIN_FAKE_SIGRETURN case.
8684
8685 2. In VG_(sigframe_destroy), look at sysno to distinguish the
8686 cases. For __NR_DARWIN_FAKE_SIGRETURN, behave as at present.
8687 For this case, restore the thread's CPU state (or at least
8688 the integer regs) from the ucontext in ARG1 (and do all the
8689 other "signal-returns" stuff too).
8690
8691 3. For (2), how do we know where the ucontext is? One way is to
8692 temporarily copy ARG1 into this thread's guest_EBX (or any
8693 other int reg), and have VG_(sigframe_destroy) read
8694 guest_EBX. Why is it ok to trash guest_EBX (or any other int
8695 reg)? Because VG_(sigframe_destroy) is just about to
8696 overwrite all the regs anyway -- since the primary purpose of
8697 calling it is to restore the register state from the ucontext
8698 pointed to by ARG1.
8699
8700 Hey, it's uggerly. But at least it's documented.
8701 */
8702 /* But in the meantime ... */
8703 VG_(debugLog)(0, "syswrap-darwin",
8704 "WARNING: Ignoring sigreturn( uctx=..., 0 );\n");
8705 VG_(debugLog)(0, "syswrap-darwin",
8706 "WARNING: Thread/program/Valgrind "
8707 "will likely segfault now.\n");
8708 VG_(debugLog)(0, "syswrap-darwin",
8709 "WARNING: Please file a bug report at "
8710 "http://www.valgrind.org.\n");
8711 SET_STATUS_Failure( VKI_ENOSYS );
8712 }
8713
8714
8715 /* ---------------------------------------------------------------------
8716 machine-dependent traps
8717 ------------------------------------------------------------------ */
8718
8719 #if defined(VGA_x86)
alloc_zeroed_x86_LDT(void)8720 static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
8721 {
8722 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
8723 return VG_(calloc)("syswrap-darwin.ldt", nbytes, 1);
8724 }
8725 #endif
8726
PRE(thread_fast_set_cthread_self)8727 PRE(thread_fast_set_cthread_self)
8728 {
8729 PRINT("thread_fast_set_cthread_self ( %#lx )", ARG1);
8730 PRE_REG_READ1(void, "thread_fast_set_cthread_self", struct pthread_t *, self);
8731
8732 #if defined(VGA_x86)
8733 // Point the USER_CTHREAD ldt entry (slot 6, reg 0x37) at this pthread
8734 {
8735 VexGuestX86SegDescr *ldt;
8736 ThreadState *tst = VG_(get_ThreadState)(tid);
8737 ldt = (VexGuestX86SegDescr *)tst->arch.vex.guest_LDT;
8738 if (!ldt) {
8739 ldt = alloc_zeroed_x86_LDT();
8740 tst->arch.vex.guest_LDT = (HWord)ldt;
8741 }
8742 VG_(memset)(&ldt[6], 0, sizeof(ldt[6]));
8743 ldt[6].LdtEnt.Bits.LimitLow = 1;
8744 ldt[6].LdtEnt.Bits.LimitHi = 0;
8745 ldt[6].LdtEnt.Bits.BaseLow = ARG1 & 0xffff;
8746 ldt[6].LdtEnt.Bits.BaseMid = (ARG1 >> 16) & 0xff;
8747 ldt[6].LdtEnt.Bits.BaseHi = (ARG1 >> 24) & 0xff;
8748 ldt[6].LdtEnt.Bits.Pres = 1; // ACC_P
8749 ldt[6].LdtEnt.Bits.Dpl = 3; // ACC_PL_U
8750 ldt[6].LdtEnt.Bits.Type = 0x12; // ACC_DATA_W
8751 ldt[6].LdtEnt.Bits.Granularity = 1; // SZ_G
8752 ldt[6].LdtEnt.Bits.Default_Big = 1; // SZ_32
8753
8754 tst->os_state.pthread = ARG1;
8755 tst->arch.vex.guest_GS = 0x37;
8756
8757 // What we would like to do is:
8758 // SET_STATUS_Success(0x37);
8759 // but that doesn't work, because this is a MDEP-class syscall,
8760 // and SET_STATUS_Success creates a UNIX-class syscall result.
8761 // Hence we have to laboriously construct the full SysRes "by hand"
8762 // and use that to set the syscall return status.
8763 SET_STATUS_from_SysRes(
8764 VG_(mk_SysRes_x86_darwin)(
8765 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
8766 False, 0, 0x37
8767 )
8768 );
8769 }
8770
8771 #elif defined(VGA_amd64)
8772 // GrP fixme bigger hack than x86
8773 {
8774 ThreadState *tst = VG_(get_ThreadState)(tid);
8775 tst->os_state.pthread = ARG1;
8776 tst->arch.vex.guest_GS_CONST = ARG1;
8777 // SET_STATUS_Success(0x60);
8778 // see comments on x86 case just above
8779 SET_STATUS_from_SysRes(
8780 VG_(mk_SysRes_amd64_darwin)(
8781 VG_DARWIN_SYSNO_CLASS(__NR_thread_fast_set_cthread_self),
8782 False, 0, 0x60
8783 )
8784 );
8785 }
8786
8787 #else
8788 #error unknown architecture
8789 #endif
8790 }
8791
8792
8793 /* ---------------------------------------------------------------------
8794 Added for OSX 10.7 (Lion)
8795 ------------------------------------------------------------------ */
8796
8797 #if DARWIN_VERS >= DARWIN_10_7
8798
PRE(getaudit_addr)8799 PRE(getaudit_addr)
8800 {
8801 PRINT("getaudit_addr(%#lx, %lu)", ARG1, ARG2);
8802 PRE_REG_READ1(void*, "auditinfo_addr", int, "length");
8803 PRE_MEM_WRITE("getaudit_addr(auditinfo_addr)", ARG1, ARG2);
8804 }
POST(getaudit_addr)8805 POST(getaudit_addr)
8806 {
8807 POST_MEM_WRITE(ARG1, ARG2);
8808 }
8809
PRE(psynch_mutexwait)8810 PRE(psynch_mutexwait)
8811 {
8812 PRINT("psynch_mutexwait(BOGUS)");
8813 *flags |= SfMayBlock;
8814 }
POST(psynch_mutexwait)8815 POST(psynch_mutexwait)
8816 {
8817 }
8818
PRE(psynch_mutexdrop)8819 PRE(psynch_mutexdrop)
8820 {
8821 PRINT("psynch_mutexdrop(BOGUS)");
8822 *flags |= SfMayBlock;
8823 }
POST(psynch_mutexdrop)8824 POST(psynch_mutexdrop)
8825 {
8826 }
8827
PRE(psynch_cvbroad)8828 PRE(psynch_cvbroad)
8829 {
8830 PRINT("psynch_cvbroad(BOGUS)");
8831 }
POST(psynch_cvbroad)8832 POST(psynch_cvbroad)
8833 {
8834 }
8835
PRE(psynch_cvsignal)8836 PRE(psynch_cvsignal)
8837 {
8838 PRINT("psynch_cvsignal(BOGUS)");
8839 }
POST(psynch_cvsignal)8840 POST(psynch_cvsignal)
8841 {
8842 }
8843
PRE(psynch_cvwait)8844 PRE(psynch_cvwait)
8845 {
8846 PRINT("psynch_cvwait(BOGUS)");
8847 *flags |= SfMayBlock;
8848 }
POST(psynch_cvwait)8849 POST(psynch_cvwait)
8850 {
8851 }
8852
PRE(psynch_rw_rdlock)8853 PRE(psynch_rw_rdlock)
8854 {
8855 PRINT("psynch_rw_rdlock(BOGUS)");
8856 *flags |= SfMayBlock;
8857 }
POST(psynch_rw_rdlock)8858 POST(psynch_rw_rdlock)
8859 {
8860 }
8861
PRE(psynch_rw_wrlock)8862 PRE(psynch_rw_wrlock)
8863 {
8864 PRINT("psynch_rw_wrlock(BOGUS)");
8865 *flags |= SfMayBlock;
8866 }
POST(psynch_rw_wrlock)8867 POST(psynch_rw_wrlock)
8868 {
8869 }
8870
PRE(psynch_rw_unlock)8871 PRE(psynch_rw_unlock)
8872 {
8873 PRINT("psynch_rw_unlock(BOGUS)");
8874 }
POST(psynch_rw_unlock)8875 POST(psynch_rw_unlock)
8876 {
8877 }
8878
PRE(psynch_cvclrprepost)8879 PRE(psynch_cvclrprepost)
8880 {
8881 PRINT("psynch_cvclrprepost(BOGUS)");
8882 *flags |= SfMayBlock;
8883 }
POST(psynch_cvclrprepost)8884 POST(psynch_cvclrprepost)
8885 {
8886 }
8887
8888 #endif /* DARWIN_VERS >= DARWIN_10_7 */
8889
8890
8891 /* ---------------------------------------------------------------------
8892 Added for OSX 10.8 (Mountain Lion)
8893 ------------------------------------------------------------------ */
8894
8895 /* About munge tags, eg munge_wllww.
8896
8897 Means the syscall takes 5 args. For a 64 bit process each arg
8898 occupies one 64-bit value and so the mapping to ARGn macros is
8899 direct. For a 32 bit process, this is more complex: 'w' denotes a
8900 32-bit word and 'l' a 64-bit word. Hence the wllww denotation
8901 indicates that, in a 64 bit process, the args are: ARG1 ARG2 ARG3
8902 ARG4 ARG5, but in a 32 bit process they are: ARG1 ARG3:ARG2
8903 ARG5:ARG4 ARG6 ARG7. And we have to laboriously reconstruct them
8904 in order to get sane values for the arguments in 32-bit
8905 processes. */
8906
munge_wwl(UWord * a1,UWord * a2,ULong * a3,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4)8907 static void munge_wwl(UWord* a1, UWord* a2, ULong* a3,
8908 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4)
8909 {
8910 # if defined(VGA_x86)
8911 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4);
8912 # else
8913 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
8914 # endif
8915 }
8916
munge_wll(UWord * a1,ULong * a2,ULong * a3,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4,UWord aRG5)8917 static void munge_wll(UWord* a1, ULong* a2, ULong* a3,
8918 UWord aRG1, UWord aRG2, UWord aRG3,
8919 UWord aRG4, UWord aRG5)
8920 {
8921 # if defined(VGA_x86)
8922 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
8923 # else
8924 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3;
8925 # endif
8926 }
8927
munge_wwlw(UWord * a1,UWord * a2,ULong * a3,UWord * a4,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4,UWord aRG5)8928 static void munge_wwlw(UWord* a1, UWord* a2, ULong* a3, UWord* a4,
8929 UWord aRG1, UWord aRG2, UWord aRG3,
8930 UWord aRG4, UWord aRG5)
8931 {
8932 # if defined(VGA_x86)
8933 *a1 = aRG1; *a2 = aRG2; *a3 = LOHI64(aRG3,aRG4); *a4 = aRG5;
8934 # else
8935 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
8936 # endif
8937 }
8938
munge_wwwl(UWord * a1,UWord * a2,UWord * a3,ULong * a4,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4,UWord aRG5)8939 static void munge_wwwl(UWord* a1, UWord* a2, UWord* a3, ULong* a4,
8940 UWord aRG1, UWord aRG2, UWord aRG3,
8941 UWord aRG4, UWord aRG5)
8942 {
8943 # if defined(VGA_x86)
8944 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = LOHI64(aRG4,aRG5);
8945 # else
8946 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4;
8947 # endif
8948 }
8949
munge_wllww(UWord * a1,ULong * a2,ULong * a3,UWord * a4,UWord * a5,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4,UWord aRG5,UWord aRG6,UWord aRG7)8950 static void munge_wllww(UWord* a1, ULong* a2, ULong* a3, UWord* a4, UWord* a5,
8951 UWord aRG1, UWord aRG2, UWord aRG3,
8952 UWord aRG4, UWord aRG5, UWord aRG6, UWord aRG7)
8953 {
8954 # if defined(VGA_x86)
8955 *a1 = aRG1; *a2 = LOHI64(aRG2,aRG3); *a3 = LOHI64(aRG4,aRG5);
8956 *a4 = aRG6; *a5 = aRG7;
8957 # else
8958 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5;
8959 # endif
8960 }
8961
munge_wwllww(UWord * a1,UWord * a2,ULong * a3,ULong * a4,UWord * a5,UWord * a6,UWord aRG1,UWord aRG2,UWord aRG3,UWord aRG4,UWord aRG5,UWord aRG6,UWord aRG7,UWord aRG8)8962 static void munge_wwllww(UWord* a1, UWord* a2, ULong* a3,
8963 ULong* a4, UWord* a5, UWord* a6,
8964 UWord aRG1, UWord aRG2, UWord aRG3, UWord aRG4,
8965 UWord aRG5, UWord aRG6, UWord aRG7, UWord aRG8)
8966 {
8967 # if defined(VGA_x86)
8968 *a1 = aRG1; *a2 = aRG2;
8969 *a3 = LOHI64(aRG3,aRG4); *a4 = LOHI64(aRG5,aRG6);
8970 *a5 = aRG7; *a6 = aRG8;
8971 # else
8972 *a1 = aRG1; *a2 = aRG2; *a3 = aRG3; *a4 = aRG4; *a5 = aRG5; *a6 = aRG6;
8973 # endif
8974 }
8975
8976 #if DARWIN_VERS >= DARWIN_10_8
8977
PRE(kernelrpc_mach_vm_allocate_trap)8978 PRE(kernelrpc_mach_vm_allocate_trap)
8979 {
8980 UWord a1; UWord a2; ULong a3; UWord a4;
8981 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
8982 PRINT("kernelrpc_mach_vm_allocate_trap"
8983 "(target:%s, address:%p, size:%#llx, flags:%#lx)",
8984 name_for_port(a1), *(void**)a2, a3, a4);
8985 PRE_MEM_WRITE("kernelrpc_mach_vm_allocate_trap(address)",
8986 a2, sizeof(void*));
8987 }
POST(kernelrpc_mach_vm_allocate_trap)8988 POST(kernelrpc_mach_vm_allocate_trap)
8989 {
8990 UWord a1; UWord a2; ULong a3; UWord a4;
8991 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
8992 PRINT("address:%p size:%#llx", *(void**)a2, a3);
8993 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
8994 POST_MEM_WRITE(a2, sizeof(void*));
8995 }
8996 if (a1 == mach_task_self()) {
8997 # if 1
8998 ML_(sync_mappings)("POST(kernelrpc_mach_vm_allocate_trap)", "??", 0);
8999 # else
9000 /* This is nearly right, but not always -- sometimes the mapping
9001 appears to be r--, for some reason. Hence resync. */
9002 ML_(notify_core_and_tool_of_mmap)(
9003 *(UWord*)a2, a3,
9004 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9005 # endif
9006 }
9007 }
9008
PRE(kernelrpc_mach_vm_deallocate_trap)9009 PRE(kernelrpc_mach_vm_deallocate_trap)
9010 {
9011 UWord a1; ULong a2; ULong a3;
9012 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9013 PRINT("kernelrpc_mach_vm_deallocate_trap"
9014 "(target:%#lx, address:%#llx, size:%#llx)", a1, a2, a3);
9015 }
POST(kernelrpc_mach_vm_deallocate_trap)9016 POST(kernelrpc_mach_vm_deallocate_trap)
9017 {
9018 UWord a1; ULong a2; ULong a3;
9019 munge_wll(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4, ARG5);
9020 // kernelrpc_mach_vm_deallocate_trap could be call with
9021 // address ==0 && size == 0,
9022 // we shall not notify any unmap then
9023 if (a3)
9024 ML_(notify_core_and_tool_of_munmap)(a2, a3);
9025 }
9026
PRE(kernelrpc_mach_vm_protect_trap)9027 PRE(kernelrpc_mach_vm_protect_trap)
9028 {
9029 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9030 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9031 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9032 PRINT("kernelrpc_mach_vm_protect_trap"
9033 "(task:%#lx, address:%#llx, size:%#llx,"
9034 " set_maximum:%#lx, new_prot:%#lx)", a1, a2, a3, a4, a5);
9035 }
POST(kernelrpc_mach_vm_protect_trap)9036 POST(kernelrpc_mach_vm_protect_trap)
9037 {
9038 UWord a1; ULong a2; ULong a3; UWord a4; UWord a5;
9039 munge_wllww(&a1, &a2, &a3, &a4, &a5,
9040 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9041 if (/*a4 set_maximum == 0 && */a1 == mach_task_self()) {
9042 ML_(notify_core_and_tool_of_mprotect)((Addr)a2, (SizeT)a3, (Int)a5);
9043 VG_(di_notify_vm_protect)((Addr)a2, (SizeT)a3, (UInt)a5);
9044 }
9045 }
9046
PRE(kernelrpc_mach_port_allocate_trap)9047 PRE(kernelrpc_mach_port_allocate_trap)
9048 {
9049 // munge_www -- no need to call helper
9050 PRINT("kernelrpc_mach_port_allocate_trap(task:%#lx, mach_port_right_t:%#lx)",
9051 ARG1, ARG2);
9052 PRE_MEM_WRITE("kernelrpc_mach_port_allocate_trap(name)",
9053 ARG3, sizeof(mach_port_name_t));
9054 }
POST(kernelrpc_mach_port_allocate_trap)9055 POST(kernelrpc_mach_port_allocate_trap)
9056 {
9057 // munge_www -- no need to call helper
9058 POST_MEM_WRITE(ARG3, sizeof(mach_port_name_t));
9059 PRINT(", name:%#x", *(mach_port_name_t*)ARG3);
9060 record_unnamed_port(tid, *(mach_port_name_t *)ARG3, ARG2);
9061 }
9062
PRE(kernelrpc_mach_port_destroy_trap)9063 PRE(kernelrpc_mach_port_destroy_trap)
9064 {
9065 // munge_ww -- no need to call helper
9066 PRINT("kernelrpc_mach_port_destroy_trap(task:%#lx, name:%#lx)", ARG1, ARG2);
9067 record_port_destroy(ARG2);
9068 }
9069
PRE(kernelrpc_mach_port_deallocate_trap)9070 PRE(kernelrpc_mach_port_deallocate_trap)
9071 {
9072 // munge_ww -- no need to call helper
9073 PRINT("kernelrpc_mach_port_deallocate_trap(task:%#lx, name:%#lx ) FIXME",
9074 ARG1, ARG2);
9075 }
POST(kernelrpc_mach_port_deallocate_trap)9076 POST(kernelrpc_mach_port_deallocate_trap)
9077 {
9078 // munge_ww -- no need to call helper
9079 }
9080
PRE(kernelrpc_mach_port_mod_refs_trap)9081 PRE(kernelrpc_mach_port_mod_refs_trap)
9082 {
9083 // munge_wwww -- no need to call helper
9084 PRINT("kernelrpc_mach_port_mod_refs_trap"
9085 "(task:%#lx, name:%#lx, right:%#lx refs:%#lx) FIXME",
9086 ARG1, ARG2, ARG3, ARG4);
9087 }
9088
PRE(kernelrpc_mach_port_move_member_trap)9089 PRE(kernelrpc_mach_port_move_member_trap)
9090 {
9091 // munge_www -- no need to call helper
9092 PRINT("kernelrpc_mach_port_move_member_trap"
9093 "(task:%#lx, name:%#lx, after:%#lx ) FIXME",
9094 ARG1, ARG2, ARG3);
9095 }
9096
PRE(kernelrpc_mach_port_insert_right_trap)9097 PRE(kernelrpc_mach_port_insert_right_trap)
9098 {
9099 //munge_wwww -- no need to call helper
9100 PRINT("kernelrpc_mach_port_insert_right_trap(FIXME)"
9101 "(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9102 }
9103
PRE(kernelrpc_mach_port_insert_member_trap)9104 PRE(kernelrpc_mach_port_insert_member_trap)
9105 {
9106 // munge_www -- no need to call helper
9107 PRINT("kernelrpc_mach_port_insert_member_trap(FIXME)"
9108 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9109 }
9110
PRE(kernelrpc_mach_port_extract_member_trap)9111 PRE(kernelrpc_mach_port_extract_member_trap)
9112 {
9113 // munge_www -- no need to call helper
9114 PRINT("kernelrpc_mach_port_extract_member_trap(FIXME)"
9115 "(%lx,%lx,%lx)", ARG1, ARG2, ARG3);
9116 }
9117
PRE(iopolicysys)9118 PRE(iopolicysys)
9119 {
9120 // munge_???
9121 PRINT("iopolicysys(FIXME)(0x%lx, 0x%lx, 0x%lx)", ARG1, ARG2, ARG3);
9122 /* mem effects unknown */
9123 }
POST(iopolicysys)9124 POST(iopolicysys)
9125 {
9126 // munge_???
9127 }
9128
PRE(process_policy)9129 PRE(process_policy)
9130 {
9131 // munge_???
9132 PRINT("process_policy(FIXME)("
9133 "scope:0x%lx, action:0x%lx, policy:0x%lx, policy_subtype:0x%lx,"
9134 " attr:%lx, target_pid:%lx, target_threadid:%lx)",
9135 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
9136 /* mem effects unknown */
9137 }
POST(process_policy)9138 POST(process_policy)
9139 {
9140 // munge_???
9141 }
9142
9143 #endif /* DARWIN_VERS >= DARWIN_10_8 */
9144
9145
9146 /* ---------------------------------------------------------------------
9147 Added for OSX 10.9 (Mavericks)
9148 ------------------------------------------------------------------ */
9149
9150 #if DARWIN_VERS >= DARWIN_10_9
9151
PRE(kernelrpc_mach_vm_map_trap)9152 PRE(kernelrpc_mach_vm_map_trap)
9153 {
9154 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9155 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9156 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9157 PRINT("kernelrpc_mach_vm_map_trap"
9158 "(target:%#lx, address:%p, size:%#llx,"
9159 " mask:%#llx, flags:%#lx, cur_prot:%#lx)",
9160 a1, *(void**)a2, a3, a4, a5, a6);
9161 PRE_MEM_WRITE("kernelrpc_mach_vm_map_trap(address)", a2, sizeof(void*));
9162 }
POST(kernelrpc_mach_vm_map_trap)9163 POST(kernelrpc_mach_vm_map_trap)
9164 {
9165 UWord a1; UWord a2; ULong a3; ULong a4; UWord a5; UWord a6;
9166 munge_wwllww(&a1, &a2, &a3, &a4, &a5, &a6,
9167 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8);
9168 PRINT("-> address:%p", *(void**)a2);
9169 if (ML_(safe_to_deref)((void*)a2, sizeof(void*))) {
9170 POST_MEM_WRITE(a2, sizeof(void*));
9171 }
9172 ML_(notify_core_and_tool_of_mmap)(
9173 *(mach_vm_address_t*)a2, a3,
9174 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0);
9175 // ML_(sync_mappings)("after", "kernelrpc_mach_vm_map_trap", 0);
9176 }
9177
PRE(kernelrpc_mach_port_construct_trap)9178 PRE(kernelrpc_mach_port_construct_trap)
9179 {
9180 UWord a1; UWord a2; ULong a3; UWord a4;
9181 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9182 PRINT("kernelrpc_mach_port_construct_trap(FIXME)"
9183 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9184 }
9185
PRE(kernelrpc_mach_port_destruct_trap)9186 PRE(kernelrpc_mach_port_destruct_trap)
9187 {
9188 UWord a1; UWord a2; UWord a3; ULong a4;
9189 munge_wwwl(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9190 PRINT("kernelrpc_mach_port_destruct_trap(FIXME)"
9191 "(%lx,%lx,%lx,%llx)", a1, a2, a3, a4);
9192 }
9193
PRE(kernelrpc_mach_port_guard_trap)9194 PRE(kernelrpc_mach_port_guard_trap)
9195 {
9196 UWord a1; UWord a2; ULong a3; UWord a4;
9197 munge_wwlw(&a1, &a2, &a3, &a4, ARG1, ARG2, ARG3, ARG4, ARG5);
9198 PRINT("kernelrpc_mach_port_guard_trap(FIXME)"
9199 "(%lx,%lx,%llx,%lx)", a1, a2, a3, a4);
9200 }
9201
PRE(kernelrpc_mach_port_unguard_trap)9202 PRE(kernelrpc_mach_port_unguard_trap)
9203 {
9204 // munge_wwl
9205 UWord a1; UWord a2; ULong a3;
9206 munge_wwl(&a1, &a2, &a3, ARG1, ARG2, ARG3, ARG4);
9207 PRINT("kernelrpc_mach_port_unguard_trap(FIXME)"
9208 "(%lx,%lx,%llx)", a1, a2, a3);
9209 }
9210
9211 #endif /* DARWIN_VERS >= DARWIN_10_9 */
9212
9213
9214 /* ---------------------------------------------------------------------
9215 Added for OSX 10.10 (Yosemite)
9216 ------------------------------------------------------------------ */
9217
9218 #if DARWIN_VERS >= DARWIN_10_10
9219
PRE(necp_match_policy)9220 PRE(necp_match_policy)
9221 {
9222 // int necp_match_policy(uint8_t *parameters, size_t parameters_size,
9223 // struct necp_aggregate_result *returned_result)
9224 PRINT("necp_match_policy(FIXME)(%lx,%ld, %lx)", ARG1, ARG2, ARG3);
9225 PRE_REG_READ3(int, "necp_match_policy", uint8_t*, parameters,
9226 size_t, parameters_size, struct necp_aggregate_result*,
9227 returned_result);
9228 PRE_MEM_READ("necp_match_policy(returned_result)", ARG1, ARG2);
9229 }
POST(necp_match_policy)9230 POST(necp_match_policy)
9231 {
9232 POST_MEM_WRITE(ARG3, sizeof(struct vki_necp_aggregate_result));
9233 }
9234
PRE(sysctlbyname)9235 PRE(sysctlbyname)
9236 {
9237 UWord name = ARG1;
9238 UWord namelen = ARG2;
9239 UWord oldp = ARG3;
9240 UWord oldlenp = ARG4;
9241 UWord newp = ARG5;
9242 UWord newlen = ARG6;
9243
9244 PRINT( "sysctlbyname ( %#lx,%ld, %#lx,%#lx, %#lx,%ld )",
9245 name, namelen, oldp, oldlenp, newp, newlen );
9246
9247 PRE_REG_READ6(int, "sysctlbyname", char*, name, size_t, namelen,
9248 void*, oldp, vki_size_t *, oldlenp,
9249 void*, newp, vki_size_t *, newlenp);
9250
9251 // reads name[0..namelen-1]
9252 PRE_MEM_READ("sysctlbyname(name)", name, namelen);
9253
9254 if (VG_(clo_trace_syscalls)) {
9255 UInt i;
9256 const HChar* t_name = (const HChar*)name;
9257 VG_(printf)(" name: ");
9258 for (i = 0; i < namelen; i++) {
9259 VG_(printf)("%c", t_name[i]);
9260 }
9261 VG_(printf)(" ");
9262 }
9263
9264 Bool is_kern_dot_userstack
9265 = False;
9266
9267 common_PRE_sysctl( /*IMPLICIT ARGS*/tid,status,flags,/*!IMPLICIT_ARGS*/
9268 is_kern_dot_userstack, oldp, oldlenp, newp, newlen );
9269 }
POST(sysctlbyname)9270 POST(sysctlbyname)
9271 {
9272 UWord oldp = ARG3;
9273 UWord oldlenp = ARG4;
9274
9275 if (SUCCESS || ERR == VKI_ENOMEM) {
9276 // sysctl can write truncated data and return VKI_ENOMEM
9277 if (oldlenp) {
9278 POST_MEM_WRITE(oldlenp, sizeof(size_t));
9279 }
9280 if (oldp && oldlenp) {
9281 POST_MEM_WRITE(oldp, *(size_t*)oldlenp);
9282 }
9283 }
9284 }
9285
PRE(getattrlistbulk)9286 PRE(getattrlistbulk)
9287 {
9288 // int getattrlistbulk(int dirfd, struct attrlist *alist,
9289 // void *attributeBuffer, size_t bufferSize,
9290 // uint64_t options);
9291 // Presumably the last arg is value-pair in the 32 bit case.
9292 PRINT("getattrlistbulk(FIXME)(%ld, %lx, %lx,%lu, %lu)",
9293 ARG1, ARG2, ARG3, ARG4, ARG5);
9294 PRE_REG_READ5(int, "getattrlistbulk", int, dirfd, void*, list,
9295 void*, attributeBuffer, size_t, bufferSize,
9296 uint32_t, options_lo32);
9297 PRE_MEM_READ("getattrlistbulk(alist)", ARG2, sizeof(struct vki_attrlist));
9298 PRE_MEM_WRITE("getattrlistbulk(attributeBuffer)", ARG3, ARG4);
9299 }
POST(getattrlistbulk)9300 POST(getattrlistbulk)
9301 {
9302 // FIXME: this isn't right. It seems as if what is returned is a
9303 // set of variable-length records -- see complication in
9304 // POST(getattrlist). For now, just paint the entire result buffer
9305 // as defined. Sigh.
9306 vg_assert(SUCCESS);
9307 if (ARG3 && /* "at least one output element was written" */RES > 0)
9308 POST_MEM_WRITE(ARG3, ARG4);
9309 }
9310
PRE(readlinkat)9311 PRE(readlinkat)
9312 {
9313 Word saved = SYSNO;
9314
9315 PRINT("readlinkat ( %ld, %#lx(%s), %#lx, %llu )", ARG1,ARG2,(char*)ARG2,ARG3,(ULong)ARG4);
9316 PRE_REG_READ4(long, "readlinkat",
9317 int, dfd, const char *, path, char *, buf, int, bufsiz);
9318 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
9319 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
9320
9321 /*
9322 * Refer to coregrind/m_syswrap/syswrap-linux.c
9323 */
9324 {
9325 /* Normal case */
9326 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
9327 }
9328
9329 if (SUCCESS && RES > 0)
9330 POST_MEM_WRITE( ARG3, RES );
9331 }
9332
PRE(bsdthread_ctl)9333 PRE(bsdthread_ctl)
9334 {
9335 // int bsdthread_ctl(user_addr_t cmd, user_addr_t arg1,
9336 // user_addr_t arg2, user_addr_t arg3)
9337 PRINT("bsdthread_ctl(FIXME)(%lx,%lx,%lx,%lx)", ARG1, ARG2, ARG3, ARG4);
9338 PRE_REG_READ4(int, "bsdthreadctl",
9339 void*, cmd, void*, arg1, void*, arg2, void*, arg3);
9340 }
9341
PRE(guarded_open_dprotected_np)9342 PRE(guarded_open_dprotected_np)
9343 {
9344 PRINT("guarded_open_dprotected_np("
9345 "path:%#lx(%s), guard:%#lx, guardflags:%#lx, flags:%#lx, "
9346 "dpclass:%#lx, dpflags: %#lx) FIXME",
9347 ARG1, (char*)ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
9348 }
9349
PRE(guarded_write_np)9350 PRE(guarded_write_np)
9351 {
9352 PRINT("guarded_write_np(fd:%ld, guard:%#lx, cbuf:%#lx, nbyte:%llu) FIXME",
9353 ARG1, ARG2, ARG3, (ULong)ARG4);
9354 }
9355
PRE(guarded_pwrite_np)9356 PRE(guarded_pwrite_np)
9357 {
9358 PRINT("guarded_pwrite_np(fd:%ld, guard:%#lx, buf:%#lx, nbyte:%llu, offset:%lld) FIXME",
9359 ARG1, ARG2, ARG3, (ULong)ARG4, (Long)ARG5);
9360 }
9361
PRE(guarded_writev_np)9362 PRE(guarded_writev_np)
9363 {
9364 PRINT("guarded_writev_np(fd:%ld, guard:%#lx, iovp:%#lx, iovcnt:%llu) FIXME",
9365 ARG1, ARG2, ARG3, (ULong)ARG4);
9366 }
9367
9368 #endif /* DARWIN_VERS >= DARWIN_10_10 */
9369
9370
9371 /* ---------------------------------------------------------------------
9372 syscall tables
9373 ------------------------------------------------------------------ */
9374
9375 /* Add a Darwin-specific, arch-independent wrapper to a syscall table. */
9376
9377 #define MACX_(sysno, name) \
9378 WRAPPER_ENTRY_X_(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
9379
9380 #define MACXY(sysno, name) \
9381 WRAPPER_ENTRY_XY(darwin, VG_DARWIN_SYSNO_INDEX(sysno), name)
9382
9383 #define _____(sysno) GENX_(sysno, sys_ni_syscall) /* UNIX style only */
9384
9385 /*
9386 _____ : unsupported by the kernel (sys_ni_syscall) (UNIX-style only)
9387 unfortunately misused for Mach too, causing assertion failures
9388 // _____ : unimplemented in valgrind
9389 GEN : handlers are in syswrap-generic.c
9390 MAC : handlers are in this file
9391 X_ : PRE handler only
9392 XY : PRE and POST handlers
9393 */
9394 const SyscallTableEntry ML_(syscall_table)[] = {
9395 // _____(__NR_syscall), // 0
9396 MACX_(__NR_exit, exit),
9397 GENX_(__NR_fork, sys_fork),
9398 GENXY(__NR_read, sys_read),
9399 GENX_(__NR_write, sys_write),
9400 GENXY(__NR_open, sys_open),
9401 GENXY(__NR_close, sys_close),
9402 GENXY(__NR_wait4, sys_wait4),
9403 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(8)), // old creat
9404 GENX_(__NR_link, sys_link),
9405 GENX_(__NR_unlink, sys_unlink),
9406 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(11)), // old execv
9407 GENX_(__NR_chdir, sys_chdir),
9408 GENX_(__NR_fchdir, sys_fchdir),
9409 GENX_(__NR_mknod, sys_mknod),
9410 GENX_(__NR_chmod, sys_chmod),
9411 GENX_(__NR_chown, sys_chown),
9412 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(17)), // old break
9413 MACXY(__NR_getfsstat, getfsstat),
9414 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(19)), // old lseek
9415 GENX_(__NR_getpid, sys_getpid), // 20
9416 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(21)), // old mount
9417 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(22)), // old umount
9418 GENX_(__NR_setuid, sys_setuid),
9419 GENX_(__NR_getuid, sys_getuid),
9420 GENX_(__NR_geteuid, sys_geteuid),
9421 MACX_(__NR_ptrace, ptrace),
9422 MACXY(__NR_recvmsg, recvmsg),
9423 MACX_(__NR_sendmsg, sendmsg),
9424 MACXY(__NR_recvfrom, recvfrom),
9425 MACXY(__NR_accept, accept),
9426 MACXY(__NR_getpeername, getpeername),
9427 MACXY(__NR_getsockname, getsockname),
9428 GENX_(__NR_access, sys_access),
9429 MACX_(__NR_chflags, chflags),
9430 MACX_(__NR_fchflags, fchflags),
9431 GENX_(__NR_sync, sys_sync),
9432 GENX_(__NR_kill, sys_kill),
9433 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(38)), // old stat
9434 GENX_(__NR_getppid, sys_getppid),
9435 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(40)), // old lstat
9436 GENXY(__NR_dup, sys_dup),
9437 MACXY(__NR_pipe, pipe),
9438 GENX_(__NR_getegid, sys_getegid),
9439 #if DARWIN_VERS >= DARWIN_10_7
9440 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(44)), // old profil
9441 #else
9442 // _____(__NR_profil),
9443 #endif
9444 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(45)), // old ktrace
9445 MACXY(__NR_sigaction, sigaction),
9446 GENX_(__NR_getgid, sys_getgid),
9447 MACXY(__NR_sigprocmask, sigprocmask),
9448 MACXY(__NR_getlogin, getlogin),
9449 // _____(__NR_setlogin),
9450 // _____(__NR_acct),
9451 MACXY(__NR_sigpending, sigpending),
9452 GENXY(__NR_sigaltstack, sys_sigaltstack),
9453 MACXY(__NR_ioctl, ioctl),
9454 // _____(__NR_reboot),
9455 // _____(__NR_revoke),
9456 GENX_(__NR_symlink, sys_symlink), // 57
9457 GENX_(__NR_readlink, sys_readlink),
9458 GENX_(__NR_execve, sys_execve),
9459 GENX_(__NR_umask, sys_umask), // 60
9460 GENX_(__NR_chroot, sys_chroot),
9461 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(62)), // old fstat
9462 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(63)), // used internally, reserved
9463 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(64)), // old getpagesize
9464 GENX_(__NR_msync, sys_msync),
9465 GENX_(__NR_vfork, sys_fork), // (We treat vfork as fork.)
9466 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(67)), // old vread
9467 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(68)), // old vwrite
9468 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(69)), // old sbrk
9469 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(70)), // old sstk
9470 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(71)), // old mmap
9471 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(72)), // old vadvise
9472 GENXY(__NR_munmap, sys_munmap),
9473 GENXY(__NR_mprotect, sys_mprotect),
9474 GENX_(__NR_madvise, sys_madvise),
9475 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(76)), // old vhangup
9476 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(77)), // old vlimit
9477 GENXY(__NR_mincore, sys_mincore),
9478 GENXY(__NR_getgroups, sys_getgroups),
9479 // _____(__NR_setgroups), // 80
9480 GENX_(__NR_getpgrp, sys_getpgrp),
9481 GENX_(__NR_setpgid, sys_setpgid),
9482 GENXY(__NR_setitimer, sys_setitimer),
9483 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(84)), // old wait
9484 // _____(__NR_swapon),
9485 GENXY(__NR_getitimer, sys_getitimer),
9486 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(87)), // old gethostname
9487 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(88)), // old sethostname
9488 MACXY(__NR_getdtablesize, getdtablesize),
9489 GENXY(__NR_dup2, sys_dup2),
9490 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(91)), // old getdopt
9491 MACXY(__NR_fcntl, fcntl),
9492 GENX_(__NR_select, sys_select),
9493 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(94)), // old setdopt
9494 GENX_(__NR_fsync, sys_fsync),
9495 GENX_(__NR_setpriority, sys_setpriority),
9496 MACXY(__NR_socket, socket),
9497 MACX_(__NR_connect, connect),
9498 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(99)), // old accept
9499 GENX_(__NR_getpriority, sys_getpriority), // 100
9500 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(101)), // old send
9501 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(102)), // old recv
9502 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(103)), // old sigreturn
9503 MACX_(__NR_bind, bind),
9504 MACX_(__NR_setsockopt, setsockopt),
9505 MACX_(__NR_listen, listen),
9506 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(107)), // old vtimes
9507 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(108)), // old sigvec
9508 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(109)), // old sigblock
9509 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(110)), // old sigsetmask
9510 MACX_(__NR_sigsuspend, sigsuspend), // old sigsuspend
9511 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(112)), // old sigstack
9512 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(113)), // old recvmsg
9513 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(114)), // old sendmsg
9514 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(115)), // old vtrace
9515 GENXY(__NR_gettimeofday, sys_gettimeofday),
9516 GENXY(__NR_getrusage, sys_getrusage),
9517 MACXY(__NR_getsockopt, getsockopt),
9518 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(119)), // old resuba
9519 GENXY(__NR_readv, sys_readv), // 120
9520 GENX_(__NR_writev, sys_writev),
9521 // _____(__NR_settimeofday),
9522 GENX_(__NR_fchown, sys_fchown),
9523 GENX_(__NR_fchmod, sys_fchmod),
9524 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(125)), // old recvfrom
9525 // _____(__NR_setreuid),
9526 // _____(__NR_setregid),
9527 GENX_(__NR_rename, sys_rename),
9528 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(129)), // old truncate
9529 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(130)), // old ftruncate
9530 GENX_(__NR_flock, sys_flock),
9531 MACXY(__NR_mkfifo, mkfifo),
9532 MACX_(__NR_sendto, sendto),
9533 MACX_(__NR_shutdown, shutdown),
9534 MACXY(__NR_socketpair, socketpair),
9535 GENX_(__NR_mkdir, sys_mkdir),
9536 GENX_(__NR_rmdir, sys_rmdir),
9537 GENX_(__NR_utimes, sys_utimes),
9538 MACX_(__NR_futimes, futimes),
9539 // _____(__NR_adjtime), // 140
9540 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(141)), // old getpeername
9541 MACXY(__NR_gethostuuid, gethostuuid),
9542 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(143)), // old sethostid
9543 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(144)), // old getrlimit
9544 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(145)), // old setrlimit
9545 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(146)), // old killpg
9546 GENX_(__NR_setsid, sys_setsid),
9547 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(148)), // old setquota
9548 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(149)), // old qquota
9549 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(150)), // old getsockname
9550 // _____(__NR_getpgid),
9551 // _____(__NR_setprivexec),
9552 GENXY(__NR_pread, sys_pread64),
9553 GENX_(__NR_pwrite, sys_pwrite64),
9554 // _____(__NR_nfssvc),
9555 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(156)), // old getdirentries
9556 GENXY(__NR_statfs, sys_statfs),
9557 GENXY(__NR_fstatfs, sys_fstatfs),
9558 // _____(__NR_unmount),
9559 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(160)), // old async_daemon
9560 // _____(__NR_getfh),
9561 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(162)), // old getdomainname
9562 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(163)), // old setdomainname
9563 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(164)), // ???
9564 // _____(__NR_quotactl),
9565 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(166)), // old exportfs
9566 MACX_(__NR_mount, mount),
9567 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(168)), // old ustat
9568 MACXY(__NR_csops, csops), // code-signing ops
9569 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(170)), // old table
9570 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(171)), // old wait3
9571 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(172)), // old rpause
9572 // _____(__NR_waitid),
9573 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(174)), // old getdents
9574 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(175)), // old gc_control
9575 // _____(__NR_add_profil),
9576 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(177)), // ???
9577 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(178)), // ???
9578 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(179)), // ???
9579 MACX_(__NR_kdebug_trace, kdebug_trace), // 180
9580 GENX_(__NR_setgid, sys_setgid),
9581 MACX_(__NR_setegid, setegid),
9582 MACX_(__NR_seteuid, seteuid),
9583 MACX_(__NR_sigreturn, sigreturn),
9584 // _____(__NR_chud),
9585 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(186)), // ???
9586 #if DARWIN_VERS >= DARWIN_10_6
9587 // _____(__NR_fdatasync),
9588 #else
9589 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(187)), // ???
9590 #endif
9591 GENXY(__NR_stat, sys_newstat),
9592 GENXY(__NR_fstat, sys_newfstat),
9593 GENXY(__NR_lstat, sys_newlstat),
9594 MACX_(__NR_pathconf, pathconf),
9595 MACX_(__NR_fpathconf, fpathconf),
9596 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(193)), // ???
9597 GENXY(__NR_getrlimit, sys_getrlimit),
9598 GENX_(__NR_setrlimit, sys_setrlimit),
9599 MACXY(__NR_getdirentries, getdirentries),
9600 MACXY(__NR_mmap, mmap),
9601 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(198)), // __syscall
9602 MACX_(__NR_lseek, lseek),
9603 GENX_(__NR_truncate, sys_truncate64), // 200
9604 GENX_(__NR_ftruncate, sys_ftruncate64),
9605 MACXY(__NR___sysctl, __sysctl),
9606 GENX_(__NR_mlock, sys_mlock),
9607 GENX_(__NR_munlock, sys_munlock),
9608 // _____(__NR_undelete),
9609 // _____(__NR_ATsocket),
9610 // _____(__NR_ATgetmsg),
9611 // _____(__NR_ATputmsg),
9612 // _____(__NR_ATPsndreq),
9613 // _____(__NR_ATPsndrsp),
9614 // _____(__NR_ATPgetreq),
9615 // _____(__NR_ATPgetrsp),
9616 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(213)), // Reserved for AppleTalk
9617 #if DARWIN_VERS >= DARWIN_10_6
9618 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(214)), // old kqueue_from_portset_np
9619 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(215)), // old kqueue_portset_np
9620 #else
9621 // _____(__NR_kqueue_from_portset_np),
9622 // _____(__NR_kqueue_portset_np),
9623 #endif
9624 // _____(__NR_mkcomplex),
9625 // _____(__NR_statv),
9626 // _____(__NR_lstatv),
9627 // _____(__NR_fstatv),
9628 MACXY(__NR_getattrlist, getattrlist), // 220
9629 MACX_(__NR_setattrlist, setattrlist),
9630 MACXY(__NR_getdirentriesattr, getdirentriesattr),
9631 MACX_(__NR_exchangedata, exchangedata),
9632 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(224)), // checkuseraccess
9633 // _____(__NR_searchfs),
9634 GENX_(__NR_delete, sys_unlink),
9635 // _____(__NR_copyfile),
9636 #if DARWIN_VERS >= DARWIN_10_6
9637 // _____(__NR_fgetattrlist),
9638 // _____(__NR_fsetattrlist),
9639 #else
9640 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(228)), // ??
9641 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(229)), // ??
9642 #endif
9643 GENXY(__NR_poll, sys_poll),
9644 MACX_(__NR_watchevent, watchevent),
9645 MACXY(__NR_waitevent, waitevent),
9646 MACX_(__NR_modwatch, modwatch),
9647 MACXY(__NR_getxattr, getxattr),
9648 MACXY(__NR_fgetxattr, fgetxattr),
9649 MACX_(__NR_setxattr, setxattr),
9650 MACX_(__NR_fsetxattr, fsetxattr),
9651 MACX_(__NR_removexattr, removexattr),
9652 MACX_(__NR_fremovexattr, fremovexattr),
9653 MACXY(__NR_listxattr, listxattr), // 240
9654 MACXY(__NR_flistxattr, flistxattr),
9655 MACXY(__NR_fsctl, fsctl),
9656 MACX_(__NR_initgroups, initgroups),
9657 MACXY(__NR_posix_spawn, posix_spawn),
9658 #if DARWIN_VERS >= DARWIN_10_6
9659 // _____(__NR_ffsctl),
9660 #else
9661 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(245)), // ???
9662 #endif
9663 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(246)), // ???
9664 // _____(__NR_nfsclnt),
9665 // _____(__NR_fhopen),
9666 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(249)), // ???
9667 // _____(__NR_minherit),
9668 // _____(__NR_semsys),
9669 // _____(__NR_msgsys),
9670 // _____(__NR_shmsys),
9671 MACXY(__NR_semctl, semctl),
9672 MACX_(__NR_semget, semget),
9673 MACX_(__NR_semop, semop),
9674 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(257)), // ???
9675 // _____(__NR_msgctl),
9676 // _____(__NR_msgget),
9677 // _____(__NR_msgsnd), // 260
9678 // _____(__NR_msgrcv),
9679 MACXY(__NR_shmat, shmat),
9680 MACXY(__NR_shmctl, shmctl),
9681 MACXY(__NR_shmdt, shmdt),
9682 MACX_(__NR_shmget, shmget),
9683 MACXY(__NR_shm_open, shm_open),
9684 MACXY(__NR_shm_unlink, shm_unlink),
9685 MACX_(__NR_sem_open, sem_open),
9686 MACX_(__NR_sem_close, sem_close),
9687 MACX_(__NR_sem_unlink, sem_unlink),
9688 MACX_(__NR_sem_wait, sem_wait),
9689 MACX_(__NR_sem_trywait, sem_trywait),
9690 MACX_(__NR_sem_post, sem_post),
9691 // 274 seems to have been repurposed for 10.10. Was sem_getvalue,
9692 // has become sysctlbyname. See below.
9693 MACXY(__NR_sem_init, sem_init),
9694 MACX_(__NR_sem_destroy, sem_destroy),
9695 MACX_(__NR_open_extended, open_extended), // 277
9696 // _____(__NR_umask_extended),
9697 MACXY(__NR_stat_extended, stat_extended),
9698 MACXY(__NR_lstat_extended, lstat_extended), // 280
9699 MACXY(__NR_fstat_extended, fstat_extended),
9700 MACX_(__NR_chmod_extended, chmod_extended),
9701 MACX_(__NR_fchmod_extended,fchmod_extended),
9702 MACXY(__NR_access_extended,access_extended),
9703 MACX_(__NR_settid, settid),
9704 #if DARWIN_VERS >= DARWIN_10_8
9705 MACX_(__NR_gettid, gettid), // 286
9706 #endif
9707 // _____(__NR_setsgroups),
9708 // _____(__NR_getsgroups),
9709 // _____(__NR_setwgroups),
9710 // _____(__NR_getwgroups),
9711 // _____(__NR_mkfifo_extended),
9712 // _____(__NR_mkdir_extended),
9713 // _____(__NR_identitysvc),
9714 // _____(__NR_shared_region_check_np),
9715 // _____(__NR_shared_region_map_np),
9716 #if DARWIN_VERS >= DARWIN_10_6
9717 // _____(__NR_vm_pressure_monitor),
9718 #else
9719 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(296)), // old load_shared_file
9720 #endif
9721 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(297)), // old reset_shared_file
9722 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(298)), // old new_system_shared_regions
9723 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(299)), // old shared_region_map_file_np
9724 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(300)), // old shared_region_make_private_np
9725 MACXY(__NR_psynch_mutexwait, psynch_mutexwait), // 301
9726 MACXY(__NR_psynch_mutexdrop, psynch_mutexdrop), // 302
9727 MACXY(__NR_psynch_cvbroad, psynch_cvbroad), // 303
9728 MACXY(__NR_psynch_cvsignal, psynch_cvsignal), // 304
9729 MACXY(__NR_psynch_cvwait, psynch_cvwait), // 305
9730 MACXY(__NR_psynch_rw_rdlock, psynch_rw_rdlock), // 306
9731 MACXY(__NR_psynch_rw_wrlock, psynch_rw_wrlock), // 307
9732 MACXY(__NR_psynch_rw_unlock, psynch_rw_unlock), // 308
9733 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(309)), // ???
9734 // _____(__NR_getsid),
9735 // _____(__NR_settid_with_pid),
9736 MACXY(__NR_psynch_cvclrprepost, psynch_cvclrprepost), // 312
9737 // _____(__NR_aio_fsync),
9738 MACXY(__NR_aio_return, aio_return),
9739 MACX_(__NR_aio_suspend, aio_suspend),
9740 // _____(__NR_aio_cancel),
9741 MACX_(__NR_aio_error, aio_error),
9742 MACXY(__NR_aio_read, aio_read),
9743 MACX_(__NR_aio_write, aio_write),
9744 // _____(__NR_lio_listio), // 320
9745 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(321)), // ???
9746
9747 #if DARWIN_VERS >= DARWIN_10_8
9748 MACXY(__NR_iopolicysys, iopolicysys),
9749 MACXY(__NR_process_policy, process_policy),
9750 #else
9751 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(322)), // ???
9752 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(323)), // ???
9753 #endif
9754 // _____(__NR_mlockall),
9755 // _____(__NR_munlockall),
9756 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(326)), // ???
9757 MACX_(__NR_issetugid, issetugid),
9758 MACX_(__NR___pthread_kill, __pthread_kill),
9759 MACX_(__NR___pthread_sigmask, __pthread_sigmask),
9760 // _____(__NR___sigwait),
9761 MACX_(__NR___disable_threadsignal, __disable_threadsignal),
9762 MACX_(__NR___pthread_markcancel, __pthread_markcancel),
9763 MACX_(__NR___pthread_canceled, __pthread_canceled),
9764 MACX_(__NR___semwait_signal, __semwait_signal),
9765 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(335)), // old utrace
9766 #if DARWIN_VERS >= DARWIN_10_6
9767 MACXY(__NR_proc_info, proc_info), // 336
9768 #endif
9769 MACXY(__NR_sendfile, sendfile),
9770 MACXY(__NR_stat64, stat64),
9771 MACXY(__NR_fstat64, fstat64),
9772 MACXY(__NR_lstat64, lstat64), // 340
9773 MACXY(__NR_stat64_extended, stat64_extended),
9774 MACXY(__NR_lstat64_extended, lstat64_extended),
9775 MACXY(__NR_fstat64_extended, fstat64_extended),
9776 MACXY(__NR_getdirentries64, getdirentries64),
9777 MACXY(__NR_statfs64, statfs64),
9778 MACXY(__NR_fstatfs64, fstatfs64),
9779 MACXY(__NR_getfsstat64, getfsstat64),
9780 MACX_(__NR___pthread_chdir, __pthread_chdir),
9781 MACX_(__NR___pthread_fchdir, __pthread_fchdir),
9782 // _____(__NR_audit),
9783 MACXY(__NR_auditon, auditon),
9784 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(352)), // ???
9785 // _____(__NR_getauid),
9786 // _____(__NR_setauid),
9787 // _____(__NR_getaudit),
9788 // _____(__NR_setaudit),
9789 #if DARWIN_VERS >= DARWIN_10_7
9790 MACXY(__NR_getaudit_addr, getaudit_addr),
9791 #endif
9792 // _____(__NR_setaudit_addr),
9793 // _____(__NR_auditctl),
9794 MACXY(__NR_bsdthread_create, bsdthread_create), // 360
9795 MACX_(__NR_bsdthread_terminate, bsdthread_terminate),
9796 MACXY(__NR_kqueue, kqueue),
9797 MACXY(__NR_kevent, kevent),
9798 GENX_(__NR_lchown, sys_lchown),
9799 // _____(__NR_stack_snapshot),
9800 MACX_(__NR_bsdthread_register, bsdthread_register),
9801 MACX_(__NR_workq_open, workq_open),
9802 MACXY(__NR_workq_ops, workq_ops),
9803 #if DARWIN_VERS >= DARWIN_10_6
9804 MACXY(__NR_kevent64, kevent64),
9805 #else
9806 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(369)), // ???
9807 #endif
9808 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(370)), // ???
9809 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(371)), // ???
9810 #if DARWIN_VERS >= DARWIN_10_6
9811 MACX_(__NR___thread_selfid, __thread_selfid),
9812 #else
9813 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(372)), // ???
9814 #endif
9815 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(373)), // ???
9816 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(374)), // ???
9817 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(375)), // ???
9818 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(376)), // ???
9819 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(377)), // ???
9820 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(378)), // ???
9821 _____(VG_DARWIN_SYSCALL_CONSTRUCT_UNIX(379)), // ???
9822 // _____(__NR___mac_execve), // 380
9823 MACX_(__NR___mac_syscall, __mac_syscall),
9824 // _____(__NR___mac_get_file),
9825 // _____(__NR___mac_set_file),
9826 // _____(__NR___mac_get_link),
9827 // _____(__NR___mac_set_link),
9828 // _____(__NR___mac_get_proc),
9829 // _____(__NR___mac_set_proc),
9830 // _____(__NR___mac_get_fd),
9831 // _____(__NR___mac_set_fd),
9832 // _____(__NR___mac_get_pid),
9833 // _____(__NR___mac_get_lcid),
9834 // _____(__NR___mac_get_lctx),
9835 // _____(__NR___mac_set_lctx),
9836 // _____(__NR_setlcid),
9837 // _____(__NR_getlcid),
9838 // GrP fixme need any special nocancel handling?
9839 GENXY(__NR_read_nocancel, sys_read),
9840 GENX_(__NR_write_nocancel, sys_write),
9841 GENXY(__NR_open_nocancel, sys_open),
9842 GENXY(__NR_close_nocancel, sys_close),
9843 GENXY(__NR_wait4_nocancel, sys_wait4), // 400
9844 MACXY(__NR_recvmsg_nocancel, recvmsg),
9845 MACX_(__NR_sendmsg_nocancel, sendmsg),
9846 MACXY(__NR_recvfrom_nocancel, recvfrom),
9847 MACXY(__NR_accept_nocancel, accept),
9848 GENX_(__NR_msync_nocancel, sys_msync),
9849 MACXY(__NR_fcntl_nocancel, fcntl),
9850 GENX_(__NR_select_nocancel, sys_select),
9851 GENX_(__NR_fsync_nocancel, sys_fsync),
9852 MACX_(__NR_connect_nocancel, connect),
9853 MACX_(__NR_sigsuspend_nocancel, sigsuspend),
9854 GENXY(__NR_readv_nocancel, sys_readv),
9855 GENX_(__NR_writev_nocancel, sys_writev),
9856 MACX_(__NR_sendto_nocancel, sendto),
9857 GENXY(__NR_pread_nocancel, sys_pread64),
9858 GENX_(__NR_pwrite_nocancel, sys_pwrite64),
9859 // _____(__NR_waitid_nocancel),
9860 GENXY(__NR_poll_nocancel, sys_poll),
9861 // _____(__NR_msgsnd_nocancel),
9862 // _____(__NR_msgrcv_nocancel),
9863 MACX_(__NR_sem_wait_nocancel, sem_wait), // 420
9864 // _____(__NR_aio_suspend_nocancel),
9865 // _____(__NR___sigwait_nocancel),
9866 MACX_(__NR___semwait_signal_nocancel, __semwait_signal),
9867 // _____(__NR___mac_mount),
9868 // _____(__NR___mac_get_mount),
9869 // _____(__NR___mac_getfsstat),
9870 #if DARWIN_VERS >= DARWIN_10_6
9871 MACXY(__NR_fsgetpath, fsgetpath),
9872 MACXY(__NR_audit_session_self, audit_session_self),
9873 // _____(__NR_audit_session_join),
9874 #endif
9875 #if DARWIN_VERS >= DARWIN_10_9
9876 MACX_(__NR_fileport_makeport, fileport_makeport),
9877 MACX_(__NR_guarded_open_np, guarded_open_np),
9878 MACX_(__NR_guarded_close_np, guarded_close_np),
9879 MACX_(__NR_guarded_kqueue_np, guarded_kqueue_np),
9880 MACX_(__NR_change_fdguard_np, change_fdguard_np),
9881 MACX_(__NR_connectx, connectx),
9882 MACX_(__NR_disconnectx, disconnectx),
9883 #endif
9884 #if DARWIN_VERS >= DARWIN_10_10
9885 MACXY(__NR_sysctlbyname, sysctlbyname), // 274
9886 MACXY(__NR_necp_match_policy, necp_match_policy), // 460
9887 MACXY(__NR_getattrlistbulk, getattrlistbulk), // 461
9888 MACX_(__NR_readlinkat, readlinkat), // 473
9889 MACX_(__NR_bsdthread_ctl, bsdthread_ctl), // 478
9890 MACX_(__NR_guarded_open_dprotected_np, guarded_open_dprotected_np),
9891 MACX_(__NR_guarded_write_np, guarded_write_np),
9892 MACX_(__NR_guarded_pwrite_np, guarded_pwrite_np),
9893 MACX_(__NR_guarded_writev_np, guarded_writev_np),
9894 #endif
9895 // _____(__NR_MAXSYSCALL)
9896 MACX_(__NR_DARWIN_FAKE_SIGRETURN, FAKE_SIGRETURN)
9897 };
9898
9899
9900 // Mach traps use negative syscall numbers.
9901 // Use ML_(mach_trap_table)[-mach_trap_number] .
9902 // cf xnu sources osfmk/kern/syscall_sw.c
9903
9904 const SyscallTableEntry ML_(mach_trap_table)[] = {
9905 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(0)),
9906 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(1)),
9907 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(2)),
9908 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(3)),
9909 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(4)),
9910 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(5)),
9911 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(6)),
9912 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(7)),
9913 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(8)),
9914 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(9)),
9915
9916 # if DARWIN_VERS >= DARWIN_10_8
9917 MACXY(__NR_kernelrpc_mach_vm_allocate_trap, kernelrpc_mach_vm_allocate_trap),
9918 # else
9919 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(10)),
9920 # endif
9921
9922 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(11)),
9923
9924 # if DARWIN_VERS >= DARWIN_10_8
9925 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12), kernelrpc_mach_vm_deallocate_trap),
9926 # else
9927 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(12)),
9928 # endif
9929
9930 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(13)),
9931
9932 # if DARWIN_VERS >= DARWIN_10_8
9933 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14), kernelrpc_mach_vm_protect_trap),
9934 # endif
9935
9936 # if DARWIN_VERS >= DARWIN_10_9
9937 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15), kernelrpc_mach_vm_map_trap),
9938 # endif
9939
9940 # if DARWIN_VERS < DARWIN_10_8
9941 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(14)),
9942 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(15)),
9943 # endif
9944
9945 # if DARWIN_VERS >= DARWIN_10_8
9946 MACXY(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16), kernelrpc_mach_port_allocate_trap),
9947 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17), kernelrpc_mach_port_destroy_trap),
9948 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18), kernelrpc_mach_port_deallocate_trap),
9949 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19), kernelrpc_mach_port_mod_refs_trap),
9950 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20), kernelrpc_mach_port_move_member_trap),
9951 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21), kernelrpc_mach_port_insert_right_trap),
9952 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22), kernelrpc_mach_port_insert_member_trap),
9953 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23), kernelrpc_mach_port_extract_member_trap),
9954 # else
9955 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(16)),
9956 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(17)),
9957 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(18)),
9958 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(19)),
9959 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(20)),
9960 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(21)),
9961 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(22)),
9962 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(23)),
9963 # endif
9964
9965 # if DARWIN_VERS >= DARWIN_10_9
9966 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24), kernelrpc_mach_port_construct_trap),
9967 MACX_(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25), kernelrpc_mach_port_destruct_trap),
9968 # else
9969 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(24)),
9970 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(25)),
9971 # endif
9972
9973 MACXY(__NR_mach_reply_port, mach_reply_port),
9974 MACXY(__NR_thread_self_trap, mach_thread_self),
9975 MACXY(__NR_task_self_trap, mach_task_self),
9976 MACXY(__NR_host_self_trap, mach_host_self),
9977 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(30)),
9978 MACXY(__NR_mach_msg_trap, mach_msg),
9979 // _____(__NR_mach_msg_overwrite_trap),
9980 MACX_(__NR_semaphore_signal_trap, semaphore_signal),
9981 MACX_(__NR_semaphore_signal_all_trap, semaphore_signal_all),
9982 MACX_(__NR_semaphore_signal_thread_trap, semaphore_signal_thread),
9983 MACX_(__NR_semaphore_wait_trap, semaphore_wait),
9984 MACX_(__NR_semaphore_wait_signal_trap, semaphore_wait_signal),
9985 MACX_(__NR_semaphore_timedwait_trap, semaphore_timedwait),
9986 MACX_(__NR_semaphore_timedwait_signal_trap, semaphore_timedwait_signal),
9987 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(40)), // -40
9988
9989 #if defined(VGA_x86)
9990 // _____(__NR_init_process),
9991 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(42)),
9992 // _____(__NR_map_fd),
9993 #else
9994 # if DARWIN_VERS >= DARWIN_10_9
9995 MACX_(__NR_kernelrpc_mach_port_guard_trap, kernelrpc_mach_port_guard_trap),
9996 MACX_(__NR_kernelrpc_mach_port_unguard_trap, kernelrpc_mach_port_unguard_trap),
9997 # endif
9998 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(43)),
9999 #endif
10000
10001 // _____(__NR_task_name_for_pid),
10002 MACXY(__NR_task_for_pid, task_for_pid),
10003 MACXY(__NR_pid_for_task, pid_for_task),
10004 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(47)),
10005 #if defined(VGA_x86)
10006 // _____(__NR_macx_swapon),
10007 // _____(__NR_macx_swapoff),
10008 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10009 // _____(__NR_macx_triggers),
10010 // _____(__NR_macx_backing_store_suspend),
10011 // _____(__NR_macx_backing_store_recovery),
10012 #else
10013 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(48)),
10014 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(49)),
10015 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(50)),
10016 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(51)),
10017 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(52)),
10018 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(53)),
10019 #endif
10020 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(54)),
10021 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(55)),
10022 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(56)),
10023 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(57)),
10024 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(58)),
10025 MACX_(__NR_swtch_pri, swtch_pri),
10026 MACX_(__NR_swtch, swtch), // -60
10027 MACX_(__NR_syscall_thread_switch, syscall_thread_switch),
10028 // _____(__NR_clock_sleep_trap),
10029 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(63)),
10030 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(64)),
10031 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(65)),
10032 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(66)),
10033 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(67)),
10034 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(68)),
10035 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(69)),
10036 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(70)),
10037 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(71)),
10038 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(72)),
10039 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(73)),
10040 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(74)),
10041 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(75)),
10042 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(76)),
10043 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(77)),
10044 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(78)),
10045 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(79)),
10046 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(80)), // -80
10047 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(81)),
10048 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(82)),
10049 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(83)),
10050 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(84)),
10051 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(85)),
10052 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(86)),
10053 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(87)),
10054 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(88)),
10055 MACXY(__NR_mach_timebase_info, mach_timebase_info),
10056 MACX_(__NR_mach_wait_until, mach_wait_until),
10057 MACXY(__NR_mk_timer_create, mk_timer_create),
10058 MACXY(__NR_mk_timer_destroy, mk_timer_destroy),
10059 MACX_(__NR_mk_timer_arm, mk_timer_arm),
10060 MACXY(__NR_mk_timer_cancel, mk_timer_cancel),
10061 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(95)),
10062 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(96)),
10063 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(97)),
10064 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(98)),
10065 _____(VG_DARWIN_SYSCALL_CONSTRUCT_MACH(99)),
10066 MACXY(__NR_iokit_user_client_trap, iokit_user_client_trap), // -100
10067 };
10068
10069
10070 // Machine-dependent traps have wacky syscall numbers, and use the Mach trap
10071 // calling convention instead of the syscall convention.
10072 // Use ML_(mdep_trap_table)[syscallno - ML_(mdep_trap_base)] .
10073
10074 #if defined(VGA_x86)
10075 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10076 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10077 };
10078 #elif defined(VGA_amd64)
10079 const SyscallTableEntry ML_(mdep_trap_table)[] = {
10080 MACX_(__NR_thread_fast_set_cthread_self, thread_fast_set_cthread_self),
10081 };
10082 #else
10083 #error unknown architecture
10084 #endif
10085
10086 const UInt ML_(syscall_table_size) =
10087 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
10088
10089 const UInt ML_(mach_trap_table_size) =
10090 sizeof(ML_(mach_trap_table)) / sizeof(ML_(mach_trap_table)[0]);
10091
10092 const UInt ML_(mdep_trap_table_size) =
10093 sizeof(ML_(mdep_trap_table)) / sizeof(ML_(mdep_trap_table)[0]);
10094
10095 #endif // defined(VGO_darwin)
10096
10097 /*--------------------------------------------------------------------*/
10098 /*--- end ---*/
10099 /*--------------------------------------------------------------------*/
10100