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