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