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