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