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