]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 2001-2019 Free Software Foundation, Inc. |
c9cf6dde AJ |
2 | This file is part of the GNU C Library. |
3 | ||
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. | |
8 | ||
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. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
c9cf6dde AJ |
17 | |
18 | #include <sysdep.h> | |
a7140723 | 19 | #include <jmpbuf-offsets.h> |
faaee1f0 | 20 | #include <jmp_buf-ssp.h> |
c9cf6dde | 21 | #include <asm-syntax.h> |
8422c9a5 | 22 | #include <stap-probe.h> |
c9cf6dde | 23 | |
faaee1f0 L |
24 | /* Don't restore shadow stack register if |
25 | 1. Shadow stack isn't enabled. Or | |
26 | 2. __longjmp is defined for __longjmp_cancel. | |
27 | */ | |
28 | #if !SHSTK_ENABLED || defined __longjmp | |
29 | # undef SHADOW_STACK_POINTER_OFFSET | |
30 | #endif | |
31 | ||
c9cf6dde AJ |
32 | /* Jump to the position specified by ENV, causing the |
33 | setjmp call there to return VAL, or 1 if VAL is 0. | |
34 | void __longjmp (__jmp_buf env, int val). */ | |
e7535de7 | 35 | .text |
c9cf6dde AJ |
36 | ENTRY(__longjmp) |
37 | /* Restore registers. */ | |
eda41706 | 38 | mov (JB_RSP*8)(%rdi),%R8_LP |
6c7fb145 | 39 | mov (JB_RBP*8)(%rdi),%R9_LP |
eda41706 | 40 | mov (JB_PC*8)(%rdi),%RDX_LP |
ff8fecbe | 41 | #ifdef PTR_DEMANGLE |
eda41706 | 42 | PTR_DEMANGLE (%R8_LP) |
6c7fb145 | 43 | PTR_DEMANGLE (%R9_LP) |
eda41706 | 44 | PTR_DEMANGLE (%RDX_LP) |
6c7fb145 RM |
45 | # ifdef __ILP32__ |
46 | /* We ignored the high bits of the %rbp value because only the low | |
47 | bits are mangled. But we cannot presume that %rbp is being used | |
48 | as a pointer and truncate it, so recover the high bits. */ | |
49 | movl (JB_RBP*8 + 4)(%rdi), %eax | |
50 | shlq $32, %rax | |
51 | orq %rax, %r9 | |
52 | # endif | |
faaee1f0 L |
53 | #endif |
54 | #ifdef SHADOW_STACK_POINTER_OFFSET | |
55 | # if IS_IN (libc) && defined SHARED && defined FEATURE_1_OFFSET | |
56 | /* Check if Shadow Stack is enabled. */ | |
57 | testl $X86_FEATURE_1_SHSTK, %fs:FEATURE_1_OFFSET | |
58 | jz L(skip_ssp) | |
59 | # else | |
60 | xorl %eax, %eax | |
61 | # endif | |
62 | /* Check and adjust the Shadow-Stack-Pointer. */ | |
63 | /* Get the current ssp. */ | |
64 | rdsspq %rax | |
65 | /* And compare it with the saved ssp value. */ | |
66 | subq SHADOW_STACK_POINTER_OFFSET(%rdi), %rax | |
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 | negq %rax | |
73 | shrq $3, %rax | |
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 | addq $1, %rax | |
78 | ||
79 | movl $255, %ebx | |
80 | L(loop): | |
81 | cmpq %rbx, %rax | |
82 | cmovb %rax, %rbx | |
83 | incsspq %rbx | |
84 | subq %rbx, %rax | |
85 | ja L(loop) | |
86 | ||
87 | L(skip_ssp): | |
ff8fecbe | 88 | #endif |
8422c9a5 | 89 | LIBC_PROBE (longjmp, 3, LP_SIZE@%RDI_LP, -4@%esi, LP_SIZE@%RDX_LP) |
7e7458e3 AJ |
90 | /* We add unwind information for the target here. */ |
91 | cfi_def_cfa(%rdi, 0) | |
ff8fecbe UD |
92 | cfi_register(%rsp,%r8) |
93 | cfi_register(%rbp,%r9) | |
94 | cfi_register(%rip,%rdx) | |
7e7458e3 | 95 | cfi_offset(%rbx,JB_RBX*8) |
7e7458e3 AJ |
96 | cfi_offset(%r12,JB_R12*8) |
97 | cfi_offset(%r13,JB_R13*8) | |
98 | cfi_offset(%r14,JB_R14*8) | |
99 | cfi_offset(%r15,JB_R15*8) | |
c9cf6dde | 100 | movq (JB_RBX*8)(%rdi),%rbx |
c9cf6dde AJ |
101 | movq (JB_R12*8)(%rdi),%r12 |
102 | movq (JB_R13*8)(%rdi),%r13 | |
103 | movq (JB_R14*8)(%rdi),%r14 | |
104 | movq (JB_R15*8)(%rdi),%r15 | |
105 | /* Set return value for setjmp. */ | |
c9cf6dde | 106 | mov %esi, %eax |
eda41706 | 107 | mov %R8_LP,%RSP_LP |
ff8fecbe | 108 | movq %r9,%rbp |
8422c9a5 RM |
109 | LIBC_PROBE (longjmp_target, 3, |
110 | LP_SIZE@%RDI_LP, -4@%eax, LP_SIZE@%RDX_LP) | |
c9cf6dde | 111 | jmpq *%rdx |
5ead9ce5 | 112 | END (__longjmp) |