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