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