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