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