2 * Copyright (c) 2012 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #if defined(__x86_64__)
28 #include <mach/i386/syscall_sw.h>
33 .globl _start_wqthread
35 // This routine is never called directly by user code, jumped from kernel
36 // Push a sentinel frame, so backtracers know when to stop.
40 sub $16,%rsp // align the stack
41 call __pthread_wqthread
47 // This routine is never called directly by user code, jumped from kernel
48 // Push a sentinel frame, so backtracers know when to stop.
52 sub $16,%rsp // align the stack
58 .globl _thread_chkstk_darwin
59 _thread_chkstk_darwin:
60 .globl ____chkstk_darwin
61 ____chkstk_darwin: // %rax == alloca size
65 // validate that the frame pointer is on our stack (no alt stack)
66 cmpq %rcx, %gs:_PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET
68 cmpq %rcx, %gs:_PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET
71 // validate alloca size
74 cmpq %rcx, %gs:_PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET
81 // POSIX mandates that stack overflow crashes with SIGSEGV
82 // so load an address in the guard page and dereference it
83 movq %gs:_PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET, %rcx
85 // if main_thread caused stack growth with setrlimit()
86 // fall into Lprobe and eventually cause SIGSEGV.
89 // probe the stack when it's not ours (altstack or some shenanigan)
109 #elif defined(__i386__)
111 #include <mach/i386/syscall_sw.h>
116 .globl _start_wqthread
118 // This routine is never called directly by user code, jumped from kernel
119 // Push a sentinel frame, so backtracers know when to stop.
123 sub $24,%esp // align the stack
124 mov %esi,20(%esp) //arg5
125 mov %edi,16(%esp) //arg5
126 mov %edx,12(%esp) //arg4
127 mov %ecx,8(%esp) //arg3
128 mov %ebx,4(%esp) //arg2
129 mov %eax,(%esp) //arg1
130 call __pthread_wqthread
136 // This routine is never called directly by user code, jumped from kernel
137 // Push a sentinel frame, so backtracers know when to stop.
141 sub $24,%esp // align the stack
142 mov %esi,20(%esp) //arg6
143 mov %edi,16(%esp) //arg5
144 mov %edx,12(%esp) //arg4
145 mov %ecx,8(%esp) //arg3
146 mov %ebx,4(%esp) //arg2
147 mov %eax,(%esp) //arg1
153 .globl _thread_chkstk_darwin
154 _thread_chkstk_darwin:
155 .globl ____chkstk_darwin
156 ____chkstk_darwin: // %eax == alloca size
161 // validate that the frame pointer is on our stack (no alt stack)
162 movl %gs:0x0, %edx // pthread_self()
163 cmpl %ecx, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET(%edx)
165 movl _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET(%edx), %edx
169 // validate alloca size
180 // POSIX mandates that stack overflow crashes with SIGSEGV
181 // so load an address in the guard page and dereference it
182 movl %gs:0x0, %ecx // pthread_self()
183 movl _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET(%ecx), %ecx
185 // if main_thread caused stack growth with setrlimit()
186 // fall into Lprobe and eventually cause SIGSEGV.
189 // probe the stack when it's not ours (altstack or some shenanigan)
210 #elif defined(__arm__)
212 #include <mach/arm/syscall_sw.h>
216 // This routine is never called directly by user code, jumped from kernel
217 // args 0 to 3 are already in the regs 0 to 3
218 // should set stack with the 2 extra args before calling pthread_wqthread()
224 .globl _start_wqthread
226 // Push a sentinel frame, so backtracers know when to stop.
231 bl __pthread_wqthread
232 trap // never returns
238 // Push a sentinel frame, so backtracers know when to stop.
244 // Stackshots will show the routine that happens to link immediately following
245 // _start_wqthread. So we add an extra instruction (nop) to make stackshots
251 #elif defined(__arm64__)
253 #include <mach/arm/syscall_sw.h>
257 // This routine is never called directly by user code, jumped from kernel
258 // args 0 to 5 in registers.
261 .globl _start_wqthread
263 // Push a sentinel frame, so backtracers know when to stop.
264 stp xzr, xzr, [sp, #-16]!
265 bl __pthread_wqthread
266 brk #1 // never returns
272 // Push a sentinel frame, so backtracers know when to stop.
273 stp xzr, xzr, [sp, #-16]!
279 .globl _thread_chkstk_darwin
280 _thread_chkstk_darwin:
281 .globl ____chkstk_darwin
282 ____chkstk_darwin: // %w9/x9 == alloca size
283 stp x10, x11, [sp, #-16]
285 // validate that the frame pointer is on our stack (no alt stack)
287 and x10, x10, #0xfffffffffffffff8
289 // (%sp - pthread_self()->stackaddr) > 0 ?
290 #if defined(__ARM64_ARCH_8_32__)
292 ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
294 ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET]
299 // %sp <= pthread_self()->stackbottom ?
300 #if defined(__ARM64_ARCH_8_32__)
301 ldur w11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET]
303 ldur x11, [x10, _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET]
309 // %sp - (uintptr_t)%x9 < pthread_self()->stackbottom ?
316 ldp x10, x11, [sp, #-16]
320 // POSIX mandates that stack overflow crashes with SIGSEGV
321 // so load an address in the guard page and dereference it
323 // x11 contains pthread_self()->stackbottom already
325 // if main_thread caused stack growth with setrlimit()
326 // fall into Lprobe and eventually cause SIGSEGV.
333 sub x10, x10, #0x1000
346 #error Unsupported architecture