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