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