]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/__longjmp.S
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / i386 / __longjmp.S
CommitLineData
e3726b05 1/* longjmp for i386.
6d7e8eda 2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
c57abfa7 3 This file is part of the GNU C Library.
e3726b05 4
c57abfa7 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
e3726b05 9
c57abfa7
UD
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
41bdb6e2 13 Lesser General Public License for more details.
e3726b05 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
e3726b05
RM
18
19#include <sysdep.h>
88f4b692 20#include <pointer_guard.h>
a7140723 21#include <jmpbuf-offsets.h>
faaee1f0 22#include <jmp_buf-ssp.h>
e5f88e0c 23#include <asm-syntax.h>
8422c9a5 24#include <stap-probe.h>
e3726b05 25
faaee1f0
L
26/* Don't restore shadow stack register if
27 1. Shadow stack isn't enabled. Or
28 2. __longjmp is defined for __longjmp_cancel.
29 */
30#if !SHSTK_ENABLED || defined __longjmp
31# undef SHADOW_STACK_POINTER_OFFSET
32#endif
33
e7535de7 34 .text
da97dfdc 35ENTRY (__longjmp)
272b2898 36#ifdef PTR_DEMANGLE
da97dfdc 37 movl 4(%esp), %eax /* User's jmp_buf in %eax. */
272b2898 38
faaee1f0
L
39# ifdef SHADOW_STACK_POINTER_OFFSET
40# if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
41 /* Check if Shadow Stack is enabled. */
42 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
43 jz L(skip_ssp)
44# else
45 xorl %edx, %edx
46# endif
47 /* Check and adjust the Shadow-Stack-Pointer. */
48 rdsspd %edx
49 /* And compare it with the saved ssp value. */
50 subl SHADOW_STACK_POINTER_OFFSET(%eax), %edx
51 je L(skip_ssp)
52 /* Count the number of frames to adjust and adjust it
53 with incssp instruction. The instruction can adjust
54 the ssp by [0..255] value only thus use a loop if
55 the number of frames is bigger than 255. */
56 negl %edx
57 shrl $2, %edx
58 /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
59 restoring Shadow-Stack-Pointer of setjmp's caller, we
60 need to unwind shadow stack by one more frame. */
61 addl $1, %edx
62 movl $255, %ebx
63L(loop):
64 cmpl %ebx, %edx
65 cmovb %edx, %ebx
66 incsspd %ebx
67 subl %ebx, %edx
68 ja L(loop)
69L(skip_ssp):
70# endif
272b2898
UD
71 /* Save the return address now. */
72 movl (JB_PC*4)(%eax), %edx
73 /* Get the stack pointer. */
74 movl (JB_SP*4)(%eax), %ecx
75 PTR_DEMANGLE (%edx)
76 PTR_DEMANGLE (%ecx)
8422c9a5 77 LIBC_PROBE (longjmp, 3, 4@%eax, -4@8(%esp), 4@%edx)
272b2898
UD
78 cfi_def_cfa(%eax, 0)
79 cfi_register(%eip, %edx)
80 cfi_register(%esp, %ecx)
81 cfi_offset(%ebx, JB_BX*4)
82 cfi_offset(%esi, JB_SI*4)
83 cfi_offset(%edi, JB_DI*4)
84 cfi_offset(%ebp, JB_BP*4)
350635a5 85 /* Restore registers. */
272b2898
UD
86 movl (JB_BX*4)(%eax), %ebx
87 movl (JB_SI*4)(%eax), %esi
88 movl (JB_DI*4)(%eax), %edi
89 movl (JB_BP*4)(%eax), %ebp
90 cfi_restore(%ebx)
91 cfi_restore(%esi)
92 cfi_restore(%edi)
93 cfi_restore(%ebp)
94
8422c9a5 95 LIBC_PROBE (longjmp_target, 3, 4@%eax, -4@8(%esp), 4@%edx)
da97dfdc 96 movl 8(%esp), %eax /* Second argument is return value. */
272b2898
UD
97 movl %ecx, %esp
98#else
da97dfdc 99 movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */
da97dfdc 100 movl 8(%esp), %eax /* Second argument is return value. */
faaee1f0
L
101# ifdef SHADOW_STACK_POINTER_OFFSET
102# if IS_IN (libc) && defined SHARED
103 /* Check if Shadow Stack is enabled. */
104 testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
105 jz L(skip_ssp)
106# endif
107 /* Check and adjust the Shadow-Stack-Pointer. */
108 xorl %edx, %edx
109 /* Get the current ssp. */
110 rdsspd %edx
111 /* And compare it with the saved ssp value. */
112 subl SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
113 je L(skip_ssp)
114 /* Count the number of frames to adjust and adjust it
115 with incssp instruction. The instruction can adjust
116 the ssp by [0..255] value only thus use a loop if
117 the number of frames is bigger than 255. */
118 negl %edx
119 shrl $2, %edx
120 /* NB: We saved Shadow-Stack-Pointer of setjmp. Since we are
121 restoring Shadow-Stack-Pointer of setjmp's caller, we
122 need to unwind shadow stack by one more frame. */
123 addl $1, %edx
124 movl $255, %ebx
125L(loop):
126 cmpl %ebx, %edx
127 cmovb %edx, %ebx
128 incsspd %ebx
129 subl %ebx, %edx
130 ja L(loop)
131L(skip_ssp):
132# endif
14e9dd67
UD
133 /* Save the return address now. */
134 movl (JB_PC*4)(%ecx), %edx
8422c9a5 135 LIBC_PROBE (longjmp, 3, 4@%ecx, -4@%eax, 4@%edx)
350635a5 136 /* Restore registers. */
44c8d1a2
RM
137 movl (JB_BX*4)(%ecx), %ebx
138 movl (JB_SI*4)(%ecx), %esi
139 movl (JB_DI*4)(%ecx), %edi
140 movl (JB_BP*4)(%ecx), %ebp
141 movl (JB_SP*4)(%ecx), %esp
8422c9a5 142 LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%ecx, 4@%edx)
827b7087 143#endif
e3726b05 144 /* Jump to saved PC. */
350635a5 145 jmp *%edx
da97dfdc 146END (__longjmp)