]> git.saurik.com Git - apple/libplatform.git/blob - src/ucontext/arm64/getcontext.s
libplatform-254.40.4.tar.gz
[apple/libplatform.git] / src / ucontext / arm64 / getcontext.s
1 /*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include "asm_help.h"
25 #include <os/tsd.h>
26 #include <TargetConditionals.h>
27
28 /*
29 * int getcontext(ucontext_t *ucp);
30 *
31 * _STRUCT_UCONTEXT {
32 * int uc_onstack;
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;
40 * #endif
41 * };
42 *
43 * _STRUCT_MCONTEXT64
44 * {
45 * _STRUCT_ARM_EXCEPTION_STATE64 __es;
46 * _STRUCT_ARM_THREAD_STATE64 __ss;
47 * _STRUCT_ARM_NEON_STATE64 __ns;
48 * };
49 *
50 * From the standard:
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.
56 *
57 * getcontext populates the following fields (with the help of a helper function):
58 * uc_sigmask
59 * uc_mcontext
60 * uc_mcsize
61 * __mcontext_data
62 * uc_stack
63 *
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
68 * just returned".
69 *
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
82 * values.
83 * - we don't need to save the arm exception state
84 */
85
86 .text
87
88 #if TARGET_OS_OSX || TARGET_OS_DRIVERKIT
89
90 /* Pointer auths fp, sp and lr and puts them in the final locations specified by
91 * input arguments
92 *
93 * Modifies: lr
94 * Uses: x9
95 */
96 .macro PTR_SIGN_FP_SP_LR fp, sp, lr, flags
97 #if defined(__arm64e__)
98 // Sign fp with fp constant discriminator
99 mov \fp, fp
100 mov x9, #17687 // x9 = ptrauth_string_discriminator("fp")
101 pacda \fp, x9
102
103 // Sign sp with sp constant discriminator
104 mov \sp, sp
105 mov x9, #52205 // x9 = ptrauth_string_discriminator("sp")
106 pacda \sp, x9
107
108 // lr is signed with sp and b key, just set a flag marking so and don't
109 // change the signature
110 mov \lr, lr
111 mov \flags, LR_SIGNED_WITH_IB
112 #else
113 mov \fp, fp
114 mov \sp, sp
115 mov \lr, lr
116 #endif
117 .endmacro
118
119 .align 2
120 .globl _getcontext
121 _getcontext:
122 ARM64_STACK_PROLOG
123
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
126 PUSH_FRAME
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.
130
131 // x0 = ucp pointer
132 // x1 = sp
133 mov x1, sp
134 bl _populate_signal_stack_context
135 POP_FRAME // Restore lr, fp and sp
136
137 // x0 = mcontext pointer
138
139 // Pointer sign fp, sp, lr and mark flags as needed
140 PTR_SIGN_FP_SP_LR x10, x11, x12, x13
141
142 // x10 = signed fp
143 // x11 = signed sp
144 // x12 = signed lr
145 // x13 = mcontext flags
146
147 // Save frame pointer and lr
148 stp x10, x12, [x0, MCONTEXT_OFFSET_FP_LR]
149
150 // Save stack pointer
151 str x11, [x0, MCONTEXT_OFFSET_SP]
152
153 #if defined(__arm64e__)
154 // Save the flags
155 str w13, [x0, MCONTEXT_OFFSET_FLAGS]
156 #endif
157
158 // Save x19 - x28
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]
164
165 // Save return value
166 str xzr, [x0, MCONTEXT_OFFSET_X0]
167
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]
177
178 mov x0, xzr /* Return value from getcontext */
179
180 ARM64_STACK_EPILOG
181
182 #endif