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