elf: Fix _dl_debug_vdprintf to work before self-relocation
[glibc.git] / sysdeps / unix / sysv / linux / i386 / ____longjmp_chk.S
blobed688c015528fabc999da3ffb564c44c3b7633d1
1 /* Copyright (C) 2001-2023 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
18 #include <sysdep.h>
19 #include <pointer_guard.h>
20 #include <jmpbuf-offsets.h>
21 #include <jmp_buf-ssp.h>
22 #include <asm-syntax.h>
23 #include <stap-probe.h>
25 /* Don't restore shadow stack register if shadow stack isn't enabled.  */
26 #if !SHSTK_ENABLED
27 # undef SHADOW_STACK_POINTER_OFFSET
28 #endif
30         .section .rodata.str1.1,"aMS",@progbits,1
31         .type   longjmp_msg,@object
32 longjmp_msg:
33         .string "longjmp causes uninitialized stack frame"
34         .size   longjmp_msg, .-longjmp_msg
37 #ifdef PIC
38 # define CALL_FAIL      movl    %ebx, %ecx;                                   \
39                         cfi_register(%ebx,%ecx);                              \
40                         LOAD_PIC_REG (bx);                                    \
41                         leal    longjmp_msg@GOTOFF(%ebx), %eax;               \
42                         movl    %eax, (%esp);                                 \
43                         call    HIDDEN_JUMPTARGET(__fortify_fail)
44 #else
45 # define CALL_FAIL      movl    $longjmp_msg, %eax;                           \
46                         movl    %eax, (%esp);                                 \
47                         call    HIDDEN_JUMPTARGET(__fortify_fail)
48 #endif
51         .text
52 ENTRY (____longjmp_chk)
53         movl    4(%esp), %ecx   /* User's jmp_buf in %ecx.  */
55 #ifdef SHADOW_STACK_POINTER_OFFSET
56 # if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET
57         /* Check if Shadow Stack is enabled.  */
58         testl   $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET
59         jz      L(skip_ssp)
60 # else
61         xorl    %edx, %edx
62 # endif
63         /* Check and adjust the Shadow-Stack-Pointer.  */
64         rdsspd  %edx
65         /* And compare it with the saved ssp value.  */
66         subl    SHADOW_STACK_POINTER_OFFSET(%ecx), %edx
67         je      L(skip_ssp)
68         /* Count the number of frames to adjust and adjust it
69            with incssp instruction.  The instruction can adjust
70            the ssp by [0..255] value only thus use a loop if
71            the number of frames is bigger than 255.  */
72         negl    %edx
73         shrl    $2, %edx
74         /* NB: We saved Shadow-Stack-Pointer of setjmp.  Since we are
75                restoring Shadow-Stack-Pointer of setjmp's caller, we
76                need to unwind shadow stack by one more frame.  */
77         addl    $1, %edx
78         movl    $255, %ebx
79 L(loop):
80         cmpl    %ebx, %edx
81         cmovb   %edx, %ebx
82         incsspd %ebx
83         subl    %ebx, %edx
84         ja      L(loop)
85 L(skip_ssp):
86 #endif
87         /* Save the return address now.  */
88         movl    (JB_PC*4)(%ecx), %edx
89         /* Get the stack pointer.  */
90         movl    (JB_SP*4)(%ecx), %edi
91         cfi_undefined(%edi)
92         PTR_DEMANGLE (%edx)
93         PTR_DEMANGLE (%edi)
95         cmpl    %edi, %esp
96         jbe     .Lok
98         subl    $12, %esp
99         cfi_adjust_cfa_offset(12)
100         xorl    %ebx, %ebx
101         movl    %esp, %ecx
102         movl    $__NR_sigaltstack, %eax
103         ENTER_KERNEL
104         /* Without working sigaltstack we cannot perform the test.  */
105         test    %eax, %eax
106         jne     .Lok2
107         testl   $1, 4(%esp)
108         jz      .Lfail
110         movl    (%esp), %eax
111         addl    8(%esp), %eax
112         subl    %edi, %eax
113         cmpl    8(%esp), %eax
114         jae     .Lok2
116 .Lfail: CALL_FAIL
118 .Lok2:  addl    $12, %esp
119         cfi_adjust_cfa_offset(-12)
120         movl    4(%esp), %ecx
122 .Lok:
123         LIBC_PROBE (longjmp, 3, 4@%ecx, -4@8(%esp), 4@%edx)
124         /* We add unwind information for the target here.  */
125         cfi_def_cfa(%ecx, 0)
126         cfi_register(%eip, %edx)
127         cfi_register(%esp, %edi)
128         cfi_offset(%ebx, JB_BX*4)
129         cfi_offset(%esi, JB_SI*4)
130         cfi_offset(%edi, JB_DI*4)
131         cfi_offset(%ebp, JB_BP*4)
133         movl    8(%esp), %eax   /* Second argument is return value.  */
134         movl    %edi, %esp
136         /* Restore registers.  */
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         cfi_restore(%ebx)
142         cfi_restore(%esi)
143         cfi_restore(%edi)
144         cfi_restore(%ebp)
146         /* Jump to saved PC.  */
147         LIBC_PROBE (longjmp_target, 3, 4@%ecx, -4@%eax, 4@%edx)
148         jmp     *%edx
149 END (____longjmp_chk)