1 | /* Copyright (C) 1997-2024 Free Software Foundation, Inc. |
2 | |
3 | This file is part of the GNU C Library. |
4 | |
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 License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | License, or (at your option) any later version. |
9 | |
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. |
14 | |
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/>. */ |
18 | |
19 | #include <sysdep.h> |
20 | #include <pointer_guard.h> |
21 | #include <jmpbuf-offsets.h> |
22 | #include <stap-probe.h> |
23 | |
24 | /* __longjmp(jmpbuf, val) */ |
25 | |
26 | ENTRY (__longjmp) |
27 | cfi_def_cfa(x0, 0) |
28 | cfi_offset(x19, JB_X19<<3) |
29 | cfi_offset(x20, JB_X20<<3) |
30 | cfi_offset(x21, JB_X21<<3) |
31 | cfi_offset(x22, JB_X22<<3) |
32 | cfi_offset(x23, JB_X23<<3) |
33 | cfi_offset(x24, JB_X24<<3) |
34 | cfi_offset(x25, JB_X25<<3) |
35 | cfi_offset(x26, JB_X26<<3) |
36 | cfi_offset(x27, JB_X27<<3) |
37 | cfi_offset(x28, JB_X28<<3) |
38 | cfi_offset(x29, JB_X29<<3) |
39 | cfi_offset(x30, JB_LR<<3) |
40 | |
41 | cfi_offset( d8, JB_D8<<3) |
42 | cfi_offset( d9, JB_D9<<3) |
43 | cfi_offset(d10, JB_D10<<3) |
44 | cfi_offset(d11, JB_D11<<3) |
45 | cfi_offset(d12, JB_D12<<3) |
46 | cfi_offset(d13, JB_D13<<3) |
47 | cfi_offset(d14, JB_D14<<3) |
48 | cfi_offset(d15, JB_D15<<3) |
49 | |
50 | PTR_ARG (0) |
51 | |
52 | #if IS_IN(libc) |
53 | /* Disable ZA state of SME in libc.a and libc.so, but not in ld.so. */ |
54 | # if HAVE_AARCH64_PAC_RET |
55 | PACIASP |
56 | cfi_window_save |
57 | # endif |
58 | stp x29, x30, [sp, -16]! |
59 | cfi_adjust_cfa_offset (16) |
60 | cfi_rel_offset (x29, 0) |
61 | cfi_rel_offset (x30, 8) |
62 | mov x29, sp |
63 | bl __libc_arm_za_disable |
64 | ldp x29, x30, [sp], 16 |
65 | cfi_adjust_cfa_offset (-16) |
66 | cfi_restore (x29) |
67 | cfi_restore (x30) |
68 | # if HAVE_AARCH64_PAC_RET |
69 | AUTIASP |
70 | cfi_window_save |
71 | # endif |
72 | #endif |
73 | |
74 | ldp x19, x20, [x0, #JB_X19<<3] |
75 | ldp x21, x22, [x0, #JB_X21<<3] |
76 | ldp x23, x24, [x0, #JB_X23<<3] |
77 | ldp x25, x26, [x0, #JB_X25<<3] |
78 | ldp x27, x28, [x0, #JB_X27<<3] |
79 | #ifdef PTR_DEMANGLE |
80 | ldp x29, x4, [x0, #JB_X29<<3] |
81 | PTR_DEMANGLE (30, 4, 3, 2) |
82 | #else |
83 | ldp x29, x30, [x0, #JB_X29<<3] |
84 | #endif |
85 | /* longjmp probe takes 3 arguments, address of jump buffer as |
86 | first argument (8@x0), return value as second argument (-4@x1), |
87 | and target address (8@x30), respectively. */ |
88 | LIBC_PROBE (longjmp, 3, 8@x0, -4@x1, 8@x30) |
89 | ldp d8, d9, [x0, #JB_D8<<3] |
90 | ldp d10, d11, [x0, #JB_D10<<3] |
91 | ldp d12, d13, [x0, #JB_D12<<3] |
92 | ldp d14, d15, [x0, #JB_D14<<3] |
93 | |
94 | /* Originally this was implemented with a series of |
95 | .cfi_restore() directives. |
96 | |
97 | The theory was that cfi_restore should revert to previous |
98 | frame value is the same as the current value. In practice |
99 | this doesn't work, even after cfi_restore() gdb continues |
100 | to try to recover a previous frame value offset from x0, |
101 | which gets stuffed after a few more instructions. The |
102 | cfi_same_value() mechanism appears to work fine. */ |
103 | |
104 | cfi_same_value(x19) |
105 | cfi_same_value(x20) |
106 | cfi_same_value(x21) |
107 | cfi_same_value(x22) |
108 | cfi_same_value(x23) |
109 | cfi_same_value(x24) |
110 | cfi_same_value(x25) |
111 | cfi_same_value(x26) |
112 | cfi_same_value(x27) |
113 | cfi_same_value(x28) |
114 | cfi_same_value(x29) |
115 | cfi_same_value(x30) |
116 | cfi_same_value(d8) |
117 | cfi_same_value(d9) |
118 | cfi_same_value(d10) |
119 | cfi_same_value(d11) |
120 | cfi_same_value(d12) |
121 | cfi_same_value(d13) |
122 | cfi_same_value(d14) |
123 | cfi_same_value(d15) |
124 | #ifdef PTR_DEMANGLE |
125 | ldr x4, [x0, #JB_SP<<3] |
126 | PTR_DEMANGLE (5, 4, 3, 2) |
127 | #else |
128 | ldr x5, [x0, #JB_SP<<3] |
129 | #endif |
130 | mov sp, x5 |
131 | |
132 | /* longjmp_target probe takes 3 arguments, address of jump buffer |
133 | as first argument (8@x0), return value as second argument (-4@x1), |
134 | and target address (8@x30), respectively. */ |
135 | LIBC_PROBE (longjmp_target, 3, 8@x0, -4@x1, 8@x30) |
136 | cmp x1, #0 |
137 | mov x0, #1 |
138 | csel x0, x1, x0, ne |
139 | /* Use br instead of ret because ret is guaranteed to mispredict */ |
140 | br x30 |
141 | END (__longjmp) |
142 | |