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