2 * Copyright (c) 2020 Apple 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 #include <TargetConditionals.h>
29 * int getcontext(ucontext_t *ucp);
33 * __darwin_sigset_t uc_sigmask; // signal mask used by this context
34 * _STRUCT_SIGALTSTACK uc_stack; // stack used by this context
35 * _STRUCT_UCONTEXT *uc_link; // pointer to resuming context
36 * __darwin_size_t uc_mcsize; // size of the machine context passed in
37 * _STRUCT_MCONTEXT *uc_mcontext; // pointer to machine specific context
38 * #ifdef _XOPEN_SOURCE
39 * _STRUCT_MCONTEXT __mcontext_data;
45 * _STRUCT_ARM_EXCEPTION_STATE64 __es;
46 * _STRUCT_ARM_THREAD_STATE64 __ss;
47 * _STRUCT_ARM_NEON_STATE64 __ns;
51 * The getcontext(3) function shall initialize the structure pointed to by
52 * ucp to the current user context of the calling thread. The ucontext_t
53 * type that ucp points to defines the user context and includes the
54 * contents of the calling thread's machine registers, the signal mask, and
55 * the current execution stack.
57 * getcontext populates the following fields (with the help of a helper function):
64 * The ASM below mainly handles populating the machine context. Per the
65 * standard, getcontext should populate the machine context such that if
66 * setcontext is called with "ucp argument which was created with getcontext(),
67 * program execution continues as if the corresponding call of getcontext() had
70 * As such, the mcontext is saved such that:
71 * - sp and fp are saved to be that of the caller.
72 * - pc is not saved, lr is saved. We'll return from setcontext to the
73 * caller (the current lr) via a ret.
74 * - only callee save registers are saved in the machine context, caller
75 * will restore the caller save registers.
76 * - For neon registers, we save d8-d15. Per the standard:
77 * Registers v8-v15 must be preserved by a callee across subroutine
78 * calls; the remaining registers (v0-v7, v16-v31) do not need to be
79 * preserved (or should be preserved by the caller). Additionally,
80 * only the bottom 64 bits of each value stored in v8-v15 need to be
81 * preserved; it is the responsibility of the caller to preserve larger
83 * - we don't need to save the arm exception state
88 #if TARGET_OS_OSX || TARGET_OS_DRIVERKIT
90 /* Pointer auths fp, sp and lr and puts them in the final locations specified by
96 .macro PTR_SIGN_FP_SP_LR fp, sp, lr, flags
97 #if defined(__arm64e__)
98 // Sign fp with fp constant discriminator
100 mov x9, #17687 // x9 = ptrauth_string_discriminator("fp")
103 // Sign sp with sp constant discriminator
105 mov x9, #52205 // x9 = ptrauth_string_discriminator("sp")
108 // lr is signed with sp and b key, just set a flag marking so and don't
109 // change the signature
111 mov \flags, LR_SIGNED_WITH_IB
124 // Note that we're pushing and popping a frame around the subroutine call so
125 // that we have the lr, fp, and sp saved
127 // We don't need to caller save x9 - x15 since we're not going to
128 // save them in the mcontext later anyways and since they are caller save
129 // registers, the caller of getcontext will restore them if needed.
134 bl _populate_signal_stack_context
135 POP_FRAME // Restore lr, fp and sp
137 // x0 = mcontext pointer
139 // Pointer sign fp, sp, lr and mark flags as needed
140 PTR_SIGN_FP_SP_LR x10, x11, x12, x13
145 // x13 = mcontext flags
147 // Save frame pointer and lr
148 stp x10, x12, [x0, MCONTEXT_OFFSET_FP_LR]
150 // Save stack pointer
151 str x11, [x0, MCONTEXT_OFFSET_SP]
153 #if defined(__arm64e__)
155 str w13, [x0, MCONTEXT_OFFSET_FLAGS]
159 stp x19, x20, [x0, MCONTEXT_OFFSET_X19_X20]
160 stp x21, x22, [x0, MCONTEXT_OFFSET_X21_X22]
161 stp x23, x24, [x0, MCONTEXT_OFFSET_X23_X24]
162 stp x25, x26, [x0, MCONTEXT_OFFSET_X25_X26]
163 stp x27, x28, [x0, MCONTEXT_OFFSET_X27_X28]
166 str xzr, [x0, MCONTEXT_OFFSET_X0]
168 // Save NEON registers
169 str d8, [x0, MCONTEXT_OFFSET_D8]
170 str d9, [x0, MCONTEXT_OFFSET_D9]
171 str d10, [x0, MCONTEXT_OFFSET_D10]
172 str d11, [x0, MCONTEXT_OFFSET_D11]
173 str d12, [x0, MCONTEXT_OFFSET_D12]
174 str d13, [x0, MCONTEXT_OFFSET_D13]
175 str d14, [x0, MCONTEXT_OFFSET_D14]
176 str d15, [x0, MCONTEXT_OFFSET_D15]
178 mov x0, xzr /* Return value from getcontext */