blob: 5de10992c43e351cd97c22e7d3eae8bdeae22040 [file] [log] [blame]
Elliott Hughese1905ed2022-10-17 23:23:36 +00001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <private/bionic_asm.h>
30#include <private/bionic_constants.h>
31
32// The internal structure of a jmp_buf is totally private.
33// Current layout (changes from release to release):
34//
35// word name description
36// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
37// 1 sigmask 64-bit signal mask
38// 2 ra
Elliott Hughes7dd38962023-04-06 14:50:31 -070039// 3 sp
40// 4 gp
41// 5 s0
Elliott Hughese1905ed2022-10-17 23:23:36 +000042// ......
Elliott Hughes7dd38962023-04-06 14:50:31 -070043// 16 s11
44// 17 fs0
Elliott Hughese1905ed2022-10-17 23:23:36 +000045// ......
Elliott Hughes7dd38962023-04-06 14:50:31 -070046// 28 fs11
47// 29 checksum
Elliott Hughese1905ed2022-10-17 23:23:36 +000048// _JBLEN: defined in bionic/libc/include/setjmp.h
49
50#define _JB_SIGFLAG 0
51#define _JB_SIGMASK 1 * 8
52#define _JB_RA 2 * 8
Elliott Hughes7dd38962023-04-06 14:50:31 -070053#define _JB_SP 3 * 8
54#define _JB_GP 4 * 8
55#define _JB_S0 5 * 8
56#define _JB_S1 6 * 8
57#define _JB_S2 7 * 8
58#define _JB_S3 8 * 8
59#define _JB_S4 9 * 8
60#define _JB_S5 10 * 8
61#define _JB_S6 11 * 8
62#define _JB_S7 12 * 8
63#define _JB_S8 13 * 8
64#define _JB_S9 14 * 8
65#define _JB_S10 15 * 8
66#define _JB_S11 16 * 8
67#define _JB_FS0 17 * 8
68#define _JB_FS1 18 * 8
69#define _JB_FS2 19 * 8
70#define _JB_FS3 20 * 8
71#define _JB_FS4 21 * 8
72#define _JB_FS5 22 * 8
73#define _JB_FS6 23 * 8
74#define _JB_FS7 24 * 8
75#define _JB_FS8 25 * 8
76#define _JB_FS9 26 * 8
77#define _JB_FS10 27 * 8
78#define _JB_FS11 28 * 8
79#define _JB_CHECKSUM 29 * 8
Elliott Hughese1905ed2022-10-17 23:23:36 +000080
81.macro m_mangle_registers reg, sp_reg
82 xor s0, s0, \reg
83 xor s1, s1, \reg
Elliott Hughes7dd38962023-04-06 14:50:31 -070084 xor s2, s2, \reg
Elliott Hughese1905ed2022-10-17 23:23:36 +000085 xor s3, s3, \reg
86 xor s4, s4, \reg
87 xor s5, s5, \reg
88 xor s6, s6, \reg
89 xor s7, s7, \reg
90 xor s8, s8, \reg
91 xor s9, s9, \reg
92 xor s10, s10, \reg
93 xor s11, s11, \reg
Elliott Hughes7dd38962023-04-06 14:50:31 -070094 xor a4, a4, \reg // a4 is the masked gp (x3) for SCS.
Elliott Hughese1905ed2022-10-17 23:23:36 +000095 xor \sp_reg, \sp_reg, \reg
96.endm
97
98.macro m_calculate_checksum dst, src, scratch
99 li \dst, 0
Elliott Hughes7dd38962023-04-06 14:50:31 -0700100 .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
Elliott Hughese1905ed2022-10-17 23:23:36 +0000101 ld \scratch, (\i * 8)(\src)
102 xor \dst, \dst, \scratch
103 .endr
104.endm
105
106.macro m_unmangle_registers reg, sp_reg
107 m_mangle_registers \reg, sp_reg=\sp_reg
108.endm
109
Elliott Hughesd7831202024-01-19 20:55:31 +0000110ENTRY_WEAK_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000111 li a1, 1
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000112 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000113END(setjmp)
114
Elliott Hughesd7831202024-01-19 20:55:31 +0000115ENTRY_WEAK_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000116 li a1, 0
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000117 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000118END(_setjmp)
119
120// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
Elliott Hughesd7831202024-01-19 20:55:31 +0000121ENTRY_WEAK_FOR_NATIVE_BRIDGE(sigsetjmp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000122 addi sp, sp, -24
123 sd a0, 0(sp)
124 sd a1, 8(sp)
125 sd ra, 16(sp)
126
127 // Get the cookie and store it along with the signal flag.
128 mv a0, a1
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000129 call __bionic_setjmp_cookie_get
Elliott Hughese1905ed2022-10-17 23:23:36 +0000130 mv a1, a0
131 ld a0, 0(sp)
132 sd a1, _JB_SIGFLAG(a0)
133
134 // Do we need to save the signal mask?
135 andi a1, a1, 1
136 beqz a1, 1f
137
138 // Save current signal mask.
139 // The 'how'/a0 argument is ignored if set is NULL.
140 li a1, 0 // NULL
141 addi a2, a0, _JB_SIGMASK // old_mask.
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000142 call sigprocmask
Elliott Hughese1905ed2022-10-17 23:23:36 +0000143
Elliott Hughese1905ed2022-10-17 23:23:36 +00001441:
Elliott Hughes45a84862022-10-18 23:04:12 +0000145 // Restore original a0/ra.
Elliott Hughese1905ed2022-10-17 23:23:36 +0000146 ld a0, 0(sp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000147 ld ra, 16(sp)
148 addi sp, sp, 24
149
Elliott Hughes45a84862022-10-18 23:04:12 +0000150 // Get the cookie.
151 ld a1, _JB_SIGFLAG(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000152 andi a1, a1, -2
153
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000154 // Mask off the high bits of the shadow call stack pointer.
Elliott Hughes7dd38962023-04-06 14:50:31 -0700155 // We only store the low bits of gp to avoid leaking the
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000156 // shadow call stack address into memory.
157 // See the SCS commentary in pthread_internal.h for more detail.
158 li a4, SCS_MASK
Elliott Hughes7dd38962023-04-06 14:50:31 -0700159 and a4, a4, gp
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000160
Elliott Hughese1905ed2022-10-17 23:23:36 +0000161 // Save core registers.
162 mv a2, sp
163 m_mangle_registers a1, sp_reg=a2
164 sd ra, _JB_RA(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700165 sd a4, _JB_GP(a0) // a4 is the masked gp (x3) for SCS.
166 sd a2, _JB_SP(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000167 sd s0, _JB_S0(a0)
168 sd s1, _JB_S1(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700169 sd s2, _JB_S2(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000170 sd s3, _JB_S3(a0)
171 sd s4, _JB_S4(a0)
172 sd s5, _JB_S5(a0)
173 sd s6, _JB_S6(a0)
174 sd s7, _JB_S7(a0)
175 sd s8, _JB_S8(a0)
176 sd s9, _JB_S9(a0)
177 sd s10, _JB_S10(a0)
178 sd s11, _JB_S11(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000179 m_unmangle_registers a1, sp_reg=a2
180
181 // Save floating point registers.
182 fsd fs0, _JB_FS0(a0)
183 fsd fs1, _JB_FS1(a0)
184 fsd fs2, _JB_FS2(a0)
185 fsd fs3, _JB_FS3(a0)
186 fsd fs4, _JB_FS4(a0)
187 fsd fs5, _JB_FS5(a0)
188 fsd fs6, _JB_FS6(a0)
189 fsd fs7, _JB_FS7(a0)
190 fsd fs8, _JB_FS8(a0)
191 fsd fs9, _JB_FS9(a0)
192 fsd fs10, _JB_FS10(a0)
193 fsd fs11, _JB_FS11(a0)
194
195 // Calculate the checksum and save it.
196 m_calculate_checksum t0, a0, t1
197 sd t0, _JB_CHECKSUM(a0)
198
199 li a0, 0
200 ret
201END(sigsetjmp)
202
203// void siglongjmp(sigjmp_buf env, int value);
Elliott Hughesd7831202024-01-19 20:55:31 +0000204ENTRY_WEAK_FOR_NATIVE_BRIDGE(siglongjmp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000205 // Check the checksum before doing anything.
206 m_calculate_checksum t0, a0, t1
207 ld t1, _JB_CHECKSUM(a0)
Elliott Hughes9e892492024-04-08 16:32:25 +0000208 bne t0, t1, L(checksum_failure)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000209
210 // Do we need to restore the signal mask?
211 ld a2, _JB_SIGFLAG(a0)
212 andi a3, a2, 1
213 beqz a3, 1f
214
215 addi sp, sp, -16
216 sd a0, 0(sp)
217 sd ra, 8(sp)
218
219 // Restore the signal mask.
220 mv t0, a1 // Save 'value'.
221
222 mv a2, a0
223 li a0, 2 // SIG_SETMASK
224 addi a1, a2, _JB_SIGMASK // new_mask
225 li a2, 0 // NULL
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000226 call sigprocmask
Elliott Hughese1905ed2022-10-17 23:23:36 +0000227 mv a1, t0 // Restore 'value'.
228
229 // Restore original a0 and ra.
230 ld a0, 0(sp)
231 ld ra, 8(sp)
232 addi sp, sp, 16
233
234 ld a2, _JB_SIGFLAG(a0)
2351:
236 // Restore core registers.
237 andi a2, a2, -2
238 ld ra, _JB_RA(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700239 ld a4, _JB_GP(a0) // Don't clobber the upper bits of gp (x3) used for SCS yet.
Elliott Hughese1905ed2022-10-17 23:23:36 +0000240 ld s0, _JB_S0(a0)
241 ld s1, _JB_S1(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700242 ld s2, _JB_S2(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000243 ld s3, _JB_S3(a0)
244 ld s4, _JB_S4(a0)
245 ld s5, _JB_S5(a0)
246 ld s6, _JB_S6(a0)
247 ld s7, _JB_S7(a0)
248 ld s8, _JB_S8(a0)
249 ld s9, _JB_S9(a0)
250 ld s10, _JB_S10(a0)
251 ld s11, _JB_S11(a0)
252 ld a3, _JB_SP(a0)
253 m_unmangle_registers a2, sp_reg=a3
254 mv sp, a3
255
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000256 // Restore the low bits of the shadow call stack pointer.
257 li a5, ~SCS_MASK
Elliott Hughes7dd38962023-04-06 14:50:31 -0700258 and gp, gp, a5
259 or gp, gp, a4
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000260
Elliott Hughese1905ed2022-10-17 23:23:36 +0000261 addi sp, sp, -24
262 sd ra, 0(sp)
263 sd a0, 8(sp)
264 sd a1, 16(sp)
265 ld a0, _JB_SIGFLAG(a0)
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000266 call __bionic_setjmp_cookie_check
Elliott Hughese1905ed2022-10-17 23:23:36 +0000267 ld ra, 0(sp)
268 ld a0, 8(sp)
269 ld a1, 16(sp)
270 addi sp, sp, 24
271
272 // Restore floating point registers.
273 fld fs0, _JB_FS0(a0)
274 fld fs1, _JB_FS1(a0)
275 fld fs2, _JB_FS2(a0)
276 fld fs3, _JB_FS3(a0)
277 fld fs4, _JB_FS4(a0)
278 fld fs5, _JB_FS5(a0)
279 fld fs6, _JB_FS6(a0)
280 fld fs7, _JB_FS7(a0)
281 fld fs8, _JB_FS8(a0)
282 fld fs9, _JB_FS9(a0)
283 fld fs10, _JB_FS10(a0)
284 fld fs11, _JB_FS11(a0)
285
286 // Set return value.
287 beqz a1, 2f
288 li a0, 1
2892:
290 mv a0, a1
291 ret
292
Elliott Hughes9e892492024-04-08 16:32:25 +0000293L(checksum_failure):
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000294 call __bionic_setjmp_checksum_mismatch
Elliott Hughese1905ed2022-10-17 23:23:36 +0000295END(siglongjmp)
296
Elliott Hughesd7831202024-01-19 20:55:31 +0000297ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(longjmp, siglongjmp)
298ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(_longjmp, siglongjmp)