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