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