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