1 /* Save current context.
2 Copyright (C) 2001-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
20 #include <asm/prctl.h>
22 #include "ucontext_i.h"
26 /* Load address of the context data structure. */
29 /* Save the preserved register values and the return address. */
35 leal 4(%esp), %ecx /* Exclude the return address. */
39 /* Save the FS segment register. We don't touch the GS register
40 since it is used for threads. */
46 /* Check if shadow stack is enabled. */
47 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
50 /* Save EAX in EDX. */
54 cmpl %gs:SSP_BASE_OFFSET, %eax
55 jnz L(shadow_stack_bound_recorded)
57 /* Save EBX in the first scratch register slot. */
58 movl %ebx, oSCRATCH1(%edx)
60 /* Get the base address and size of the default shadow stack
61 which must be the current shadow stack since nothing has
65 movl $ARCH_CET_STATUS, %ebx
66 movl $__NR_arch_prctl, %eax
71 /* This should never happen. */
75 /* Restore EBX from the first scratch register slot. */
76 movl oSCRATCH1(%edx), %ebx
78 /* Record the base of the current shadow stack. */
80 movl %eax, %gs:SSP_BASE_OFFSET
83 L(shadow_stack_bound_recorded):
84 /* Load address of the context data structure. */
87 /* Get the current shadow stack pointer. */
89 /* NB: Save the caller's shadow stack so that we can jump back
90 to the caller directly. */
94 /* Save the current shadow stack base in ucontext. */
95 movl %gs:SSP_BASE_OFFSET, %edx
96 movl %edx, (oSSP + 4)(%eax)
100 /* We have separate floating-point register content memory on the
101 stack. We use the __fpregs_mem block in the context. Set the
102 links up correctly. */
103 leal oFPREGSMEM(%eax), %ecx
104 movl %ecx, oFPREGS(%eax)
105 /* Save the floating-point context. */
107 /* And load it right back since the processor changes the mask.
108 Intel thought this opcode to be used in interrupt handlers which
109 would block all exceptions. */
112 /* Save the current signal mask. */
114 cfi_adjust_cfa_offset (4)
115 cfi_rel_offset (ebx, 0)
116 leal oSIGMASK(%eax), %edx
118 movl $SIG_BLOCK, %ebx
119 movl $__NR_sigprocmask, %eax
122 cfi_adjust_cfa_offset (-4)
124 cmpl $-4095, %eax /* Check %eax for error. */
125 jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */
127 /* All done, return 0 for success. */
130 PSEUDO_END(__getcontext)
132 weak_alias (__getcontext, getcontext)