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