1 | /* Copyright (C) 1997-2022 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 <jmpbuf-offsets.h> |
21 | #include <stap-probe.h> |
22 | |
23 | /* __longjmp(jmpbuf, val) */ |
24 | |
25 | ENTRY (__longjmp) |
26 | cfi_def_cfa(x0, 0) |
27 | cfi_offset(x19, JB_X19<<3) |
28 | cfi_offset(x20, JB_X20<<3) |
29 | cfi_offset(x21, JB_X21<<3) |
30 | cfi_offset(x22, JB_X22<<3) |
31 | cfi_offset(x23, JB_X23<<3) |
32 | cfi_offset(x24, JB_X24<<3) |
33 | cfi_offset(x25, JB_X25<<3) |
34 | cfi_offset(x26, JB_X26<<3) |
35 | cfi_offset(x27, JB_X27<<3) |
36 | cfi_offset(x28, JB_X28<<3) |
37 | cfi_offset(x29, JB_X29<<3) |
38 | cfi_offset(x30, JB_LR<<3) |
39 | |
40 | cfi_offset( d8, JB_D8<<3) |
41 | cfi_offset( d9, JB_D9<<3) |
42 | cfi_offset(d10, JB_D10<<3) |
43 | cfi_offset(d11, JB_D11<<3) |
44 | cfi_offset(d12, JB_D12<<3) |
45 | cfi_offset(d13, JB_D13<<3) |
46 | cfi_offset(d14, JB_D14<<3) |
47 | cfi_offset(d15, JB_D15<<3) |
48 | |
49 | PTR_ARG (0) |
50 | |
51 | ldp x19, x20, [x0, #JB_X19<<3] |
52 | ldp x21, x22, [x0, #JB_X21<<3] |
53 | ldp x23, x24, [x0, #JB_X23<<3] |
54 | ldp x25, x26, [x0, #JB_X25<<3] |
55 | ldp x27, x28, [x0, #JB_X27<<3] |
56 | #ifdef PTR_DEMANGLE |
57 | ldp x29, x4, [x0, #JB_X29<<3] |
58 | PTR_DEMANGLE (30, 4, 3, 2) |
59 | #else |
60 | ldp x29, x30, [x0, #JB_X29<<3] |
61 | #endif |
62 | /* longjmp probe takes 3 arguments, address of jump buffer as |
63 | first argument (8@x0), return value as second argument (-4@x1), |
64 | and target address (8@x30), respectively. */ |
65 | LIBC_PROBE (longjmp, 3, 8@x0, -4@x1, 8@x30) |
66 | ldp d8, d9, [x0, #JB_D8<<3] |
67 | ldp d10, d11, [x0, #JB_D10<<3] |
68 | ldp d12, d13, [x0, #JB_D12<<3] |
69 | ldp d14, d15, [x0, #JB_D14<<3] |
70 | |
71 | /* Originally this was implemented with a series of |
72 | .cfi_restore() directives. |
73 | |
74 | The theory was that cfi_restore should revert to previous |
75 | frame value is the same as the current value. In practice |
76 | this doesn't work, even after cfi_restore() gdb continues |
77 | to try to recover a previous frame value offset from x0, |
78 | which gets stuffed after a few more instructions. The |
79 | cfi_same_value() mechanism appears to work fine. */ |
80 | |
81 | cfi_same_value(x19) |
82 | cfi_same_value(x20) |
83 | cfi_same_value(x21) |
84 | cfi_same_value(x22) |
85 | cfi_same_value(x23) |
86 | cfi_same_value(x24) |
87 | cfi_same_value(x25) |
88 | cfi_same_value(x26) |
89 | cfi_same_value(x27) |
90 | cfi_same_value(x28) |
91 | cfi_same_value(x29) |
92 | cfi_same_value(x30) |
93 | cfi_same_value(d8) |
94 | cfi_same_value(d9) |
95 | cfi_same_value(d10) |
96 | cfi_same_value(d11) |
97 | cfi_same_value(d12) |
98 | cfi_same_value(d13) |
99 | cfi_same_value(d14) |
100 | cfi_same_value(d15) |
101 | #ifdef PTR_DEMANGLE |
102 | ldr x4, [x0, #JB_SP<<3] |
103 | PTR_DEMANGLE (5, 4, 3, 2) |
104 | #else |
105 | ldr x5, [x0, #JB_SP<<3] |
106 | #endif |
107 | mov sp, x5 |
108 | |
109 | /* longjmp_target probe takes 3 arguments, address of jump buffer |
110 | as first argument (8@x0), return value as second argument (-4@x1), |
111 | and target address (8@x30), respectively. */ |
112 | LIBC_PROBE (longjmp_target, 3, 8@x0, -4@x1, 8@x30) |
113 | cmp x1, #0 |
114 | mov x0, #1 |
115 | csel x0, x1, x0, ne |
116 | /* Use br instead of ret because ret is guaranteed to mispredict */ |
117 | br x30 |
118 | END (__longjmp) |
119 | |