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