1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Darwin-specific syscalls, etc. syswrap-amd64-darwin.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Copyright (C) 2005-2013 Apple Inc. 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Greg Parker gparker@apple.com 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_amd64_darwin) 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "config.h" // DARWIN_VERS 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 36b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuginfo.h" // VG_(di_notify_*) 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab.h" // VG_(discard_translations) 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcfile.h" 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h" 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h" 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)() 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h" 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h" 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h" 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_types_n_macros.h" 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-generic.h" /* for decls of generic wrappers */ 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-main.h" 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <mach/mach.h> 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void x86_thread_state64_from_vex(x86_thread_state64_t *mach, 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex) 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rax = vex->guest_RAX; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rbx = vex->guest_RBX; 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rcx = vex->guest_RCX; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rdx = vex->guest_RDX; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rdi = vex->guest_RDI; 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rsi = vex->guest_RSI; 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rbp = vex->guest_RBP; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rsp = vex->guest_RSP; 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rflags = LibVEX_GuestAMD64_get_rflags(vex); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rip = vex->guest_RIP; 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r8 = vex->guest_R8; 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r9 = vex->guest_R9; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r10 = vex->guest_R10; 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r11 = vex->guest_R11; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r12 = vex->guest_R12; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r13 = vex->guest_R13; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r14 = vex->guest_R14; 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__r15 = vex->guest_R15; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* GrP fixme 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__cs = vex->guest_CS; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__fs = vex->guest_FS; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__gs = vex->guest_GS; 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void x86_float_state64_from_vex(x86_float_state64_t *mach, 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex) 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning GrP fixme fp state 100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // JRS: what about the YMMHI bits? Are they important? 101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm0, &vex->guest_YMM0, sizeof(mach->__fpu_xmm0)); 102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm1, &vex->guest_YMM1, sizeof(mach->__fpu_xmm1)); 103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm2, &vex->guest_YMM2, sizeof(mach->__fpu_xmm2)); 104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm3, &vex->guest_YMM3, sizeof(mach->__fpu_xmm3)); 105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm4, &vex->guest_YMM4, sizeof(mach->__fpu_xmm4)); 106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm5, &vex->guest_YMM5, sizeof(mach->__fpu_xmm5)); 107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm6, &vex->guest_YMM6, sizeof(mach->__fpu_xmm6)); 108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm7, &vex->guest_YMM7, sizeof(mach->__fpu_xmm7)); 109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm8, &vex->guest_YMM8, sizeof(mach->__fpu_xmm8)); 110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm9, &vex->guest_YMM9, sizeof(mach->__fpu_xmm9)); 111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm10, &vex->guest_YMM10, sizeof(mach->__fpu_xmm10)); 112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm11, &vex->guest_YMM11, sizeof(mach->__fpu_xmm11)); 113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm12, &vex->guest_YMM12, sizeof(mach->__fpu_xmm12)); 114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm13, &vex->guest_YMM13, sizeof(mach->__fpu_xmm13)); 115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm14, &vex->guest_YMM14, sizeof(mach->__fpu_xmm14)); 116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&mach->__fpu_xmm15, &vex->guest_YMM15, sizeof(mach->__fpu_xmm15)); 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_state_from_vex(thread_state_t mach_generic, 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_state_flavor_t flavor, 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach_msg_type_number_t count, 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestArchState *vex_generic) 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex = (VexGuestAMD64State *)vex_generic; 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch (flavor) { 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case x86_THREAD_STATE64: 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_THREAD_STATE64_COUNT); 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86_thread_state64_from_vex((x86_thread_state64_t *)mach_generic, vex); 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case x86_FLOAT_STATE64: 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_FLOAT_STATE64_COUNT); 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86_float_state64_from_vex((x86_float_state64_t *)mach_generic, vex); 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void x86_thread_state64_to_vex(const x86_thread_state64_t *mach, 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex) 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestAMD64_initialise(vex); 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RAX = mach->__rax; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RBX = mach->__rbx; 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RCX = mach->__rcx; 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDX = mach->__rdx; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDI = mach->__rdi; 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSI = mach->__rsi; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RBP = mach->__rbp; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSP = mach->__rsp; 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning GrP fixme eflags 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RIP = mach->__rip; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R8 = mach->__r8; 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R9 = mach->__r9; 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R10 = mach->__r10; 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R11 = mach->__r11; 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R12 = mach->__r12; 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R13 = mach->__r13; 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R14 = mach->__r14; 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R15 = mach->__r15; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* GrP fixme 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_CS = mach->__cs; 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_FS = mach->__fs; 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_GS = mach->__gs; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void x86_float_state64_to_vex(const x86_float_state64_t *mach, 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex) 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: #warning GrP fixme fp state 177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng // JRS: what about the YMMHI bits? Are they important? 178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM0, &mach->__fpu_xmm0, sizeof(mach->__fpu_xmm0)); 179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM1, &mach->__fpu_xmm1, sizeof(mach->__fpu_xmm1)); 180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM2, &mach->__fpu_xmm2, sizeof(mach->__fpu_xmm2)); 181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM3, &mach->__fpu_xmm3, sizeof(mach->__fpu_xmm3)); 182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM4, &mach->__fpu_xmm4, sizeof(mach->__fpu_xmm4)); 183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM5, &mach->__fpu_xmm5, sizeof(mach->__fpu_xmm5)); 184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM6, &mach->__fpu_xmm6, sizeof(mach->__fpu_xmm6)); 185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM7, &mach->__fpu_xmm7, sizeof(mach->__fpu_xmm7)); 186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM8, &mach->__fpu_xmm8, sizeof(mach->__fpu_xmm8)); 187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM9, &mach->__fpu_xmm9, sizeof(mach->__fpu_xmm9)); 188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM10, &mach->__fpu_xmm10, sizeof(mach->__fpu_xmm10)); 189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM11, &mach->__fpu_xmm11, sizeof(mach->__fpu_xmm11)); 190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM12, &mach->__fpu_xmm12, sizeof(mach->__fpu_xmm12)); 191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM13, &mach->__fpu_xmm13, sizeof(mach->__fpu_xmm13)); 192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM14, &mach->__fpu_xmm14, sizeof(mach->__fpu_xmm14)); 193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(memcpy)(&vex->guest_YMM15, &mach->__fpu_xmm15, sizeof(mach->__fpu_xmm15)); 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_state_to_vex(const thread_state_t mach_generic, 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_state_flavor_t flavor, 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach_msg_type_number_t count, 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestArchState *vex_generic) 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex = (VexGuestAMD64State *)vex_generic; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown switch(flavor) { 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case x86_THREAD_STATE64: 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_THREAD_STATE64_COUNT); 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86_thread_state64_to_vex((const x86_thread_state64_t*)mach_generic,vex); 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown case x86_FLOAT_STATE64: 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_FLOAT_STATE64_COUNT); 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86_float_state64_to_vex((const x86_float_state64_t*)mach_generic,vex); 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown default: 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownThreadState *build_thread(const thread_state_t state, 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_state_flavor_t flavor, 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach_msg_type_number_t count) 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(alloc_ThreadState)(); 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = VG_(get_ThreadState)(tid); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(flavor == x86_THREAD_STATE64); 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_THREAD_STATE64_COUNT); 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Initialize machine registers 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_state_to_vex(state, flavor, count, &tst->arch.vex); 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown I_die_here; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme signals, sig_mask, tmp_sig_mask, os_state.parent 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown find_stack_segment(tid, tst->arch.vex.guest_RSP); 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return tst; 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Edit the thread state to send to the real kernel. 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The real thread will run start_thread_NORETURN(tst) 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// on a separate non-client stack. 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid hijack_thread_state(thread_state_t mach_generic, 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_state_flavor_t flavor, 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach_msg_type_number_t count, 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst) 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown x86_thread_state64_t *mach = (x86_thread_state64_t *)mach_generic; 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *stack; 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(flavor == x86_THREAD_STATE64); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(count == x86_THREAD_STATE64_COUNT); 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack = (char *)allocstack(tst->tid); 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack -= 64+320; // make room for top frame 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memset(stack, 0, 64+320); // ...and clear it 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *(uintptr_t *)stack = 0; // push fake return address 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rdi = (uintptr_t)tst; // arg1 = tst 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rip = (uintptr_t)&start_thread_NORETURN; 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mach->__rsp = (uintptr_t)stack; 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Call f(arg1), but first switch stacks, using 'stack' as the new 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack, and use 'retaddr' as f's return-to address. Also, clear all 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the integer registers before entering f.*/ 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noreturn)) 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid call_on_new_stack_0_1 ( Addr stack, 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr retaddr, 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void (*f)(Word), 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Word arg1 ); 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// %rdi == stack (must be 16-byte aligned) 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// %rsi == retaddr 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// %rdx == f 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// %rcx == arg1 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm( 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl _call_on_new_stack_0_1\n" 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"_call_on_new_stack_0_1:\n" 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq %rsp, %rbp\n" // remember old stack pointer 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq %rdi, %rsp\n" // set new stack 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq %rcx, %rdi\n" // set arg1 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" pushq %rsi\n" // retaddr to new stack 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" pushq %rdx\n" // f to new stack 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rax\n" // zero all other GP regs 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rbx\n" 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rcx\n" 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rdx\n" 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rsi\n" 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %rbp\n" 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r8\n" 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r9\n" 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r10\n" 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r11\n" 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r12\n" 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r13\n" 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r14\n" 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq $0, %r15\n" 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" ret\n" // jump to f 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" ud2\n" // should never get here 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown); 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm( 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl _pthread_hijack_asm\n" 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"_pthread_hijack_asm:\n" 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq %rsp,%rbp\n" 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" push $0\n" // alignment pad 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" push %rbp\n" // original sp 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // other values stay where they are in registers 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" push $0\n" // fake return address 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" jmp _pthread_hijack\n" 316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov); 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid pthread_hijack(Addr self, Addr kport, Addr func, Addr func_arg, 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr stacksize, Addr flags, Addr sp) 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t blockall; 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst = (ThreadState *)func_arg; 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex = &tst->arch.vex; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // 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); 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Wait for parent thread's permission. 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The parent thread holds V's lock on our behalf. 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown semaphore_wait(tst->os_state.child_go); 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start the thread with all signals blocked. VG_(scheduler) will 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set the mask correctly when we finally get there. */ 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&blockall); 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, NULL); 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set thread's registers 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Do this FIRST because some code below tries to collect a backtrace, 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // which requires valid register data. 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestAMD64_initialise(vex); 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RIP = pthread_starter; 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDI = self; 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSI = kport; 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDX = func; 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RCX = tst->os_state.func_arg; 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R8 = stacksize; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R9 = flags; 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSP = sp; 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Record thread's stack and Mach port and pthread struct 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.pthread = self; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.lwpid = kport; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "thread-%p"); 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((flags & 0x01000000) == 0) { 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // kernel allocated stack - needs mapping 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr stack = VG_PGROUNDUP(sp) - stacksize; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->client_stack_highest_word = stack+stacksize; 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->client_stack_szB = stacksize; 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // pthread structure 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack+stacksize, pthread_structsize, 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack contents 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack, stacksize, 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // guard page 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack-VKI_PAGE_SIZE, VKI_PAGE_SIZE, 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, VKI_MAP_PRIVATE, -1, 0); 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // client allocated stack 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown find_stack_segment(tst->tid, sp); 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sync_mappings)("after", "pthread_hijack", 0); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: should this be here rather than in POST(sys_bsdthread_create)? 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // But we don't have ptid here... 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown //VG_TRACK ( pre_thread_ll_create, ptid, tst->tid ); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Tell parent thread's POST(sys_bsdthread_create) that we're done 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // initializing registers and mapping memory. 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown semaphore_signal(tst->os_state.child_done); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // LOCK IS GONE BELOW THIS POINT 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Go! 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call_on_new_stack_0_1(tst->os_state.valgrind_stack_init_SP, 0, 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start_thread_NORETURN, (Word)tst); 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm( 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl _wqthread_hijack_asm\n" 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"_wqthread_hijack_asm:\n" 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" movq %rsp,%r9\n" // original sp 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // other values stay where they are in registers 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" push $0\n" // fake return address 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown" jmp _wqthread_hijack\n" 406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov); 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* wqthread note: The kernel may create or destroy pthreads in the 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wqthread pool at any time with no userspace interaction, 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown and wqthread_start may be entered at any time with no userspace 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown interaction. 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown To handle this in valgrind, we create and destroy a valgrind 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread for every work item. 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid wqthread_hijack(Addr self, Addr kport, Addr stackaddr, Addr workitem, 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int reuse, Addr sp) 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadState *tst; 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VexGuestAMD64State *vex; 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr stack; 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT stacksize; 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigset_t blockall; 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* When we enter here we hold no lock (!), so we better acquire it 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pronto. Why do we hold no lock? Because (presumably) the only 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown way to get here is as a result of a SfMayBlock syscall 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "workq_ops(WQOPS_THREAD_RETURN)", which will have dropped the 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lock. At least that's clear for the 'reuse' case. The 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown non-reuse case? Dunno, perhaps it's a new thread the kernel 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pulled out of a hat. In any case we still need to take a 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lock. */ 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(acquire_BigLock_LL)("wqthread_hijack"); 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (0) VG_(printf)( 436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "wqthread_hijack: self %#lx, kport %#lx, " 437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov "stackaddr %#lx, workitem %#lx, reuse/flags %x, sp %#lx\n", 438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov self, kport, stackaddr, workitem, reuse, sp); 439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Start the thread with all signals blocked. VG_(scheduler) will 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set the mask correctly when we finally get there. */ 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigfillset)(&blockall); 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, NULL); 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov /* For 10.7 and earlier, |reuse| appeared to be used as a simple 446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov boolean. In 10.8 and later its name changed to |flags| and has 447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov various other bits OR-d into it too, so it's necessary to fish 448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov out just the relevant parts. Hence: */ 449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# if DARWIN_VERS <= DARWIN_10_7 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool is_reuse = reuse != 0; 451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# elif DARWIN_VERS == DARWIN_10_8 452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Bool is_reuse = (reuse & 0x20000 /* == WQ_FLAG_THREAD_REUSE */) != 0; 453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov# endif 454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (is_reuse) { 456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* For whatever reason, tst->os_state.pthread appear to have a 458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov constant offset of 96 on 10.7, but zero on 10.6 and 10.5. No 459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov idea why. */ 460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if DARWIN_VERS <= DARWIN_10_6 461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord magic_delta = 0; 462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif DARWIN_VERS >= DARWIN_10_7 463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UWord magic_delta = 0x60; 464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This thread already exists; we're merely re-entering 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // after leaving via workq_ops(WQOPS_THREAD_RETURN). 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Don't allocate any V thread resources. 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Do reset thread registers. 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(lwpid_to_vgtid)(kport); 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(VG_(is_valid_tid)(tid)); 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(mach_thread_self() == kport); 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(tid); 475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (0) VG_(printf)("wqthread_hijack reuse %s: tid %d, tst %p, " 477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "tst->os_state.pthread %#lx\n", 478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tst->os_state.pthread == self ? "SAME" : "DIFF", 479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tid, tst, tst->os_state.pthread); 480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex = &tst->arch.vex; 482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(tst->os_state.pthread - magic_delta == self); 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // This is a new thread. 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst = VG_(get_ThreadState)(VG_(alloc_ThreadState)()); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex = &tst->arch.vex; 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown allocstack(tst->tid); 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LibVEX_GuestAMD64_initialise(vex); 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Set thread's registers 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Do this FIRST because some code below tries to collect a backtrace, 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // which requires valid register data. 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RIP = wqthread_starter; 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDI = self; 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSI = kport; 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RDX = stackaddr; 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RCX = workitem; 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R8 = reuse; 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_R9 = 0; 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vex->guest_RSP = sp; 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stacksize = 512*1024; // wq stacks are always DEFAULT_STACK_SIZE 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack = VG_PGROUNDUP(sp) - stacksize; 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (is_reuse) { 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Continue V's thread back in the scheduler. 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // The client thread is of course in another location entirely. 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Drop the lock before going into 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(wqthread_continue_NORETURN). The latter will immediately 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown attempt to reacquire it in non-LL mode, which is a bit 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown wasteful but I don't think is harmful. A better solution 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown would be to not drop the lock but instead "upgrade" it from a 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown LL lock to a full lock, but that's too much like hard work 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown right now. */ 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock_LL)("wqthread_hijack(1)"); 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(wqthread_continue_NORETURN)(tst->tid); 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Record thread's stack and Mach port and pthread struct 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.pthread = self; 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->os_state.lwpid = kport; 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown record_named_port(tst->tid, kport, MACH_PORT_RIGHT_SEND, "wqthread-%p"); 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // kernel allocated stack - needs mapping 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->client_stack_highest_word = stack+stacksize; 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tst->client_stack_szB = stacksize; 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme scheduler lock?! 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // pthread structure 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack+stacksize, pthread_structsize, 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // stack contents 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme uninitialized! 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack, stacksize, 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VKI_PROT_READ|VKI_PROT_WRITE, VKI_MAP_PRIVATE, -1, 0); 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // guard page 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // GrP fixme ban_mem_stack! 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(notify_core_and_tool_of_mmap)( 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown stack-VKI_PAGE_SIZE, VKI_PAGE_SIZE, 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, VKI_MAP_PRIVATE, -1, 0); 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ML_(sync_mappings)("after", "wqthread_hijack", 0); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Go! 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Same comments as the 'release' in the then-clause. 552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start_thread_NORETURN calls run_thread_NORETURN calls 553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_wrapper which acquires the lock before continuing. 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Let's hope nothing non-thread-local happens until that point. 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown DDD: I think this is plain wrong .. if we get to 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_wrapper not holding the lock, and someone has recycled 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown this thread slot in the meantime, we're hosed. Is that 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown possible, though? */ 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(release_BigLock_LL)("wqthread_hijack(2)"); 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown call_on_new_stack_0_1(tst->os_state.valgrind_stack_init_SP, 0, 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown start_thread_NORETURN, (Word)tst); 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*NOTREACHED*/ 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(0); 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_amd64_darwin) 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 574