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