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