]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/i386/makecontext.S
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / makecontext.S
CommitLineData
4ee87ecc 1/* Create new context.
2b778ceb 2 Copyright (C) 2001-2021 Free Software Foundation, Inc.
4ee87ecc
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
4ee87ecc
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
4ee87ecc 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6 17 License along with the GNU C Library; if not, see
5a82c748 18 <https://www.gnu.org/licenses/>. */
4ee87ecc
UD
19
20#include <sysdep.h>
5d844e1b 21#include <asm/prctl.h>
4ee87ecc
UD
22
23#include "ucontext_i.h"
24
25
26ENTRY(__makecontext)
27 movl 4(%esp), %eax
28
29 /* Load the address of the function we are supposed to run. */
30 movl 8(%esp), %ecx
31
32 /* Compute the address of the stack. The information comes from
33 to us_stack element. */
34 movl oSS_SP(%eax), %edx
35 movl %ecx, oEIP(%eax)
36 addl oSS_SIZE(%eax), %edx
37
4ee87ecc
UD
38 /* Remember the number of parameters for the exit handler since
39 it has to remove them. We store the number in the EBX register
40 which the function we will call must preserve. */
41 movl 12(%esp), %ecx
42 movl %ecx, oEBX(%eax)
43
148e12ed
UD
44 /* Make room on the new stack for the parameters.
45 Room for the arguments, return address (== L(exitcode)) and
46 oLINK pointer is needed. One of the pointer sizes is subtracted
47 after aligning the stack. */
4ee87ecc 48 negl %ecx
148e12ed 49 leal -4(%edx,%ecx,4), %edx
4ee87ecc 50 negl %ecx
51bd20d9
UD
51
52 /* Align the stack. */
51bd20d9
UD
53 andl $0xfffffff0, %edx
54 subl $4, %edx
55
4ee87ecc
UD
56 /* Store the future stack pointer. */
57 movl %edx, oESP(%eax)
58
51bd20d9
UD
59 /* Put the next context on the new stack (from the uc_link
60 element). */
61 movl oLINK(%eax), %eax
62 movl %eax, 4(%edx,%ecx,4)
63
4ee87ecc
UD
64 /* Copy all the parameters. */
65 jecxz 2f
661: movl 12(%esp,%ecx,4), %eax
67 movl %eax, (%edx,%ecx,4)
68 decl %ecx
69 jnz 1b
702:
71
5d844e1b
L
72#if SHSTK_ENABLED
73 /* Check if Shadow Stack is enabled. */
74 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
75 jz L(skip_ssp)
76
77 /* Reload the pointer to ucontext. */
78 movl 4(%esp), %eax
79
80 /* Shadow stack is enabled. We need to allocate a new shadow
81 stack. */
82 subl oSS_SP(%eax), %edx
83 shrl $STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT, %edx
84
85 /* Align shadow stack size to 8 bytes. */
86 addl $7, %edx
87 andl $-8, %edx
88
89 /* Store shadow stack size in __ssp[2]. */
90 movl %edx, (oSSP + 8)(%eax)
91
92 /* Save ESI in the second scratch register slot. */
93 movl %esi, oSCRATCH2(%eax)
94 /* Save EDI in the third scratch register slot. */
95 movl %edi, oSCRATCH3(%eax)
96
97 /* Save the pointer to ucontext. */
98 movl %eax, %edi
99
100 /* Get the original shadow stack pointer. */
101 rdsspd %esi
102
103 /* Align the saved original shadow stack pointer to the next
104 8 byte aligned boundary. */
105 andl $-8, %esi
106
107 /* Load the top of the new stack into EDX. */
108 movl oESP(%eax), %edx
109
110 /* We need to terminate the FDE here because the unwinder looks
111 at ra-1 for unwind information. */
112 cfi_endproc
113
114 /* Swap the original stack pointer with the top of the new
115 stack. */
116 xchgl %esp, %edx
117
118 /* Add 4 bytes since CALL will push the 4-byte return address
119 onto stack. */
120 addl $4, %esp
121
122 /* Allocate the new shadow stack. Save EBX in the first scratch
123 register slot. */
124 movl %ebx, oSCRATCH1(%eax)
125
126 /* CET syscall takes 64-bit sizes. */
127 subl $16, %esp
128 movl (oSSP + 8)(%eax), %ecx
129 movl %ecx, (%esp)
130 movl $0, 4(%esp)
131 movl %ecx, 8(%esp)
132 movl $0, 12(%esp)
133 movl %esp, %ecx
134
135 movl $ARCH_CET_ALLOC_SHSTK, %ebx
136 movl $__NR_arch_prctl, %eax
137 ENTER_KERNEL
138 testl %eax, %eax
139 jne L(hlt) /* This should never happen. */
140
141 /* Copy the base address of the new shadow stack to __ssp[1]. */
142 movl (%esp), %eax
143 movl %eax, (oSSP + 4)(%edi)
144
145 addl $16, %esp
146
147 /* Restore EBX from the first scratch register slot. */
148 movl oSCRATCH1(%edi), %ebx
149
150 /* Get the size of the new shadow stack. */
151 movl (oSSP + 8)(%edi), %ecx
152
153 /* Use the restore stoken to restore the new shadow stack. */
154 rstorssp -8(%eax, %ecx)
155
156 /* Save the restore token at the next 8 byte aligned boundary
157 on the original shadow stack. */
158 saveprevssp
159
160 /* Push the address of "jmp exitcode" onto the new stack as
161 well as the new shadow stack. */
162 call 1f
163 jmp L(exitcode)
1641:
165
166 /* Get the new shadow stack pointer. */
167 rdsspd %eax
168
169 /* Use the restore stoken to restore the original shadow stack. */
170 rstorssp -8(%esi)
171
172 /* Save the restore token on the new shadow stack. */
173 saveprevssp
174
175 /* Store the new shadow stack pointer in __ssp[0]. */
176 movl %eax, oSSP(%edi)
177
178 /* Restore the original stack. */
179 mov %edx, %esp
180
181 cfi_startproc
182
183 /* Restore ESI from the second scratch register slot. */
184 movl oSCRATCH2(%edi), %esi
185 /* Restore EDI from the third scratch register slot. */
186 movl oSCRATCH3(%edi), %edi
187
188 ret
189
190L(skip_ssp):
191#endif
192
4ee87ecc
UD
193 /* If the function we call returns we must continue with the
194 context which is given in the uc_link element. To do this
195 set the return address for the function the user provides
196 to a little bit of helper code which does the magic (see
197 below). */
198#ifdef PIC
199 call 1f
fee732e5 200 cfi_adjust_cfa_offset (4)
4ee87ecc 2011: popl %ecx
fee732e5 202 cfi_adjust_cfa_offset (-4)
4ee87ecc
UD
203 addl $L(exitcode)-1b, %ecx
204 movl %ecx, (%edx)
205#else
206 movl $L(exitcode), (%edx)
207#endif
bbab82c2
AS
208 /* We need to terminate the FDE here instead of after ret because
209 the unwinder looks at ra-1 for unwind information. */
210 cfi_endproc
211
4ee87ecc
UD
212 /* 'makecontext' returns no value. */
213 ret
214
215 /* This is the helper code which gets called if a function which
216 is registered with 'makecontext' returns. In this case we
217 have to install the context listed in the uc_link element of
218 the context 'makecontext' manipulated at the time of the
219 'makecontext' call. If the pointer is NULL the process must
220 terminate. */
221L(exitcode):
222 /* This removes the parameters passed to the function given to
223 'makecontext' from the stack. EBX contains the number of
224 parameters (see above). */
225 leal (%esp,%ebx,4), %esp
226
9b6bf8a3 227 cmpl $0, (%esp) /* Check the next context. */
4ee87ecc
UD
228 je 2f /* If it is zero exit. */
229
7e58ab24 230 call HIDDEN_JUMPTARGET(__setcontext)
4ee87ecc
UD
231 /* If this returns (which can happen if the syscall fails) we'll
232 exit the program with the return error value (-1). */
8a5df95f 233 jmp L(call_exit)
4ee87ecc 234
8a5df95f
FW
2352:
236 /* Exit with status 0. */
237 xorl %eax, %eax
238
239L(call_exit):
240 /* Align the stack and pass the exit code (from %eax). */
241 andl $0xfffffff0, %esp
242 subl $12, %esp
243 pushl %eax
244
245 call HIDDEN_JUMPTARGET(exit)
4ee87ecc
UD
246 /* The 'exit' call should never return. In case it does cause
247 the process to terminate. */
5d844e1b 248L(hlt):
4ee87ecc 249 hlt
fee732e5 250 cfi_startproc
4ee87ecc
UD
251END(__makecontext)
252
1ab18a5b 253weak_alias (__makecontext, makecontext)