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-2011 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_libcsetjmp.h" // to keep _threadstate.h happy 37 #include "pub_core_threadstate.h" 38 #include "pub_core_aspacemgr.h" 39 #include "pub_core_xarray.h" 40 #include "pub_core_clientstate.h" 41 #include "pub_core_debuglog.h" 42 #include "pub_core_debuginfo.h" // VG_(di_notify_*) 43 #include "pub_core_transtab.h" // VG_(discard_translations) 44 #include "pub_tool_gdbserver.h" // VG_(gdbserver) 45 #include "pub_core_libcbase.h" 46 #include "pub_core_libcassert.h" 47 #include "pub_core_libcfile.h" 48 #include "pub_core_libcprint.h" 49 #include "pub_core_libcproc.h" 50 #include "pub_core_libcsignal.h" 51 #include "pub_core_machine.h" // VG_(get_SP) 52 #include "pub_core_mallocfree.h" 53 #include "pub_core_options.h" 54 #include "pub_core_oset.h" 55 #include "pub_core_scheduler.h" 56 #include "pub_core_sigframe.h" // For VG_(sigframe_destroy)() 57 #include "pub_core_signals.h" 58 #include "pub_core_syscall.h" 59 #include "pub_core_syswrap.h" 60 #include "pub_core_tooliface.h" 61 62 #include "priv_types_n_macros.h" 63 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */ 64 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */ 65 #include "priv_syswrap-main.h" 66 67 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 68 #include <mach/mach.h> 69 #include <mach/mach_vm.h> 70 #include <semaphore.h> 71 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 72 73 #define msgh_request_port msgh_remote_port 74 #define msgh_reply_port msgh_local_port 75 #define BOOTSTRAP_MAX_NAME_LEN 128 76 typedef char name_t[BOOTSTRAP_MAX_NAME_LEN]; 77 78 typedef uint64_t mig_addr_t; 79 80 81 // Saved ports 82 static mach_port_t vg_host_port = 0; 83 static mach_port_t vg_task_port = 0; 84 static mach_port_t vg_bootstrap_port = 0; 85 86 // Run a thread from beginning to end and return the thread's 87 // scheduler-return-code. 88 static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW) 89 { 90 VgSchedReturnCode ret; 91 ThreadId tid = (ThreadId)tidW; 92 ThreadState* tst = VG_(get_ThreadState)(tid); 93 94 VG_(debugLog)(1, "syswrap-darwin", 95 "thread_wrapper(tid=%lld): entry\n", 96 (ULong)tidW); 97 98 vg_assert(tst->status == VgTs_Init); 99 100 /* make sure we get the CPU lock before doing anything significant */ 101 VG_(acquire_BigLock)(tid, "thread_wrapper"); 102 103 if (0) 104 VG_(printf)("thread tid %d started: stack = %p\n", 105 tid, &tid); 106 107 /* Make sure error reporting is enabled in the new thread. */ 108 tst->err_disablement_level = 0; 109 110 VG_TRACK(pre_thread_first_insn, tid); 111 112 tst->os_state.lwpid = VG_(gettid)(); 113 tst->os_state.threadgroup = VG_(getpid)(); 114 115 /* Thread created with all signals blocked; scheduler will set the 116 appropriate mask */ 117 118 ret = VG_(scheduler)(tid); 119 120 vg_assert(VG_(is_exiting)(tid)); 121 122 vg_assert(tst->status == VgTs_Runnable); 123 vg_assert(VG_(is_running_thread)(tid)); 124 125 VG_(debugLog)(1, "syswrap-darwin", 126 "thread_wrapper(tid=%lld): done\n", 127 (ULong)tidW); 128 129 /* Return to caller, still holding the lock. */ 130 return ret; 131 } 132 133 134 135 /* Allocate a stack for this thread, if it doesn't already have one. 136 Returns the initial stack pointer value to use, or 0 if allocation 137 failed. */ 138 139 Addr allocstack ( ThreadId tid ) 140 { 141 ThreadState* tst = VG_(get_ThreadState)(tid); 142 VgStack* stack; 143 Addr initial_SP; 144 145 /* Either the stack_base and stack_init_SP are both zero (in which 146 case a stack hasn't been allocated) or they are both non-zero, 147 in which case it has. */ 148 149 if (tst->os_state.valgrind_stack_base == 0) 150 vg_assert(tst->os_state.valgrind_stack_init_SP == 0); 151 152 if (tst->os_state.valgrind_stack_base != 0) 153 vg_assert(tst->os_state.valgrind_stack_init_SP != 0); 154 155 /* If no stack is present, allocate one. */ 156 157 if (tst->os_state.valgrind_stack_base == 0) { 158 stack = VG_(am_alloc_VgStack)( &initial_SP ); 159 if (stack) { 160 tst->os_state.valgrind_stack_base = (Addr)stack; 161 tst->os_state.valgrind_stack_init_SP = initial_SP; 162 } 163 } 164 165 VG_(debugLog)( 2, "syswrap-darwin", "stack for tid %d at %p; init_SP=%p\n", 166 tid, 167 (void*)tst->os_state.valgrind_stack_base, 168 (void*)tst->os_state.valgrind_stack_init_SP ); 169 170 vg_assert(VG_IS_32_ALIGNED(tst->os_state.valgrind_stack_init_SP)); 171 172 return tst->os_state.valgrind_stack_init_SP; 173 } 174 175 176 void find_stack_segment(ThreadId tid, Addr sp) 177 { 178 /* We don't really know where the client stack is, because it's 179 allocated by the client. The best we can do is look at the 180 memory mappings and try to derive some useful information. We 181 assume that esp starts near its highest possible value, and can 182 only go down to the start of the mmaped segment. */ 183 ThreadState *tst = VG_(get_ThreadState)(tid); 184 const NSegment *seg = VG_(am_find_nsegment)(sp); 185 if (seg && seg->kind != SkResvn) { 186 tst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp); 187 tst->client_stack_szB = tst->client_stack_highest_word - seg->start; 188 189 if (1) 190 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n", 191 tid, seg->start, VG_PGROUNDUP(sp)); 192 } else { 193 VG_(printf)("couldn't find user stack\n"); 194 VG_(message)(Vg_UserMsg, "!? New thread %d starts with SP(%#lx) unmapped\n", 195 tid, sp); 196 tst->client_stack_szB = 0; 197 } 198 } 199 200 201 /* Run a thread all the way to the end, then do appropriate exit actions 202 (this is the last-one-out-turn-off-the-lights bit). 203 */ 204 static void run_a_thread_NORETURN ( Word tidW ) 205 { 206 Int c; 207 VgSchedReturnCode src; 208 ThreadId tid = (ThreadId)tidW; 209 ThreadState* tst; 210 211 VG_(debugLog)(1, "syswrap-darwin", 212 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n", 213 (ULong)tidW); 214 215 tst = VG_(get_ThreadState)(tid); 216 vg_assert(tst); 217 218 /* Run the thread all the way through. */ 219 src = thread_wrapper(tid); 220 221 VG_(debugLog)(1, "syswrap-darwin", 222 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n", 223 (ULong)tidW); 224 225 c = VG_(count_living_threads)(); 226 vg_assert(c >= 1); /* stay sane */ 227 228 // Tell the tool this thread is exiting 229 VG_TRACK( pre_thread_ll_exit, tid ); 230 231 /* If the thread is exiting with errors disabled, complain loudly; 232 doing so is bad (does the user know this has happened?) Also, 233 in all cases, be paranoid and clear the flag anyway so that the 234 thread slot is safe in this respect if later reallocated. This 235 should be unnecessary since the flag should be cleared when the 236 slot is reallocated, in thread_wrapper(). */ 237 if (tst->err_disablement_level > 0) { 238 VG_(umsg)( 239 "WARNING: exiting thread has error reporting disabled.\n" 240 "WARNING: possibly as a result of some mistake in the use\n" 241 "WARNING: of the VALGRIND_DISABLE_ERROR_REPORTING macros.\n" 242 ); 243 VG_(debugLog)( 244 1, "syswrap-linux", 245 "run_a_thread_NORETURN(tid=%lld): " 246 "WARNING: exiting thread has err_disablement_level = %u\n", 247 (ULong)tidW, tst->err_disablement_level 248 ); 249 } 250 tst->err_disablement_level = 0; 251 252 if (c == 1) { 253 254 VG_(debugLog)(1, "syswrap-darwin", 255 "run_a_thread_NORETURN(tid=%lld): " 256 "last one standing\n", 257 (ULong)tidW); 258 259 /* We are the last one standing. Keep hold of the lock and 260 carry on to show final tool results, then exit the entire system. 261 Use the continuation pointer set at startup in m_main. */ 262 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src); 263 264 } else { 265 266 mach_msg_header_t msg; 267 268 VG_(debugLog)(1, "syswrap-darwin", 269 "run_a_thread_NORETURN(tid=%lld): " 270 "not last one standing\n", 271 (ULong)tidW); 272 273 /* OK, thread is dead, but others still exist. Just exit. */ 274 275 /* This releases the run lock */ 276 VG_(exit_thread)(tid); 277 vg_assert(tst->status == VgTs_Zombie); 278 279 /* tid is now invalid. */ 280 281 // GrP fixme exit race 282 msg.msgh_bits = MACH_MSGH_BITS(17, MACH_MSG_TYPE_MAKE_SEND_ONCE); 283 msg.msgh_request_port = VG_(gettid)(); 284 msg.msgh_reply_port = 0; 285 msg.msgh_id = 3600; // thread_terminate 286 287 tst->status = VgTs_Empty; 288 // GrP fixme race here! new thread may claim this V thread stack 289 // before we get out here! 290 // GrP fixme use bsdthread_terminate for safe cleanup? 291 mach_msg(&msg, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, 292 sizeof(msg), 0, 0, MACH_MSG_TIMEOUT_NONE, 0); 293 294 // DDD: This is reached sometimes on none/tests/manythreads, maybe 295 // because of the race above. 296 VG_(core_panic)("Thread exit failed?\n"); 297 } 298 299 /*NOTREACHED*/ 300 vg_assert(0); 301 } 302 303 304 /* Allocate a stack for the main thread, and run it all the way to the 305 end. Although we already have a working VgStack 306 (VG_(interim_stack)) it's better to allocate a new one, so that 307 overflow detection works uniformly for all threads. 308 */ 309 void VG_(main_thread_wrapper_NORETURN)(ThreadId tid) 310 { 311 Addr sp; 312 VG_(debugLog)(1, "syswrap-darwin", 313 "entering VG_(main_thread_wrapper_NORETURN)\n"); 314 315 sp = allocstack(tid); 316 317 /* If we can't even allocate the first thread's stack, we're hosed. 318 Give up. */ 319 vg_assert2(sp != 0, "Cannot allocate main thread's stack."); 320 321 /* shouldn't be any other threads around yet */ 322 vg_assert( VG_(count_living_threads)() == 1 ); 323 324 call_on_new_stack_0_1( 325 (Addr)sp, /* stack */ 326 0, /*bogus return address*/ 327 run_a_thread_NORETURN, /* fn to call */ 328 (Word)tid /* arg to give it */ 329 ); 330 331 /*NOTREACHED*/ 332 vg_assert(0); 333 } 334 335 336 void start_thread_NORETURN ( Word arg ) 337 { 338 ThreadState* tst = (ThreadState*)arg; 339 ThreadId tid = tst->tid; 340 341 run_a_thread_NORETURN ( (Word)tid ); 342 /*NOTREACHED*/ 343 vg_assert(0); 344 } 345 346 347 void VG_(cleanup_thread) ( ThreadArchState* arch ) 348 { 349 } 350 351 352 /* --------------------------------------------------------------------- 353 Mach port tracking (based on syswrap-generic's fd tracker) 354 ------------------------------------------------------------------ */ 355 356 /* One of these is allocated for each open port. */ 357 typedef struct OpenPort 358 { 359 mach_port_t port; 360 mach_port_type_t type; /* right type(s) */ 361 Int send_count; /* number of send rights */ 362 Char *name; /* bootstrap name or NULL */ 363 ExeContext *where; /* first allocation only */ 364 struct OpenPort *next, *prev; 365 } OpenPort; 366 367 // strlen("0x12345678") 368 #define PORT_STRLEN (2+2*sizeof(mach_port_t)) 369 370 /* List of allocated ports. */ 371 static OpenPort *allocated_ports; 372 373 /* Count of open ports. */ 374 static Int allocated_port_count = 0; 375 376 377 __attribute__((unused)) 378 static Bool port_exists(mach_port_t port) 379 { 380 OpenPort *i; 381 382 /* Check to see if this port is already open. */ 383 i = allocated_ports; 384 while (i) { 385 if (i->port == port) { 386 return True; 387 } 388 i = i->next; 389 } 390 391 return False; 392 } 393 394 static OpenPort *info_for_port(mach_port_t port) 395 { 396 OpenPort *i; 397 if (!port) return NULL; 398 399 i = allocated_ports; 400 while (i) { 401 if (i->port == port) { 402 return i; 403 } 404 i = i->next; 405 } 406 407 return NULL; 408 } 409 410 411 // Give a port a name, without changing its refcount 412 // GrP fixme don't override name if it already has a specific one 413 __private_extern__ void assign_port_name(mach_port_t port, const char *name) 414 { 415 OpenPort *i; 416 if (!port) return; 417 vg_assert(name); 418 419 i = info_for_port(port); 420 vg_assert(i); 421 422 if (i->name) VG_(arena_free)(VG_AR_CORE, i->name); 423 i->name = 424 VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port-name", 425 VG_(strlen)(name) + PORT_STRLEN + 1); 426 VG_(sprintf)(i->name, name, port); 427 } 428 429 430 // Return the name of the given port or "UNKNOWN 0x1234" if not known. 431 static const char *name_for_port(mach_port_t port) 432 { 433 static char buf[8 + PORT_STRLEN + 1]; 434 OpenPort *i; 435 436 // hack 437 if (port == VG_(gettid)()) return "mach_thread_self()"; 438 if (port == 0) return "NULL"; 439 440 i = allocated_ports; 441 while (i) { 442 if (i->port == port) { 443 return i->name; 444 } 445 i = i->next; 446 } 447 448 VG_(sprintf)(buf, "NONPORT-%#x", port); 449 return buf; 450 } 451 452 /* Note the fact that a port was just deallocated. */ 453 454 static 455 void record_port_mod_refs(mach_port_t port, mach_port_type_t right, Int delta) 456 { 457 OpenPort *i = allocated_ports; 458 if (!port) return; 459 460 while(i) { 461 if(i->port == port) { 462 vg_assert(right != MACH_PORT_TYPE_DEAD_NAME); 463 if (right & MACH_PORT_TYPE_SEND) { 464 // send rights are refcounted 465 if (delta == INT_MIN) delta = -i->send_count; // INT_MIN == destroy 466 i->send_count += delta; 467 if (i->send_count > 0) i->type |= MACH_PORT_TYPE_SEND; 468 else i->type &= ~MACH_PORT_TYPE_SEND; 469 } 470 right = right & ~MACH_PORT_TYPE_SEND; 471 if (right) { 472 // other rights are not refcounted 473 if (delta > 0) { 474 i->type |= right; 475 } else if (delta < 0) { 476 i->type &= ~right; 477 } 478 } 479 480 if (i->type != 0) return; 481 482 // Port has no rights left. Kill it. 483 // VG_(printf)("deleting port %p %s", i->port, i->name); 484 if(i->prev) 485 i->prev->next = i->next; 486 else 487 allocated_ports = i->next; 488 if(i->next) 489 i->next->prev = i->prev; 490 if(i->name) 491 VG_(arena_free) (VG_AR_CORE, i->name); 492 VG_(arena_free) (VG_AR_CORE, i); 493 allocated_port_count--; 494 return; 495 } 496 i = i->next; 497 } 498 499 VG_(printf)("UNKNOWN Mach port modified (port %#x delta %d)\n", port, delta); 500 } 501 502 static 503 void record_port_insert_rights(mach_port_t port, mach_msg_type_name_t type) 504 { 505 switch (type) { 506 case MACH_MSG_TYPE_PORT_NAME: 507 // this task has no rights for the name 508 break; 509 case MACH_MSG_TYPE_PORT_RECEIVE: 510 // this task gets receive rights 511 record_port_mod_refs(port, MACH_PORT_TYPE_RECEIVE, 1); 512 break; 513 case MACH_MSG_TYPE_PORT_SEND: 514 // this task gets a send right 515 record_port_mod_refs(port, MACH_PORT_TYPE_SEND, 1); 516 break; 517 case MACH_MSG_TYPE_PORT_SEND_ONCE: 518 // this task gets send-once rights 519 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_ONCE, 1); 520 break; 521 default: 522 vg_assert(0); 523 break; 524 } 525 } 526 527 static 528 void record_port_dealloc(mach_port_t port) 529 { 530 // deletes 1 send or send-once right (port can't have both) 531 record_port_mod_refs(port, MACH_PORT_TYPE_SEND_RIGHTS, -1); 532 } 533 534 static 535 void record_port_destroy(mach_port_t port) 536 { 537 // deletes all rights to port 538 record_port_mod_refs(port, MACH_PORT_TYPE_ALL_RIGHTS, INT_MIN); 539 } 540 541 542 /* Note the fact that a Mach port was just allocated or transferred. 543 If the port is already known, increment its reference count. */ 544 void record_named_port(ThreadId tid, mach_port_t port, 545 mach_port_right_t right, const char *name) 546 { 547 OpenPort *i; 548 if (!port) return; 549 550 /* Check to see if this port is already open. */ 551 i = allocated_ports; 552 while (i) { 553 if (i->port == port) { 554 if (right != -1) record_port_mod_refs(port, MACH_PORT_TYPE(right), 1); 555 return; 556 } 557 i = i->next; 558 } 559 560 /* Not already one: allocate an OpenPort */ 561 if (i == NULL) { 562 i = VG_(arena_malloc)(VG_AR_CORE, "syswrap-darwin.mach-port", 563 sizeof(OpenPort)); 564 565 i->prev = NULL; 566 i->next = allocated_ports; 567 if(allocated_ports) allocated_ports->prev = i; 568 allocated_ports = i; 569 allocated_port_count++; 570 571 i->port = port; 572 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid, 0); 573 i->name = NULL; 574 if (right != -1) { 575 i->type = MACH_PORT_TYPE(right); 576 i->send_count = (right == MACH_PORT_RIGHT_SEND) ? 1 : 0; 577 } else { 578 i->type = 0; 579 i->send_count = 0; 580 } 581 582 assign_port_name(port, name); 583 } 584 } 585 586 587 // Record opening of a nameless port. 588 static void record_unnamed_port(ThreadId tid, mach_port_t port, mach_port_right_t right) 589 { 590 record_named_port(tid, port, right, "unnamed-%p"); 591 } 592 593 594 /* Dump summary of open Mach ports, like VG_(show_open_fds) */ 595 void VG_(show_open_ports)(void) 596 { 597 OpenPort *i; 598 599 VG_(message)(Vg_UserMsg, 600 "MACH PORTS: %d open at exit.", allocated_port_count); 601 602 for (i = allocated_ports; i; i = i->next) { 603 if (i->name) { 604 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x: %s", i->port, i->name); 605 } else { 606 VG_(message)(Vg_UserMsg, "Open Mach port 0x%x", i->port); 607 } 608 609 if (i->where) { 610 VG_(pp_ExeContext)(i->where); 611 VG_(message)(Vg_UserMsg, ""); 612 } 613 } 614 615 VG_(message)(Vg_UserMsg, ""); 616 } 617 618 619 /* --------------------------------------------------------------------- 620 sync_mappings 621 ------------------------------------------------------------------ */ 622 623 void ML_(sync_mappings)(const HChar *when, const HChar *where, Int num) 624 { 625 // Usually the number of segments added/removed in a single calls is very 626 // small e.g. 1. But it sometimes gets up to at least 100 or so (eg. for 627 // Quicktime). So we use a repeat-with-bigger-buffers-until-success model, 628 // because we can't do dynamic allocation within VG_(get_changed_segments), 629 // because it's in m_aspacemgr. 630 ChangedSeg* css = NULL; 631 Int css_size; 632 Int css_used; 633 Int i; 634 Bool ok; 635 636 if (VG_(clo_trace_syscalls)) { 637 VG_(debugLog)(0, "syswrap-darwin", 638 "sync_mappings(\"%s\", \"%s\", %d)\n", 639 when, where, num); 640 } 641 642 // 16 is enough for most cases, but small enough that overflow happens 643 // occasionally and thus the overflow path gets some test coverage. 644 css_size = 16; 645 ok = False; 646 while (!ok) { 647 VG_(free)(css); // css is NULL on first iteration; that's ok. 648 css = VG_(malloc)("sys_wrap.sync_mappings", css_size*sizeof(ChangedSeg)); 649 ok = VG_(get_changed_segments)(when, where, css, css_size, &css_used); 650 css_size *= 2; 651 } 652 653 // Now add/remove them. 654 for (i = 0; i < css_used; i++) { 655 ChangedSeg* cs = &css[i]; 656 Char* action; 657 if (cs->is_added) { 658 ML_(notify_core_and_tool_of_mmap)( 659 cs->start, cs->end - cs->start + 1, 660 cs->prot, VKI_MAP_PRIVATE, 0, cs->offset); 661 // should this call VG_(di_notify_mmap) also? 662 action = "added"; 663 664 } else { 665 ML_(notify_core_and_tool_of_munmap)( 666 cs->start, cs->end - cs->start + 1); 667 action = "removed"; 668 } 669 if (VG_(clo_trace_syscalls)) { 670 VG_(debugLog)(0, "syswrap-darwin", 671 " %s region 0x%010lx..0x%010lx at %s (%s)\n", 672 action, cs->start, cs->end + 1, where, when); 673 } 674 } 675 676 VG_(free)(css); 677 } 678 679 /* --------------------------------------------------------------------- 680 wrappers 681 ------------------------------------------------------------------ */ 682 683 #define PRE(name) DEFN_PRE_TEMPLATE(darwin, name) 684 #define POST(name) DEFN_POST_TEMPLATE(darwin, name) 685 686 #define PRE_FN(name) vgSysWrap_darwin_##name##_before 687 #define POST_FN(name) vgSysWrap_darwin_##name##_after 688 689 #define CALL_PRE(name) PRE_FN(name)(tid, layout, arrghs, status, flags) 690 #define CALL_POST(name) POST_FN(name)(tid, arrghs, status) 691 692 #if VG_WORDSIZE == 4 693 // Combine two 32-bit values into a 64-bit value 694 // Always use with low-numbered arg first (e.g. LOHI64(ARG1,ARG2) ) 695 # if defined(VGA_x86) 696 # define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) ) 697 # else 698 # error unknown architecture 699 # endif 700 #endif 701 702 // Retrieve the current Mach thread 703 #define MACH_THREAD ((Addr)VG_(get_ThreadState)(tid)->os_state.lwpid) 704 705 // Set the POST handler for a mach_msg derivative 706 #define AFTER VG_(get_ThreadState)(tid)->os_state.post_mach_trap_fn 707 708 // Set or get values saved from Mach messages 709 #define MACH_ARG(x) VG_(get_ThreadState)(tid)->os_state.mach_args.x 710 #define MACH_REMOTE VG_(get_ThreadState)(tid)->os_state.remote_port 711 #define MACH_MSGH_ID VG_(get_ThreadState)(tid)->os_state.msgh_id 712 713 /* --------------------------------------------------------------------- 714 darwin ioctl wrapper 715 ------------------------------------------------------------------ */ 716 717 PRE(ioctl) 718 { 719 *flags |= SfMayBlock; 720 721 /* Handle ioctls that don't take an arg first */ 722 switch (ARG2 /* request */) { 723 case VKI_TIOCSCTTY: 724 case VKI_TIOCEXCL: 725 case VKI_TIOCPTYGRANT: 726 case VKI_TIOCPTYUNLK: 727 case VKI_DTRACEHIOC_REMOVE: 728 PRINT("ioctl ( %ld, 0x%lx )",ARG1,ARG2); 729 PRE_REG_READ2(long, "ioctl", 730 unsigned int, fd, unsigned int, request); 731 return; 732 default: 733 PRINT("ioctl ( %ld, 0x%lx, %#lx )",ARG1,ARG2,ARG3); 734 PRE_REG_READ3(long, "ioctl", 735 unsigned int, fd, unsigned int, request, unsigned long, arg); 736 } 737 738 switch (ARG2 /* request */) { 739 case VKI_TIOCGWINSZ: 740 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) ); 741 break; 742 case VKI_TIOCSWINSZ: 743 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) ); 744 break; 745 case VKI_TIOCMBIS: 746 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) ); 747 break; 748 case VKI_TIOCMBIC: 749 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) ); 750 break; 751 case VKI_TIOCMSET: 752 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) ); 753 break; 754 case VKI_TIOCMGET: 755 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) ); 756 break; 757 case VKI_TIOCGPGRP: 758 /* Get process group ID for foreground processing group. */ 759 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) ); 760 break; 761 case VKI_TIOCSPGRP: 762 /* Set a process group ID? */ 763 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) ); 764 break; 765 case VKI_FIONBIO: 766 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) ); 767 break; 768 case VKI_FIOASYNC: 769 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) ); 770 break; 771 case VKI_FIONREAD: /* identical to SIOCINQ */ 772 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) ); 773 break; 774 775 776 /* These all use struct ifreq AFAIK */ 777 /* GrP fixme is sizeof(struct vki_if_req) correct if it's using a sockaddr? */ 778 case VKI_SIOCGIFFLAGS: /* get flags */ 779 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)", 780 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 781 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq)); 782 break; 783 case VKI_SIOCGIFMTU: /* get MTU size */ 784 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)", 785 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 786 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq)); 787 break; 788 case VKI_SIOCGIFADDR: /* get PA address */ 789 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)", 790 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 791 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq)); 792 break; 793 case VKI_SIOCGIFNETMASK: /* get network PA mask */ 794 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)", 795 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 796 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq)); 797 break; 798 case VKI_SIOCGIFMETRIC: /* get metric */ 799 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)", 800 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 801 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq)); 802 break; 803 case VKI_SIOCGIFDSTADDR: /* get remote PA address */ 804 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)", 805 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 806 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq)); 807 break; 808 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */ 809 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)", 810 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 811 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq)); 812 break; 813 case VKI_SIOCGIFCONF: /* get iface list */ 814 /* WAS: 815 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf)); 816 KERNEL_DO_SYSCALL(tid,RES); 817 if (!VG_(is_kerror)(RES) && RES == 0) 818 POST_MEM_WRITE(ARG3, sizeof(struct ifconf)); 819 */ 820 PRE_MEM_READ( "ioctl(SIOCGIFCONF)", 821 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len, 822 sizeof(((struct vki_ifconf *)ARG3)->ifc_len)); 823 PRE_MEM_READ( "ioctl(SIOCGIFCONF)", 824 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf, 825 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf)); 826 if ( ARG3 ) { 827 // TODO len must be readable and writable 828 // buf pointer only needs to be readable 829 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3; 830 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf", 831 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len ); 832 } 833 break; 834 835 case VKI_SIOCSIFFLAGS: /* set flags */ 836 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)", 837 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 838 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)", 839 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags, 840 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) ); 841 break; 842 case VKI_SIOCSIFADDR: /* set PA address */ 843 case VKI_SIOCSIFDSTADDR: /* set remote PA address */ 844 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */ 845 case VKI_SIOCSIFNETMASK: /* set network PA mask */ 846 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)", 847 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 848 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)", 849 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr, 850 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) ); 851 break; 852 case VKI_SIOCSIFMETRIC: /* set metric */ 853 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)", 854 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 855 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)", 856 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric, 857 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) ); 858 break; 859 case VKI_SIOCSIFMTU: /* set MTU size */ 860 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)", 861 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name ); 862 PRE_MEM_READ( "ioctl(SIOCSIFMTU)", 863 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu, 864 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) ); 865 break; 866 /* Routing table calls. */ 867 #ifdef VKI_SIOCADDRT 868 case VKI_SIOCADDRT: /* add routing table entry */ 869 case VKI_SIOCDELRT: /* delete routing table entry */ 870 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3, 871 sizeof(struct vki_rtentry)); 872 break; 873 #endif 874 875 case VKI_SIOCGPGRP: 876 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) ); 877 break; 878 case VKI_SIOCSPGRP: 879 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) ); 880 //tst->sys_flags &= ~SfMayBlock; 881 break; 882 883 case VKI_FIODTYPE: 884 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) ); 885 break; 886 887 case VKI_DTRACEHIOC_ADDDOF: 888 break; 889 890 // ttycom.h 891 case VKI_TIOCGETA: 892 PRE_MEM_WRITE( "ioctl(TIOCGETA)", ARG3, sizeof(struct vki_termios) ); 893 break; 894 case VKI_TIOCSETA: 895 PRE_MEM_READ( "ioctl(TIOCSETA)", ARG3, sizeof(struct vki_termios) ); 896 break; 897 case VKI_TIOCGETD: 898 PRE_MEM_WRITE( "ioctl(TIOCGETD)", ARG3, sizeof(int) ); 899 break; 900 case VKI_TIOCSETD: 901 PRE_MEM_READ( "ioctl(TIOCSETD)", ARG3, sizeof(int) ); 902 break; 903 case VKI_TIOCPTYGNAME: 904 PRE_MEM_WRITE( "ioctl(TIOCPTYGNAME)", ARG3, 128 ); 905 break; 906 907 default: 908 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3); 909 break; 910 } 911 } 912 913 914 POST(ioctl) 915 { 916 vg_assert(SUCCESS); 917 switch (ARG2 /* request */) { 918 case VKI_TIOCGWINSZ: 919 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) ); 920 break; 921 case VKI_TIOCSWINSZ: 922 case VKI_TIOCMBIS: 923 case VKI_TIOCMBIC: 924 case VKI_TIOCMSET: 925 break; 926 case VKI_TIOCMGET: 927 POST_MEM_WRITE( ARG3, sizeof(unsigned int) ); 928 break; 929 case VKI_TIOCGPGRP: 930 /* Get process group ID for foreground processing group. */ 931 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) ); 932 break; 933 case VKI_TIOCSPGRP: 934 /* Set a process group ID? */ 935 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) ); 936 break; 937 case VKI_TIOCSCTTY: 938 break; 939 case VKI_FIONBIO: 940 break; 941 case VKI_FIOASYNC: 942 break; 943 case VKI_FIONREAD: /* identical to SIOCINQ */ 944 POST_MEM_WRITE( ARG3, sizeof(int) ); 945 break; 946 947 /* These all use struct ifreq AFAIK */ 948 case VKI_SIOCGIFFLAGS: /* get flags */ 949 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags, 950 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) ); 951 break; 952 case VKI_SIOCGIFMTU: /* get MTU size */ 953 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu, 954 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) ); 955 break; 956 case VKI_SIOCGIFADDR: /* get PA address */ 957 case VKI_SIOCGIFDSTADDR: /* get remote PA address */ 958 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */ 959 case VKI_SIOCGIFNETMASK: /* get network PA mask */ 960 POST_MEM_WRITE( 961 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr, 962 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) ); 963 break; 964 case VKI_SIOCGIFMETRIC: /* get metric */ 965 POST_MEM_WRITE( 966 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric, 967 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) ); 968 break; 969 case VKI_SIOCGIFCONF: /* get iface list */ 970 /* WAS: 971 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf)); 972 KERNEL_DO_SYSCALL(tid,RES); 973 if (!VG_(is_kerror)(RES) && RES == 0) 974 POST_MEM_WRITE(ARG3, sizeof(struct ifconf)); 975 */ 976 if (RES == 0 && ARG3 ) { 977 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3; 978 if (ifc->vki_ifc_buf != NULL) 979 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len ); 980 } 981 break; 982 983 case VKI_SIOCSIFFLAGS: /* set flags */ 984 case VKI_SIOCSIFDSTADDR: /* set remote PA address */ 985 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */ 986 case VKI_SIOCSIFNETMASK: /* set network PA mask */ 987 case VKI_SIOCSIFMETRIC: /* set metric */ 988 case VKI_SIOCSIFADDR: /* set PA address */ 989 case VKI_SIOCSIFMTU: /* set MTU size */ 990 break; 991 992 #ifdef VKI_SIOCADDRT 993 /* Routing table calls. */ 994 case VKI_SIOCADDRT: /* add routing table entry */ 995 case VKI_SIOCDELRT: /* delete routing table entry */ 996 break; 997 #endif 998 999 case VKI_SIOCGPGRP: 1000 POST_MEM_WRITE(ARG3, sizeof(int)); 1001 break; 1002 case VKI_SIOCSPGRP: 1003 break; 1004 1005 case VKI_FIODTYPE: 1006 POST_MEM_WRITE( ARG3, sizeof(int) ); 1007 break; 1008 1009 case VKI_DTRACEHIOC_REMOVE: 1010 case VKI_DTRACEHIOC_ADDDOF: 1011 break; 1012 1013 // ttycom.h 1014 case VKI_TIOCGETA: 1015 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios)); 1016 break; 1017 case VKI_TIOCSETA: 1018 break; 1019 case VKI_TIOCGETD: 1020 POST_MEM_WRITE( ARG3, sizeof(int) ); 1021 break; 1022 case VKI_TIOCSETD: 1023 break; 1024 case VKI_TIOCPTYGNAME: 1025 POST_MEM_WRITE( ARG3, 128); 1026 break; 1027 case VKI_TIOCPTYGRANT: 1028 case VKI_TIOCPTYUNLK: 1029 break; 1030 1031 default: 1032 break; 1033 } 1034 } 1035 1036 1037 /* --------------------------------------------------------------------- 1038 darwin fcntl wrapper 1039 ------------------------------------------------------------------ */ 1040 static const char *name_for_fcntl(UWord cmd) { 1041 #define F(n) case VKI_##n: return #n 1042 switch (cmd) { 1043 F(F_CHKCLEAN); 1044 F(F_RDAHEAD); 1045 F(F_NOCACHE); 1046 F(F_FULLFSYNC); 1047 F(F_FREEZE_FS); 1048 F(F_THAW_FS); 1049 F(F_GLOBAL_NOCACHE); 1050 F(F_PREALLOCATE); 1051 F(F_SETSIZE); 1052 F(F_RDADVISE); 1053 F(F_READBOOTSTRAP); 1054 F(F_WRITEBOOTSTRAP); 1055 F(F_LOG2PHYS); 1056 F(F_GETPATH); 1057 F(F_PATHPKG_CHECK); 1058 F(F_ADDSIGS); 1059 default: 1060 return "UNKNOWN"; 1061 } 1062 #undef F 1063 } 1064 1065 PRE(fcntl) 1066 { 1067 switch (ARG2) { 1068 // These ones ignore ARG3. 1069 case VKI_F_GETFD: 1070 case VKI_F_GETFL: 1071 case VKI_F_GETOWN: 1072 PRINT("fcntl ( %ld, %ld )", ARG1,ARG2); 1073 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); 1074 break; 1075 1076 // These ones use ARG3 as "arg". 1077 case VKI_F_DUPFD: 1078 case VKI_F_SETFD: 1079 case VKI_F_SETFL: 1080 case VKI_F_SETOWN: 1081 PRINT("fcntl[ARG3=='arg'] ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); 1082 PRE_REG_READ3(long, "fcntl", 1083 unsigned int, fd, unsigned int, cmd, unsigned long, arg); 1084 break; 1085 1086 // These ones use ARG3 as "lock". 1087 case VKI_F_GETLK: 1088 case VKI_F_SETLK: 1089 case VKI_F_SETLKW: 1090 PRINT("fcntl[ARG3=='lock'] ( %ld, %ld, %#lx )", ARG1,ARG2,ARG3); 1091 PRE_REG_READ3(long, "fcntl", 1092 unsigned int, fd, unsigned int, cmd, 1093 struct flock64 *, lock); 1094 // GrP fixme mem read sizeof(flock64) 1095 if (ARG2 == VKI_F_SETLKW) 1096 *flags |= SfMayBlock; 1097 break; 1098 1099 // none 1100 case VKI_F_CHKCLEAN: 1101 case VKI_F_RDAHEAD: 1102 case VKI_F_NOCACHE: 1103 case VKI_F_FULLFSYNC: 1104 case VKI_F_FREEZE_FS: 1105 case VKI_F_THAW_FS: 1106 case VKI_F_GLOBAL_NOCACHE: 1107 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG1)); 1108 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd); 1109 break; 1110 1111 // struct fstore 1112 case VKI_F_PREALLOCATE: 1113 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1114 PRE_REG_READ3(long, "fcntl", 1115 unsigned int, fd, unsigned int, cmd, 1116 struct fstore *, fstore); 1117 { 1118 struct vki_fstore *fstore = (struct vki_fstore *)ARG3; 1119 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)", 1120 fstore->fst_flags ); 1121 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)", 1122 fstore->fst_posmode ); 1123 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)", 1124 fstore->fst_offset ); 1125 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, fstore->fst_flags)", 1126 fstore->fst_length ); 1127 PRE_FIELD_WRITE( "fcntl(F_PREALLOCATE, fstore->fst_bytesalloc)", 1128 fstore->fst_bytesalloc); 1129 } 1130 break; 1131 1132 // off_t 1133 case VKI_F_SETSIZE: 1134 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1135 PRE_REG_READ3(long, "fcntl", 1136 unsigned int, fd, unsigned int, cmd, 1137 vki_off_t *, offset); 1138 break; 1139 1140 // struct radvisory 1141 case VKI_F_RDADVISE: 1142 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1143 PRE_REG_READ3(long, "fcntl", 1144 unsigned int, fd, unsigned int, cmd, 1145 struct vki_radvisory *, radvisory); 1146 { 1147 struct vki_radvisory *radvisory = (struct vki_radvisory *)ARG3; 1148 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_offset)", 1149 radvisory->ra_offset ); 1150 PRE_FIELD_READ( "fcntl(F_PREALLOCATE, radvisory->ra_count)", 1151 radvisory->ra_count ); 1152 } 1153 break; 1154 1155 // struct fbootstraptransfer 1156 case VKI_F_READBOOTSTRAP: 1157 case VKI_F_WRITEBOOTSTRAP: 1158 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1159 PRE_REG_READ3(long, "fcntl", 1160 unsigned int, fd, unsigned int, cmd, 1161 struct fbootstraptransfer *, bootstrap); 1162 PRE_MEM_READ( "fcntl(F_READ/WRITEBOOTSTRAP, bootstrap)", 1163 ARG3, sizeof(struct vki_fbootstraptransfer) ); 1164 break; 1165 1166 // struct log2phys (out) 1167 case VKI_F_LOG2PHYS: 1168 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1169 PRE_REG_READ3(long, "fcntl", 1170 unsigned int, fd, unsigned int, cmd, 1171 struct log2phys *, l2p); 1172 PRE_MEM_WRITE( "fcntl(F_LOG2PHYS, l2p)", 1173 ARG3, sizeof(struct vki_log2phys) ); 1174 break; 1175 1176 // char[maxpathlen] (out) 1177 case VKI_F_GETPATH: 1178 PRINT("fcntl ( %ld, %s, %#lx )", ARG1, name_for_fcntl(ARG2), ARG3); 1179 PRE_REG_READ3(long, "fcntl", 1180 unsigned int, fd, unsigned int, cmd, 1181 char *, pathbuf); 1182 PRE_MEM_WRITE( "fcntl(F_GETPATH, pathbuf)", 1183 ARG3, VKI_MAXPATHLEN ); 1184 break; 1185 1186 // char[maxpathlen] (in) 1187 case VKI_F_PATHPKG_CHECK: 1188 PRINT("fcntl ( %ld, %s, %#lx '%s')", ARG1, name_for_fcntl(ARG2), ARG3, 1189 (char *)ARG3); 1190 PRE_REG_READ3(long, "fcntl", 1191 unsigned int, fd, unsigned int, cmd, 1192 char *, pathbuf); 1193 PRE_MEM_RASCIIZ( "fcntl(F_PATHPKG_CHECK, pathbuf)", ARG3); 1194 break; 1195 1196 case VKI_F_ADDSIGS: /* Add detached signatures (for code signing) */ 1197 PRINT("fcntl ( %ld, %s )", ARG1, name_for_fcntl(ARG2)); 1198 PRE_REG_READ3(long, "fcntl", 1199 unsigned int, fd, unsigned int, cmd, 1200 vki_fsignatures_t *, sigs); 1201 1202 { 1203 vki_fsignatures_t *fsigs = (vki_fsignatures_t*)ARG3; 1204 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)", 1205 fsigs->fs_blob_start); 1206 PRE_FIELD_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_size)", 1207 fsigs->fs_blob_size); 1208 1209 if (fsigs->fs_blob_start) 1210 PRE_MEM_READ( "fcntl(F_ADDSIGS, fsigs->fs_blob_start)", 1211 (Addr)fsigs->fs_blob_start, fsigs->fs_blob_size); 1212 } 1213 break; 1214 1215 default: 1216 PRINT("fcntl ( %ld, %ld [??] )", ARG1, ARG2); 1217 VG_(printf)("UNKNOWN fcntl %ld!", ARG2); 1218 break; 1219 } 1220 } 1221 1222 POST(fcntl) 1223 { 1224 vg_assert(SUCCESS); 1225 switch (ARG2) { 1226 case VKI_F_DUPFD: 1227 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) { 1228 VG_(close)(RES); 1229 SET_STATUS_Failure( VKI_EMFILE ); 1230 } else { 1231 if (VG_(clo_track_fds)) 1232 ML_(record_fd_open_named)(tid, RES); 1233 } 1234 break; 1235 1236 case VKI_F_GETFD: 1237 case VKI_F_GETFL: 1238 case VKI_F_GETOWN: 1239 case VKI_F_SETFD: 1240 case VKI_F_SETFL: 1241 case VKI_F_SETOWN: 1242 case VKI_F_GETLK: 1243 case VKI_F_SETLK: 1244 case VKI_F_SETLKW: 1245 break; 1246 1247 case VKI_F_PREALLOCATE: 1248 { 1249 struct vki_fstore *fstore = (struct vki_fstore *)ARG3; 1250 POST_FIELD_WRITE( fstore->fst_bytesalloc ); 1251 } 1252 break; 1253 1254 case VKI_F_LOG2PHYS: 1255 POST_MEM_WRITE( ARG3, sizeof(struct vki_log2phys) ); 1256 break; 1257 1258 case VKI_F_GETPATH: 1259 POST_MEM_WRITE( ARG3, 1+VG_(strlen)((char *)ARG3) ); 1260 PRINT("\"%s\"", (char*)ARG3); 1261 break; 1262 1263 default: 1264 // DDD: ugh, missing lots of cases here, not nice 1265 break; 1266 } 1267 } 1268 1269 /* --------------------------------------------------------------------- 1270 unix syscalls 1271 ------------------------------------------------------------------ */ 1272 1273 PRE(futimes) 1274 { 1275 PRINT("futimes ( %ld, %#lx )", ARG1,ARG2); 1276 PRE_REG_READ2(long, "futimes", int, fd, struct timeval *, tvp); 1277 if (!ML_(fd_allowed)(ARG1, "futimes", tid, False)) { 1278 SET_STATUS_Failure( VKI_EBADF ); 1279 } else if (ARG2 != 0) { 1280 PRE_timeval_READ( "futimes(tvp[0])", ARG2 ); 1281 PRE_timeval_READ( "futimes(tvp[1])", ARG2+sizeof(struct vki_timeval) ); 1282 } 1283 } 1284 1285 PRE(semget) 1286 { 1287 PRINT("semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); 1288 PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg); 1289 } 1290 1291 PRE(semop) 1292 { 1293 *flags |= SfMayBlock; 1294 PRINT("semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3); 1295 PRE_REG_READ3(long, "semop", 1296 int, semid, struct sembuf *, sops, vki_size_t, nsoops); 1297 ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3); 1298 } 1299 1300 PRE(semctl) 1301 { 1302 switch (ARG3) { 1303 case VKI_IPC_STAT: 1304 case VKI_IPC_SET: 1305 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); 1306 PRE_REG_READ4(long, "semctl", 1307 int, semid, int, semnum, int, cmd, struct semid_ds *, arg); 1308 break; 1309 case VKI_GETALL: 1310 case VKI_SETALL: 1311 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); 1312 PRE_REG_READ4(long, "semctl", 1313 int, semid, int, semnum, int, cmd, unsigned short *, arg); 1314 break; 1315 case VKI_SETVAL: 1316 PRINT("semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); 1317 PRE_REG_READ4(long, "semctl", 1318 int, semid, int, semnum, int, cmd, int, arg); 1319 break; 1320 default: 1321 PRINT("semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); 1322 PRE_REG_READ3(long, "semctl", 1323 int, semid, int, semnum, int, cmd); 1324 break; 1325 } 1326 ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3,ARG4); 1327 } 1328 POST(semctl) 1329 { 1330 ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3,ARG4); 1331 } 1332 1333 PRE(sem_open) 1334 { 1335 if (ARG2 & VKI_O_CREAT) { 1336 // 4-arg version 1337 PRINT("sem_open ( %#lx(%s), %ld, %ld, %ld )", 1338 ARG1,(char*)ARG1,ARG2,ARG3,ARG4); 1339 PRE_REG_READ4(vki_sem_t *, "sem_open", 1340 const char *, name, int, oflag, vki_mode_t, mode, 1341 unsigned int, value); 1342 } else { 1343 // 2-arg version 1344 PRINT("sem_open ( %#lx(%s), %ld )",ARG1,(char*)ARG1,ARG2); 1345 PRE_REG_READ2(vki_sem_t *, "sem_open", 1346 const char *, name, int, oflag); 1347 } 1348 PRE_MEM_RASCIIZ( "sem_open(name)", ARG1 ); 1349 1350 /* Otherwise handle normally */ 1351 *flags |= SfMayBlock; 1352 } 1353 1354 PRE(sem_close) 1355 { 1356 PRINT("sem_close( %#lx )", ARG1); 1357 PRE_REG_READ1(int, "sem_close", vki_sem_t *, sem); 1358 } 1359 1360 PRE(sem_unlink) 1361 { 1362 PRINT("sem_unlink( %#lx(%s) )", ARG1,(char*)ARG1); 1363 PRE_REG_READ1(int, "sem_unlink", const char *, name); 1364 PRE_MEM_RASCIIZ( "sem_unlink(name)", ARG1 ); 1365 } 1366 1367 PRE(sem_post) 1368 { 1369 PRINT("sem_post( %#lx )", ARG1); 1370 PRE_REG_READ1(int, "sem_post", vki_sem_t *, sem); 1371 *flags |= SfMayBlock; 1372 } 1373 1374 PRE(sem_destroy) 1375 { 1376 PRINT("sem_destroy( %#lx )", ARG1); 1377 PRE_REG_READ1(int, "sem_destroy", vki_sem_t *, sem); 1378 PRE_MEM_READ("sem_destroy(sem)", ARG1, sizeof(vki_sem_t)); 1379 } 1380 1381 PRE(sem_init) 1382 { 1383 PRINT("sem_init( %#lx, %ld, %ld )", ARG1, ARG2, ARG3); 1384 PRE_REG_READ3(int, "sem_init", vki_sem_t *, sem, 1385 int, pshared, unsigned int, value); 1386 PRE_MEM_WRITE("sem_init(sem)", ARG1, sizeof(vki_sem_t)); 1387 } 1388 1389 POST(sem_init) 1390 { 1391 POST_MEM_WRITE(ARG1, sizeof(vki_sem_t)); 1392 } 1393 1394 PRE(sem_wait) 1395 { 1396 PRINT("sem_wait( %#lx )", ARG1); 1397 PRE_REG_READ1(int, "sem_wait", vki_sem_t *, sem); 1398 *flags |= SfMayBlock; 1399 } 1400 1401 PRE(sem_trywait) 1402 { 1403 PRINT("sem_trywait( %#lx )", ARG1); 1404 PRE_REG_READ1(int, "sem_trywait", vki_sem_t *, sem); 1405 *flags |= SfMayBlock; 1406 } 1407 1408 PRE(kqueue) 1409 { 1410 PRINT("kqueue()"); 1411 } 1412 1413 POST(kqueue) 1414 { 1415 if (!ML_(fd_allowed)(RES, "kqueue", tid, True)) { 1416 VG_(close)(RES); 1417 SET_STATUS_Failure( VKI_EMFILE ); 1418 } else { 1419 if (VG_(clo_track_fds)) { 1420 ML_(record_fd_open_with_given_name)(tid, RES, NULL); 1421 } 1422 } 1423 } 1424 1425 PRE(kevent) 1426 { 1427 PRINT("kevent( %ld, %#lx, %ld, %#lx, %ld, %#lx )", 1428 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); 1429 PRE_REG_READ6(int,"kevent", int,kq, 1430 const struct vki_kevent *,changelist, int,nchanges, 1431 struct vki_kevent *,eventlist, int,nevents, 1432 const struct vki_timespec *,timeout); 1433 1434 if (ARG3) PRE_MEM_READ ("kevent(changelist)", 1435 ARG2, ARG3 * sizeof(struct vki_kevent)); 1436 if (ARG5) PRE_MEM_WRITE("kevent(eventlist)", 1437 ARG4, ARG5 * sizeof(struct vki_kevent)); 1438 if (ARG6) PRE_MEM_READ ("kevent(timeout)", 1439 ARG6, sizeof(struct vki_timespec)); 1440 1441 *flags |= SfMayBlock; 1442 } 1443 1444 POST(kevent) 1445 { 1446 PRINT("kevent ret %ld dst %#lx (%zu)", RES, ARG4, sizeof(struct vki_kevent)); 1447 if (RES > 0) POST_MEM_WRITE(ARG4, RES * sizeof(struct vki_kevent)); 1448 } 1449 1450 1451 Addr pthread_starter = 0; 1452 Addr wqthread_starter = 0; 1453 SizeT pthread_structsize = 0; 1454 1455 PRE(bsdthread_register) 1456 { 1457 PRINT("bsdthread_register( %#lx, %#lx, %lu )", ARG1, ARG2, ARG3); 1458 PRE_REG_READ3(int,"__bsdthread_register", void *,"threadstart", 1459 void *,"wqthread", size_t,"pthsize"); 1460 1461 pthread_starter = ARG1; 1462 wqthread_starter = ARG2; 1463 pthread_structsize = ARG3; 1464 ARG1 = (Word)&pthread_hijack_asm; 1465 ARG2 = (Word)&wqthread_hijack_asm; 1466 } 1467 1468 PRE(workq_open) 1469 { 1470 PRINT("workq_open()"); 1471 PRE_REG_READ0(int, "workq_open"); 1472 1473 // This creates lots of threads and thread stacks under the covers, 1474 // but we ignore them all until some work item starts running on it. 1475 } 1476 1477 static const char *workqop_name(int op) 1478 { 1479 switch (op) { 1480 case VKI_WQOPS_QUEUE_ADD: return "QUEUE_ADD"; 1481 case VKI_WQOPS_QUEUE_REMOVE: return "QUEUE_REMOVE"; 1482 case VKI_WQOPS_THREAD_RETURN: return "THREAD_RETURN"; 1483 default: return "?"; 1484 } 1485 } 1486 1487 1488 PRE(workq_ops) 1489 { 1490 PRINT("workq_ops( %ld(%s), %#lx, %ld )", ARG1, workqop_name(ARG1), ARG2, 1491 ARG3); 1492 PRE_REG_READ3(int,"workq_ops", int,"options", void *,"item", 1493 int,"priority"); 1494 1495 switch (ARG1) { 1496 case VKI_WQOPS_QUEUE_ADD: 1497 case VKI_WQOPS_QUEUE_REMOVE: 1498 // GrP fixme need anything here? 1499 // GrP fixme may block? 1500 break; 1501 1502 case VKI_WQOPS_THREAD_RETURN: { 1503 // The interesting case. The kernel will do one of two things: 1504 // 1. Return normally. We continue; libc proceeds to stop the thread. 1505 // V does nothing special here. 1506 // 2. Jump to wqthread_hijack. This wipes the stack and runs a 1507 // new work item, and never returns from workq_ops. 1508 // V handles this by longjmp() from wqthread_hijack back to the 1509 // scheduler, which continues at the new client SP/IP/state. 1510 // This works something like V's signal handling. 1511 // To the tool, this looks like workq_ops() sometimes returns 1512 // to a strange address. 1513 ThreadState *tst = VG_(get_ThreadState)(tid); 1514 tst->os_state.wq_jmpbuf_valid = True; 1515 *flags |= SfMayBlock; // GrP fixme true? 1516 break; 1517 } 1518 1519 default: 1520 VG_(printf)("UNKNOWN workq_ops option %ld\n", ARG1); 1521 break; 1522 } 1523 } 1524 POST(workq_ops) 1525 { 1526 ThreadState *tst = VG_(get_ThreadState)(tid); 1527 tst->os_state.wq_jmpbuf_valid = False; 1528 } 1529 1530 1531 1532 PRE(__mac_syscall) 1533 { 1534 PRINT("__mac_syscall( %#lx, %ld, %#lx )", ARG1, ARG2, ARG3); 1535 PRE_REG_READ3(int,"__mac_syscall", char *,"policy", 1536 int,"call", void *,"arg"); 1537 1538 // GrP fixme check call's arg? 1539 // GrP fixme check policy? 1540 } 1541 1542 1543 /* Not like syswrap-generic's sys_exit, which exits only one thread. 1544 More like syswrap-generic's sys_exit_group. */ 1545 PRE(exit) 1546 { 1547 ThreadId t; 1548 ThreadState* tst; 1549 1550 PRINT("darwin exit( %ld )", ARG1); 1551 PRE_REG_READ1(void, "exit", int, status); 1552 1553 tst = VG_(get_ThreadState)(tid); 1554 1555 /* A little complex; find all the threads with the same threadgroup 1556 as this one (including this one), and mark them to exit */ 1557 for (t = 1; t < VG_N_THREADS; t++) { 1558 if ( /* not alive */ 1559 VG_(threads)[t].status == VgTs_Empty 1560 /* GrP fixme zombie? */ 1561 ) 1562 continue; 1563 1564 VG_(threads)[t].exitreason = VgSrc_ExitProcess; 1565 VG_(threads)[t].os_state.exitcode = ARG1; 1566 1567 if (t != tid) 1568 VG_(get_thread_out_of_syscall)(t); /* unblock it, if blocked */ 1569 } 1570 1571 /* We have to claim the syscall already succeeded. */ 1572 SET_STATUS_Success(0); 1573 } 1574 1575 1576 PRE(sigaction) 1577 { 1578 PRINT("sigaction ( %ld, %#lx, %#lx )", ARG1,ARG2,ARG3); 1579 PRE_REG_READ3(long, "sigaction", 1580 int, signum, vki_sigaction_toK_t *, act, 1581 vki_sigaction_fromK_t *, oldact); 1582 1583 if (ARG2 != 0) { 1584 vki_sigaction_toK_t *sa = (vki_sigaction_toK_t *)ARG2; 1585 PRE_MEM_READ( "sigaction(act->sa_handler)", 1586 (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler)); 1587 PRE_MEM_READ( "sigaction(act->sa_mask)", 1588 (Addr)&sa->sa_mask, sizeof(sa->sa_mask)); 1589 PRE_MEM_READ( "sigaction(act->sa_flags)", 1590 (Addr)&sa->sa_flags, sizeof(sa->sa_flags)); 1591 } 1592 if (ARG3 != 0) 1593 PRE_MEM_WRITE( "sigaction(oldact)", 1594 ARG3, sizeof(vki_sigaction_fromK_t)); 1595 1596 SET_STATUS_from_SysRes( 1597 VG_(do_sys_sigaction)(ARG1, (const vki_sigaction_toK_t *)ARG2, 1598 (vki_sigaction_fromK_t *)ARG3) 1599 ); 1600 } 1601 POST(sigaction) 1602 { 1603 vg_assert(SUCCESS); 1604 if (RES == 0 && ARG3 != 0) 1605 POST_MEM_WRITE( ARG3, sizeof(vki_sigaction_fromK_t)); 1606 } 1607 1608 1609 PRE(__pthread_kill) 1610 { 1611 PRINT("__pthread_kill ( %ld, %ld )", ARG1, ARG2); 1612 PRE_REG_READ2(long, "__pthread_kill", vki_pthread_t*, thread, int, sig); 1613 } 1614 1615 1616 PRE(__pthread_sigmask) 1617 { 1618 // GrP fixme 1619 // JRS: arguments are identical to sigprocmask 1620 // (how, sigset_t*, sigset_t*). Perhaps behave identically? 1621 static Bool warned; 1622 if (!warned) { 1623 VG_(printf)("UNKNOWN __pthread_sigmask is unsupported. " 1624 "This warning will not be repeated.\n"); 1625 warned = True; 1626 } 1627 SET_STATUS_Success( 0 ); 1628 } 1629 1630 1631 PRE(__pthread_canceled) 1632 { 1633 *flags |= SfMayBlock; /* might kill this thread??? */ 1634 /* I don't think so -- I think it just changes the cancellation 1635 state. But taking no chances. */ 1636 PRINT("__pthread_canceled ( %ld )", ARG1); 1637 PRE_REG_READ1(long, "__pthread_canceled", void*, arg1); 1638 } 1639 1640 1641 PRE(__pthread_markcancel) 1642 { 1643 *flags |= SfMayBlock; /* might kill this thread??? */ 1644 PRINT("__pthread_markcancel ( %#lx )", ARG1); 1645 PRE_REG_READ1(long, "__pthread_markcancel", void*, arg1); 1646 /* Just let it go through. No idea if this is correct. */ 1647 } 1648 1649 1650 PRE(__disable_threadsignal) 1651 { 1652 vki_sigset_t set; 1653 PRINT("__disable_threadsignal(%ld, %ld, %ld)", ARG1, ARG2, ARG3); 1654 /* I don't think this really looks at its arguments. So don't 1655 bother to check them. */ 1656 1657 VG_(sigfillset)( &set ); 1658 SET_STATUS_from_SysRes( 1659 VG_(do_sys_sigprocmask) ( tid, VKI_SIG_BLOCK, &set, NULL ) 1660 ); 1661 1662 /* We don't expect that blocking all signals for this thread could 1663 cause any more to be delivered (how could it?), but just in case 1664 .. */ 1665 if (SUCCESS) 1666 *flags |= SfPollAfter; 1667 } 1668 1669 1670 PRE(kdebug_trace) 1671 { 1672 PRINT("kdebug_trace(%ld, %ld, %ld, %ld, %ld, %ld)", 1673 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); 1674 /* 1675 Don't check anything - some clients pass fewer arguments. 1676 PRE_REG_READ6(long, "kdebug_trace", 1677 int,"code", int,"arg1", int,"arg2", 1678 int,"arg3", int,"arg4", int,"arg5"); 1679 */ 1680 } 1681 1682 1683 PRE(seteuid) 1684 { 1685 PRINT("seteuid(%ld)", ARG1); 1686 PRE_REG_READ1(long, "seteuid", vki_uid_t, "uid"); 1687 } 1688 1689 1690 PRE(setegid) 1691 { 1692 PRINT("setegid(%ld)", ARG1); 1693 PRE_REG_READ1(long, "setegid", vki_uid_t, "uid"); 1694 } 1695 1696 PRE(settid) 1697 { 1698 PRINT("settid(%ld, %ld)", ARG1, ARG2); 1699 PRE_REG_READ2(long, "settid", vki_uid_t, "uid", vki_gid_t, "gid"); 1700 } 1701 1702 /* XXX need to check whether we need POST operations for 1703 * waitevent, watchevent, modwatch -- jpeach 1704 */ 1705 PRE(watchevent) 1706 { 1707 PRINT("watchevent(%#lx, %#lx)", ARG1, ARG2); 1708 PRE_REG_READ2(long, "watchevent", 1709 vki_eventreq *, "event", unsigned int, "eventmask"); 1710 1711 PRE_MEM_READ("watchevent(event)", ARG1, sizeof(vki_eventreq)); 1712 PRE_MEM_READ("watchevent(eventmask)", ARG2, sizeof(unsigned int)); 1713 *flags |= SfMayBlock; 1714 } 1715 1716 #define WAITEVENT_FAST_POLL ((Addr)(struct timeval *)-1) 1717 PRE(waitevent) 1718 { 1719 PRINT("waitevent(%#lx, %#lx)", ARG1, ARG2); 1720 PRE_REG_READ2(long, "waitevent", 1721 vki_eventreq *, "event", struct timeval *, "timeout"); 1722 PRE_MEM_WRITE("waitevent(event)", ARG1, sizeof(vki_eventreq)); 1723 1724 if (ARG2 && ARG2 != WAITEVENT_FAST_POLL) { 1725 PRE_timeval_READ("waitevent(timeout)", ARG2); 1726 } 1727 1728 /* XXX ((timeval*)-1) is valid for ARG2 -- jpeach */ 1729 *flags |= SfMayBlock; 1730 } 1731 1732 POST(waitevent) 1733 { 1734 POST_MEM_WRITE(ARG1, sizeof(vki_eventreq)); 1735 } 1736 1737 PRE(modwatch) 1738 { 1739 PRINT("modwatch(%#lx, %#lx)", ARG1, ARG2); 1740 PRE_REG_READ2(long, "modwatch", 1741 vki_eventreq *, "event", unsigned int, "eventmask"); 1742 1743 PRE_MEM_READ("modwatch(event)", ARG1, sizeof(vki_eventreq)); 1744 PRE_MEM_READ("modwatch(eventmask)", ARG2, sizeof(unsigned int)); 1745 } 1746 1747 PRE(getxattr) 1748 { 1749 PRINT("getxattr(%#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld)", 1750 ARG1, (char *)ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6); 1751 1752 PRE_REG_READ6(vki_ssize_t, "getxattr", 1753 const char *, path, char *, name, void *, value, 1754 vki_size_t, size, uint32_t, position, int, options); 1755 PRE_MEM_RASCIIZ("getxattr(path)", ARG1); 1756 PRE_MEM_RASCIIZ("getxattr(name)", ARG2); 1757 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4); 1758 } 1759 1760 POST(getxattr) 1761 { 1762 vg_assert((vki_ssize_t)RES >= 0); 1763 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES); 1764 } 1765 1766 PRE(fgetxattr) 1767 { 1768 PRINT("fgetxattr(%ld, %#lx(%s), %#lx, %lu, %lu, %ld)", 1769 ARG1, ARG2, (char *)ARG2, ARG3, ARG4, ARG5, ARG6); 1770 1771 PRE_REG_READ6(vki_ssize_t, "fgetxattr", 1772 int, fd, char *, name, void *, value, 1773 vki_size_t, size, uint32_t, position, int, options); 1774 PRE_MEM_RASCIIZ("getxattr(name)", ARG2); 1775 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4); 1776 } 1777 1778 POST(fgetxattr) 1779 { 1780 vg_assert((vki_ssize_t)RES >= 0); 1781 POST_MEM_WRITE(ARG3, (vki_ssize_t)RES); 1782 } 1783 1784 PRE(setxattr) 1785 { 1786 PRINT("setxattr ( %#lx(%s), %#lx(%s), %#lx, %lu, %lu, %ld )", 1787 ARG1, (char *)ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 ); 1788 PRE_REG_READ6(int, "setxattr", 1789 const char *,"path", char *,"name", void *,"value", 1790 vki_size_t,"size", uint32_t,"position", int,"options" ); 1791 1792 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 ); 1793 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 ); 1794 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 ); 1795 } 1796 1797 1798 PRE(fsetxattr) 1799 { 1800 PRINT( "fsetxattr ( %ld, %#lx(%s), %#lx, %lu, %lu, %ld )", 1801 ARG1, ARG2, (char*)ARG2, ARG3, ARG4, ARG5, ARG6 ); 1802 PRE_REG_READ6(int, "fsetxattr", 1803 int,"fd", char *,"name", void *,"value", 1804 vki_size_t,"size", uint32_t,"position", int,"options" ); 1805 1806 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 ); 1807 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 ); 1808 } 1809 1810 1811 PRE(removexattr) 1812 { 1813 PRINT( "removexattr ( %#lx(%s), %#lx(%s), %ld )", 1814 ARG1, (HChar*)ARG1, ARG2, (HChar*)ARG2, ARG3 ); 1815 PRE_REG_READ3(int, "removexattr", 1816 const char*, "path", char*, "attrname", int, "options"); 1817 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 ); 1818 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 ); 1819 } 1820 1821 1822 PRE(fremovexattr) 1823 { 1824 PRINT( "fremovexattr ( %ld, %#lx(%s), %ld )", 1825 ARG1, ARG2, (HChar*)ARG2, ARG3 ); 1826 PRE_REG_READ3(int, "fremovexattr", 1827 int, "fd", char*, "attrname", int, "options"); 1828 PRE_MEM_RASCIIZ( "removexattr(attrname)", ARG2 ); 1829 } 1830 1831 1832 PRE(listxattr) 1833 { 1834 PRINT( "listxattr ( %#lx(%s), %#lx, %lu, %ld )", 1835 ARG1, (char *)ARG1, ARG2, ARG3, ARG4 ); 1836 PRE_REG_READ4 (long, "listxattr", 1837 const char *,"path", char *,"namebuf", 1838 vki_size_t,"size", int,"options" ); 1839 1840 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 ); 1841 PRE_MEM_WRITE( "listxattr(namebuf)", ARG2, ARG3 ); 1842 *flags |= SfMayBlock; 1843 } 1844 POST(listxattr) 1845 { 1846 vg_assert(SUCCESS); 1847 vg_assert((vki_ssize_t)RES >= 0); 1848 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES ); 1849 } 1850 1851 1852 PRE(flistxattr) 1853 { 1854 PRINT( "flistxattr ( %ld, %#lx, %lu, %ld )", 1855 ARG1, ARG2, ARG3, ARG4 ); 1856 PRE_REG_READ4 (long, "flistxattr", 1857 int, "fd", char *,"namebuf", 1858 vki_size_t,"size", int,"options" ); 1859 PRE_MEM_WRITE( "flistxattr(namebuf)", ARG2, ARG3 ); 1860 *flags |= SfMayBlock; 1861 } 1862 POST(flistxattr) 1863 { 1864 vg_assert(SUCCESS); 1865 vg_assert((vki_ssize_t)RES >= 0); 1866 POST_MEM_WRITE( ARG2, (vki_ssize_t)RES ); 1867 } 1868 1869 1870 PRE(shmat) 1871 { 1872 UWord arg2tmp; 1873 PRINT("shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 1874 PRE_REG_READ3(long, "shmat", 1875 int, shmid, const void *, shmaddr, int, shmflg); 1876 arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3); 1877 if (arg2tmp == 0) 1878 SET_STATUS_Failure( VKI_EINVAL ); 1879 else 1880 ARG2 = arg2tmp; // used in POST 1881 } 1882 POST(shmat) 1883 { 1884 ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3); 1885 } 1886 1887 PRE(shmctl) 1888 { 1889 PRINT("shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3); 1890 PRE_REG_READ3(long, "shmctl", 1891 int, shmid, int, cmd, struct vki_shmid_ds *, buf); 1892 ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3); 1893 } 1894 POST(shmctl) 1895 { 1896 ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3); 1897 } 1898 1899 PRE(shmdt) 1900 { 1901 PRINT("shmdt ( %#lx )",ARG1); 1902 PRE_REG_READ1(long, "shmdt", const void *, shmaddr); 1903 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1)) 1904 SET_STATUS_Failure( VKI_EINVAL ); 1905 } 1906 POST(shmdt) 1907 { 1908 ML_(generic_POST_sys_shmdt)(tid, RES,ARG1); 1909 } 1910 1911 PRE(shmget) 1912 { 1913 PRINT("shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); 1914 PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg); 1915 } 1916 1917 PRE(shm_open) 1918 { 1919 PRINT("shm_open(%#lx(%s), %ld, %ld)", ARG1, (char *)ARG1, ARG2, ARG3); 1920 PRE_REG_READ3(long, "shm_open", 1921 const char *,"name", int,"flags", vki_mode_t,"mode"); 1922 1923 PRE_MEM_RASCIIZ( "shm_open(filename)", ARG1 ); 1924 1925 *flags |= SfMayBlock; 1926 } 1927 POST(shm_open) 1928 { 1929 vg_assert(SUCCESS); 1930 if (!ML_(fd_allowed)(RES, "shm_open", tid, True)) { 1931 VG_(close)(RES); 1932 SET_STATUS_Failure( VKI_EMFILE ); 1933 } else { 1934 if (VG_(clo_track_fds)) 1935 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1); 1936 } 1937 } 1938 1939 1940 PRE(stat_extended) 1941 { 1942 PRINT("stat_extended( %#lx(%s), %#lx, %#lx, %#lx )", 1943 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 1944 PRE_REG_READ4(int, "stat_extended", char *, file_name, struct stat *, buf, 1945 void *, fsacl, vki_size_t *, fsacl_size); 1946 PRE_MEM_RASCIIZ( "stat_extended(file_name)", ARG1 ); 1947 PRE_MEM_WRITE( "stat_extended(buf)", ARG2, sizeof(struct vki_stat) ); 1948 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1949 PRE_MEM_WRITE("stat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 1950 PRE_MEM_READ( "stat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 1951 } 1952 POST(stat_extended) 1953 { 1954 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 1955 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1956 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 1957 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 1958 } 1959 1960 1961 PRE(lstat_extended) 1962 { 1963 PRINT("lstat_extended( %#lx(%s), %#lx, %#lx, %#lx )", 1964 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 1965 PRE_REG_READ4(int, "lstat_extended", char *, file_name, struct stat *, buf, 1966 void *, fsacl, vki_size_t *, fsacl_size); 1967 PRE_MEM_RASCIIZ( "lstat_extended(file_name)", ARG1 ); 1968 PRE_MEM_WRITE( "lstat_extended(buf)", ARG2, sizeof(struct vki_stat) ); 1969 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1970 PRE_MEM_WRITE("lstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 1971 PRE_MEM_READ( "lstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 1972 } 1973 POST(lstat_extended) 1974 { 1975 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 1976 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1977 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 1978 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 1979 } 1980 1981 1982 PRE(fstat_extended) 1983 { 1984 PRINT("fstat_extended( %ld, %#lx, %#lx, %#lx )", 1985 ARG1, ARG2, ARG3, ARG4); 1986 PRE_REG_READ4(int, "fstat_extended", int, fd, struct stat *, buf, 1987 void *, fsacl, vki_size_t *, fsacl_size); 1988 PRE_MEM_WRITE( "fstat_extended(buf)", ARG2, sizeof(struct vki_stat) ); 1989 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1990 PRE_MEM_WRITE("fstat_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 1991 PRE_MEM_READ( "fstat_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 1992 } 1993 POST(fstat_extended) 1994 { 1995 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) ); 1996 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 1997 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 1998 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 1999 } 2000 2001 2002 PRE(stat64_extended) 2003 { 2004 PRINT("stat64_extended( %#lx(%s), %#lx, %#lx, %#lx )", 2005 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 2006 PRE_REG_READ4(int, "stat64_extended", char *, file_name, struct stat64 *, buf, 2007 void *, fsacl, vki_size_t *, fsacl_size); 2008 PRE_MEM_RASCIIZ( "stat64_extended(file_name)", ARG1 ); 2009 PRE_MEM_WRITE( "stat64_extended(buf)", ARG2, sizeof(struct vki_stat64) ); 2010 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2011 PRE_MEM_WRITE("stat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 2012 PRE_MEM_READ( "stat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 2013 } 2014 POST(stat64_extended) 2015 { 2016 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2017 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2018 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 2019 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 2020 } 2021 2022 2023 PRE(lstat64_extended) 2024 { 2025 PRINT("lstat64_extended( %#lx(%s), %#lx, %#lx, %#lx )", 2026 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 2027 PRE_REG_READ4(int, "lstat64_extended", char *, file_name, struct stat64 *, buf, 2028 void *, fsacl, vki_size_t *, fsacl_size); 2029 PRE_MEM_RASCIIZ( "lstat64_extended(file_name)", ARG1 ); 2030 PRE_MEM_WRITE( "lstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) ); 2031 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2032 PRE_MEM_WRITE( "lstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 2033 PRE_MEM_READ( "lstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 2034 } 2035 POST(lstat64_extended) 2036 { 2037 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2038 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2039 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 2040 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 2041 } 2042 2043 2044 PRE(fstat64_extended) 2045 { 2046 PRINT("fstat64_extended( %ld, %#lx, %#lx, %#lx )", 2047 ARG1, ARG2, ARG3, ARG4); 2048 PRE_REG_READ4(int, "fstat64_extended", int, fd, struct stat64 *, buf, 2049 void *, fsacl, vki_size_t *, fsacl_size); 2050 PRE_MEM_WRITE( "fstat64_extended(buf)", ARG2, sizeof(struct vki_stat64) ); 2051 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2052 PRE_MEM_WRITE("fstat64_extended(fsacl)", ARG3, *(vki_size_t *)ARG4 ); 2053 PRE_MEM_READ( "fstat64_extended(fsacl_size)", ARG4, sizeof(vki_size_t) ); 2054 } 2055 POST(fstat64_extended) 2056 { 2057 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2058 if (ML_(safe_to_deref)( (void*)ARG4, sizeof(vki_size_t) )) 2059 POST_MEM_WRITE( ARG3, *(vki_size_t *)ARG4 ); 2060 POST_MEM_WRITE( ARG4, sizeof(vki_size_t) ); 2061 } 2062 2063 2064 PRE(fchmod_extended) 2065 { 2066 /* DDD: Note: this is not really correct. Handling of 2067 chmod_extended is broken in the same way. */ 2068 PRINT("fchmod_extended ( %ld, %ld, %ld, %ld, %#lx )", 2069 ARG1, ARG2, ARG3, ARG4, ARG5); 2070 PRE_REG_READ5(long, "fchmod_extended", 2071 unsigned int, fildes, 2072 uid_t, uid, 2073 gid_t, gid, 2074 vki_mode_t, mode, 2075 void* /*really,user_addr_t*/, xsecurity); 2076 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this 2077 is just way wrong. [The trouble is with the size, which depends on a 2078 non-trival kernel computation] */ 2079 if (ARG5) { 2080 PRE_MEM_READ( "fchmod_extended(xsecurity)", ARG5, 2081 sizeof(struct vki_kauth_filesec) ); 2082 } 2083 } 2084 2085 PRE(chmod_extended) 2086 { 2087 /* DDD: Note: this is not really correct. Handling of 2088 fchmod_extended is broken in the same way. */ 2089 PRINT("chmod_extended ( %#lx(%s), %ld, %ld, %ld, %#lx )", 2090 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", ARG2, ARG3, ARG4, ARG5); 2091 PRE_REG_READ5(long, "chmod_extended", 2092 unsigned int, fildes, 2093 uid_t, uid, 2094 gid_t, gid, 2095 vki_mode_t, mode, 2096 void* /*really,user_addr_t*/, xsecurity); 2097 PRE_MEM_RASCIIZ("chmod_extended(path)", ARG1); 2098 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this 2099 is just way wrong. [The trouble is with the size, which depends on a 2100 non-trival kernel computation] */ 2101 if (ARG5) { 2102 PRE_MEM_READ( "chmod_extended(xsecurity)", ARG5, 2103 sizeof(struct vki_kauth_filesec) ); 2104 } 2105 } 2106 2107 PRE(open_extended) 2108 { 2109 /* DDD: Note: this is not really correct. Handling of 2110 {,f}chmod_extended is broken in the same way. */ 2111 PRINT("open_extended ( %#lx(%s), 0x%lx, %ld, %ld, %ld, %#lx )", 2112 ARG1, ARG1 ? (HChar*)ARG1 : "(null)", 2113 ARG2, ARG3, ARG4, ARG5, ARG6); 2114 PRE_REG_READ6(long, "open_extended", 2115 char*, path, 2116 int, flags, 2117 uid_t, uid, 2118 gid_t, gid, 2119 vki_mode_t, mode, 2120 void* /*really,user_addr_t*/, xsecurity); 2121 PRE_MEM_RASCIIZ("open_extended(path)", ARG1); 2122 /* DDD: relative to the xnu sources (kauth_copyinfilesec), this 2123 is just way wrong. [The trouble is with the size, which depends on a 2124 non-trival kernel computation] */ 2125 if (ARG6) 2126 PRE_MEM_READ( "open_extended(xsecurity)", ARG6, 2127 sizeof(struct vki_kauth_filesec) ); 2128 } 2129 2130 // This is a ridiculous syscall. Specifically, the 'entries' argument points 2131 // to a buffer that contains one or more 'accessx_descriptor' structs followed 2132 // by one or more strings. Each accessx_descriptor contains a field, 2133 // 'ad_name_offset', which points to one of the strings (or it can contain 2134 // zero which means "reuse the string from the previous accessx_descriptor"). 2135 // 2136 // What's really ridiculous is that we are only given the size of the overall 2137 // buffer, not the number of accessx_descriptors, nor the number of strings. 2138 // The kernel determines the number of accessx_descriptors by walking through 2139 // them one by one, checking that the ad_name_offset points within the buffer, 2140 // past the current point (or that it's a zero, unless its the first 2141 // descriptor); if so, we assume that this really is an accessx_descriptor, 2142 // if not, we assume we've hit the strings section. Gah. 2143 // 2144 // This affects us here because number of entries in the 'results' buffer is 2145 // determined by the number of accessx_descriptors. So we have to know that 2146 // number in order to do PRE_MEM_WRITE/POST_MEM_WRITE of 'results'. In 2147 // practice, we skip the PRE_MEM_WRITE step because it's easier to do the 2148 // computation after the syscall has succeeded, because the kernel will have 2149 // checked for all the zillion different ways this syscall can fail, and we'll 2150 // know we have a well-formed 'entries' buffer. This means we might miss some 2151 // uses of unaddressable memory but oh well. 2152 // 2153 PRE(access_extended) 2154 { 2155 PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )", 2156 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 2157 // XXX: the accessx_descriptor struct contains padding, so this can cause 2158 // unnecessary undefined value errors. But you arguably shouldn't be 2159 // passing undefined values to the kernel anyway... 2160 PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size, 2161 vki_errno_t *, results, vki_uid_t *, uid); 2162 PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 ); 2163 2164 // XXX: as mentioned above, this check is too hard to do before the 2165 // syscall. 2166 //PRE_MEM_WRITE("access_extended(results)", ARG3, ??? ); 2167 } 2168 POST(access_extended) 2169 { 2170 // 'n_descs' is the number of descriptors we think are in the buffer. We 2171 // start with the maximum possible value, which occurs if we have the 2172 // shortest possible string section. The shortest string section allowed 2173 // consists of a single one-char string (plus the NUL char). Hence the 2174 // '2'. 2175 struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1; 2176 SizeT size = ARG2; 2177 Int n_descs = (size - 2) / sizeof(struct accessx_descriptor); 2178 Int i; // Current position in the descriptors section array. 2179 Int u; // Upper bound on the length of the descriptors array 2180 // (recomputed each time around the loop) 2181 vg_assert(n_descs > 0); 2182 2183 // Step through the descriptors, lowering 'n_descs' until we know we've 2184 // reached the string section. 2185 for (i = 0; True; i++) { 2186 // If we're past our estimate, we must be one past the end of the 2187 // descriptors section (ie. at the start of the string section). Stop. 2188 if (i >= n_descs) 2189 break; 2190 2191 // Get the array index for the string, but pretend momentarily that it 2192 // is actually another accessx_descriptor. That gives us an upper bound 2193 // on the length of the descriptors section. (Unless the index is zero, 2194 // in which case we have no new info.) 2195 u = entries[i].ad_name_offset / sizeof(struct vki_accessx_descriptor); 2196 if (u == 0) { 2197 vg_assert(i != 0); 2198 continue; 2199 } 2200 2201 // If the upper bound is below our current estimate, revise that 2202 // estimate downwards. 2203 if (u < n_descs) 2204 n_descs = u; 2205 } 2206 2207 // Sanity check. 2208 vg_assert(n_descs <= VKI_ACCESSX_MAX_DESCRIPTORS); 2209 2210 POST_MEM_WRITE( ARG3, n_descs * sizeof(vki_errno_t) ); 2211 } 2212 2213 2214 PRE(chflags) 2215 { 2216 PRINT("chflags ( %#lx(%s), %lu )", ARG1, (char *)ARG1, ARG2); 2217 PRE_REG_READ2(int, "chflags", const char *,path, unsigned int,flags); 2218 PRE_MEM_RASCIIZ("chflags(path)", ARG1); 2219 2220 // GrP fixme sanity-check flags value? 2221 } 2222 2223 PRE(fchflags) 2224 { 2225 PRINT("fchflags ( %ld, %lu )", ARG1, ARG2); 2226 PRE_REG_READ2(int, "fchflags", int,fd, unsigned int,flags); 2227 2228 // GrP fixme sanity-check flags value? 2229 } 2230 2231 PRE(stat64) 2232 { 2233 PRINT("stat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2); 2234 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf); 2235 PRE_MEM_RASCIIZ("stat64(path)", ARG1); 2236 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) ); 2237 } 2238 POST(stat64) 2239 { 2240 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2241 } 2242 2243 PRE(lstat64) 2244 { 2245 PRINT("lstat64 ( %#lx(%s), %#lx )", ARG1, (char *)ARG1, ARG2); 2246 PRE_REG_READ2(long, "stat", const char *,path, struct stat64 *,buf); 2247 PRE_MEM_RASCIIZ("lstat64(path)", ARG1); 2248 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) ); 2249 } 2250 POST(lstat64) 2251 { 2252 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2253 } 2254 2255 PRE(fstat64) 2256 { 2257 PRINT("fstat64 ( %ld, %#lx )", ARG1,ARG2); 2258 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat64 *, buf); 2259 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) ); 2260 } 2261 POST(fstat64) 2262 { 2263 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) ); 2264 } 2265 2266 PRE(getfsstat) 2267 { 2268 PRINT("getfsstat(%#lx, %ld, %ld)", ARG1, ARG2, ARG3); 2269 PRE_REG_READ3(int, "getfsstat", 2270 struct vki_statfs *, buf, int, bufsize, int, flags); 2271 if (ARG1) { 2272 // ARG2 is a BYTE SIZE 2273 PRE_MEM_WRITE("getfsstat(buf)", ARG1, ARG2); 2274 } 2275 } 2276 POST(getfsstat) 2277 { 2278 if (ARG1) { 2279 // RES is a STRUCT COUNT 2280 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs)); 2281 } 2282 } 2283 2284 PRE(getfsstat64) 2285 { 2286 PRINT("getfsstat64(%#lx, %ld, %ld)", ARG1, ARG2, ARG3); 2287 PRE_REG_READ3(int, "getfsstat64", 2288 struct vki_statfs64 *, buf, int, bufsize, int, flags); 2289 if (ARG1) { 2290 // ARG2 is a BYTE SIZE 2291 PRE_MEM_WRITE("getfsstat64(buf)", ARG1, ARG2); 2292 } 2293 } 2294 POST(getfsstat64) 2295 { 2296 if (ARG1) { 2297 // RES is a STRUCT COUNT 2298 POST_MEM_WRITE(ARG1, RES * sizeof(struct vki_statfs64)); 2299 } 2300 } 2301 2302 PRE(mount) 2303 { 2304 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored. 2305 // We are conservative and check everything, except the memory pointed to 2306 // by 'data'. 2307 *flags |= SfMayBlock; 2308 PRINT("sys_mount( %#lx(%s), %#lx(%s), %#lx, %#lx )", 2309 ARG1,(Char*)ARG1, ARG2,(Char*)ARG2, ARG3, ARG4); 2310 PRE_REG_READ4(long, "mount", 2311 const char *, type, const char *, dir, 2312 int, flags, void *, data); 2313 PRE_MEM_RASCIIZ( "mount(type)", ARG1); 2314 PRE_MEM_RASCIIZ( "mount(dir)", ARG2); 2315 } 2316 2317 2318 static void scan_attrlist(ThreadId tid, struct vki_attrlist *attrList, 2319 void *attrBuf, SizeT attrBufSize, 2320 void (*fn)(ThreadId, void *attrData, SizeT size) 2321 ) 2322 { 2323 typedef struct { 2324 uint32_t attrBit; 2325 int32_t attrSize; 2326 } attrspec; 2327 static const attrspec commonattr[] = { 2328 // This order is important. 2329 #if DARWIN_VERS >= DARWIN_10_6 2330 { ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t) }, 2331 #endif 2332 { ATTR_CMN_NAME, -1 }, 2333 { ATTR_CMN_DEVID, sizeof(dev_t) }, 2334 { ATTR_CMN_FSID, sizeof(fsid_t) }, 2335 { ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t) }, 2336 { ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t) }, 2337 { ATTR_CMN_OBJID, sizeof(fsobj_id_t) }, 2338 { ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t) }, 2339 { ATTR_CMN_PAROBJID, sizeof(fsobj_id_t) }, 2340 { ATTR_CMN_SCRIPT, sizeof(text_encoding_t) }, 2341 { ATTR_CMN_CRTIME, sizeof(struct timespec) }, 2342 { ATTR_CMN_MODTIME, sizeof(struct timespec) }, 2343 { ATTR_CMN_CHGTIME, sizeof(struct timespec) }, 2344 { ATTR_CMN_ACCTIME, sizeof(struct timespec) }, 2345 { ATTR_CMN_BKUPTIME, sizeof(struct timespec) }, 2346 { ATTR_CMN_FNDRINFO, 32 /*FileInfo+ExtendedFileInfo, or FolderInfo+ExtendedFolderInfo*/ }, 2347 { ATTR_CMN_OWNERID, sizeof(uid_t) }, 2348 { ATTR_CMN_GRPID, sizeof(gid_t) }, 2349 { ATTR_CMN_ACCESSMASK, sizeof(uint32_t) }, 2350 { ATTR_CMN_NAMEDATTRCOUNT, sizeof(uint32_t) }, 2351 { ATTR_CMN_NAMEDATTRLIST, -1 }, 2352 { ATTR_CMN_FLAGS, sizeof(uint32_t) }, 2353 { ATTR_CMN_USERACCESS, sizeof(uint32_t) }, 2354 { ATTR_CMN_EXTENDED_SECURITY, -1 }, 2355 { ATTR_CMN_UUID, sizeof(guid_t) }, 2356 { ATTR_CMN_GRPUUID, sizeof(guid_t) }, 2357 { ATTR_CMN_FILEID, sizeof(uint64_t) }, 2358 { ATTR_CMN_PARENTID, sizeof(uint64_t) }, 2359 #if DARWIN_VERS >= DARWIN_10_6 2360 { ATTR_CMN_FULLPATH, -1 }, 2361 #endif 2362 { 0, 0 } 2363 }; 2364 static const attrspec volattr[] = { 2365 // This order is important. 2366 { ATTR_VOL_INFO, 0 }, 2367 { ATTR_VOL_FSTYPE, sizeof(uint32_t) }, 2368 { ATTR_VOL_SIGNATURE, sizeof(uint32_t) }, 2369 { ATTR_VOL_SIZE, sizeof(off_t) }, 2370 { ATTR_VOL_SPACEFREE, sizeof(off_t) }, 2371 { ATTR_VOL_SPACEAVAIL, sizeof(off_t) }, 2372 { ATTR_VOL_MINALLOCATION, sizeof(off_t) }, 2373 { ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t) }, 2374 { ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t) }, 2375 { ATTR_VOL_OBJCOUNT, sizeof(uint32_t) }, 2376 { ATTR_VOL_FILECOUNT, sizeof(uint32_t) }, 2377 { ATTR_VOL_DIRCOUNT, sizeof(uint32_t) }, 2378 { ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t) }, 2379 { ATTR_VOL_MOUNTPOINT, -1 }, 2380 { ATTR_VOL_NAME, -1 }, 2381 { ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t) }, 2382 { ATTR_VOL_MOUNTEDDEVICE, -1 }, 2383 { ATTR_VOL_ENCODINGSUSED, sizeof(uint64_t) }, 2384 { ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t) }, 2385 #if DARWIN_VERS >= DARWIN_10_6 2386 { ATTR_VOL_UUID, sizeof(uuid_t) }, 2387 #endif 2388 { ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t) }, 2389 { 0, 0 } 2390 }; 2391 static const attrspec dirattr[] = { 2392 // This order is important. 2393 { ATTR_DIR_LINKCOUNT, sizeof(uint32_t) }, 2394 { ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t) }, 2395 { ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t) }, 2396 { 0, 0 } 2397 }; 2398 static const attrspec fileattr[] = { 2399 // This order is important. 2400 { ATTR_FILE_LINKCOUNT, sizeof(uint32_t) }, 2401 { ATTR_FILE_TOTALSIZE, sizeof(off_t) }, 2402 { ATTR_FILE_ALLOCSIZE, sizeof(off_t) }, 2403 { ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t) }, 2404 { ATTR_FILE_CLUMPSIZE, sizeof(uint32_t) }, 2405 { ATTR_FILE_DEVTYPE, sizeof(uint32_t) }, 2406 { ATTR_FILE_FILETYPE, sizeof(uint32_t) }, 2407 { ATTR_FILE_FORKCOUNT, sizeof(uint32_t) }, 2408 { ATTR_FILE_FORKLIST, -1 }, 2409 { ATTR_FILE_DATALENGTH, sizeof(off_t) }, 2410 { ATTR_FILE_DATAALLOCSIZE, sizeof(off_t) }, 2411 { ATTR_FILE_DATAEXTENTS, sizeof(extentrecord) }, 2412 { ATTR_FILE_RSRCLENGTH, sizeof(off_t) }, 2413 { ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t) }, 2414 { ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord) }, 2415 { 0, 0 } 2416 }; 2417 static const attrspec forkattr[] = { 2418 // This order is important. 2419 { ATTR_FORK_TOTALSIZE, sizeof(off_t) }, 2420 { ATTR_FORK_ALLOCSIZE, sizeof(off_t) }, 2421 { 0, 0 } 2422 }; 2423 2424 static const attrspec *attrdefs[5] = { 2425 commonattr, volattr, dirattr, fileattr, forkattr 2426 }; 2427 attrgroup_t a[5]; 2428 uint8_t *d, *dend; 2429 int g, i; 2430 2431 vg_assert(attrList->bitmapcount == 5); 2432 VG_(memcpy)(a, &attrList->commonattr, sizeof(a)); 2433 d = attrBuf; 2434 dend = d + attrBufSize; 2435 2436 #if DARWIN_VERS >= DARWIN_10_6 2437 // ATTR_CMN_RETURNED_ATTRS tells us what's really here, if set 2438 if (a[0] & ATTR_CMN_RETURNED_ATTRS) { 2439 // fixme range check this? 2440 a[0] &= ~ATTR_CMN_RETURNED_ATTRS; 2441 fn(tid, d, sizeof(attribute_set_t)); 2442 VG_(memcpy)(a, d, sizeof(a)); 2443 } 2444 #endif 2445 2446 for (g = 0; g < 5; g++) { 2447 for (i = 0; attrdefs[g][i].attrBit; i++) { 2448 uint32_t bit = attrdefs[g][i].attrBit; 2449 int32_t size = attrdefs[g][i].attrSize; 2450 2451 if (a[g] & bit) { 2452 a[g] &= ~bit; // clear bit for error check later 2453 if (size == -1) { 2454 attrreference_t *ref = (attrreference_t *)d; 2455 size = MIN(sizeof(attrreference_t), dend - d); 2456 fn(tid, d, size); 2457 if (size >= sizeof(attrreference_t) && 2458 d + ref->attr_dataoffset < dend) 2459 { 2460 fn(tid, d + ref->attr_dataoffset, 2461 MIN(ref->attr_length, dend - (d + ref->attr_dataoffset))); 2462 } 2463 d += size; 2464 } 2465 else { 2466 size = MIN(size, dend - d); 2467 fn(tid, d, size); 2468 d += size; 2469 } 2470 2471 if ((uintptr_t)d % 4) d += 4 - ((uintptr_t)d % 4); 2472 if (d > dend) d = dend; 2473 } 2474 } 2475 2476 // Known bits are cleared. Die if any bits are left. 2477 if (a[g] != 0) { 2478 VG_(message)(Vg_UserMsg, "UNKNOWN attrlist flags %d:0x%x\n", g, a[g]); 2479 } 2480 } 2481 } 2482 2483 static void get1attr(ThreadId tid, void *attrData, SizeT attrDataSize) 2484 { 2485 POST_MEM_WRITE((Addr)attrData, attrDataSize); 2486 } 2487 2488 static void set1attr(ThreadId tid, void *attrData, SizeT attrDataSize) 2489 { 2490 PRE_MEM_READ("setattrlist(attrBuf value)", (Addr)attrData, attrDataSize); 2491 } 2492 2493 PRE(getattrlist) 2494 { 2495 PRINT("getattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)", 2496 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5); 2497 PRE_REG_READ5(int, "getattrlist", 2498 const char *,path, struct vki_attrlist *,attrList, 2499 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options); 2500 PRE_MEM_RASCIIZ("getattrlist(path)", ARG1); 2501 PRE_MEM_READ("getattrlist(attrList)", ARG2, sizeof(struct vki_attrlist)); 2502 PRE_MEM_WRITE("getattrlist(attrBuf)", ARG3, ARG4); 2503 } 2504 2505 POST(getattrlist) 2506 { 2507 if (ARG4 > sizeof(vki_uint32_t)) { 2508 // attrBuf is uint32_t size followed by attr data 2509 vki_uint32_t *sizep = (vki_uint32_t *)ARG3; 2510 POST_MEM_WRITE(ARG3, sizeof(vki_uint32_t)); 2511 if (ARG5 & FSOPT_REPORT_FULLSIZE) { 2512 // *sizep is bytes required for return value, including *sizep 2513 } else { 2514 // *sizep is actual bytes returned, including *sizep 2515 } 2516 scan_attrlist(tid, (struct vki_attrlist *)ARG2, sizep+1, MIN(*sizep, ARG4), &get1attr); 2517 } 2518 } 2519 2520 2521 PRE(setattrlist) 2522 { 2523 PRINT("setattrlist(%#lx(%s), %#lx, %#lx, %lu, %lu)", 2524 ARG1, (char *)ARG1, ARG2, ARG3, ARG4, ARG5); 2525 PRE_REG_READ5(int, "setattrlist", 2526 const char *,path, struct vki_attrlist *,attrList, 2527 void *,attrBuf, vki_size_t,attrBufSize, unsigned int,options); 2528 PRE_MEM_RASCIIZ("setattrlist(path)", ARG1); 2529 PRE_MEM_READ("setattrlist(attrList)", ARG2, sizeof(struct vki_attrlist)); 2530 scan_attrlist(tid, (struct vki_attrlist *)ARG2, (void*)ARG3, ARG4, &set1attr); 2531 } 2532 2533 2534 PRE(getdirentriesattr) 2535 { 2536 PRINT("getdirentriesattr(%ld, %#lx, %#lx, %ld, %#lx, %#lx, %#lx, %ld)", 2537 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8); 2538 PRE_REG_READ8(int, "getdirentriesattr", 2539 int,fd, struct vki_attrlist *,attrList, 2540 void *,attrBuf, size_t,attrBufSize, 2541 unsigned int *,count, unsigned int *,basep, 2542 unsigned int *,newState, unsigned int,options); 2543 PRE_MEM_READ("getdirentriesattr(attrList)", 2544 ARG2, sizeof(struct vki_attrlist)); 2545 PRE_MEM_WRITE("getdirentriesattr(attrBuf)", ARG3, ARG4); 2546 PRE_MEM_READ("getdirentriesattr(count)", ARG5, sizeof(unsigned int)); 2547 PRE_MEM_WRITE("getdirentriesattr(count)", ARG5, sizeof(unsigned int)); 2548 PRE_MEM_WRITE("getdirentriesattr(basep)", ARG6, sizeof(unsigned int)); 2549 PRE_MEM_WRITE("getdirentriesattr(newState)", ARG7, sizeof(unsigned int)); 2550 } 2551 POST(getdirentriesattr) 2552 { 2553 char *p, *end; 2554 unsigned int count; 2555 unsigned int i; 2556 2557 POST_MEM_WRITE(ARG5, sizeof(unsigned int)); 2558 POST_MEM_WRITE(ARG6, sizeof(unsigned int)); 2559 POST_MEM_WRITE(ARG7, sizeof(unsigned int)); 2560 2561 // return buffer is concatenation of variable-size structs 2562 count = *(unsigned int *)ARG5; 2563 p = (char *)ARG3; 2564 end = (char *)ARG3 + ARG4; 2565 for (i = 0; i < count; i++) { 2566 vg_assert(p < end); // failure is kernel bug or Valgrind bug 2567 p += *(unsigned int *)p; 2568 } 2569 2570 POST_MEM_WRITE(ARG3, p - (char *)ARG3); 2571 2572 PRINT("got %d records, %ld/%lu bytes\n", 2573 count, (Addr)p-(Addr)ARG3, ARG4); 2574 } 2575 2576 2577 PRE(fsgetpath) 2578 { 2579 #if VG_WORDSIZE == 4 2580 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %llu)", 2581 ARG1, ARG2, ARG3, 2582 ((unsigned int *)ARG3)[0], ((unsigned int *)ARG3)[1], 2583 LOHI64(ARG4, ARG5)); 2584 PRE_REG_READ5(ssize_t, "fsgetpath", 2585 void*,"buf", size_t,"bufsize", 2586 fsid_t *,"fsid", 2587 vki_uint32_t, "objid_low32", vki_uint32_t, "objid_high32"); 2588 #else 2589 PRINT("fsgetpath(%#lx, %ld, %#lx {%u,%u}, %lu)", 2590 ARG1, ARG2, ARG3, 2591 ((unsigned int *)ARG3)[0], 2592 ((unsigned int *)ARG3)[1], ARG4); 2593 PRE_REG_READ4(ssize_t, "fsgetpath", 2594 void*,"buf", size_t,"bufsize", 2595 fsid_t *,"fsid", uint64_t,"objid"); 2596 #endif 2597 PRE_MEM_READ("fsgetpath(fsid)", ARG3, sizeof(fsid_t)); 2598 PRE_MEM_WRITE("fsgetpath(buf)", ARG1, ARG2); 2599 } 2600 2601 POST(fsgetpath) 2602 { 2603 POST_MEM_WRITE(ARG1, RES); 2604 } 2605 2606 PRE(audit_session_self) 2607 { 2608 PRINT("audit_session_self()"); 2609 } 2610 2611 POST(audit_session_self) 2612 { 2613 record_named_port(tid, RES, MACH_PORT_RIGHT_SEND, "audit-session-%p"); 2614 PRINT("audit-session %#lx", RES); 2615 } 2616 2617 PRE(exchangedata) 2618 { 2619 PRINT("exchangedata(%#lx(%s), %#lx(%s), %lu)", 2620 ARG1, (char*)ARG1, ARG2, (char*)ARG2, ARG3); 2621 PRE_REG_READ3(int, "exchangedata", 2622 char *, path1, char *, path2, unsigned long, options); 2623 PRE_MEM_RASCIIZ( "exchangedata(path1)", ARG1 ); 2624 PRE_MEM_RASCIIZ( "exchangedata(path2)", ARG2 ); 2625 } 2626 2627 PRE(fsctl) 2628 { 2629 PRINT("fsctl ( %#lx(%s), %ld, %#lx, %ld )", 2630 ARG1, (char *)ARG1, ARG2, ARG3, ARG4); 2631 PRE_REG_READ4( long, "fsctl", 2632 char *,"path", unsigned int,"request", 2633 void *,"data", unsigned int,"options"); 2634 2635 PRE_MEM_RASCIIZ( "fsctl(path)", ARG1 ); 2636 2637 switch (ARG2) { 2638 case VKI_afpfsByteRangeLock2FSCTL: { 2639 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3; 2640 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->offset)", 2641 pb->offset); 2642 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->length)", 2643 pb->length); 2644 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->unLockFlag)", 2645 pb->unLockFlag); 2646 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->startEndFlag)", 2647 pb->startEndFlag); 2648 PRE_FIELD_READ("fsctl(afpfsByteRangeLock2, pb->fd)", 2649 pb->fd); 2650 2651 PRE_FIELD_WRITE("fsctl(afpfsByteRangeLock2, pb->retRangeStart)", 2652 pb->retRangeStart); 2653 2654 // GrP fixme check fd 2655 break; 2656 } 2657 case VKI_FSIOC_SYNC_VOLUME: 2658 PRE_MEM_READ( "fsctl(FSIOC_SYNC_VOLUME)", ARG3, sizeof(int) ); 2659 break; 2660 2661 default: 2662 // fsctl requests use ioctl encoding 2663 ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3); 2664 break; 2665 } 2666 } 2667 2668 POST(fsctl) 2669 { 2670 switch (ARG2) { 2671 case VKI_afpfsByteRangeLock2FSCTL: { 2672 struct vki_ByteRangeLockPB2 *pb = (struct vki_ByteRangeLockPB2 *)ARG3; 2673 POST_FIELD_WRITE(pb->retRangeStart); 2674 break; 2675 } 2676 case VKI_FSIOC_SYNC_VOLUME: 2677 break; 2678 2679 default: 2680 // fsctl requests use ioctl encoding 2681 ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3); 2682 break; 2683 } 2684 } 2685 2686 PRE(initgroups) 2687 { 2688 PRINT("initgroups(%s, %#lx, %lu)", (char *)ARG1, ARG2, ARG3); 2689 PRE_REG_READ3(long, "initgroups", 2690 int, setlen, vki_gid_t *, gidset, vki_uid_t, gmuid); 2691 PRE_MEM_READ("gidset", ARG2, ARG1 * sizeof(vki_gid_t)); 2692 } 2693 2694 2695 //--------- posix_spawn ---------// 2696 /* Largely copied from PRE(sys_execve) in syswrap-generic.c, and from 2697 the simpler AIX equivalent (syswrap-aix5.c). */ 2698 // Pre_read a char** argument. 2699 static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2) 2700 { 2701 while (True) { 2702 Addr a_deref; 2703 Addr* a_p = (Addr*)a; 2704 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) ); 2705 a_deref = *a_p; 2706 if (0 == a_deref) 2707 break; 2708 PRE_MEM_RASCIIZ( s2, a_deref ); 2709 a += sizeof(char*); 2710 } 2711 } 2712 static SysRes simple_pre_exec_check ( const HChar* exe_name, 2713 Bool trace_this_child ) 2714 { 2715 Int fd, ret; 2716 SysRes res; 2717 Bool setuid_allowed; 2718 2719 // Check it's readable 2720 res = VG_(open)(exe_name, VKI_O_RDONLY, 0); 2721 if (sr_isError(res)) { 2722 return res; 2723 } 2724 fd = sr_Res(res); 2725 VG_(close)(fd); 2726 2727 // Check we have execute permissions. We allow setuid executables 2728 // to be run only in the case when we are not simulating them, that 2729 // is, they to be run natively. 2730 setuid_allowed = trace_this_child ? False : True; 2731 ret = VG_(check_executable)(NULL/*&is_setuid*/, 2732 (HChar*)exe_name, setuid_allowed); 2733 if (0 != ret) { 2734 return VG_(mk_SysRes_Error)(ret); 2735 } 2736 return VG_(mk_SysRes_Success)(0); 2737 } 2738 PRE(posix_spawn) 2739 { 2740 Char* path = NULL; /* path to executable */ 2741 Char** envp = NULL; 2742 Char** argv = NULL; 2743 Char** arg2copy; 2744 Char* launcher_basename = NULL; 2745 Int i, j, tot_args; 2746 SysRes res; 2747 Bool trace_this_child; 2748 2749 /* args: pid_t* pid 2750 char* path 2751 posix_spawn_file_actions_t* file_actions 2752 char** argv 2753 char** envp 2754 */ 2755 PRINT("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )", 2756 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 ); 2757 2758 /* Standard pre-syscall checks */ 2759 2760 PRE_REG_READ5(int, "posix_spawn", vki_pid_t*, pid, char*, path, 2761 void*, file_actions, char**, argv, char**, envp ); 2762 PRE_MEM_WRITE("posix_spawn(pid)", ARG1, sizeof(vki_pid_t) ); 2763 PRE_MEM_RASCIIZ("posix_spawn(path)", ARG2); 2764 // DDD: check file_actions 2765 if (ARG4 != 0) 2766 pre_argv_envp( ARG4, tid, "posix_spawn(argv)", 2767 "posix_spawn(argv[i])" ); 2768 if (ARG5 != 0) 2769 pre_argv_envp( ARG5, tid, "posix_spawn(envp)", 2770 "posix_spawn(envp[i])" ); 2771 2772 if (0) 2773 VG_(printf)("posix_spawn( %#lx, %#lx(%s), %#lx, %#lx, %#lx )\n", 2774 ARG1, ARG2, ARG2 ? (HChar*)ARG2 : "(null)", ARG3, ARG4, ARG5 ); 2775 2776 /* Now follows a bunch of logic copied from PRE(sys_execve) in 2777 syswrap-generic.c. */ 2778 2779 /* Check that the name at least begins in client-accessible storage. */ 2780 if (ARG2 == 0 /* obviously bogus */ 2781 || !VG_(am_is_valid_for_client)( ARG2, 1, VKI_PROT_READ )) { 2782 SET_STATUS_Failure( VKI_EFAULT ); 2783 return; 2784 } 2785 2786 // Decide whether or not we want to follow along 2787 { // Make 'child_argv' be a pointer to the child's arg vector 2788 // (skipping the exe name) 2789 HChar** child_argv = (HChar**)ARG4; 2790 if (child_argv && child_argv[0] == NULL) 2791 child_argv = NULL; 2792 trace_this_child = VG_(should_we_trace_this_child)( (HChar*)ARG2, child_argv ); 2793 } 2794 2795 // Do the important checks: it is a file, is executable, permissions are 2796 // ok, etc. We allow setuid executables to run only in the case when 2797 // we are not simulating them, that is, they to be run natively. 2798 res = simple_pre_exec_check( (const HChar*)ARG2, trace_this_child ); 2799 if (sr_isError(res)) { 2800 SET_STATUS_Failure( sr_Err(res) ); 2801 return; 2802 } 2803 2804 /* If we're tracing the child, and the launcher name looks bogus 2805 (possibly because launcher.c couldn't figure it out, see 2806 comments therein) then we have no option but to fail. */ 2807 if (trace_this_child 2808 && (VG_(name_of_launcher) == NULL 2809 || VG_(name_of_launcher)[0] != '/')) { 2810 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */ 2811 return; 2812 } 2813 2814 /* Ok. So let's give it a try. */ 2815 VG_(debugLog)(1, "syswrap", "Posix_spawn of %s\n", (Char*)ARG2); 2816 2817 // Terminate gdbserver if it is active. 2818 if (VG_(clo_vgdb) != Vg_VgdbNo) { 2819 // If the child will not be traced, we need to terminate gdbserver 2820 // to cleanup the gdbserver resources (e.g. the FIFO files). 2821 // If child will be traced, we also terminate gdbserver: the new 2822 // Valgrind will start a fresh gdbserver after exec. 2823 VG_(gdbserver) (tid); 2824 } 2825 2826 // Set up the child's exe path. 2827 // 2828 if (trace_this_child) { 2829 2830 // We want to exec the launcher. Get its pre-remembered path. 2831 path = VG_(name_of_launcher); 2832 // VG_(name_of_launcher) should have been acquired by m_main at 2833 // startup. The following two assertions should be assured by 2834 // the "If we're tracking the child .." test just above here. 2835 vg_assert(path); 2836 vg_assert(path[0] == '/'); 2837 launcher_basename = path; 2838 2839 } else { 2840 path = (Char*)ARG2; 2841 } 2842 2843 // Set up the child's environment. 2844 // 2845 // Remove the valgrind-specific stuff from the environment so the 2846 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc. 2847 // This is done unconditionally, since if we are tracing the child, 2848 // the child valgrind will set up the appropriate client environment. 2849 // Nb: we make a copy of the environment before trying to mangle it 2850 // as it might be in read-only memory (this was bug #101881). 2851 // 2852 // Then, if tracing the child, set VALGRIND_LIB for it. 2853 // 2854 if (ARG5 == 0) { 2855 envp = NULL; 2856 } else { 2857 envp = VG_(env_clone)( (Char**)ARG5 ); 2858 vg_assert(envp); 2859 VG_(env_remove_valgrind_env_stuff)( envp ); 2860 } 2861 2862 if (trace_this_child) { 2863 // Set VALGRIND_LIB in ARG5 (the environment) 2864 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir)); 2865 } 2866 2867 // Set up the child's args. If not tracing it, they are 2868 // simply ARG4. Otherwise, they are 2869 // 2870 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG2] ++ ARG4[1..] 2871 // 2872 // except that the first VG_(args_for_valgrind_noexecpass) args 2873 // are omitted. 2874 // 2875 if (!trace_this_child) { 2876 argv = (Char**)ARG4; 2877 } else { 2878 vg_assert( VG_(args_for_valgrind) ); 2879 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 ); 2880 vg_assert( VG_(args_for_valgrind_noexecpass) 2881 <= VG_(sizeXA)( VG_(args_for_valgrind) ) ); 2882 /* how many args in total will there be? */ 2883 // launcher basename 2884 tot_args = 1; 2885 // V's args 2886 tot_args += VG_(sizeXA)( VG_(args_for_valgrind) ); 2887 tot_args -= VG_(args_for_valgrind_noexecpass); 2888 // name of client exe 2889 tot_args++; 2890 // args for client exe, skipping [0] 2891 arg2copy = (Char**)ARG4; 2892 if (arg2copy && arg2copy[0]) { 2893 for (i = 1; arg2copy[i]; i++) 2894 tot_args++; 2895 } 2896 // allocate 2897 argv = VG_(malloc)( "di.syswrap.pre_sys_execve.1", 2898 (tot_args+1) * sizeof(HChar*) ); 2899 vg_assert(argv); 2900 // copy 2901 j = 0; 2902 argv[j++] = launcher_basename; 2903 for (i = 0; i < VG_(sizeXA)( VG_(args_for_valgrind) ); i++) { 2904 if (i < VG_(args_for_valgrind_noexecpass)) 2905 continue; 2906 argv[j++] = * (HChar**) VG_(indexXA)( VG_(args_for_valgrind), i ); 2907 } 2908 argv[j++] = (Char*)ARG2; 2909 if (arg2copy && arg2copy[0]) 2910 for (i = 1; arg2copy[i]; i++) 2911 argv[j++] = arg2copy[i]; 2912 argv[j++] = NULL; 2913 // check 2914 vg_assert(j == tot_args+1); 2915 } 2916 2917 /* DDD: sort out the signal state. What signal 2918 state does the child inherit from the parent? */ 2919 2920 if (0) { 2921 Char **cpp; 2922 VG_(printf)("posix_spawn: %s\n", path); 2923 for (cpp = argv; cpp && *cpp; cpp++) 2924 VG_(printf)("argv: %s\n", *cpp); 2925 if (1) 2926 for (cpp = envp; cpp && *cpp; cpp++) 2927 VG_(printf)("env: %s\n", *cpp); 2928 } 2929 2930 /* Let the call go through as usual. However, we have to poke 2931 the altered arguments back into the argument slots. */ 2932 ARG2 = (UWord)path; 2933 ARG4 = (UWord)argv; 2934 ARG5 = (UWord)envp; 2935 2936 /* not to mention .. */ 2937 *flags |= SfMayBlock; 2938 } 2939 POST(posix_spawn) 2940 { 2941 vg_assert(SUCCESS); 2942 //POST_MEM_WRITE( ARG1, sizeof(vki_pid_t) ); 2943 } 2944 2945 2946 PRE(socket) 2947 { 2948 PRINT("socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3); 2949 PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol); 2950 } 2951 2952 POST(socket) 2953 { 2954 SysRes r; 2955 vg_assert(SUCCESS); 2956 r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES)); 2957 SET_STATUS_from_SysRes(r); 2958 } 2959 2960 2961 PRE(setsockopt) 2962 { 2963 PRINT("setsockopt ( %ld, %ld, %ld, %#lx, %ld )", 2964 ARG1,ARG2,ARG3,ARG4,ARG5); 2965 PRE_REG_READ5(long, "setsockopt", 2966 int, s, int, level, int, optname, 2967 const void *, optval, vki_socklen_t, optlen); 2968 ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5); 2969 } 2970 2971 2972 PRE(getsockopt) 2973 { 2974 Addr optval_p = ARG4; 2975 Addr optlen_p = ARG5; 2976 PRINT("getsockopt ( %ld, %ld, %ld, %#lx, %#lx )", 2977 ARG1,ARG2,ARG3,ARG4,ARG5); 2978 PRE_REG_READ5(long, "getsockopt", 2979 int, s, int, level, int, optname, 2980 void *, optval, vki_socklen_t *, optlen); 2981 /* int getsockopt(int socket, int level, int option_name, 2982 void *restrict option_value, 2983 socklen_t *restrict option_len); */ 2984 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */ 2985 if (optval_p != (Addr)NULL) { 2986 ML_(buf_and_len_pre_check) ( tid, optval_p, optlen_p, 2987 "socketcall.getsockopt(optval)", 2988 "socketcall.getsockopt(optlen)" ); 2989 } 2990 // DDD: #warning GrP fixme darwin-specific sockopts 2991 } 2992 2993 POST(getsockopt) 2994 { 2995 Addr optval_p = ARG4; 2996 Addr optlen_p = ARG5; 2997 vg_assert(SUCCESS); 2998 if (optval_p != (Addr)NULL) { 2999 ML_(buf_and_len_post_check) ( tid, VG_(mk_SysRes_Success)(RES), 3000 optval_p, optlen_p, 3001 "socketcall.getsockopt(optlen_out)" ); 3002 // DDD: #warning GrP fixme darwin-specific sockopts 3003 } 3004 } 3005 3006 3007 PRE(connect) 3008 { 3009 *flags |= SfMayBlock; 3010 PRINT("connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3011 PRE_REG_READ3(long, "connect", 3012 int, sockfd, struct sockaddr *, serv_addr, int, addrlen); 3013 ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3); 3014 } 3015 3016 3017 PRE(accept) 3018 { 3019 *flags |= SfMayBlock; 3020 PRINT("accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3021 PRE_REG_READ3(long, "accept", 3022 int, s, struct sockaddr *, addr, int, *addrlen); 3023 ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3); 3024 } 3025 3026 POST(accept) 3027 { 3028 SysRes r; 3029 vg_assert(SUCCESS); 3030 r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES), 3031 ARG1,ARG2,ARG3); 3032 SET_STATUS_from_SysRes(r); 3033 } 3034 3035 3036 PRE(sendto) 3037 { 3038 *flags |= SfMayBlock; 3039 PRINT("sendto ( %ld, %s, %ld, %lu, %#lx, %ld )", 3040 ARG1,(char *)ARG2,ARG3,ARG4,ARG5,ARG6); 3041 PRE_REG_READ6(long, "sendto", 3042 int, s, const void *, msg, int, len, 3043 unsigned int, flags, 3044 const struct sockaddr *, to, int, tolen); 3045 ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); 3046 } 3047 3048 PRE(sendfile) 3049 { 3050 #if VG_WORDSIZE == 4 3051 PRINT("sendfile(%ld, %ld, %llu, %#lx, %#lx, %ld)", 3052 ARG1, ARG2, LOHI64(ARG3, ARG4), ARG5, ARG6, ARG7); 3053 3054 PRE_REG_READ7(long, "sendfile", 3055 int, fromfd, int, tofd, 3056 vki_uint32_t, offset_low32, vki_uint32_t, offset_high32, 3057 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags); 3058 PRE_MEM_WRITE("sendfile(nwritten)", ARG5, sizeof(vki_uint64_t)); 3059 if (ARG6) PRE_MEM_WRITE("sendfile(sf_header)", ARG6, sizeof(struct sf_hdtr)); 3060 #else 3061 PRINT("sendfile(%ld, %ld, %ld, %#lx, %#lx, %ld)", 3062 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6); 3063 3064 PRE_REG_READ6(long, "sendfile", 3065 int, fromfd, int, tofd, 3066 vki_uint64_t, offset, 3067 vki_uint64_t *, nwritten, struct sf_hdtr *, sf_header, int, flags); 3068 PRE_MEM_WRITE("sendfile(nwritten)", ARG4, sizeof(vki_uint64_t)); 3069 if (ARG5) PRE_MEM_WRITE("sendfile(sf_header)", ARG5, sizeof(struct sf_hdtr)); 3070 #endif 3071 3072 *flags |= SfMayBlock; 3073 } 3074 POST(sendfile) 3075 { 3076 #if VG_WORDSIZE == 4 3077 POST_MEM_WRITE(ARG5, sizeof(vki_uint64_t)); 3078 if (ARG6) POST_MEM_WRITE(ARG6, sizeof(struct sf_hdtr)); 3079 #else 3080 POST_MEM_WRITE(ARG4, sizeof(vki_uint64_t)); 3081 if (ARG5) POST_MEM_WRITE(ARG5, sizeof(struct sf_hdtr)); 3082 #endif 3083 } 3084 3085 PRE(recvfrom) 3086 { 3087 *flags |= SfMayBlock; 3088 PRINT("recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )", 3089 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); 3090 PRE_REG_READ6(long, "recvfrom", 3091 int, s, void *, buf, int, len, unsigned int, flags, 3092 struct sockaddr *, from, int *, fromlen); 3093 ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); 3094 } 3095 3096 POST(recvfrom) 3097 { 3098 vg_assert(SUCCESS); 3099 ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES), 3100 ARG1,ARG2,ARG3,ARG4,ARG5,ARG6); 3101 } 3102 3103 3104 PRE(sendmsg) 3105 { 3106 *flags |= SfMayBlock; 3107 PRINT("sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3108 PRE_REG_READ3(long, "sendmsg", 3109 int, s, const struct msghdr *, msg, int, flags); 3110 ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2); 3111 } 3112 3113 3114 PRE(recvmsg) 3115 { 3116 *flags |= SfMayBlock; 3117 PRINT("recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3118 PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags); 3119 ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2); 3120 } 3121 3122 POST(recvmsg) 3123 { 3124 ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2); 3125 } 3126 3127 3128 PRE(shutdown) 3129 { 3130 *flags |= SfMayBlock; 3131 PRINT("shutdown ( %ld, %ld )",ARG1,ARG2); 3132 PRE_REG_READ2(int, "shutdown", int, s, int, how); 3133 } 3134 3135 3136 PRE(bind) 3137 { 3138 PRINT("bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3); 3139 PRE_REG_READ3(long, "bind", 3140 int, sockfd, struct sockaddr *, my_addr, int, addrlen); 3141 ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3); 3142 } 3143 3144 3145 PRE(listen) 3146 { 3147 PRINT("listen ( %ld, %ld )",ARG1,ARG2); 3148 PRE_REG_READ2(long, "listen", int, s, int, backlog); 3149 } 3150 3151 3152 PRE(getsockname) 3153 { 3154 PRINT("getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); 3155 PRE_REG_READ3(long, "getsockname", 3156 int, s, struct sockaddr *, name, int *, namelen); 3157 ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3); 3158 } 3159 3160 POST(getsockname) 3161 { 3162 vg_assert(SUCCESS); 3163 ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES), 3164 ARG1,ARG2,ARG3); 3165 } 3166 3167 3168 PRE(getpeername) 3169 { 3170 PRINT("getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3); 3171 PRE_REG_READ3(long, "getpeername", 3172 int, s, struct sockaddr *, name, int *, namelen); 3173 ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3); 3174 } 3175 3176 POST(getpeername) 3177 { 3178 vg_assert(SUCCESS); 3179 ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES), 3180 ARG1,ARG2,ARG3); 3181 } 3182 3183 3184 PRE(socketpair) 3185 { 3186 PRINT("socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4); 3187 PRE_REG_READ4(long, "socketpair", 3188 int, d, int, type, int, protocol, int *, sv); 3189 ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4); 3190 } 3191 3192 POST(socketpair) 3193 { 3194 vg_assert(SUCCESS); 3195 ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES), 3196 ARG1,ARG2,ARG3,ARG4); 3197 } 3198 3199 3200 PRE(gethostuuid) 3201 { 3202 PRINT("gethostuuid ( %#lx, %#lx )", ARG1, ARG2); 3203 PRE_REG_READ2(int,"gethostuuid", 3204 char *,"uuid_buf", 3205 const struct vki_timespec *,"timeout"); 3206 3207 PRE_MEM_WRITE("uuid_buf", ARG1, 16); 3208 PRE_MEM_READ("timeout", ARG2, sizeof(struct vki_timespec)); 3209 3210 *flags |= SfMayBlock; 3211 } 3212 3213 3214 POST(gethostuuid) 3215 { 3216 POST_MEM_WRITE(ARG1, 16); 3217 } 3218 3219 /* Darwin pipe() returns the two descriptors in two registers. */ 3220 PRE(pipe) 3221 { 3222 PRINT("pipe ( )"); 3223 PRE_REG_READ0(int, "pipe"); 3224 } 3225 3226 POST(pipe) 3227 { 3228 Int p0, p1; 3229 vg_assert(SUCCESS); 3230 p0 = RES; 3231 p1 = RESHI; 3232 3233 if (!ML_(fd_allowed)(p0, "pipe", tid, True) || 3234 !ML_(fd_allowed)(p1, "pipe", tid, True)) { 3235 VG_(close)(p0); 3236 VG_(close)(p1); 3237 SET_STATUS_Failure( VKI_EMFILE ); 3238 } else { 3239 if (VG_(clo_track_fds)) { 3240 ML_(record_fd_open_nameless)(tid, p0); 3241 ML_(record_fd_open_nameless)(tid, p1); 3242 } 3243 } 3244 } 3245 3246 3247 PRE(getlogin) 3248 { 3249 PRINT("getlogin ( %#lx, %ld )", ARG1, ARG2); 3250 PRE_REG_READ2(long, "getlogin", 3251 char *,"namebuf", unsigned int,"namelen"); 3252 3253 PRE_MEM_WRITE("getlogin(namebuf)", ARG1, ARG2); 3254 } 3255 3256 POST(getlogin) 3257 { 3258 POST_MEM_WRITE(ARG1, ARG2); 3259 } 3260 3261 3262 PRE(ptrace) 3263 { 3264 PRINT("ptrace ( %ld, %ld, %#lx, %ld )", ARG1, ARG2, ARG3, ARG4); 3265 PRE_REG_READ4(long, "ptrace", 3266 int,"request", vki_pid_t,"pid", 3267 vki_caddr_t,"addr", int,"data"); 3268 3269 // Note: some code uses ptrace(random, 0, 0, 0) as a profiling mechanism. 3270 3271 // GrP fixme anything needed? 3272 } 3273 3274 3275 PRE(issetugid) 3276 { 3277 PRINT("issetugid ( )"); 3278 PRE_REG_READ0(long, "issetugid"); 3279 } 3280 3281 3282 PRE(getdtablesize) 3283 { 3284 PRINT("getdtablesize ( )"); 3285 PRE_REG_READ0(long, "getdtablesize"); 3286 } 3287 3288 POST(getdtablesize) 3289 { 3290 // Subtract Valgrind's fd range from client's dtable 3291 if (RES > VG_(fd_hard_limit)) SET_STATUS_Success(VG_(fd_hard_limit)); 3292 } 3293 3294 PRE(lseek) 3295 { 3296 PRINT("lseek ( %ld, %ld, %ld )", ARG1,ARG2,ARG3); 3297 PRE_REG_READ4(vki_off_t, "lseek", 3298 unsigned int,fd, int,offset_hi, int,offset_lo, 3299 unsigned int,whence); 3300 } 3301 3302 3303 PRE(pathconf) 3304 { 3305 PRINT("pathconf(%#lx(%s), %ld)", ARG1,(char *)ARG1,ARG2); 3306 PRE_REG_READ2(long,"pathconf", const char *,"path", int,"name"); 3307 PRE_MEM_RASCIIZ("pathconf(path)", ARG1); 3308 } 3309 3310 3311 PRE(fpathconf) 3312 { 3313 PRINT("fpathconf(%ld, %ld)", ARG1,ARG2); 3314 PRE_REG_READ2(long,"fpathconf", int,"fd", int,"name"); 3315 3316 if (!ML_(fd_allowed)(ARG1, "fpathconf", tid, False)) 3317 SET_STATUS_Failure( VKI_EBADF ); 3318 } 3319 3320 3321 PRE(getdirentries) 3322 { 3323 PRINT("getdirentries(%ld, %#lx, %ld, %#lx)", ARG1, ARG2, ARG3, ARG4); 3324 PRE_REG_READ4(int, "getdirentries", 3325 int, fd, char *, buf, int, nbytes, long *, basep); 3326 PRE_MEM_WRITE("getdirentries(basep)", ARG4, sizeof(long)); 3327 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3); 3328 } 3329 3330 POST(getdirentries) 3331 { 3332 POST_MEM_WRITE(ARG4, sizeof(long)); 3333 // GrP fixme be specific about d_name? 3334 POST_MEM_WRITE(ARG2, RES); 3335 } 3336 3337 3338 PRE(getdirentries64) 3339 { 3340 PRINT("getdirentries64(%ld, %#lx, %lu, %#lx)", ARG1, ARG2, ARG3, ARG4); 3341 PRE_REG_READ4(vki_ssize_t, "getdirentries", 3342 int,fd, char *,buf, vki_size_t,nbytes, vki_off_t *,basep); 3343 PRE_MEM_WRITE("getdirentries(position)", ARG4, sizeof(vki_off_t)); 3344 PRE_MEM_WRITE("getdirentries(buf)", ARG2, ARG3); 3345 } 3346 POST(getdirentries64) 3347 { 3348 POST_MEM_WRITE(ARG4, sizeof(vki_off_t)); 3349 // GrP fixme be specific about d_name? (fixme copied from 32 bit version) 3350 POST_MEM_WRITE(ARG2, RES); 3351 } 3352 3353 3354 PRE(statfs64) 3355 { 3356 PRINT("statfs64 ( %#lx(%s), %#lx )",ARG1,(char *)ARG1,ARG2); 3357 PRE_REG_READ2(long, "statfs64", const char *, path, struct statfs64 *, buf); 3358 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 ); 3359 PRE_MEM_WRITE( "statfs64(buf)", ARG2, sizeof(struct vki_statfs64) ); 3360 } 3361 POST(statfs64) 3362 { 3363 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) ); 3364 } 3365 3366 3367 PRE(fstatfs64) 3368 { 3369 PRINT("fstatfs64 ( %ld, %#lx )",ARG1,ARG2); 3370 PRE_REG_READ2(long, "fstatfs64", 3371 unsigned int, fd, struct statfs *, buf); 3372 PRE_MEM_WRITE( "fstatfs64(buf)", ARG2, sizeof(struct vki_statfs64) ); 3373 } 3374 POST(fstatfs64) 3375 { 3376 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs64) ); 3377 } 3378 3379 PRE(csops) 3380 { 3381 PRINT("csops ( %ld, %#lx, %#lx, %lu )", ARG1, ARG2, ARG3, ARG4); 3382 PRE_REG_READ4(int, "csops", 3383 vki_pid_t, pid, uint32_t, ops, 3384 void *, useraddr, vki_size_t, usersize); 3385 3386 PRE_MEM_WRITE( "csops(useraddr)", ARG3, ARG4 ); 3387 3388 // If the pid is ours, don't mark the program as KILL or HARD 3389 // Maybe we should keep track of this for later calls to STATUS 3390 if (!ARG1 || VG_(getpid)() == ARG1) { 3391 switch (ARG2) { 3392 case VKI_CS_OPS_MARKINVALID: 3393 case VKI_CS_OPS_MARKHARD: 3394 case VKI_CS_OPS_MARKKILL: 3395 SET_STATUS_Success(0); 3396 } 3397 } 3398 } 3399 POST(csops) 3400 { 3401 POST_MEM_WRITE( ARG3, ARG4 ); 3402 } 3403 3404 PRE(auditon) 3405 { 3406 PRINT("auditon ( %ld, %#lx, %ld )", ARG1, ARG2, ARG3); 3407 PRE_REG_READ3(int,"auditon", 3408 int,"cmd", void*,"data", unsigned int,"length"); 3409 3410 switch (ARG1) { 3411 3412 case VKI_A_SETPOLICY: 3413 case VKI_A_SETKMASK: 3414 case VKI_A_SETQCTRL: 3415 case VKI_A_SETCOND: 3416 case VKI_A_SETCLASS: 3417 case VKI_A_SETPMASK: 3418 case VKI_A_SETFSIZE: 3419 #if DARWIN_VERS >= DARWIN_10_6 3420 case VKI_A_SENDTRIGGER: 3421 #endif 3422 // kernel reads data..data+length 3423 PRE_MEM_READ("auditon(data)", ARG2, ARG3); 3424 break; 3425 3426 case VKI_A_GETKMASK: 3427 case VKI_A_GETPOLICY: 3428 case VKI_A_GETQCTRL: 3429 case VKI_A_GETFSIZE: 3430 case VKI_A_GETCOND: 3431 // kernel writes data..data+length 3432 // GrP fixme be precise about what gets written 3433 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3); 3434 break; 3435 3436 3437 case VKI_A_GETCLASS: 3438 case VKI_A_GETPINFO: 3439 case VKI_A_GETPINFO_ADDR: 3440 #if DARWIN_VERS >= DARWIN_10_6 3441 case VKI_A_GETSINFO_ADDR: 3442 #endif 3443 // kernel reads and writes data..data+length 3444 // GrP fixme be precise about what gets read and written 3445 PRE_MEM_READ("auditon(data)", ARG2, ARG3); 3446 PRE_MEM_WRITE("auditon(data)", ARG2, ARG3); 3447 break; 3448 3449 case VKI_A_SETKAUDIT: 3450 case VKI_A_SETSTAT: 3451 case VKI_A_SETUMASK: 3452 case VKI_A_SETSMASK: 3453 case VKI_A_GETKAUDIT: 3454 case VKI_A_GETCWD: 3455 case VKI_A_GETCAR: 3456 case VKI_A_GETSTAT: 3457 // unimplemented on darwin 3458 break; 3459 3460 default: 3461 VG_(message)(Vg_UserMsg, "UNKNOWN auditon cmd %ld", ARG1); 3462 break; 3463 } 3464 } 3465 POST(auditon) 3466 { 3467 switch (ARG1) { 3468 3469 case VKI_A_SETPOLICY: 3470 case VKI_A_SETKMASK: 3471 case VKI_A_SETQCTRL: 3472 case VKI_A_SETCOND: 3473 case VKI_A_SETCLASS: 3474 case VKI_A_SETPMASK: 3475 case VKI_A_SETFSIZE: 3476 #if DARWIN_VERS >= DARWIN_10_6 3477 case VKI_A_SENDTRIGGER: 3478 #endif 3479 // kernel reads data..data+length 3480 break; 3481 3482 case VKI_A_GETKMASK: 3483 case VKI_A_GETPOLICY: 3484 case VKI_A_GETQCTRL: 3485 case VKI_A_GETFSIZE: 3486 case VKI_A_GETCOND: 3487 // kernel writes data..data+length 3488 // GrP fixme be precise about what gets written 3489 POST_MEM_WRITE(ARG2, ARG3); 3490 break; 3491 3492 3493 case VKI_A_GETCLASS: 3494 case VKI_A_GETPINFO: 3495 case VKI_A_GETPINFO_ADDR: 3496 #if DARWIN_VERS >= DARWIN_10_6 3497 case VKI_A_GETSINFO_ADDR: 3498 #endif 3499 // kernel reads and writes data..data+length 3500 // GrP fixme be precise about what gets read and written 3501 POST_MEM_WRITE(ARG2, ARG3); 3502 break; 3503 3504 case VKI_A_SETKAUDIT: 3505 case VKI_A_SETSTAT: 3506 case VKI_A_SETUMASK: 3507 case VKI_A_SETSMASK: 3508 case VKI_A_GETKAUDIT: 3509 case VKI_A_GETCWD: 3510 case VKI_A_GETCAR: 3511 case VKI_A_GETSTAT: 3512 // unimplemented on darwin 3513 break; 3514 3515 default: 3516 break; 3517 } 3518 } 3519 3520 3521 PRE(mmap) 3522 { 3523 // SysRes r; 3524 3525 #if VG_WORDSIZE == 4 3526 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %lld )", 3527 ARG1, ARG2, ARG3, ARG4, ARG5, LOHI64(ARG6, ARG7) ); 3528 PRE_REG_READ7(Addr, "mmap", 3529 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd, 3530 unsigned long,offset_hi, unsigned long,offset_lo); 3531 // GrP fixme V mmap and kernel mach_msg collided once - don't use 3532 // V's mechanism for now 3533 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, 3534 // (Off64T)LOHI64(ARG6, ARG7) ); 3535 #else 3536 PRINT("mmap ( %#lx, %lu, %ld, %ld, %ld, %ld )", 3537 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); 3538 PRE_REG_READ6(long, "mmap", 3539 Addr,start, vki_size_t,length, int,prot, int,flags, int,fd, 3540 Off64T,offset); 3541 // r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); 3542 3543 #endif 3544 3545 // SET_STATUS_from_SysRes(r); 3546 } 3547 3548 POST(mmap) 3549 { 3550 if (RES != -1) { 3551 ML_(notify_core_and_tool_of_mmap)(RES, ARG2, ARG3, ARG4, ARG5, ARG6); 3552 // Try to load symbols from the region 3553 VG_(di_notify_mmap)( (Addr)RES, False/*allow_SkFileV*/, 3554 -1/*don't use_fd*/ ); 3555 } 3556 } 3557 3558 3559 PRE(__sysctl) 3560 { 3561 PRINT( "__sysctl ( %#lx, %ld, %#lx, %#lx, %#lx, %ld )", 3562 ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 ); 3563 3564 PRE_REG_READ6(int, "__sysctl", int*, name, unsigned int, namelen, 3565 void*, oldp, vki_size_t *, oldlenp, 3566 void*, newp, vki_size_t *, newlenp); 3567 3568 PRE_MEM_READ("sysctl(name)", ARG1, ARG2); // reads name[0..namelen-1] 3569 if (ARG4) { 3570 // writes *ARG4 3571 PRE_MEM_WRITE("sysctl(oldlenp)", ARG4, sizeof(size_t)); 3572 if (ARG3) { 3573 // also reads *ARG4, and writes as much as ARG3[0..ARG4-1] 3574 PRE_MEM_READ("sysctl(oldlenp)", ARG4, sizeof(size_t)); 3575 PRE_MEM_WRITE("sysctl(oldp)", ARG3, *(size_t *)ARG4); 3576 } 3577 } 3578 if (ARG5) { 3579 PRE_MEM_READ("sysctl(newp)", ARG5, ARG6); 3580 } 3581 3582 if (VG_(clo_trace_syscalls)) { 3583 unsigned int i; 3584 int *name = (int *)ARG1; 3585 VG_(printf)(" mib: [ "); 3586 for (i = 0; i < ARG2; i++) { 3587 VG_(printf)("%d ", name[i]); 3588 } 3589 VG_(printf)("]"); 3590 } 3591 3592 // GrP fixme intercept KERN_PROCARGS and KERN_PROC_PID for our pid 3593 // (executable path and arguments and environment 3594 3595 { 3596 // Intercept sysctl(kern.usrstack). The kernel's reply would be 3597 // Valgrind's stack, not the client's stack. 3598 // GrP fixme kern_usrstack64 3599 if (ARG1 && ARG2 == 2 && 3600 ((int *)ARG1)[0] == VKI_CTL_KERN && 3601 #if VG_WORDSIZE == 4 3602 ((int *)ARG1)[1] == VKI_KERN_USRSTACK32 3603 #else 3604 ((int *)ARG1)[1] == VKI_KERN_USRSTACK64 3605 #endif 3606 ) 3607 { 3608 if (ARG5/*newp*/ || ARG6/*newlen*/) { 3609 SET_STATUS_Failure(VKI_EPERM); // USRSTACK is read-only 3610 } else { 3611 Addr *oldp = (Addr *)ARG3; 3612 size_t *oldlenp = (size_t *)ARG4; 3613 if (oldlenp) { 3614 Addr stack_end = VG_(clstk_end)+1; 3615 size_t oldlen = *oldlenp; 3616 // always return actual size 3617 *oldlenp = sizeof(Addr); 3618 if (oldp && oldlen >= sizeof(Addr)) { 3619 // oldp is big enough 3620 // copy value and return 0 3621 *oldp = stack_end; 3622 SET_STATUS_Success(0); 3623 } else { 3624 // oldp isn't big enough 3625 // copy as much as possible and return ENOMEM 3626 if (oldp) VG_(memcpy)(oldp, &stack_end, oldlen); 3627 SET_STATUS_Failure(VKI_ENOMEM); 3628 } 3629 } 3630 } 3631 } 3632 } 3633 3634 if (!SUCCESS && !FAILURE) { 3635 // Don't set SfPostOnFail if we've already handled it locally. 3636 *flags |= SfPostOnFail; 3637 } 3638 } 3639 3640 POST(__sysctl) 3641 { 3642 if (SUCCESS || ERR == VKI_ENOMEM) { 3643 // sysctl can write truncated data and return VKI_ENOMEM 3644 if (ARG4) { 3645 POST_MEM_WRITE(ARG4, sizeof(size_t)); 3646 } 3647 if (ARG3 && ARG4) { 3648 POST_MEM_WRITE(ARG3, *(size_t *)ARG4); 3649 } 3650 } 3651 } 3652 3653 3654 PRE(sigpending) 3655 { 3656 PRINT( "sigpending ( %#lx )", ARG1 ); 3657 PRE_REG_READ1(long, "sigpending", vki_sigset_t *, set); 3658 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_sigset_t)); 3659 } 3660 POST(sigpending) 3661 { 3662 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ; 3663 } 3664 3665 3666 PRE(sigprocmask) 3667 { 3668 UWord arg1; 3669 PRINT("sigprocmask ( %ld, %#lx, %#lx )", ARG1, ARG2, ARG3); 3670 PRE_REG_READ3(long, "sigprocmask", 3671 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset); 3672 if (ARG2 != 0) 3673 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_sigset_t)); 3674 if (ARG3 != 0) 3675 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t)); 3676 3677 /* Massage ARG1 ('how'). If ARG2 (the new mask) is NULL then the 3678 value of 'how' is irrelevant, and it appears that Darwin's libc 3679 passes zero, which is not equal to any of 3680 SIG_{BLOCK,UNBLOCK,SETMASK}. This causes 3681 VG_(do_sys_sigprocmask) to complain, since it checks the 'how' 3682 value independently of the other args. Solution: in this case, 3683 simply pass a valid (but irrelevant) value for 'how'. */ 3684 /* Also, in this case the new set is passed to the kernel by 3685 reference, not value, as in some other sigmask related Darwin 3686 syscalls. */ 3687 arg1 = ARG1; 3688 if (ARG2 == 0 /* the new-set is NULL */ 3689 && ARG1 != VKI_SIG_BLOCK 3690 && ARG1 != VKI_SIG_UNBLOCK && ARG1 != VKI_SIG_SETMASK) { 3691 arg1 = VKI_SIG_SETMASK; 3692 } 3693 SET_STATUS_from_SysRes( 3694 VG_(do_sys_sigprocmask) ( tid, arg1, (vki_sigset_t*)ARG2, 3695 (vki_sigset_t*)ARG3 ) 3696 ); 3697 3698 if (SUCCESS) 3699 *flags |= SfPollAfter; 3700 } 3701 3702 POST(sigprocmask) 3703 { 3704 vg_assert(SUCCESS); 3705 if (RES == 0 && ARG3 != 0) 3706 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t)); 3707 } 3708 3709 3710 PRE(sigsuspend) 3711 { 3712 /* Just hand this off to the kernel. Is that really correct? And 3713 shouldn't we at least set SfPollAfter? These questions apply to 3714 all the Linux versions too. */ 3715 /* I think the first arg is the 32-bit signal mask (by value), and 3716 the other two args are ignored. */ 3717 *flags |= SfMayBlock; 3718 PRINT("sigsuspend ( mask=0x%08lx )", ARG1 ); 3719 PRE_REG_READ1(int, "sigsuspend", int, sigmask); 3720 } 3721 3722 3723 /* Be careful about the 4th arg, since that is a uint64_t. Hence 64- 3724 and 32-bit wrappers are different. 3725 3726 ARG5 and ARG6 (buffer, buffersize) specify a buffer start and 3727 length in the usual way. I have seen values NULL, 0 passed in some 3728 cases. I left the calls to PRE_MEM_WRITE/READ unconditional on the 3729 basis that they don't do anything if the length is zero, so it's OK 3730 for the buffer pointer to be NULL in that case (meaning they don't 3731 complain). 3732 3733 int proc_info(int32_t callnum, int32_t pid, 3734 uint32_t flavor, uint64_t arg, 3735 user_addr_t buffer, int32_t buffersize) 3736 */ 3737 #if DARWIN_VERS >= DARWIN_10_6 3738 PRE(proc_info) 3739 { 3740 #if VG_WORDSIZE == 4 3741 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)", 3742 (Int)ARG1, (Int)ARG2, (UInt)ARG3, LOHI64(ARG4,ARG5), ARG6, (Int)ARG7); 3743 PRE_REG_READ7(int, "proc_info", 3744 int, callnum, int, pid, unsigned int, flavor, 3745 vki_uint32_t, arg_low32, 3746 vki_uint32_t, arg_high32, 3747 void*, buffer, int, buffersize); 3748 PRE_MEM_WRITE("proc_info(buffer)", ARG6, ARG7); 3749 #else 3750 PRINT("proc_info(%d, %d, %u, %llu, %#lx, %d)", 3751 (Int)ARG1, (Int)ARG2, (UInt)ARG3, (ULong)ARG4, ARG5, (Int)ARG6); 3752 PRE_REG_READ6(int, "proc_info", 3753 int, callnum, int, pid, unsigned int, flavor, 3754 unsigned long long int, arg, 3755 void*, buffer, int, buffersize); 3756 PRE_MEM_WRITE("proc_info(buffer)", ARG5, ARG6); 3757 #endif 3758 } 3759 3760 POST(proc_info) 3761 { 3762 #if VG_WORDSIZE == 4 3763 vg_assert(SUCCESS); 3764 POST_MEM_WRITE(ARG6, ARG7); 3765 #else 3766 vg_assert(SUCCESS); 3767 POST_MEM_WRITE(ARG5, ARG6); 3768 #endif 3769 } 3770 3771 #endif /* DARWIN_VERS >= DARWIN_10_6 */ 3772 3773 /* --------------------------------------------------------------------- 3774 aio_* 3775 ------------------------------------------------------------------ */ 3776 3777 // We must record the aiocbp for each aio_read() in a table so that when 3778 // aio_return() is called we can mark the memory written asynchronously by 3779 // aio_read() as having been written. We don't have to do this for 3780 // aio_write(). See bug 197227 for more details. 3781 static OSet* aiocbp_table = NULL; 3782 static Bool aio_init_done = False; 3783 3784 static void aio_init(void) 3785 { 3786 aiocbp_table = VG_(OSetWord_Create)(VG_(malloc), "syswrap.aio", VG_(free)); 3787 aio_init_done = True; 3788 } 3789 3790 static Bool was_a_successful_aio_read = False; 3791 3792 PRE(aio_return) 3793 { 3794 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1; 3795 // This assumes that the kernel looks at the struct pointer, but not the 3796 // contents of the struct. 3797 PRINT( "aio_return ( %#lx )", ARG1 ); 3798 PRE_REG_READ1(long, "aio_return", struct vki_aiocb*, aiocbp); 3799 3800 if (!aio_init_done) aio_init(); 3801 was_a_successful_aio_read = VG_(OSetWord_Remove)(aiocbp_table, (UWord)aiocbp); 3802 } 3803 POST(aio_return) 3804 { 3805 // If we found the aiocbp in our own table it must have been an aio_read(), 3806 // so mark the buffer as written. If we didn't find it, it must have been 3807 // an aio_write() or a bogus aio_return() (eg. a second one on the same 3808 // aiocbp). Either way, the buffer won't have been written so we don't 3809 // have to mark the buffer as written. 3810 if (was_a_successful_aio_read) { 3811 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1; 3812 POST_MEM_WRITE((Addr)aiocbp->aio_buf, aiocbp->aio_nbytes); 3813 was_a_successful_aio_read = False; 3814 } 3815 } 3816 3817 PRE(aio_suspend) 3818 { 3819 // This assumes that the kernel looks at the struct pointers in the list, 3820 // but not the contents of the structs. 3821 PRINT( "aio_suspend ( %#lx )", ARG1 ); 3822 PRE_REG_READ3(long, "aio_suspend", 3823 const struct vki_aiocb *, aiocbp, int, nent, 3824 const struct vki_timespec *, timeout); 3825 if (ARG2 > 0) 3826 PRE_MEM_READ("aio_suspend(list)", ARG1, ARG2 * sizeof(struct vki_aiocb *)); 3827 if (ARG3) 3828 PRE_MEM_READ ("aio_suspend(timeout)", ARG3, sizeof(struct vki_timespec)); 3829 } 3830 3831 PRE(aio_error) 3832 { 3833 // This assumes that the kernel looks at the struct pointer, but not the 3834 // contents of the struct. 3835 PRINT( "aio_error ( %#lx )", ARG1 ); 3836 PRE_REG_READ1(long, "aio_error", struct vki_aiocb*, aiocbp); 3837 } 3838 3839 PRE(aio_read) 3840 { 3841 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1; 3842 3843 PRINT( "aio_read ( %#lx )", ARG1 ); 3844 PRE_REG_READ1(long, "aio_read", struct vki_aiocb*, aiocbp); 3845 PRE_MEM_READ( "aio_read(aiocbp)", ARG1, sizeof(struct vki_aiocb)); 3846 3847 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) { 3848 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_read", tid, /*isNewFd*/False)) { 3849 PRE_MEM_WRITE("aio_read(aiocbp->aio_buf)", 3850 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes); 3851 } else { 3852 SET_STATUS_Failure( VKI_EBADF ); 3853 } 3854 } else { 3855 SET_STATUS_Failure( VKI_EINVAL ); 3856 } 3857 } 3858 POST(aio_read) 3859 { 3860 // We have to record the fact that there is an asynchronous read request 3861 // pending. When a successful aio_return() occurs for this aiocb, then we 3862 // will mark the memory as having been defined. 3863 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1; 3864 if (!aio_init_done) aio_init(); 3865 // aiocbp shouldn't already be in the table -- if it was a dup, the kernel 3866 // should have caused the aio_read() to fail and we shouldn't have reached 3867 // here. 3868 VG_(OSetWord_Insert)(aiocbp_table, (UWord)aiocbp); 3869 } 3870 3871 PRE(aio_write) 3872 { 3873 struct vki_aiocb* aiocbp = (struct vki_aiocb*)ARG1; 3874 3875 PRINT( "aio_write ( %#lx )", ARG1 ); 3876 PRE_REG_READ1(long, "aio_write", struct vki_aiocb*, aiocbp); 3877 PRE_MEM_READ( "aio_write(aiocbp)", ARG1, sizeof(struct vki_aiocb)); 3878 3879 if (ML_(safe_to_deref)(aiocbp, sizeof(struct vki_aiocb))) { 3880 if (ML_(fd_allowed)(aiocbp->aio_fildes, "aio_write", tid, /*isNewFd*/False)) { 3881 PRE_MEM_READ("aio_write(aiocbp->aio_buf)", 3882 (Addr)aiocbp->aio_buf, aiocbp->aio_nbytes); 3883 } else { 3884 SET_STATUS_Failure( VKI_EBADF ); 3885 } 3886 } else { 3887 SET_STATUS_Failure( VKI_EINVAL ); 3888 } 3889 } 3890 3891 /* --------------------------------------------------------------------- 3892 mach_msg: formatted messages 3893 ------------------------------------------------------------------ */ 3894 3895 static size_t desc_size(mach_msg_descriptor_t *desc) 3896 { 3897 switch (desc->type.type) { 3898 case MACH_MSG_PORT_DESCRIPTOR: return sizeof(desc->port); 3899 case MACH_MSG_OOL_DESCRIPTOR: return sizeof(desc->out_of_line); 3900 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: return sizeof(desc->out_of_line); 3901 case MACH_MSG_OOL_PORTS_DESCRIPTOR: return sizeof(desc->ool_ports); 3902 default: 3903 VG_(printf)("UNKNOWN mach message descriptor %d\n", desc->type.type); 3904 return sizeof(desc->type); // guess 3905 } 3906 } 3907 3908 3909 static void assign_port_names(mach_msg_ool_ports_descriptor_t *desc, 3910 const char *name) 3911 { 3912 mach_msg_size_t i; 3913 mach_port_t *ports = (mach_port_t *)desc->address; 3914 for (i = 0; i < desc->count; i++) { 3915 assign_port_name(ports[i], name); 3916 } 3917 } 3918 3919 3920 static void import_complex_message(ThreadId tid, mach_msg_header_t *mh) 3921 { 3922 mach_msg_body_t *body; 3923 mach_msg_size_t count, i; 3924 uint8_t *p; 3925 mach_msg_descriptor_t *desc; 3926 3927 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX); 3928 3929 body = (mach_msg_body_t *)(mh+1); 3930 count = body->msgh_descriptor_count; 3931 p = (uint8_t *)(body+1); 3932 3933 for (i = 0; i < count; i++) { 3934 desc = (mach_msg_descriptor_t *)p; 3935 p += desc_size(desc); 3936 3937 switch (desc->type.type) { 3938 case MACH_MSG_PORT_DESCRIPTOR: 3939 // single port 3940 record_unnamed_port(tid, desc->port.name, -1); 3941 record_port_insert_rights(desc->port.name, desc->port.disposition); 3942 PRINT("got port %s;\n", name_for_port(desc->port.name)); 3943 break; 3944 3945 case MACH_MSG_OOL_DESCRIPTOR: 3946 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: 3947 // out-of-line memory - map it 3948 // GrP fixme how is VOLATILE different? do we care? 3949 // GrP fixme do other flags tell us anything? assume shared for now 3950 // GrP fixme more SF_ flags marking mach_msg memory might be nice 3951 // GrP fixme protection 3952 if (desc->out_of_line.size > 0) { 3953 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address); 3954 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + 3955 (Addr)desc->out_of_line.size); 3956 PRINT("got ool mem %p..%#lx;\n", desc->out_of_line.address, 3957 (Addr)desc->out_of_line.address+desc->out_of_line.size); 3958 3959 ML_(notify_core_and_tool_of_mmap)( 3960 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE, 3961 VKI_MAP_PRIVATE, -1, 0); 3962 } 3963 // GrP fixme mark only un-rounded part as initialized 3964 break; 3965 3966 case MACH_MSG_OOL_PORTS_DESCRIPTOR: 3967 // out-of-line array of ports - map it 3968 // GrP fixme see fixmes above 3969 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)); 3970 3971 if (desc->ool_ports.count > 0) { 3972 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address); 3973 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + desc->ool_ports.count * sizeof(mach_port_t)); 3974 mach_port_t *ports = (mach_port_t *)desc->ool_ports.address; 3975 3976 ML_(notify_core_and_tool_of_mmap)( 3977 start, end - start, VKI_PROT_READ|VKI_PROT_WRITE, 3978 VKI_MAP_PRIVATE, -1, 0); 3979 3980 PRINT(":"); 3981 for (i = 0; i < desc->ool_ports.count; i++) { 3982 record_unnamed_port(tid, ports[i], -1); 3983 record_port_insert_rights(ports[i], desc->port.disposition); 3984 PRINT(" %s", name_for_port(ports[i])); 3985 } 3986 } 3987 PRINT(";\n"); 3988 break; 3989 3990 default: 3991 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type); 3992 break; 3993 } 3994 } 3995 } 3996 3997 3998 static void pre_port_desc_read(ThreadId tid, mach_msg_port_descriptor_t *desc2) 3999 { 4000 #pragma pack(4) 4001 struct { 4002 mach_port_t name; 4003 mach_msg_size_t pad1; 4004 uint16_t pad2; 4005 uint8_t disposition; 4006 uint8_t type; 4007 } *desc = (void*)desc2; 4008 #pragma pack() 4009 4010 PRE_FIELD_READ("msg->desc.port.name", desc->name); 4011 PRE_FIELD_READ("msg->desc.port.disposition", desc->disposition); 4012 PRE_FIELD_READ("msg->desc.port.type", desc->type); 4013 } 4014 4015 4016 static void pre_ool_desc_read(ThreadId tid, mach_msg_ool_descriptor_t *desc2) 4017 { 4018 #pragma pack(4) 4019 struct { 4020 Addr address; 4021 #if VG_WORDSIZE != 8 4022 mach_msg_size_t size; 4023 #endif 4024 uint8_t deallocate; 4025 uint8_t copy; 4026 uint8_t pad1; 4027 uint8_t type; 4028 #if VG_WORDSIZE == 8 4029 mach_msg_size_t size; 4030 #endif 4031 } *desc = (void*)desc2; 4032 #pragma pack() 4033 4034 PRE_FIELD_READ("msg->desc.out_of_line.address", desc->address); 4035 PRE_FIELD_READ("msg->desc.out_of_line.size", desc->size); 4036 PRE_FIELD_READ("msg->desc.out_of_line.deallocate", desc->deallocate); 4037 PRE_FIELD_READ("msg->desc.out_of_line.copy", desc->copy); 4038 PRE_FIELD_READ("msg->desc.out_of_line.type", desc->type); 4039 } 4040 4041 static void pre_oolports_desc_read(ThreadId tid, 4042 mach_msg_ool_ports_descriptor_t *desc2) 4043 { 4044 #pragma pack(4) 4045 struct { 4046 Addr address; 4047 #if VG_WORDSIZE != 8 4048 mach_msg_size_t size; 4049 #endif 4050 uint8_t deallocate; 4051 uint8_t copy; 4052 uint8_t disposition; 4053 uint8_t type; 4054 #if VG_WORDSIZE == 8 4055 mach_msg_size_t size; 4056 #endif 4057 } *desc = (void*)desc2; 4058 #pragma pack() 4059 4060 PRE_FIELD_READ("msg->desc.ool_ports.address", desc->address); 4061 PRE_FIELD_READ("msg->desc.ool_ports.size", desc->size); 4062 PRE_FIELD_READ("msg->desc.ool_ports.deallocate", desc->deallocate); 4063 PRE_FIELD_READ("msg->desc.ool_ports.copy", desc->copy); 4064 PRE_FIELD_READ("msg->desc.ool_ports.disposition", desc->disposition); 4065 PRE_FIELD_READ("msg->desc.ool_ports.type", desc->type); 4066 } 4067 4068 4069 // Returns the size of the descriptor area 4070 // (mach_msg_body_t + any mach_msg_descriptor_t) 4071 static size_t export_complex_message(ThreadId tid, mach_msg_header_t *mh) 4072 { 4073 mach_msg_body_t *body; 4074 mach_msg_size_t count, i; 4075 uint8_t *p; 4076 mach_msg_descriptor_t *desc; 4077 4078 vg_assert(mh->msgh_bits & MACH_MSGH_BITS_COMPLEX); 4079 4080 body = (mach_msg_body_t *)(mh+1); 4081 PRE_MEM_READ("msg->msgh_descriptor_count)", (Addr)body, sizeof(*body)); 4082 4083 count = body->msgh_descriptor_count; 4084 p = (uint8_t *)(body+1); 4085 4086 for (i = 0; i < count; i++) { 4087 desc = (mach_msg_descriptor_t *)p; 4088 p += desc_size(desc); 4089 4090 switch (desc->type.type) { 4091 case MACH_MSG_PORT_DESCRIPTOR: 4092 // single port; no memory map effects 4093 pre_port_desc_read(tid, &desc->port); 4094 break; 4095 4096 case MACH_MSG_OOL_DESCRIPTOR: 4097 case MACH_MSG_OOL_VOLATILE_DESCRIPTOR: 4098 // out-of-line memory - unmap it if it's marked dealloc 4099 // GrP fixme need to remap if message fails? 4100 // GrP fixme how is VOLATILE different? do we care? 4101 // GrP fixme struct is different for lp64 4102 pre_ool_desc_read(tid, &desc->out_of_line); 4103 4104 if (desc->out_of_line.deallocate && desc->out_of_line.size > 0) { 4105 vm_size_t size = desc->out_of_line.size; 4106 Addr start = VG_PGROUNDDN((Addr)desc->out_of_line.address); 4107 Addr end = VG_PGROUNDUP((Addr)desc->out_of_line.address + size); 4108 PRINT("kill ool mem %p..%#lx; ", desc->out_of_line.address, 4109 (Addr)desc->out_of_line.address + size); 4110 ML_(notify_core_and_tool_of_munmap)(start, end - start); 4111 } 4112 break; 4113 4114 case MACH_MSG_OOL_PORTS_DESCRIPTOR: 4115 // out-of-line array of ports - unmap it if it's marked dealloc 4116 // GrP fixme need to remap if message fails? 4117 // GrP fixme struct different for lp64 4118 pre_oolports_desc_read(tid, &desc->ool_ports); 4119 4120 if (desc->ool_ports.deallocate && desc->ool_ports.count > 0) { 4121 vm_size_t size = desc->ool_ports.count * sizeof(mach_port_t); 4122 Addr start = VG_PGROUNDDN((Addr)desc->ool_ports.address); 4123 Addr end = VG_PGROUNDUP((Addr)desc->ool_ports.address + size); 4124 PRINT("kill ool port array %p..%#lx; ", desc->ool_ports.address, 4125 (Addr)desc->ool_ports.address + size); 4126 ML_(notify_core_and_tool_of_munmap)(start, end - start); 4127 } 4128 break; 4129 default: 4130 VG_(printf)("UNKNOWN Mach descriptor type %u!\n", desc->type.type); 4131 break; 4132 } 4133 } 4134 4135 return (size_t)((Addr)p - (Addr)body); 4136 } 4137 4138 4139 /* --------------------------------------------------------------------- 4140 mach_msg: host-related messages 4141 ------------------------------------------------------------------ */ 4142 4143 4144 POST(host_info) 4145 { 4146 #pragma pack(4) 4147 typedef struct { 4148 mach_msg_header_t Head; 4149 NDR_record_t NDR; 4150 kern_return_t RetCode; 4151 mach_msg_type_number_t host_info_outCnt; 4152 integer_t host_info_out[14]; 4153 } Reply; 4154 #pragma pack() 4155 4156 Reply *reply = (Reply *)ARG1; 4157 4158 if (reply->RetCode) PRINT("mig return %d", reply->RetCode); 4159 } 4160 4161 PRE(host_info) 4162 { 4163 #pragma pack(4) 4164 typedef struct { 4165 mach_msg_header_t Head; 4166 NDR_record_t NDR; 4167 host_flavor_t flavor; 4168 mach_msg_type_number_t host_info_outCnt; 4169 } Request; 4170 #pragma pack() 4171 4172 Request *req = (Request *)ARG1; 4173 4174 PRINT("host_info(mach_host_self(), flavor %d)", req->flavor); 4175 4176 AFTER = POST_FN(host_info); 4177 } 4178 4179 4180 POST(host_page_size) 4181 { 4182 #pragma pack(4) 4183 typedef struct { 4184 mach_msg_header_t Head; 4185 NDR_record_t NDR; 4186 kern_return_t RetCode; 4187 vm_size_t out_page_size; 4188 } Reply; 4189 #pragma pack() 4190 4191 Reply *reply = (Reply *)ARG1; 4192 4193 if (!reply->RetCode) { 4194 PRINT("page size %llu", (ULong)reply->out_page_size); 4195 } else { 4196 PRINT("mig return %d", reply->RetCode); 4197 } 4198 } 4199 4200 PRE(host_page_size) 4201 { 4202 PRINT("host_page_size(mach_host_self(), ...)"); 4203 4204 AFTER = POST_FN(host_page_size); 4205 } 4206 4207 4208 POST(host_get_io_master) 4209 { 4210 #pragma pack(4) 4211 typedef struct { 4212 mach_msg_header_t Head; 4213 /* start of the kernel processed data */ 4214 mach_msg_body_t msgh_body; 4215 mach_msg_port_descriptor_t io_master; 4216 /* end of the kernel processed data */ 4217 } Reply; 4218 #pragma pack() 4219 4220 Reply *reply = (Reply *)ARG1; 4221 4222 assign_port_name(reply->io_master.name, "io_master-%p"); 4223 PRINT("%s", name_for_port(reply->io_master.name)); 4224 } 4225 4226 PRE(host_get_io_master) 4227 { 4228 #pragma pack(4) 4229 typedef struct { 4230 mach_msg_header_t Head; 4231 } Request; 4232 #pragma pack() 4233 4234 // Request *req = (Request *)ARG1; 4235 4236 PRINT("host_get_io_master(mach_host_self())"); 4237 4238 AFTER = POST_FN(host_get_io_master); 4239 } 4240 4241 4242 POST(host_get_clock_service) 4243 { 4244 #pragma pack(4) 4245 typedef struct { 4246 mach_msg_header_t Head; 4247 /* start of the kernel processed data */ 4248 mach_msg_body_t msgh_body; 4249 mach_msg_port_descriptor_t clock_serv; 4250 /* end of the kernel processed data */ 4251 } Reply; 4252 #pragma pack() 4253 4254 Reply *reply = (Reply *)ARG1; 4255 4256 assign_port_name(reply->clock_serv.name, "clock-%p"); 4257 PRINT("%s", name_for_port(reply->clock_serv.name)); 4258 } 4259 4260 PRE(host_get_clock_service) 4261 { 4262 #pragma pack(4) 4263 typedef struct { 4264 mach_msg_header_t Head; 4265 NDR_record_t NDR; 4266 clock_id_t clock_id; 4267 } Request; 4268 #pragma pack() 4269 4270 Request *req = (Request *)ARG1; 4271 4272 PRINT("host_get_clock_service(mach_host_self(), %d)", req->clock_id); 4273 4274 AFTER = POST_FN(host_get_clock_service); 4275 } 4276 4277 4278 PRE(host_request_notification) 4279 { 4280 #pragma pack(4) 4281 typedef struct { 4282 mach_msg_header_t Head; 4283 /* start of the kernel processed data */ 4284 mach_msg_body_t msgh_body; 4285 mach_msg_port_descriptor_t notify_port; 4286 /* end of the kernel processed data */ 4287 NDR_record_t NDR; 4288 host_flavor_t notify_type; 4289 } Request; 4290 #pragma pack() 4291 4292 Request *req = (Request *)ARG1; 4293 4294 if (MACH_REMOTE == mach_task_self()) { 4295 if (req->notify_type == 0) { 4296 PRINT("host_request_notification(mach_host_self(), %s, %s)", 4297 "HOST_NOTIFY_CALENDAR_CHANGE", 4298 name_for_port(req->notify_port.name)); 4299 } else { 4300 PRINT("host_request_notification(mach_host_self(), %d, %s)", 4301 req->notify_type, 4302 name_for_port(req->notify_port.name)); 4303 } 4304 } else { 4305 PRINT("host_request_notification(%s, %d, %s)", 4306 name_for_port(MACH_REMOTE), 4307 req->notify_type, 4308 name_for_port(req->notify_port.name)); 4309 } 4310 4311 // GrP fixme only do this on success 4312 assign_port_name(req->notify_port.name, "host_notify-%p"); 4313 } 4314 4315 4316 /* --------------------------------------------------------------------- 4317 mach_msg: messages to a task 4318 ------------------------------------------------------------------ */ 4319 4320 // JRS 2011-Aug-25: just guessing here. I have no clear idea how 4321 // these structs are derived. They obviously relate to the various 4322 // .def files in the xnu sources, and can also be found in some 4323 // form in /usr/include/mach/*.h, but not sure how these all 4324 // relate to each other. 4325 4326 PRE(mach_port_set_context) 4327 { 4328 #pragma pack(4) 4329 typedef struct { 4330 mach_msg_header_t Head; 4331 NDR_record_t NDR; 4332 mach_port_name_t name; 4333 mach_vm_address_t context; 4334 } Request; 4335 #pragma pack() 4336 4337 Request *req = (Request *)ARG1; 4338 4339 PRINT("mach_port_set_context(%s, %s, 0x%llx)", 4340 name_for_port(MACH_REMOTE), 4341 name_for_port(req->name), req->context); 4342 4343 AFTER = POST_FN(mach_port_set_context); 4344 } 4345 4346 POST(mach_port_set_context) 4347 { 4348 #pragma pack(4) 4349 typedef struct { 4350 mach_msg_header_t Head; 4351 NDR_record_t NDR; 4352 kern_return_t RetCode; 4353 } Reply; 4354 #pragma pack() 4355 } 4356 4357 4358 // JRS 2011-Aug-25 FIXME completely bogus 4359 PRE(task_get_exception_ports) 4360 { 4361 #pragma pack(4) 4362 typedef struct { 4363 mach_msg_header_t Head; 4364 NDR_record_t NDR; 4365 exception_mask_t exception_mask; 4366 } Request; 4367 #pragma pack() 4368 4369 PRINT("task_get_exception_ports(BOGUS)"); 4370 AFTER = POST_FN(task_get_exception_ports); 4371 } 4372 4373 POST(task_get_exception_ports) 4374 { 4375 #pragma pack(4) 4376 typedef struct { 4377 mach_msg_header_t Head; 4378 /* start of the kernel processed data */ 4379 mach_msg_body_t msgh_body; 4380 mach_msg_port_descriptor_t old_handlers[32]; 4381 /* end of the kernel processed data */ 4382 NDR_record_t NDR; 4383 mach_msg_type_number_t masksCnt; 4384 exception_mask_t masks[32]; 4385 exception_behavior_t old_behaviors[32]; 4386 thread_state_flavor_t old_flavors[32]; 4387 } Reply; 4388 #pragma pack() 4389 } 4390 4391 4392 /////////////////////////////////////////////////// 4393 4394 PRE(mach_port_type) 4395 { 4396 #pragma pack(4) 4397 typedef struct { 4398 mach_msg_header_t Head; 4399 NDR_record_t NDR; 4400 mach_port_name_t name; 4401 } Request; 4402 #pragma pack() 4403 4404 Request *req = (Request *)ARG1; 4405 4406 PRINT("mach_port_type(%s, %s, ...)", 4407 name_for_port(MACH_REMOTE), name_for_port(req->name)); 4408 4409 AFTER = POST_FN(mach_port_type); 4410 } 4411 4412 POST(mach_port_type) 4413 { 4414 } 4415 4416 4417 PRE(mach_port_extract_member) 4418 { 4419 #pragma pack(4) 4420 typedef struct { 4421 mach_msg_header_t Head; 4422 NDR_record_t NDR; 4423 mach_port_name_t name; 4424 mach_port_name_t pset; 4425 } Request; 4426 #pragma pack() 4427 4428 Request *req = (Request *)ARG1; 4429 4430 PRINT("mach_port_extract_member(%s, 0x%x, 0x%x)", 4431 name_for_port(MACH_REMOTE), 4432 req->name, req->pset); 4433 4434 AFTER = POST_FN(mach_port_extract_member); 4435 4436 // GrP fixme port tracker? 4437 } 4438 4439 POST(mach_port_extract_member) 4440 { 4441 #pragma pack(4) 4442 typedef struct { 4443 mach_msg_header_t Head; 4444 NDR_record_t NDR; 4445 kern_return_t RetCode; 4446 } Reply; 4447 #pragma pack() 4448 4449 Reply *reply = (Reply *)ARG1; 4450 4451 if (reply->RetCode) PRINT("mig return %d", reply->RetCode); 4452 } 4453 4454 4455 PRE(mach_port_allocate) 4456 { 4457 #pragma pack(4) 4458 typedef struct { 4459 mach_msg_header_t Head; 4460 NDR_record_t NDR; 4461 mach_port_right_t right; 4462 } Request; 4463 #pragma pack() 4464 4465 Request *req = (Request *)ARG1; 4466 4467 PRINT("mach_port_allocate(mach_task_self(), %d, ...)", req->right); 4468 4469 MACH_ARG(mach_port_allocate.right) = req->right; 4470 4471 AFTER = POST_FN(mach_port_allocate); 4472 } 4473 4474 POST(mach_port_allocate) 4475 { 4476 #pragma pack(4) 4477 typedef struct { 4478 mach_msg_header_t Head; 4479 NDR_record_t NDR; 4480 kern_return_t RetCode; 4481 mach_port_name_t name; 4482 } Reply; 4483 #pragma pack() 4484 4485 Reply *reply = (Reply *)ARG1; 4486 4487 if (!reply->RetCode) { 4488 if (MACH_REMOTE == vg_task_port) { 4489 // GrP fixme port tracking is too imprecise 4490 // vg_assert(!port_exists(reply->name)); 4491 record_unnamed_port(tid, reply->name, MACH_ARG(mach_port_allocate.right)); 4492 PRINT("got port 0x%x", reply->name); 4493 } else { 4494 VG_(printf)("UNKNOWN inserted port 0x%x into remote task\n", reply->name); 4495 } 4496 } else { 4497 PRINT("mig return %d", reply->RetCode); 4498 } 4499 } 4500 4501 4502 PRE(mach_port_deallocate) 4503 { 4504 #pragma pack(4) 4505 typedef struct { 4506 mach_msg_header_t Head; 4507 NDR_record_t NDR; 4508 mach_port_name_t name; 4509 } Request; 4510 #pragma pack() 4511 4512 Request *req = (Request *)ARG1; 4513 4514 PRINT("mach_port_deallocate(%s, %s)", 4515 name_for_port(MACH_REMOTE), 4516 name_for_port(req->name)); 4517 4518 MACH_ARG(mach_port.port) = req->name; 4519 4520 AFTER = POST_FN(mach_port_deallocate); 4521 4522 // Must block to prevent race (other thread allocates and 4523 // notifies after we deallocate but before we notify) 4524 *flags &= ~SfMayBlock; 4525 } 4526 4527 POST(mach_port_deallocate) 4528 { 4529 #pragma pack(4) 4530 typedef struct { 4531 mach_msg_header_t Head; 4532 NDR_record_t NDR; 4533 kern_return_t RetCode; 4534 } Reply; 4535 #pragma pack() 4536 4537 Reply *reply = (Reply *)ARG1; 4538 4539 if (!reply->RetCode) { 4540 if (MACH_REMOTE == vg_task_port) { 4541 // Must have cleared SfMayBlock in PRE to prevent race 4542 record_port_dealloc(MACH_ARG(mach_port.port)); 4543 } else { 4544 VG_(printf)("UNKNOWN remote port dealloc\n"); 4545 } 4546 } else { 4547 PRINT("mig return %d", reply->RetCode); 4548 } 4549 } 4550 4551 4552 PRE(mach_port_get_refs) 4553 { 4554 #pragma pack(4) 4555 typedef struct { 4556 mach_msg_header_t Head; 4557 NDR_record_t NDR; 4558 mach_port_name_t name; 4559 mach_port_right_t right; 4560 } Request; 4561 #pragma pack() 4562 4563 Request *req = (Request *)ARG1; 4564 4565 PRINT("mach_port_get_refs(%s, %s, 0x%x)", 4566 name_for_port(MACH_REMOTE), 4567 name_for_port(req->name), req->right); 4568 4569 MACH_ARG(mach_port_mod_refs.port) = req->name; 4570 MACH_ARG(mach_port_mod_refs.right) = req->right; 4571 4572 AFTER = POST_FN(mach_port_get_refs); 4573 } 4574 4575 POST(mach_port_get_refs) 4576 { 4577 #pragma pack(4) 4578 typedef struct { 4579 mach_msg_header_t Head; 4580 NDR_record_t NDR; 4581 kern_return_t RetCode; 4582 mach_port_urefs_t refs; 4583 } Reply; 4584 #pragma pack() 4585 4586 Reply *reply = (Reply *)ARG1; 4587 4588 if (!reply->RetCode) { 4589 PRINT("got refs=%d", reply->refs); 4590 } else { 4591 PRINT("mig return %d", reply->RetCode); 4592 } 4593 } 4594 4595 4596 PRE(mach_port_mod_refs) 4597 { 4598 #pragma pack(4) 4599 typedef struct { 4600 mach_msg_header_t Head; 4601 NDR_record_t NDR; 4602 mach_port_name_t name; 4603 mach_port_right_t right; 4604 mach_port_delta_t delta; 4605 } Request; 4606 #pragma pack() 4607 4608 Request *req = (Request *)ARG1; 4609 4610 PRINT("mach_port_mod_refs(%s, %s, 0x%x, 0x%x)", 4611 name_for_port(MACH_REMOTE), 4612 name_for_port(req->name), req->right, req->delta); 4613 4614 MACH_ARG(mach_port_mod_refs.port) = req->name; 4615 MACH_ARG(mach_port_mod_refs.right) = req->right; 4616 MACH_ARG(mach_port_mod_refs.delta) = req->delta; 4617 4618 AFTER = POST_FN(mach_port_mod_refs); 4619 4620 // Must block to prevent race (other thread allocates and 4621 // notifies after we deallocate but before we notify) 4622 *flags &= ~SfMayBlock; 4623 } 4624 4625 POST(mach_port_mod_refs) 4626 { 4627 #pragma pack(4) 4628 typedef struct { 4629 mach_msg_header_t Head; 4630 NDR_record_t NDR; 4631 kern_return_t RetCode; 4632 } Reply; 4633 #pragma pack() 4634 4635 Reply *reply = (Reply *)ARG1; 4636 4637 if (!reply->RetCode) { 4638 if (MACH_REMOTE == vg_task_port) { 4639 // Must have cleared SfMayBlock in PRE to prevent race 4640 record_port_mod_refs(MACH_ARG(mach_port_mod_refs.port), 4641 MACH_PORT_TYPE(MACH_ARG(mach_port_mod_refs.right)), 4642 MACH_ARG(mach_port_mod_refs.delta)); 4643 } else { 4644 VG_(printf)("UNKNOWN remote port mod refs\n"); 4645 } 4646 } else { 4647 PRINT("mig return %d", reply->RetCode); 4648 } 4649 } 4650 4651 4652 PRE(mach_port_get_set_status) 4653 { 4654 #pragma pack(4) 4655 typedef struct { 4656 mach_msg_header_t Head; 4657 NDR_record_t NDR; 4658 mach_port_name_t name; 4659 } Request; 4660 #pragma pack() 4661 4662 Request *req = (Request *)ARG1; 4663 4664 PRINT("mach_port_get_set_status(%s, %s)", 4665 name_for_port(MACH_REMOTE), 4666 name_for_port(req->name)); 4667 4668 AFTER = POST_FN(mach_port_get_set_status); 4669 } 4670 4671 POST(mach_port_get_set_status) 4672 { 4673 #pragma pack(4) 4674 typedef struct { 4675 mach_msg_header_t Head; 4676 /* start of the kernel processed data */ 4677 mach_msg_body_t msgh_body; 4678 mach_msg_ool_descriptor_t members; 4679 /* end of the kernel processed data */ 4680 NDR_record_t NDR; 4681 mach_msg_type_number_t membersCnt; 4682 mach_msg_trailer_t trailer; 4683 } Reply; 4684 #pragma pack() 4685 4686 // Reply *reply = (Reply *)ARG1; 4687 4688 // GrP fixme nothing to do? 4689 } 4690 4691 4692 PRE(mach_port_move_member) 4693 { 4694 #pragma pack(4) 4695 typedef struct { 4696 mach_msg_header_t Head; 4697 NDR_record_t NDR; 4698 mach_port_name_t member; 4699 mach_port_name_t after; 4700 } Request; 4701 #pragma pack() 4702 4703 Request *req = (Request *)ARG1; 4704 4705 PRINT("mach_port_move_member(%s, %s, %s)", 4706 name_for_port(MACH_REMOTE), 4707 name_for_port(req->member), 4708 name_for_port(req->after)); 4709 /* 4710 MACH_ARG(mach_port_move_member.member) = req->member; 4711 MACH_ARG(mach_port_move_member.after) = req->after; 4712 */ 4713 AFTER = POST_FN(mach_port_move_member); 4714 } 4715 4716 POST(mach_port_move_member) 4717 { 4718 #pragma pack(4) 4719 typedef struct { 4720 mach_msg_header_t Head; 4721 NDR_record_t NDR; 4722 kern_return_t RetCode; 4723 mach_msg_trailer_t trailer; 4724 } Reply; 4725 #pragma pack() 4726 4727 Reply *reply = (Reply *)ARG1; 4728 4729 if (!reply->RetCode) { 4730 // fixme port set tracker? 4731 } else { 4732 PRINT("mig return %d", reply->RetCode); 4733 } 4734 } 4735 4736 4737 PRE(mach_port_destroy) 4738 { 4739 #pragma pack(4) 4740 typedef struct { 4741 mach_msg_header_t Head; 4742 NDR_record_t NDR; 4743 mach_port_name_t name; 4744 } Request; 4745 #pragma pack() 4746 4747 Request *req = (Request *)ARG1; 4748 4749 PRINT("mach_port_destroy(%s, %s)", 4750 name_for_port(MACH_REMOTE), 4751 name_for_port(req->name)); 4752 4753 MACH_ARG(mach_port.port) = req->name; 4754 4755 AFTER = POST_FN(mach_port_destroy); 4756 4757 // Must block to prevent race (other thread allocates and 4758 // notifies after we deallocate but before we notify) 4759 *flags &= ~SfMayBlock; 4760 } 4761 4762 POST(mach_port_destroy) 4763 { 4764 #pragma pack(4) 4765 typedef struct { 4766 mach_msg_header_t Head; 4767 NDR_record_t NDR; 4768 kern_return_t RetCode; 4769 } Reply; 4770 #pragma pack() 4771 4772 Reply *reply = (Reply *)ARG1; 4773 4774 if (!reply->RetCode) { 4775 if (MACH_REMOTE == vg_task_port) { 4776 // Must have cleared SfMayBlock in PRE to prevent race 4777 record_port_destroy(MACH_ARG(mach_port.port)); 4778 } else { 4779 VG_(printf)("UNKNOWN remote port destroy\n"); 4780 } 4781 } else { 4782 PRINT("mig return %d", reply->RetCode); 4783 } 4784 } 4785 4786 4787 PRE(mach_port_request_notification) 4788 { 4789 #pragma pack(4) 4790 typedef struct { 4791 mach_msg_header_t Head; 4792 /* start of the kernel processed data */ 4793 mach_msg_body_t msgh_body; 4794 mach_msg_port_descriptor_t notify; 4795 /* end of the kernel processed data */ 4796 NDR_record_t NDR; 4797 mach_port_name_t name; 4798 mach_msg_id_t msgid; 4799 mach_port_mscount_t sync; 4800 } Request; 4801 #pragma pack() 4802 4803 Request *req = (Request *)ARG1; 4804 4805 PRINT("mach_port_request_notification(%s, %s, %d, %d, %d, %d, ...)", 4806 name_for_port(MACH_REMOTE), 4807 name_for_port(req->name), req->msgid, req->sync, 4808 req->notify.name, req->notify.disposition); 4809 4810 AFTER = POST_FN(mach_port_request_notification); 4811 } 4812 4813 POST(mach_port_request_notification) 4814 { 4815 // GrP fixme port tracker? not sure 4816 } 4817 4818 4819 PRE(mach_port_insert_right) 4820 { 4821 #pragma pack(4) 4822 typedef struct { 4823 mach_msg_header_t Head; 4824 /* start of the kernel processed data */ 4825 mach_msg_body_t msgh_body; 4826 mach_msg_port_descriptor_t poly; 4827 /* end of the kernel processed data */ 4828 NDR_record_t NDR; 4829 mach_port_name_t name; 4830 } Request; 4831 #pragma pack() 4832 4833 Request *req = (Request *)ARG1; 4834 4835 PRINT("mach_port_insert_right(%s, %s, %d, %d)", 4836 name_for_port(MACH_REMOTE), 4837 name_for_port(req->name), req->poly.name, req->poly.disposition); 4838 4839 AFTER = POST_FN(mach_port_insert_right); 4840 4841 if (MACH_REMOTE == mach_task_self()) { 4842 // GrP fixme import_complex_message handles everything? 4843 // what about export_complex_message for MOVE variants? 4844 } else { 4845 VG_(printf)("UNKNOWN mach_port_insert_right into remote task!\n"); 4846 // GrP fixme also may remove rights from this task? 4847 } 4848 4849 // GrP fixme port tracker? 4850 } 4851 4852 POST(mach_port_insert_right) 4853 { 4854 } 4855 4856 4857 PRE(mach_port_extract_right) 4858 { 4859 #pragma pack(4) 4860 typedef struct { 4861 mach_msg_header_t Head; 4862 NDR_record_t NDR; 4863 mach_port_name_t name; 4864 mach_msg_type_name_t msgt_name; 4865 } Request; 4866 #pragma pack() 4867 4868 Request *req = (Request *)ARG1; 4869 4870 PRINT("mach_port_extract_right(%s, %s, %d)", 4871 name_for_port(MACH_REMOTE), 4872 name_for_port(req->name), req->msgt_name); 4873 4874 AFTER = POST_FN(mach_port_extract_right); 4875 4876 // fixme port tracker? 4877 } 4878 4879 POST(mach_port_extract_right) 4880 { 4881 // fixme import_complex_message handles the returned result, right? 4882 } 4883 4884 4885 PRE(mach_port_get_attributes) 4886 { 4887 #pragma pack(4) 4888 typedef struct { 4889 mach_msg_header_t Head; 4890 NDR_record_t NDR; 4891 mach_port_name_t name; 4892 mach_port_flavor_t flavor; 4893 mach_msg_type_number_t port_info_outCnt; 4894 } Request; 4895 #pragma pack() 4896 4897 Request *req = (Request *)ARG1; 4898 4899 PRINT("mach_port_get_attributes(%s, %s, %d, ..., %d)", 4900 name_for_port(MACH_REMOTE), 4901 name_for_port(req->name), req->flavor, req->port_info_outCnt); 4902 4903 AFTER = POST_FN(mach_port_get_attributes); 4904 } 4905 4906 POST(mach_port_get_attributes) 4907 { 4908 } 4909 4910 4911 PRE(mach_port_set_attributes) 4912 { 4913 #pragma pack(4) 4914 typedef struct { 4915 mach_msg_header_t Head; 4916 NDR_record_t NDR; 4917 mach_port_name_t name; 4918 mach_port_flavor_t flavor; 4919 mach_msg_type_number_t port_infoCnt; 4920 integer_t port_info[10]; 4921 } Request; 4922 #pragma pack() 4923 4924 Request *req = (Request *)ARG1; 4925 4926 PRINT("mach_port_set_attributes(%s, %s, %d, ..., %d)", 4927 name_for_port(MACH_REMOTE), 4928 name_for_port(req->name), req->flavor, req->port_infoCnt); 4929 4930 AFTER = POST_FN(mach_port_set_attributes); 4931 } 4932 4933 POST(mach_port_set_attributes) 4934 { 4935 } 4936 4937 4938 PRE(mach_port_insert_member) 4939 { 4940 #pragma pack(4) 4941 typedef struct { 4942 mach_msg_header_t Head; 4943 NDR_record_t NDR; 4944 mach_port_name_t name; 4945 mach_port_name_t pset; 4946 } Request; 4947 #pragma pack() 4948 4949 Request *req = (Request *)ARG1; 4950 4951 PRINT("mach_port_insert_member(%s, 0x%x, 0x%x)", 4952 name_for_port(MACH_REMOTE), req->name, req->pset); 4953 4954 AFTER = POST_FN(mach_port_insert_member); 4955 4956 // GrP fixme port tracker? 4957 } 4958 4959 POST(mach_port_insert_member) 4960 { 4961 } 4962 4963 4964 PRE(task_get_special_port) 4965 { 4966 #pragma pack(4) 4967 typedef struct { 4968 mach_msg_header_t Head; 4969 NDR_record_t NDR; 4970 int which_port; 4971 } Request; 4972 #pragma pack() 4973 4974 Request *req = (Request *)ARG1; 4975 4976 switch (req->which_port) { 4977 case TASK_KERNEL_PORT: 4978 PRINT("task_get_special_port(%s, TASK_KERNEL_PORT)", 4979 name_for_port(MACH_REMOTE)); 4980 break; 4981 case TASK_HOST_PORT: 4982 PRINT("task_get_special_port(%s, TASK_HOST_PORT)", 4983 name_for_port(MACH_REMOTE)); 4984 break; 4985 case TASK_BOOTSTRAP_PORT: 4986 PRINT("task_get_special_port(%s, TASK_BOOTSTRAP_PORT)", 4987 name_for_port(MACH_REMOTE)); 4988 break; 4989 case TASK_WIRED_LEDGER_PORT: 4990 PRINT("task_get_special_port(%s, TASK_WIRED_LEDGER_PORT)", 4991 name_for_port(MACH_REMOTE)); 4992 break; 4993 case TASK_PAGED_LEDGER_PORT: 4994 PRINT("task_get_special_port(%s, TASK_PAGED_LEDGER_PORT)", 4995 name_for_port(MACH_REMOTE)); 4996 break; 4997 default: 4998 PRINT("task_get_special_port(%s, %d)", 4999 name_for_port(MACH_REMOTE), req->which_port); 5000 break; 5001 } 5002 5003 MACH_ARG(task_get_special_port.which_port) = req->which_port; 5004 5005 AFTER = POST_FN(task_get_special_port); 5006 } 5007 5008 POST(task_get_special_port) 5009 { 5010 #pragma pack(4) 5011 typedef struct { 5012 mach_msg_header_t Head; 5013 /* start of the kernel processed data */ 5014 mach_msg_body_t msgh_body; 5015 mach_msg_port_descriptor_t special_port; 5016 /* end of the kernel processed data */ 5017 } Reply; 5018 #pragma pack() 5019 5020 Reply *reply = (Reply *)ARG1; 5021 5022 PRINT("got port %#x ", reply->special_port.name); 5023 5024 switch (MACH_ARG(task_get_special_port.which_port)) { 5025 case TASK_BOOTSTRAP_PORT: 5026 vg_bootstrap_port = reply->special_port.name; 5027 assign_port_name(reply->special_port.name, "bootstrap"); 5028 break; 5029 case TASK_KERNEL_PORT: 5030 assign_port_name(reply->special_port.name, "kernel"); 5031 break; 5032 case TASK_HOST_PORT: 5033 assign_port_name(reply->special_port.name, "host"); 5034 break; 5035 case TASK_WIRED_LEDGER_PORT: 5036 assign_port_name(reply->special_port.name, "wired-ledger"); 5037 break; 5038 case TASK_PAGED_LEDGER_PORT: 5039 assign_port_name(reply->special_port.name, "paged-ledger"); 5040 break; 5041 default: 5042 assign_port_name(reply->special_port.name, "special-%p"); 5043 break; 5044 } 5045 5046 PRINT("%s", name_for_port(reply->special_port.name)); 5047 } 5048 5049 5050 PRE(semaphore_create) 5051 { 5052 #pragma pack(4) 5053 typedef struct { 5054 mach_msg_header_t Head; 5055 NDR_record_t NDR; 5056 int policy; 5057 int value; 5058 } Request; 5059 #pragma pack() 5060 5061 Request *req = (Request *)ARG1; 5062 5063 PRINT("semaphore_create(%s, ..., %d, %d)", 5064 name_for_port(MACH_REMOTE), req->policy, req->value); 5065 5066 AFTER = POST_FN(semaphore_create); 5067 } 5068 5069 POST(semaphore_create) 5070 { 5071 #pragma pack(4) 5072 typedef struct { 5073 mach_msg_header_t Head; 5074 /* start of the kernel processed data */ 5075 mach_msg_body_t msgh_body; 5076 mach_msg_port_descriptor_t semaphore; 5077 /* end of the kernel processed data */ 5078 mach_msg_trailer_t trailer; 5079 } Reply; 5080 #pragma pack() 5081 5082 Reply *reply = (Reply *)ARG1; 5083 5084 assign_port_name(reply->semaphore.name, "semaphore-%p"); 5085 PRINT("%s", name_for_port(reply->semaphore.name)); 5086 } 5087 5088 5089 PRE(semaphore_destroy) 5090 { 5091 #pragma pack(4) 5092 typedef struct { 5093 mach_msg_header_t Head; 5094 /* start of the kernel processed data */ 5095 mach_msg_body_t msgh_body; 5096 mach_msg_port_descriptor_t semaphore; 5097 /* end of the kernel processed data */ 5098 mach_msg_trailer_t trailer; 5099 } Request; 5100 #pragma pack() 5101 5102 Request *req = (Request *)ARG1; 5103 5104 PRINT("semaphore_destroy(%s, %s)", 5105 name_for_port(MACH_REMOTE), name_for_port(req->semaphore.name)); 5106 5107 record_port_destroy(req->semaphore.name); 5108 5109 AFTER = POST_FN(semaphore_destroy); 5110 } 5111 5112 POST(semaphore_destroy) 5113 { 5114 #pragma pack(4) 5115 typedef struct { 5116 mach_msg_header_t Head; 5117 NDR_record_t NDR; 5118 kern_return_t RetCode; 5119 mach_msg_trailer_t trailer; 5120 } Reply; 5121 #pragma pack() 5122 5123 Reply *reply = (Reply *)ARG1; 5124 if (!reply->RetCode) { 5125 } else { 5126 PRINT("mig return %d", reply->RetCode); 5127 } 5128 } 5129 5130 5131 PRE(mach_ports_lookup) 5132 { 5133 #pragma pack(4) 5134 typedef struct { 5135 mach_msg_header_t Head; 5136 } Request; 5137 #pragma pack() 5138 5139 // Request *req = (Request *)ARG1; 5140 5141 PRINT("mach_ports_lookup(%s)", name_for_port(MACH_REMOTE)); 5142 5143 AFTER = POST_FN(mach_ports_lookup); 5144 } 5145 5146 POST(mach_ports_lookup) 5147 { 5148 #pragma pack(4) 5149 typedef struct { 5150 mach_msg_header_t Head; 5151 /* start of the kernel processed data */ 5152 mach_msg_body_t msgh_body; 5153 mach_msg_ool_ports_descriptor_t init_port_set; 5154 /* end of the kernel processed data */ 5155 NDR_record_t NDR; 5156 mach_msg_type_number_t init_port_setCnt; 5157 } Reply; 5158 #pragma pack() 5159 5160 // Reply *reply = (Reply *)ARG1; 5161 } 5162 5163 5164 PRE(task_threads) 5165 { 5166 #pragma pack(4) 5167 typedef struct { 5168 mach_msg_header_t Head; 5169 } Request; 5170 #pragma pack() 5171 5172 // Request *req = (Request *)ARG1; 5173 5174 PRINT("task_threads(%s)", name_for_port(MACH_REMOTE)); 5175 5176 AFTER = POST_FN(task_threads); 5177 } 5178 5179 POST(task_threads) 5180 { 5181 #pragma pack(4) 5182 typedef struct { 5183 mach_msg_header_t Head; 5184 /* start of the kernel processed data */ 5185 mach_msg_body_t msgh_body; 5186 mach_msg_ool_ports_descriptor_t act_list; 5187 /* end of the kernel processed data */ 5188 NDR_record_t NDR; 5189 mach_msg_type_number_t act_listCnt; 5190 mach_msg_trailer_t trailer; 5191 } Reply; 5192 #pragma pack() 5193 5194 Reply *reply = (Reply *)ARG1; 5195 5196 if (MACH_REMOTE == vg_task_port) { 5197 assign_port_names(&reply->act_list, "thread-%p"); 5198 } else { 5199 assign_port_names(&reply->act_list, "remote-thread-%p"); 5200 } 5201 } 5202 5203 5204 PRE(task_suspend) 5205 { 5206 PRINT("task_suspend(%s)", name_for_port(MACH_REMOTE)); 5207 5208 if (MACH_REMOTE == vg_task_port) { 5209 // GrP fixme self-suspend 5210 vg_assert(0); 5211 } else { 5212 // suspend other - no problem 5213 } 5214 5215 AFTER = POST_FN(task_suspend); 5216 } 5217 5218 POST(task_suspend) 5219 { 5220 } 5221 5222 5223 PRE(task_resume) 5224 { 5225 PRINT("task_resume(%s)", name_for_port(MACH_REMOTE)); 5226 5227 if (MACH_REMOTE == vg_task_port) { 5228 // GrP fixme self-resume 5229 vg_assert(0); 5230 } else { 5231 // resume other - no problem 5232 } 5233 5234 AFTER = POST_FN(task_resume); 5235 } 5236 5237 POST(task_resume) 5238 { 5239 } 5240 5241 5242 PRE(vm_allocate) 5243 { 5244 #pragma pack(4) 5245 typedef struct { 5246 mach_msg_header_t Head; 5247 NDR_record_t NDR; 5248 vm_address_t address; 5249 vm_size_t size; 5250 int flags; 5251 } Request; 5252 #pragma pack() 5253 5254 Request *req = (Request *)ARG1; 5255 5256 PRINT("vm_allocate (%s, at %#llx, size %lld, flags %#x)", 5257 name_for_port(MACH_REMOTE), 5258 (ULong)req->address, (ULong)req->size, req->flags); 5259 5260 MACH_ARG(vm_allocate.size) = req->size; 5261 MACH_ARG(vm_allocate.flags) = req->flags; 5262 5263 AFTER = POST_FN(vm_allocate); 5264 } 5265 5266 POST(vm_allocate) 5267 { 5268 #pragma pack(4) 5269 typedef struct { 5270 mach_msg_header_t Head; 5271 NDR_record_t NDR; 5272 kern_return_t RetCode; 5273 vm_address_t address; 5274 mach_msg_trailer_t trailer; 5275 } Reply; 5276 #pragma pack() 5277 5278 Reply *reply = (Reply *)ARG1; 5279 5280 if (!reply->RetCode) { 5281 if (MACH_REMOTE == vg_task_port) { 5282 PRINT("allocated at %#llx", (ULong)reply->address); 5283 // requesting 0 bytes returns address 0 with no error 5284 if (MACH_ARG(vm_allocate.size)) { 5285 ML_(notify_core_and_tool_of_mmap)( 5286 reply->address, MACH_ARG(vm_allocate.size), 5287 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_ANON, -1, 0); 5288 } 5289 } else { 5290 PRINT("allocated at %#llx in remote task %s", 5291 (ULong)reply->address, 5292 name_for_port(MACH_REMOTE)); 5293 } 5294 } else { 5295 PRINT("mig return %d", reply->RetCode); 5296 } 5297 } 5298 5299 5300 PRE(vm_deallocate) 5301 { 5302 #pragma pack(4) 5303 typedef struct { 5304 mach_msg_header_t Head; 5305 NDR_record_t NDR; 5306 vm_address_t address; 5307 vm_size_t size; 5308 } Request; 5309 #pragma pack() 5310 5311 Request *req = (Request *)ARG1; 5312 5313 PRINT("vm_deallocate(%s, at %#llx, size %lld)", 5314 name_for_port(MACH_REMOTE), 5315 (ULong)req->address, (ULong)req->size); 5316 5317 MACH_ARG(vm_deallocate.address) = req->address; 5318 MACH_ARG(vm_deallocate.size) = req->size; 5319 5320 AFTER = POST_FN(vm_deallocate); 5321 5322 // Must block to prevent race (other thread allocates and 5323 // notifies after we deallocate but before we notify) 5324 *flags &= ~SfMayBlock; 5325 } 5326 5327 POST(vm_deallocate) 5328 { 5329 #pragma pack(4) 5330 typedef struct { 5331 mach_msg_header_t Head; 5332 NDR_record_t NDR; 5333 kern_return_t RetCode; 5334 mach_msg_trailer_t trailer; 5335 } Reply; 5336 #pragma pack() 5337 5338 Reply *reply = (Reply *)ARG1; 5339 5340 if (!reply->RetCode) { 5341 if (MACH_REMOTE == vg_task_port) { 5342 if (MACH_ARG(vm_deallocate.size)) { 5343 Addr start = VG_PGROUNDDN(MACH_ARG(vm_deallocate.address)); 5344 Addr end = VG_PGROUNDUP(MACH_ARG(vm_deallocate.address) + 5345 MACH_ARG(vm_deallocate.size)); 5346 // Must have cleared SfMayBlock in PRE to prevent race 5347 ML_(notify_core_and_tool_of_munmap)(start, end - start); 5348 } 5349 } 5350 } else { 5351 PRINT("mig return %d", reply->RetCode); 5352 } 5353 } 5354 5355 5356 PRE(vm_protect) 5357 { 5358 #pragma pack(4) 5359 typedef struct { 5360 mach_msg_header_t Head; 5361 NDR_record_t NDR; 5362 vm_address_t address; 5363 vm_size_t size; 5364 boolean_t set_maximum; 5365 vm_prot_t new_protection; 5366 } Request; 5367 #pragma pack() 5368 5369 Request *req = (Request *)ARG1; 5370 5371 PRINT("vm_protect(%s, at %#llx, size %lld, set_max %d, prot %d)", 5372 name_for_port(MACH_REMOTE), 5373 (ULong)req->address, (ULong)req->size, 5374 req->set_maximum, req->new_protection); 5375 5376 MACH_ARG(vm_protect.address) = req->address; 5377 MACH_ARG(vm_protect.size) = req->size; 5378 MACH_ARG(vm_protect.set_maximum) = req->set_maximum; 5379 MACH_ARG(vm_protect.new_protection) = req->new_protection; 5380 5381 AFTER = POST_FN(vm_protect); 5382 } 5383 5384 POST(vm_protect) 5385 { 5386 #pragma pack(4) 5387 typedef struct { 5388 mach_msg_header_t Head; 5389 NDR_record_t NDR; 5390 kern_return_t RetCode; 5391 mach_msg_trailer_t trailer; 5392 } Reply; 5393 #pragma pack() 5394 5395 Reply *reply = (Reply *)ARG1; 5396 5397 if (!reply->RetCode) { 5398 if (MACH_REMOTE == vg_task_port) { 5399 Addr start = VG_PGROUNDDN(MACH_ARG(vm_protect.address)); 5400 Addr end = VG_PGROUNDUP(MACH_ARG(vm_protect.address) + 5401 MACH_ARG(vm_protect.size)); 5402 UInt prot = MACH_ARG(vm_protect.new_protection); 5403 if (MACH_ARG(vm_protect.set_maximum)) { 5404 // GrP fixme mprotect max 5405 VG_(printf)("UNKNOWN vm_protect set maximum"); 5406 //VG_(mprotect_max_range)(start, end-start, prot); 5407 } else { 5408 ML_(notify_core_and_tool_of_mprotect)(start, end-start, prot); 5409 VG_(di_notify_vm_protect)(start, end-start, prot); 5410 } 5411 } 5412 } else { 5413 PRINT("mig return %d", reply->RetCode); 5414 } 5415 } 5416 5417 5418 PRE(vm_inherit) 5419 { 5420 #pragma pack(4) 5421 typedef struct { 5422 mach_msg_header_t Head; 5423 NDR_record_t NDR; 5424 vm_address_t address; 5425 vm_size_t size; 5426 vm_inherit_t new_inheritance; 5427 } Request; 5428 #pragma pack() 5429 5430 Request *req = (Request *)ARG1; 5431 5432 PRINT("vm_inherit(%s, at %#llx, size %lld, value %d)", 5433 name_for_port(MACH_REMOTE), 5434 (ULong)req->address, (ULong)req->size, 5435 req->new_inheritance); 5436 5437 AFTER = POST_FN(vm_inherit); 5438 } 5439 5440 POST(vm_inherit) 5441 { 5442 #pragma pack(4) 5443 typedef struct { 5444 mach_msg_header_t Head; 5445 NDR_record_t NDR; 5446 kern_return_t RetCode; 5447 mach_msg_trailer_t trailer; 5448 } Reply; 5449 #pragma pack() 5450 5451 Reply *reply = (Reply *)ARG1; 5452 5453 if (!reply->RetCode) { 5454 if (MACH_REMOTE == vg_task_port) { 5455 // GrP fixme do something? 5456 } 5457 } else { 5458 PRINT("mig return %d", reply->RetCode); 5459 } 5460 } 5461 5462 5463 PRE(vm_read) 5464 { 5465 #pragma pack(4) 5466 typedef struct { 5467 mach_msg_header_t Head; 5468 NDR_record_t NDR; 5469 vm_address_t address; 5470 vm_size_t size; 5471 } Request; 5472 #pragma pack() 5473 5474 Request *req = (Request *)ARG1; 5475 5476 PRINT("vm_read(from %s at %#llx size %llu)", 5477 name_for_port(MACH_REMOTE), 5478 (ULong)req->address, (ULong)req->size); 5479 5480 MACH_ARG(vm_read.addr) = req->address; 5481 MACH_ARG(vm_read.size) = req->size; 5482 5483 AFTER = POST_FN(vm_read); 5484 } 5485 5486 POST(vm_read) 5487 { 5488 #pragma pack(4) 5489 typedef struct { 5490 mach_msg_header_t Head; 5491 /* start of the kernel processed data */ 5492 mach_msg_body_t msgh_body; 5493 mach_msg_ool_descriptor_t data; 5494 /* end of the kernel processed data */ 5495 NDR_record_t NDR; 5496 mach_msg_type_number_t dataCnt; 5497 } Reply; 5498 #pragma pack() 5499 5500 // Reply *reply = (Reply *)ARG1; 5501 5502 if (MACH_REMOTE == vg_task_port) { 5503 // vm_read from self 5504 // GrP fixme copy initialized state 5505 } 5506 } 5507 5508 5509 5510 PRE(mach_vm_read) 5511 { 5512 #pragma pack(4) 5513 typedef struct { 5514 mach_msg_header_t Head; 5515 NDR_record_t NDR; 5516 mach_vm_address_t address; 5517 mach_vm_size_t size; 5518 } Request; 5519 #pragma pack() 5520 5521 Request *req = (Request *)ARG1; 5522 5523 PRINT("mach_vm_read(from %s at 0x%llx size %llu)", 5524 name_for_port(MACH_REMOTE), req->address, req->size); 5525 5526 MACH_ARG(mach_vm_read.addr) = req->address; 5527 MACH_ARG(mach_vm_read.size) = req->size; 5528 5529 AFTER = POST_FN(mach_vm_read); 5530 } 5531 5532 POST(mach_vm_read) 5533 { 5534 #pragma pack(4) 5535 typedef struct { 5536 mach_msg_header_t Head; 5537 /* start of the kernel processed data */ 5538 mach_msg_body_t msgh_body; 5539 mach_msg_ool_descriptor_t data; 5540 /* end of the kernel processed data */ 5541 NDR_record_t NDR; 5542 mach_msg_type_number_t dataCnt; 5543 } Reply; 5544 #pragma pack() 5545 5546 // Reply *reply = (Reply *)ARG1; 5547 5548 if (MACH_REMOTE == vg_task_port) { 5549 // vm_read from self 5550 // GrP fixme copy initialized state 5551 } 5552 } 5553 5554 5555 PRE(vm_read_overwrite) 5556 { 5557 #pragma pack(4) 5558 typedef struct { 5559 mach_msg_header_t Head; 5560 NDR_record_t NDR; 5561 vm_address_t address; 5562 vm_size_t size; 5563 vm_address_t data; 5564 } Request; 5565 #pragma pack() 5566 5567 Request *req = (Request *)ARG1; 5568 5569 PRINT("vm_read_overwrite(from %s at %#llx size %llu to %#llx)", 5570 name_for_port(MACH_REMOTE), 5571 (ULong)req->address, (ULong)req->size, (ULong)req->data); 5572 5573 MACH_ARG(vm_read_overwrite.addr) = req->address; 5574 MACH_ARG(vm_read_overwrite.size) = req->size; 5575 MACH_ARG(vm_read_overwrite.data) = req->data; 5576 5577 PRE_MEM_WRITE("vm_read_overwrite(data)", req->data, req->size); 5578 5579 AFTER = POST_FN(vm_read_overwrite); 5580 } 5581 5582 POST(vm_read_overwrite) 5583 { 5584 #pragma pack(4) 5585 typedef struct { 5586 mach_msg_header_t Head; 5587 NDR_record_t NDR; 5588 kern_return_t RetCode; 5589 vm_size_t outsize; 5590 } Reply; 5591 #pragma pack() 5592 5593 Reply *reply = (Reply *)ARG1; 5594 5595 if (reply->RetCode) { 5596 PRINT("mig return %d", reply->RetCode); 5597 } else { 5598 PRINT("read %llu bytes", (unsigned long long)reply->outsize); 5599 if (MACH_REMOTE == vg_task_port) { 5600 // vm_read_overwrite from self 5601 // GrP fixme copy initialized state 5602 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize); 5603 } else { 5604 // vm_read_overwrite from remote 5605 POST_MEM_WRITE(MACH_ARG(vm_read_overwrite.data), reply->outsize); 5606 } 5607 } 5608 } 5609 5610 5611 PRE(vm_copy) 5612 { 5613 #pragma pack(4) 5614 typedef struct { 5615 mach_msg_header_t Head; 5616 NDR_record_t NDR; 5617 vm_address_t source_address; 5618 vm_size_t size; 5619 vm_address_t dest_address; 5620 } Request; 5621 #pragma pack() 5622 5623 Request *req = (Request *)ARG1; 5624 5625 PRINT("vm_copy(%s, %#llx, %lld, %#llx)", 5626 name_for_port(MACH_REMOTE), 5627 (ULong)req->source_address, 5628 (ULong)req->size, (ULong)req->dest_address); 5629 5630 MACH_ARG(vm_copy.src) = req->source_address; 5631 MACH_ARG(vm_copy.dst) = req->dest_address; 5632 MACH_ARG(vm_copy.size) = req->size; 5633 5634 AFTER = POST_FN(vm_copy); 5635 } 5636 5637 POST(vm_copy) 5638 { 5639 #pragma pack(4) 5640 typedef struct { 5641 mach_msg_header_t Head; 5642 NDR_record_t NDR; 5643 kern_return_t RetCode; 5644 mach_msg_trailer_t trailer; 5645 } Reply; 5646 #pragma pack() 5647 5648 Reply *reply = (Reply *)ARG1; 5649 5650 if (!reply->RetCode) { 5651 if (MACH_REMOTE == vg_task_port) { 5652 // GrP fixme set dst's initialization equal to src's 5653 // and wipe any symbols or translations in dst 5654 } 5655 } else { 5656 PRINT("mig return %d", reply->RetCode); 5657 } 5658 } 5659 5660 5661 PRE(vm_map) 5662 { 5663 #pragma pack(4) 5664 typedef struct { 5665 mach_msg_header_t Head; 5666 /* start of the kernel processed data */ 5667 mach_msg_body_t msgh_body; 5668 mach_msg_port_descriptor_t object; 5669 /* end of the kernel processed data */ 5670 NDR_record_t NDR; 5671 vm_address_t address; 5672 vm_size_t size; 5673 vm_address_t mask; 5674 int flags; 5675 vm_offset_t offset; 5676 boolean_t copy; 5677 vm_prot_t cur_protection; 5678 vm_prot_t max_protection; 5679 vm_inherit_t inheritance; 5680 } Request; 5681 #pragma pack() 5682 5683 Request *req = (Request *)ARG1; 5684 5685 // GrP fixme check these 5686 PRINT("vm_map(in %s, at %#llx, size %lld, from %s ...)", 5687 name_for_port(MACH_REMOTE), 5688 (ULong)req->address, (ULong)req->size, 5689 name_for_port(req->object.name)); 5690 5691 MACH_ARG(vm_map.size) = req->size; 5692 MACH_ARG(vm_map.copy) = req->copy; 5693 MACH_ARG(vm_map.protection) = (req->cur_protection & req->max_protection); 5694 5695 AFTER = POST_FN(vm_map); 5696 } 5697 5698 POST(vm_map) 5699 { 5700 #pragma pack(4) 5701 typedef struct { 5702 mach_msg_header_t Head; 5703 NDR_record_t NDR; 5704 kern_return_t RetCode; 5705 vm_address_t address; 5706 mach_msg_trailer_t trailer; 5707 } Reply; 5708 #pragma pack() 5709 5710 Reply *reply = (Reply *)ARG1; 5711 5712 if (!reply->RetCode) { 5713 // GrP fixme check src and dest tasks 5714 PRINT("mapped at %#llx", (ULong)reply->address); 5715 // GrP fixme max prot 5716 ML_(notify_core_and_tool_of_mmap)( 5717 reply->address, VG_PGROUNDUP(MACH_ARG(vm_map.size)), 5718 MACH_ARG(vm_map.protection), VKI_MAP_SHARED, -1, 0); 5719 // GrP fixme VKI_MAP_PRIVATE if !copy? 5720 } else { 5721 PRINT("mig return %d", reply->RetCode); 5722 } 5723 } 5724 5725 5726 PRE(vm_remap) 5727 { 5728 #pragma pack(4) 5729 typedef struct { 5730 mach_msg_header_t Head; 5731 /* start of the kernel processed data */ 5732 mach_msg_body_t msgh_body; 5733 mach_msg_port_descriptor_t src_task; 5734 /* end of the kernel processed data */ 5735 NDR_record_t NDR; 5736 vm_address_t target_address; 5737 vm_size_t size; 5738 vm_address_t mask; 5739 boolean_t anywhere; 5740 vm_address_t src_address; 5741 boolean_t copy; 5742 vm_inherit_t inheritance; 5743 } Request; 5744 #pragma pack() 5745 5746 Request *req = (Request *)ARG1; 5747 5748 // GrP fixme check src and dest tasks 5749 5750 if (VG_(clo_trace_syscalls)) { 5751 mach_port_name_t source_task = req->src_task.name; 5752 if (source_task == mach_task_self()) { 5753 PRINT("vm_remap(mach_task_self(), " 5754 "to %#llx size %lld, from mach_task_self() at %#llx, ...)", 5755 (ULong)req->target_address, 5756 (ULong)req->size, (ULong)req->src_address); 5757 } else { 5758 PRINT("vm_remap(mach_task_self(), " 5759 "to %#llx size %lld, from task %u at %#llx, ...)", 5760 (ULong)req->target_address, (ULong)req->size, 5761 source_task, (ULong)req->src_address); 5762 } 5763 } 5764 5765 // arg1 is task 5766 // vt->syscall_arg2 = req->target_address; 5767 MACH_ARG(vm_remap.size) = req->size; 5768 // vt->syscall_arg4 = req->copy; 5769 5770 AFTER = POST_FN(vm_remap); 5771 } 5772 5773 POST(vm_remap) 5774 { 5775 #pragma pack(4) 5776 typedef struct { 5777 mach_msg_header_t Head; 5778 NDR_record_t NDR; 5779 kern_return_t RetCode; 5780 vm_address_t target_address; 5781 vm_prot_t cur_protection; 5782 vm_prot_t max_protection; 5783 mach_msg_trailer_t trailer; 5784 } Reply; 5785 #pragma pack() 5786 5787 Reply *reply = (Reply *)ARG1; 5788 5789 if (!reply->RetCode) { 5790 // GrP fixme check src and dest tasks 5791 UInt prot = reply->cur_protection & reply->max_protection; 5792 // GrP fixme max prot 5793 PRINT("mapped at %#llx", (ULong)reply->target_address); 5794 ML_(notify_core_and_tool_of_mmap)( 5795 reply->target_address, VG_PGROUNDUP(MACH_ARG(vm_remap.size)), 5796 prot, VKI_MAP_SHARED, -1, 0); 5797 // GrP fixme VKI_MAP_FIXED if !copy? 5798 // GrP fixme copy initialized bits from source to dest if source_task is also mach_task_self 5799 } else { 5800 PRINT("mig return %d", reply->RetCode); 5801 } 5802 } 5803 5804 5805 PRE(mach_make_memory_entry_64) 5806 { 5807 #pragma pack(4) 5808 typedef struct { 5809 mach_msg_header_t Head; 5810 /* start of the kernel processed data */ 5811 mach_msg_body_t msgh_body; 5812 mach_msg_port_descriptor_t parent_entry; 5813 /* end of the kernel processed data */ 5814 NDR_record_t NDR; 5815 memory_object_size_t size; 5816 memory_object_offset_t offset; 5817 vm_prot_t permission; 5818 } Request; 5819 #pragma pack() 5820 5821 Request *req = (Request *)ARG1; 5822 5823 PRINT("mach_make_memory_entry_64(%s, %llu, %llu, %d, ..., %u)", 5824 name_for_port(MACH_REMOTE), 5825 req->size, req->offset, req->permission, req->parent_entry.type); 5826 5827 AFTER = POST_FN(mach_make_memory_entry_64); 5828 } 5829 5830 POST(mach_make_memory_entry_64) 5831 { 5832 #pragma pack(4) 5833 typedef struct { 5834 mach_msg_header_t Head; 5835 mach_msg_body_t msgh_body; 5836 mach_msg_port_descriptor_t object; 5837 NDR_record_t NDR; 5838 memory_object_size_t size; 5839 } Reply; 5840 #pragma pack() 5841 5842 Reply *reply = (Reply *)ARG1; 5843 5844 if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { 5845 assign_port_name(reply->object.name, "memory-%p"); 5846 PRINT("%s", name_for_port(reply->object.name)); 5847 } 5848 } 5849 5850 5851 PRE(vm_purgable_control) 5852 { 5853 #pragma pack(4) 5854 typedef struct { 5855 mach_msg_header_t Head; 5856 NDR_record_t NDR; 5857 vm_address_t address; 5858 vm_purgable_t control; 5859 int state; 5860 } Request; 5861 #pragma pack() 5862 5863 Request *req = (Request *)ARG1; 5864 5865 PRINT("vm_purgable_control(%s, %#llx, %d, %d)", 5866 name_for_port(MACH_REMOTE), 5867 (ULong)req->address, req->control, req->state); 5868 5869 // GrP fixme verify address? 5870 5871 AFTER = POST_FN(vm_purgable_control); 5872 } 5873 5874 POST(vm_purgable_control) 5875 { 5876 #pragma pack(4) 5877 typedef struct { 5878 mach_msg_header_t Head; 5879 NDR_record_t NDR; 5880 kern_return_t RetCode; 5881 int state; 5882 } Reply; 5883 #pragma pack() 5884 5885 Reply *reply = (Reply *)ARG1; 5886 5887 if (!reply->RetCode) { 5888 } else { 5889 PRINT("mig return %d", reply->RetCode); 5890 } 5891 } 5892 5893 5894 PRE(mach_vm_purgable_control) 5895 { 5896 #pragma pack(4) 5897 typedef struct { 5898 mach_msg_header_t Head; 5899 NDR_record_t NDR; 5900 mach_vm_address_t address; 5901 vm_purgable_t control; 5902 int state; 5903 } Request; 5904 #pragma pack() 5905 5906 Request *req = (Request *)ARG1; 5907 5908 PRINT("mach_vm_purgable_control(%s, 0x%llx, %d, %d)", 5909 name_for_port(MACH_REMOTE), 5910 (unsigned l