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