1 2/*--------------------------------------------------------------------*/ 3/*--- Darwin-specific syscalls, etc. syswrap-x86-darwin.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2005-2011 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(VGP_x86_darwin) 32 33#include "pub_core_basics.h" 34#include "pub_core_vki.h" 35#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 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_mallocfree.h" 50#include "pub_core_options.h" 51#include "pub_core_scheduler.h" 52#include "pub_core_signals.h" 53#include "pub_core_syscall.h" 54#include "pub_core_syswrap.h" 55#include "pub_core_tooliface.h" 56 57#include "priv_types_n_macros.h" 58#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ 59#include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */ 60#include "priv_syswrap-main.h" 61 62 63#include <mach/mach.h> 64 65static void x86_thread_state32_from_vex(i386_thread_state_t *mach, 66 VexGuestX86State *vex) 67{ 68 mach->__eax = vex->guest_EAX; 69 mach->__ebx = vex->guest_EBX; 70 mach->__ecx = vex->guest_ECX; 71 mach->__edx = vex->guest_EDX; 72 mach->__edi = vex->guest_EDI; 73 mach->__esi = vex->guest_ESI; 74 mach->__ebp = vex->guest_EBP; 75 mach->__esp = vex->guest_ESP; 76 mach->__ss = vex->guest_SS; 77 mach->__eflags = LibVEX_GuestX86_get_eflags(vex); 78 mach->__eip = vex->guest_EIP; 79 mach->__cs = vex->guest_CS; 80 mach->__ds = vex->guest_DS; 81 mach->__es = vex->guest_ES; 82 mach->__fs = vex->guest_FS; 83 mach->__gs = vex->guest_GS; 84} 85 86 87static void x86_float_state32_from_vex(i386_float_state_t *mach, 88 VexGuestX86State *vex) 89{ 90 // DDD: #warning GrP fixme fp state 91 92 VG_(memcpy)(&mach->__fpu_xmm0, &vex->guest_XMM0, 8 * sizeof(mach->__fpu_xmm0)); 93} 94 95 96void thread_state_from_vex(thread_state_t mach_generic, 97 thread_state_flavor_t flavor, 98 mach_msg_type_number_t count, 99 VexGuestArchState *vex_generic) 100{ 101 VexGuestX86State *vex = (VexGuestX86State *)vex_generic; 102 103 switch (flavor) { 104 case i386_THREAD_STATE: 105 vg_assert(count == i386_THREAD_STATE_COUNT); 106 x86_thread_state32_from_vex((i386_thread_state_t *)mach_generic, vex); 107 break; 108 109 case i386_FLOAT_STATE: 110 vg_assert(count == i386_FLOAT_STATE_COUNT); 111 x86_float_state32_from_vex((i386_float_state_t *)mach_generic, vex); 112 break; 113 114 default: 115 vg_assert(0); 116 } 117} 118 119 120static void x86_thread_state32_to_vex(const i386_thread_state_t *mach, 121 VexGuestX86State *vex) 122{ 123 LibVEX_GuestX86_initialise(vex); 124 vex->guest_EAX = mach->__eax; 125 vex->guest_EBX = mach->__ebx; 126 vex->guest_ECX = mach->__ecx; 127 vex->guest_EDX = mach->__edx; 128 vex->guest_EDI = mach->__edi; 129 vex->guest_ESI = mach->__esi; 130 vex->guest_EBP = mach->__ebp; 131 vex->guest_ESP = mach->__esp; 132 vex->guest_SS = mach->__ss; 133 // DDD: #warning GrP fixme eflags 134 vex->guest_EIP = mach->__eip; 135 vex->guest_CS = mach->__cs; 136 vex->guest_DS = mach->__ds; 137 vex->guest_ES = mach->__es; 138 vex->guest_FS = mach->__fs; 139 vex->guest_GS = mach->__gs; 140} 141 142static void x86_float_state32_to_vex(const i386_float_state_t *mach, 143 VexGuestX86State *vex) 144{ 145 // DDD: #warning GrP fixme fp state 146 147 VG_(memcpy)(&vex->guest_XMM0, &mach->__fpu_xmm0, 8 * sizeof(mach->__fpu_xmm0)); 148} 149 150 151void thread_state_to_vex(const thread_state_t mach_generic, 152 thread_state_flavor_t flavor, 153 mach_msg_type_number_t count, 154 VexGuestArchState *vex_generic) 155{ 156 VexGuestX86State *vex = (VexGuestX86State *)vex_generic; 157 158 switch(flavor) { 159 case i386_THREAD_STATE: 160 vg_assert(count == i386_THREAD_STATE_COUNT); 161 x86_thread_state32_to_vex((const i386_thread_state_t*)mach_generic,vex); 162 break; 163 case i386_FLOAT_STATE: 164 vg_assert(count == i386_FLOAT_STATE_COUNT); 165 x86_float_state32_to_vex((const i386_float_state_t*)mach_generic,vex); 166 break; 167 168 default: 169 vg_assert(0); 170 break; 171 } 172} 173 174 175ThreadState *build_thread(const thread_state_t state, 176 thread_state_flavor_t flavor, 177 mach_msg_type_number_t count) 178{ 179 ThreadId tid = VG_(alloc_ThreadState)(); 180 ThreadState *tst = VG_(get_ThreadState)(tid); 181 182 vg_assert(flavor == i386_THREAD_STATE); 183 vg_assert(count == i386_THREAD_STATE_COUNT); 184 185 // Initialize machine registers 186 187 thread_state_to_vex(state, flavor, count, &tst->arch.vex); 188 189 I_die_here; 190 // GrP fixme signals, sig_mask, tmp_sig_mask, os_state.parent 191 192 find_stack_segment(tid, tst->arch.vex.guest_ESP); 193 194 return tst; 195} 196 197 198// Edit the thread state to send to the real kernel. 199// The real thread will run start_thread_NORETURN(tst) 200// on a separate non-client stack. 201void hijack_thread_state(thread_state_t mach_generic, 202 thread_state_flavor_t flavor, 203 mach_msg_type_number_t count, 204 ThreadState *tst) 205{ 206 i386_thread_state_t *mach = (i386_thread_state_t *)mach_generic; 207 char *stack; 208 209 vg_assert(flavor == i386_THREAD_STATE); 210 vg_assert(count == i386_THREAD_STATE_COUNT); 211 212 stack = (char *)allocstack(tst->tid); 213 stack -= 64+320; // make room for top frame 214 memset(stack, 0, 64+320); // ...and clear it 215 *(uintptr_t *)stack = (uintptr_t)tst; // set parameter 216 stack -= sizeof(uintptr_t); 217 *(uintptr_t *)stack = 0; // push fake return address 218 219 mach->__eip = (uintptr_t)&start_thread_NORETURN; 220 mach->__esp = (uintptr_t)stack; 221} 222 223 224/* Call f(arg1), but first switch stacks, using 'stack' as the new 225 stack, and use 'retaddr' as f's return-to address. Also, clear all 226 the integer registers before entering f.*/ 227__attribute__((noreturn)) 228void call_on_new_stack_0_1 ( Addr stack, 229 Addr retaddr, 230 void (*f)(Word), 231 Word arg1 ); 232// 4(%esp) == stack (must be 16-byte aligned) 233// 8(%esp) == retaddr 234// 12(%esp) == f 235// 16(%esp) == arg1 236asm( 237".globl _call_on_new_stack_0_1\n" 238"_call_on_new_stack_0_1:\n" 239" movl %esp, %esi\n" // remember old stack pointer 240" movl 4(%esi), %esp\n" // set new stack 241" pushl $0\n" // align stack 242" pushl $0\n" // align stack 243" pushl $0\n" // align stack 244" pushl 16(%esi)\n" // arg1 to stack 245" pushl 8(%esi)\n" // retaddr to stack 246" pushl 12(%esi)\n" // f to stack 247" movl $0, %eax\n" // zero all GP regs 248" movl $0, %ebx\n" 249" movl $0, %ecx\n" 250" movl $0, %edx\n" 251" movl $0, %esi\n" 252" movl $0, %edi\n" 253" movl $0, %ebp\n" 254" ret\n" // jump to f 255" ud2\n" // should never get here 256); 257 258 259asm( 260".globl _pthread_hijack_asm\n" 261"_pthread_hijack_asm:\n" 262" movl %esp,%ebp\n" 263" push $0\n" // alignment pad 264" push %ebp\n" // original sp 265" push %esi\n" // flags 266" push %edi\n" // stacksize 267" push %edx\n" // func_arg 268" push %ecx\n" // func 269" push %ebx\n" // kport 270" push %eax\n" // self 271" push $0\n" // fake return address 272" jmp _pthread_hijack\n" 273 ); 274 275 276 277void pthread_hijack(Addr self, Addr kport, Addr func, Addr func_arg, 278 Addr stacksize, Addr flags, Addr sp) 279{ 280 vki_sigset_t blockall; 281 ThreadState *tst = (ThreadState *)func_arg; 282 VexGuestX86State *vex = &tst->arch.vex; 283 284 // VG_(printf)("pthread_hijack pthread %p, machthread %p, func %p, arg %p, stack %p, flags %p, stack %p\n", self, kport, func, func_arg, stacksize, flags, sp); 285 286 // Wait for parent thread's permission. 287 // The parent thread holds V's lock on our behalf. 288 semaphore_wait(tst->os_state.child_go); 289 290 /* Start the thread with all signals blocked. VG_(scheduler) will 291 set the mask correctly when we finally get there. */ 292 VG_(sigfillset)(&blockall); 293 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, NULL); 294 295 // Set thread's registers 296 // Do this FIRST because some code below tries to collect a backtrace, 297 // which requires valid register data. 298 // DDD: need to do post_reg_write events here? 299 LibVEX_GuestX86_initialise(vex); 300 vex->guest_EIP = pthread_starter; 301 vex->guest_EAX = self; 302 vex->guest_EBX = kport; 303 vex->guest_ECX = func; 304 vex->guest_EDX = tst->os_state.func_arg; 305 vex->guest_EDI = stacksize; 306 vex->guest_ESI = flags; 307 vex->guest_ESP = sp; 308 309 // Record thread's stack and Mach port and pthread struct 310 tst->os_state.pthread = self; 311 tst->os_state.lwpid = kport; 312 record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "thread-%p"); 313 314 if ((flags & 0x01000000) == 0) { 315 // kernel allocated stack - needs mapping 316 Addr stack = VG_PGROUNDUP(sp) - stacksize; 317 tst->client_stack_highest_word = stack+stacksize; 318 tst->client_stack_szB = stacksize; 319 320 // pthread structure 321 ML_(notify_core_and_tool_of_mmap)( 322 stack+stacksize, pthread_structsize, 323 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 324 // stack contents 325 ML_(notify_core_and_tool_of_mmap)( 326 stack, stacksize, 327 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 328 // guard page 329 ML_(notify_core_and_tool_of_mmap)( 330 stack-VKI_PAGE_SIZE, VKI_PAGE_SIZE, 331 0, VKI_MAP_PRIVATE, -1, 0); 332 } else { 333 // client allocated stack 334 find_stack_segment(tst->tid, sp); 335 } 336 ML_(sync_mappings)("after", "pthread_hijack", 0); 337 338 // DDD: should this be here rather than in POST(sys_bsdthread_create)? 339 // But we don't have ptid here... 340 //VG_TRACK ( pre_thread_ll_create, ptid, tst->tid ); 341 342 // Tell parent thread's POST(sys_bsdthread_create) that we're done 343 // initializing registers and mapping memory. 344 semaphore_signal(tst->os_state.child_done); 345 // LOCK IS GONE BELOW THIS POINT 346 347 // Go! 348 call_on_new_stack_0_1(tst->os_state.valgrind_stack_init_SP, 0, 349 start_thread_NORETURN, (Word)tst); 350 351 /*NOTREACHED*/ 352 vg_assert(0); 353} 354 355 356 357asm( 358".globl _wqthread_hijack_asm\n" 359"_wqthread_hijack_asm:\n" 360" movl %esp,%ebp\n" 361" push $0\n" // alignment 362" push $0\n" // alignment 363" push %ebp\n" // original sp 364" push %edi\n" // reuse 365" push %edx\n" // workitem 366" push %ecx\n" // stackaddr 367" push %ebx\n" // kport 368" push %eax\n" // self 369" push $0\n" // fake return address 370" jmp _wqthread_hijack\n" 371 ); 372 373 374/* wqthread note: The kernel may create or destroy pthreads in the 375 wqthread pool at any time with no userspace interaction, 376 and wqthread_start may be entered at any time with no userspace 377 interaction. 378 To handle this in valgrind, we create and destroy a valgrind 379 thread for every work item. 380*/ 381void wqthread_hijack(Addr self, Addr kport, Addr stackaddr, Addr workitem, 382 Int reuse, Addr sp) 383{ 384 ThreadState *tst; 385 VexGuestX86State *vex; 386 Addr stack; 387 SizeT stacksize; 388 vki_sigset_t blockall; 389 390 /* When we enter here we hold no lock (!), so we better acquire it 391 pronto. Why do we hold no lock? Because (presumably) the only 392 way to get here is as a result of a SfMayBlock syscall 393 "workq_ops(WQOPS_THREAD_RETURN)", which will have dropped the 394 lock. At least that's clear for the 'reuse' case. The 395 non-reuse case? Dunno, perhaps it's a new thread the kernel 396 pulled out of a hat. In any case we still need to take a 397 lock. */ 398 VG_(acquire_BigLock_LL)("wqthread_hijack"); 399 400 /* Start the thread with all signals blocked. VG_(scheduler) will 401 set the mask correctly when we finally get there. */ 402 VG_(sigfillset)(&blockall); 403 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, NULL); 404 if (reuse) { 405 406 /* For whatever reason, tst->os_state.pthread appear to have a 407 constant offset of 72 on 10.7, but zero on 10.6 and 10.5. No 408 idea why. */ 409# if DARWIN_VERS <= DARWIN_10_6 410 UWord magic_delta = 0; 411# elif DARWIN_VERS == DARWIN_10_7 412 UWord magic_delta = 0x48; 413# endif 414 415 // This thread already exists; we're merely re-entering 416 // after leaving via workq_ops(WQOPS_THREAD_RETURN). 417 // Don't allocate any V thread resources. 418 // Do reset thread registers. 419 ThreadId tid = VG_(lwpid_to_vgtid)(kport); 420 vg_assert(VG_(is_valid_tid)(tid)); 421 vg_assert(mach_thread_self() == kport); 422 423 tst = VG_(get_ThreadState)(tid); 424 425 if (0) VG_(printf)("wqthread_hijack reuse %s: tid %d, tst %p, " 426 "tst->os_state.pthread %#lx, self %#lx\n", 427 tst->os_state.pthread == self ? "SAME" : "DIFF", 428 tid, tst, tst->os_state.pthread, self); 429 430 vex = &tst->arch.vex; 431 vg_assert(tst->os_state.pthread - magic_delta == self); 432 } 433 else { 434 // This is a new thread. 435 tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)()); 436 vex = &tst->arch.vex; 437 allocstack(tst->tid); 438 LibVEX_GuestX86_initialise(vex); 439 /* Tell threading tools the new thread exists. FIXME: we need 440 to know the identity (tid) of the parent thread, in order 441 that threading tools can make a dependency edge from it to 442 this thread. But we don't know what the parent thread is. 443 Hence pass 1 (the root thread). This is completely wrong in 444 general, and could cause large numbers of false races to be 445 reported. In fact, it's positively dangerous; we don't even 446 know if thread 1 is still alive, and the thread checkers are 447 likely to assert if it isn't. */ 448 VG_TRACK(pre_thread_ll_create, 1/*BOGUS*/, tst->tid); 449 } 450 451 // Set thread's registers 452 // Do this FIRST because some code below tries to collect a backtrace, 453 // which requires valid register data. 454 vex->guest_EIP = wqthread_starter; 455 vex->guest_EAX = self; 456 vex->guest_EBX = kport; 457 vex->guest_ECX = stackaddr; 458 vex->guest_EDX = workitem; 459 vex->guest_EDI = reuse; 460 vex->guest_ESI = 0; 461 vex->guest_ESP = sp; 462 463 stacksize = 512*1024; // wq stacks are always DEFAULT_STACK_SIZE 464 stack = VG_PGROUNDUP(sp) - stacksize; 465 466 VG_TRACK(workq_task_start, tst->tid, workitem); 467 if (reuse) { 468 // Continue V's thread back in the scheduler. 469 // The client thread is of course in another location entirely. 470 471 /* Drop the lock before going into 472 ML_(wqthread_continue_NORETURN). The latter will immediately 473 attempt to reacquire it in non-LL mode, which is a bit 474 wasteful but I don't think is harmful. A better solution 475 would be to not drop the lock but instead "upgrade" it from a 476 LL lock to a full lock, but that's too much like hard work 477 right now. */ 478 VG_(release_BigLock_LL)("wqthread_hijack(1)"); 479 ML_(wqthread_continue_NORETURN)(tst->tid); 480 } 481 else { 482 // Record thread's stack and Mach port and pthread struct 483 tst->os_state.pthread = self; 484 tst->os_state.lwpid = kport; 485 record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "wqthread-%p"); 486 487 // kernel allocated stack - needs mapping 488 tst->client_stack_highest_word = stack+stacksize; 489 tst->client_stack_szB = stacksize; 490 491 // tell the tool that we are at a point after the new thread 492 // has its registers set up (so we can take a stack snapshot), 493 // but before it has executed any instructions (or, really, 494 // before it has done any memory references). 495 VG_TRACK(pre_thread_first_insn, tst->tid); 496 497 // pthread structure 498 ML_(notify_core_and_tool_of_mmap)( 499 stack+stacksize, pthread_structsize, 500 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 501 // stack contents 502 // GrP fixme uninitialized! 503 ML_(notify_core_and_tool_of_mmap)( 504 stack, stacksize, 505 VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 506 // guard page 507 // GrP fixme ban_mem_stack! 508 ML_(notify_core_and_tool_of_mmap)( 509 stack-VKI_PAGE_SIZE, VKI_PAGE_SIZE, 510 0, VKI_MAP_PRIVATE, -1, 0); 511 512 ML_(sync_mappings)("after", "wqthread_hijack", 0); 513 514 // Go! 515 /* Same comments as the 'release' in the then-clause. 516 start_thread_NORETURN calls run_thread_NORETURN calls 517 thread_wrapper which acquires the lock before continuing. 518 Let's hope nothing non-thread-local happens until that point. 519 520 DDD: I think this is plain wrong .. if we get to 521 thread_wrapper not holding the lock, and someone has recycled 522 this thread slot in the meantime, we're hosed. Is that 523 possible, though? */ 524 VG_(release_BigLock_LL)("wqthread_hijack(2)"); 525 call_on_new_stack_0_1(tst->os_state.valgrind_stack_init_SP, 0, 526 start_thread_NORETURN, (Word)tst); 527 } 528 529 /*NOTREACHED*/ 530 vg_assert(0); 531} 532 533#endif // defined(VGP_x86_darwin) 534 535/*--------------------------------------------------------------------*/ 536/*--- end ---*/ 537/*--------------------------------------------------------------------*/ 538