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