2 /*--------------------------------------------------------------------*/
3 /*--- Darwin-specific syscalls, etc. syswrap-x86-darwin.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2005-2017 Apple Inc.
11 Greg Parker gparker@apple.com
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
29 #if defined(VGP_x86_darwin)
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
33 #include "pub_core_threadstate.h"
34 #include "pub_core_aspacemgr.h"
35 #include "pub_core_xarray.h"
36 #include "pub_core_clientstate.h"
37 #include "pub_core_debuglog.h"
38 #include "pub_core_debuginfo.h" // VG_(di_notify_*)
39 #include "pub_core_transtab.h" // VG_(discard_translations)
40 #include "pub_core_libcbase.h"
41 #include "pub_core_libcassert.h"
42 #include "pub_core_libcfile.h"
43 #include "pub_core_libcprint.h"
44 #include "pub_core_libcproc.h"
45 #include "pub_core_libcsignal.h"
46 #include "pub_core_mallocfree.h"
47 #include "pub_core_options.h"
48 #include "pub_core_scheduler.h"
49 #include "pub_core_signals.h"
50 #include "pub_core_syscall.h"
51 #include "pub_core_syswrap.h"
52 #include "pub_core_tooliface.h"
54 #include "priv_types_n_macros.h"
55 #include "priv_syswrap-generic.h" /* for decls of generic wrappers */
56 #include "priv_syswrap-darwin.h" /* for decls of darwin-ish wrappers */
57 #include "priv_syswrap-main.h"
60 #include <mach/mach.h>
62 static void x86_thread_state32_from_vex(i386_thread_state_t
*mach
,
63 VexGuestX86State
*vex
)
65 mach
->__eax
= vex
->guest_EAX
;
66 mach
->__ebx
= vex
->guest_EBX
;
67 mach
->__ecx
= vex
->guest_ECX
;
68 mach
->__edx
= vex
->guest_EDX
;
69 mach
->__edi
= vex
->guest_EDI
;
70 mach
->__esi
= vex
->guest_ESI
;
71 mach
->__ebp
= vex
->guest_EBP
;
72 mach
->__esp
= vex
->guest_ESP
;
73 mach
->__ss
= vex
->guest_SS
;
74 mach
->__eflags
= LibVEX_GuestX86_get_eflags(vex
);
75 mach
->__eip
= vex
->guest_EIP
;
76 mach
->__cs
= vex
->guest_CS
;
77 mach
->__ds
= vex
->guest_DS
;
78 mach
->__es
= vex
->guest_ES
;
79 mach
->__fs
= vex
->guest_FS
;
80 mach
->__gs
= vex
->guest_GS
;
84 static void x86_float_state32_from_vex(i386_float_state_t
*mach
,
85 VexGuestX86State
*vex
)
87 // DDD: #warning GrP fixme fp state
89 VG_(memcpy
)(&mach
->__fpu_xmm0
, &vex
->guest_XMM0
, 8 * sizeof(mach
->__fpu_xmm0
));
93 void thread_state_from_vex(thread_state_t mach_generic
,
94 thread_state_flavor_t flavor
,
95 mach_msg_type_number_t count
,
96 VexGuestArchState
*vex_generic
)
98 VexGuestX86State
*vex
= (VexGuestX86State
*)vex_generic
;
101 case i386_THREAD_STATE
:
102 vg_assert(count
== i386_THREAD_STATE_COUNT
);
103 x86_thread_state32_from_vex((i386_thread_state_t
*)mach_generic
, vex
);
106 case i386_FLOAT_STATE
:
107 vg_assert(count
== i386_FLOAT_STATE_COUNT
);
108 x86_float_state32_from_vex((i386_float_state_t
*)mach_generic
, vex
);
117 static void x86_thread_state32_to_vex(const i386_thread_state_t
*mach
,
118 VexGuestX86State
*vex
)
120 LibVEX_GuestX86_initialise(vex
);
121 vex
->guest_EAX
= mach
->__eax
;
122 vex
->guest_EBX
= mach
->__ebx
;
123 vex
->guest_ECX
= mach
->__ecx
;
124 vex
->guest_EDX
= mach
->__edx
;
125 vex
->guest_EDI
= mach
->__edi
;
126 vex
->guest_ESI
= mach
->__esi
;
127 vex
->guest_EBP
= mach
->__ebp
;
128 vex
->guest_ESP
= mach
->__esp
;
129 vex
->guest_SS
= mach
->__ss
;
130 // DDD: #warning GrP fixme eflags
131 vex
->guest_EIP
= mach
->__eip
;
132 vex
->guest_CS
= mach
->__cs
;
133 vex
->guest_DS
= mach
->__ds
;
134 vex
->guest_ES
= mach
->__es
;
135 vex
->guest_FS
= mach
->__fs
;
136 vex
->guest_GS
= mach
->__gs
;
139 static void x86_float_state32_to_vex(const i386_float_state_t
*mach
,
140 VexGuestX86State
*vex
)
142 // DDD: #warning GrP fixme fp state
144 VG_(memcpy
)(&vex
->guest_XMM0
, &mach
->__fpu_xmm0
, 8 * sizeof(mach
->__fpu_xmm0
));
148 void thread_state_to_vex(const thread_state_t mach_generic
,
149 thread_state_flavor_t flavor
,
150 mach_msg_type_number_t count
,
151 VexGuestArchState
*vex_generic
)
153 VexGuestX86State
*vex
= (VexGuestX86State
*)vex_generic
;
156 case i386_THREAD_STATE
:
157 vg_assert(count
== i386_THREAD_STATE_COUNT
);
158 x86_thread_state32_to_vex((const i386_thread_state_t
*)mach_generic
,vex
);
160 case i386_FLOAT_STATE
:
161 vg_assert(count
== i386_FLOAT_STATE_COUNT
);
162 x86_float_state32_to_vex((const i386_float_state_t
*)mach_generic
,vex
);
172 ThreadState
*build_thread(const thread_state_t state
,
173 thread_state_flavor_t flavor
,
174 mach_msg_type_number_t count
)
176 ThreadId tid
= VG_(alloc_ThreadState
)();
177 ThreadState
*tst
= VG_(get_ThreadState
)(tid
);
179 vg_assert(flavor
== i386_THREAD_STATE
);
180 vg_assert(count
== i386_THREAD_STATE_COUNT
);
182 // Initialize machine registers
184 thread_state_to_vex(state
, flavor
, count
, &tst
->arch
.vex
);
187 // GrP fixme signals, sig_mask, tmp_sig_mask, os_state.parent
189 find_stack_segment(tid
, tst
->arch
.vex
.guest_ESP
);
195 // Edit the thread state to send to the real kernel.
196 // The real thread will run start_thread_NORETURN(tst)
197 // on a separate non-client stack.
198 void hijack_thread_state(thread_state_t mach_generic
,
199 thread_state_flavor_t flavor
,
200 mach_msg_type_number_t count
,
203 i386_thread_state_t
*mach
= (i386_thread_state_t
*)mach_generic
;
206 vg_assert(flavor
== i386_THREAD_STATE
);
207 vg_assert(count
== i386_THREAD_STATE_COUNT
);
209 stack
= (char *)allocstack(tst
->tid
);
210 stack
-= 64+320; // make room for top frame
211 memset(stack
, 0, 64+320); // ...and clear it
212 *(uintptr_t *)stack
= (uintptr_t)tst
; // set parameter
213 stack
-= sizeof(uintptr_t);
214 *(uintptr_t *)stack
= 0; // push fake return address
216 mach
->__eip
= (uintptr_t)&start_thread_NORETURN
;
217 mach
->__esp
= (uintptr_t)stack
;
221 /* Call f(arg1), but first switch stacks, using 'stack' as the new
222 stack, and use 'retaddr' as f's return-to address. Also, clear all
223 the integer registers before entering f.*/
224 __attribute__((noreturn
))
225 void call_on_new_stack_0_1 ( Addr stack
,
229 // 4(%esp) == stack (must be 16-byte aligned)
230 // 8(%esp) == retaddr
234 ".globl _call_on_new_stack_0_1\n"
235 "_call_on_new_stack_0_1:\n"
236 " movl %esp, %esi\n" // remember old stack pointer
237 " movl 4(%esi), %esp\n" // set new stack
238 " pushl $0\n" // align stack
239 " pushl $0\n" // align stack
240 " pushl $0\n" // align stack
241 " pushl 16(%esi)\n" // arg1 to stack
242 " pushl 8(%esi)\n" // retaddr to stack
243 " pushl 12(%esi)\n" // f to stack
244 " movl $0, %eax\n" // zero all GP regs
251 " ret\n" // jump to f
252 " ud2\n" // should never get here
257 ".globl _pthread_hijack_asm\n"
258 "_pthread_hijack_asm:\n"
260 " push $0\n" // alignment pad
261 " push %ebp\n" // original sp
262 " push %esi\n" // flags
263 " push %edi\n" // stacksize
264 " push %edx\n" // func_arg
265 " push %ecx\n" // func
266 " push %ebx\n" // kport
267 " push %eax\n" // self
268 " push $0\n" // fake return address
269 " jmp _pthread_hijack\n"
274 void pthread_hijack(Addr self
, Addr kport
, Addr func
, Addr func_arg
,
275 Addr stacksize
, Addr flags
, Addr sp
)
277 vki_sigset_t blockall
;
278 ThreadState
*tst
= (ThreadState
*)func_arg
;
279 VexGuestX86State
*vex
= &tst
->arch
.vex
;
281 // 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);
283 // Wait for parent thread's permission.
284 // The parent thread holds V's lock on our behalf.
285 semaphore_wait(tst
->os_state
.child_go
);
287 /* Start the thread with all signals blocked. VG_(scheduler) will
288 set the mask correctly when we finally get there. */
289 VG_(sigfillset
)(&blockall
);
290 VG_(sigprocmask
)(VKI_SIG_SETMASK
, &blockall
, NULL
);
292 // Set thread's registers
293 // Do this FIRST because some code below tries to collect a backtrace,
294 // which requires valid register data.
295 // DDD: need to do post_reg_write events here?
296 LibVEX_GuestX86_initialise(vex
);
297 vex
->guest_EIP
= pthread_starter
;
298 vex
->guest_EAX
= self
;
299 vex
->guest_EBX
= kport
;
300 vex
->guest_ECX
= func
;
301 vex
->guest_EDX
= tst
->os_state
.func_arg
;
302 vex
->guest_EDI
= stacksize
;
303 vex
->guest_ESI
= flags
;
306 // Record thread's stack and Mach port and pthread struct
307 tst
->os_state
.pthread
= self
;
308 tst
->os_state
.lwpid
= kport
;
309 record_named_port(tst
->tid
, kport
, MACH_PORT_RIGHT_SEND
, "thread-%p");
311 if ((flags
& 0x01000000) == 0) {
312 // kernel allocated stack - needs mapping
313 Addr stack
= VG_PGROUNDUP(sp
) - stacksize
;
314 tst
->client_stack_highest_byte
= stack
+stacksize
-1;
315 tst
->client_stack_szB
= stacksize
;
318 ML_(notify_core_and_tool_of_mmap
)(
319 stack
+stacksize
, pthread_structsize
,
320 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_PRIVATE
, -1, 0);
322 ML_(notify_core_and_tool_of_mmap
)(
324 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_PRIVATE
, -1, 0);
326 ML_(notify_core_and_tool_of_mmap
)(
327 stack
-VKI_PAGE_SIZE
, VKI_PAGE_SIZE
,
328 0, VKI_MAP_PRIVATE
, -1, 0);
330 // client allocated stack
331 find_stack_segment(tst
->tid
, sp
);
333 ML_(sync_mappings
)("after", "pthread_hijack", 0);
335 // DDD: should this be here rather than in POST(sys_bsdthread_create)?
336 // But we don't have ptid here...
337 //VG_TRACK ( pre_thread_ll_create, ptid, tst->tid );
339 // Tell parent thread's POST(sys_bsdthread_create) that we're done
340 // initializing registers and mapping memory.
341 semaphore_signal(tst
->os_state
.child_done
);
342 // LOCK IS GONE BELOW THIS POINT
345 call_on_new_stack_0_1(tst
->os_state
.valgrind_stack_init_SP
, 0,
346 start_thread_NORETURN
, (Word
)tst
);
355 ".globl _wqthread_hijack_asm\n"
356 "_wqthread_hijack_asm:\n"
358 " push $0\n" // alignment
359 " push $0\n" // alignment
360 " push %ebp\n" // original sp
361 " push %edi\n" // reuse
362 " push %edx\n" // workitem
363 " push %ecx\n" // stackaddr
364 " push %ebx\n" // kport
365 " push %eax\n" // self
366 " push $0\n" // fake return address
367 " jmp _wqthread_hijack\n"
371 /* wqthread note: The kernel may create or destroy pthreads in the
372 wqthread pool at any time with no userspace interaction,
373 and wqthread_start may be entered at any time with no userspace
375 To handle this in valgrind, we create and destroy a valgrind
376 thread for every work item.
378 void wqthread_hijack(Addr self
, Addr kport
, Addr stackaddr
, Addr workitem
,
382 VexGuestX86State
*vex
;
385 vki_sigset_t blockall
;
387 /* When we enter here we hold no lock (!), so we better acquire it
388 pronto. Why do we hold no lock? Because (presumably) the only
389 way to get here is as a result of a SfMayBlock syscall
390 "workq_ops(WQOPS_THREAD_RETURN)", which will have dropped the
391 lock. At least that's clear for the 'reuse' case. The
392 non-reuse case? Dunno, perhaps it's a new thread the kernel
393 pulled out of a hat. In any case we still need to take a
395 VG_(acquire_BigLock_LL
)("wqthread_hijack");
398 "wqthread_hijack: self %#lx, kport %#lx, "
399 "stackaddr %#lx, workitem %#lx, reuse/flags %x, sp %#lx\n",
400 self
, kport
, stackaddr
, workitem
, reuse
, sp
);
402 /* Start the thread with all signals blocked. VG_(scheduler) will
403 set the mask correctly when we finally get there. */
404 VG_(sigfillset
)(&blockall
);
405 VG_(sigprocmask
)(VKI_SIG_SETMASK
, &blockall
, NULL
);
407 /* For 10.7 and earlier, |reuse| appeared to be used as a simple
408 boolean. In 10.8 and later its name changed to |flags| and has
409 various other bits OR-d into it too, so it's necessary to fish
410 out just the relevant parts. Hence: */
411 # if DARWIN_VERS <= DARWIN_10_7
412 Bool is_reuse
= reuse
!= 0;
413 # elif DARWIN_VERS > DARWIN_10_7
414 Bool is_reuse
= (reuse
& 0x20000 /* == WQ_FLAG_THREAD_REUSE */) != 0;
416 # error "Unsupported Darwin version"
421 /* For whatever reason, tst->os_state.pthread appear to have a
422 constant offset of 72 on 10.7, but zero on 10.6 and 10.5. No
424 # if DARWIN_VERS <= DARWIN_10_6
425 UWord magic_delta
= 0;
426 # elif DARWIN_VERS == DARWIN_10_7 || DARWIN_VERS == DARWIN_10_8
427 UWord magic_delta
= 0x48;
428 # elif DARWIN_VERS == DARWIN_10_9 \
429 || DARWIN_VERS == DARWIN_10_10 \
430 || DARWIN_VERS == DARWIN_10_11 \
431 || DARWIN_VERS == DARWIN_10_12 \
432 || DARWIN_VERS == DARWIN_10_13
433 UWord magic_delta
= 0xB0;
435 # error "magic_delta: to be computed on new OS version"
436 // magic_delta = tst->os_state.pthread - self
439 // This thread already exists; we're merely re-entering
440 // after leaving via workq_ops(WQOPS_THREAD_RETURN).
441 // Don't allocate any V thread resources.
442 // Do reset thread registers.
443 ThreadId tid
= VG_(lwpid_to_vgtid
)(kport
);
444 vg_assert(VG_(is_valid_tid
)(tid
));
445 vg_assert(mach_thread_self() == kport
);
447 tst
= VG_(get_ThreadState
)(tid
);
449 if (0) VG_(printf
)("wqthread_hijack reuse %s: tid %u, tst %p, "
450 "tst->os_state.pthread %#lx, self %#lx\n",
451 tst
->os_state
.pthread
== self
? "SAME" : "DIFF",
452 tid
, tst
, tst
->os_state
.pthread
, self
);
454 vex
= &tst
->arch
.vex
;
455 vg_assert(tst
->os_state
.pthread
- magic_delta
== self
);
458 // This is a new thread.
459 tst
= VG_(get_ThreadState
)(VG_(alloc_ThreadState
)());
460 vex
= &tst
->arch
.vex
;
461 allocstack(tst
->tid
);
462 LibVEX_GuestX86_initialise(vex
);
465 // Set thread's registers
466 // Do this FIRST because some code below tries to collect a backtrace,
467 // which requires valid register data.
468 vex
->guest_EIP
= wqthread_starter
;
469 vex
->guest_EAX
= self
;
470 vex
->guest_EBX
= kport
;
471 vex
->guest_ECX
= stackaddr
;
472 vex
->guest_EDX
= workitem
;
473 vex
->guest_EDI
= reuse
;
477 stacksize
= 512*1024; // wq stacks are always DEFAULT_STACK_SIZE
478 stack
= VG_PGROUNDUP(sp
) - stacksize
;
481 // Continue V's thread back in the scheduler.
482 // The client thread is of course in another location entirely.
484 /* Drop the lock before going into
485 ML_(wqthread_continue_NORETURN). The latter will immediately
486 attempt to reacquire it in non-LL mode, which is a bit
487 wasteful but I don't think is harmful. A better solution
488 would be to not drop the lock but instead "upgrade" it from a
489 LL lock to a full lock, but that's too much like hard work
491 VG_(release_BigLock_LL
)("wqthread_hijack(1)");
492 ML_(wqthread_continue_NORETURN
)(tst
->tid
);
495 // Record thread's stack and Mach port and pthread struct
496 tst
->os_state
.pthread
= self
;
497 tst
->os_state
.lwpid
= kport
;
498 record_named_port(tst
->tid
, kport
, MACH_PORT_RIGHT_SEND
, "wqthread-%p");
500 // kernel allocated stack - needs mapping
501 tst
->client_stack_highest_byte
= stack
+stacksize
-1;
502 tst
->client_stack_szB
= stacksize
;
504 // GrP fixme scheduler lock?!
507 ML_(notify_core_and_tool_of_mmap
)(
508 stack
+stacksize
, pthread_structsize
,
509 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_PRIVATE
, -1, 0);
511 // GrP fixme uninitialized!
512 ML_(notify_core_and_tool_of_mmap
)(
514 VKI_PROT_READ
|VKI_PROT_WRITE
, VKI_MAP_PRIVATE
, -1, 0);
516 // GrP fixme ban_mem_stack!
517 ML_(notify_core_and_tool_of_mmap
)(
518 stack
-VKI_PAGE_SIZE
, VKI_PAGE_SIZE
,
519 0, VKI_MAP_PRIVATE
, -1, 0);
521 ML_(sync_mappings
)("after", "wqthread_hijack", 0);
524 /* Same comments as the 'release' in the then-clause.
525 start_thread_NORETURN calls run_thread_NORETURN calls
526 thread_wrapper which acquires the lock before continuing.
527 Let's hope nothing non-thread-local happens until that point.
529 DDD: I think this is plain wrong .. if we get to
530 thread_wrapper not holding the lock, and someone has recycled
531 this thread slot in the meantime, we're hosed. Is that
533 VG_(release_BigLock_LL
)("wqthread_hijack(2)");
534 call_on_new_stack_0_1(tst
->os_state
.valgrind_stack_init_SP
, 0,
535 start_thread_NORETURN
, (Word
)tst
);
542 #endif // defined(VGP_x86_darwin)
544 /*--------------------------------------------------------------------*/
546 /*--------------------------------------------------------------------*/