blob: 26f7ec9d37b1f460b2fbe0cd4ca650e39141dfde [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
110ENTRY(setjmp)
111__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
112 li a1, 1
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000113 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000114END(setjmp)
115
116ENTRY(_setjmp)
117__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
118 li a1, 0
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000119 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000120END(_setjmp)
121
122// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
123ENTRY(sigsetjmp)
124__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
125 addi sp, sp, -24
126 sd a0, 0(sp)
127 sd a1, 8(sp)
128 sd ra, 16(sp)
129
130 // Get the cookie and store it along with the signal flag.
131 mv a0, a1
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000132 call __bionic_setjmp_cookie_get
Elliott Hughese1905ed2022-10-17 23:23:36 +0000133 mv a1, a0
134 ld a0, 0(sp)
135 sd a1, _JB_SIGFLAG(a0)
136
137 // Do we need to save the signal mask?
138 andi a1, a1, 1
139 beqz a1, 1f
140
141 // Save current signal mask.
142 // The 'how'/a0 argument is ignored if set is NULL.
143 li a1, 0 // NULL
144 addi a2, a0, _JB_SIGMASK // old_mask.
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000145 call sigprocmask
Elliott Hughese1905ed2022-10-17 23:23:36 +0000146
Elliott Hughese1905ed2022-10-17 23:23:36 +00001471:
Elliott Hughes45a84862022-10-18 23:04:12 +0000148 // Restore original a0/ra.
Elliott Hughese1905ed2022-10-17 23:23:36 +0000149 ld a0, 0(sp)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000150 ld ra, 16(sp)
151 addi sp, sp, 24
152
Elliott Hughes45a84862022-10-18 23:04:12 +0000153 // Get the cookie.
154 ld a1, _JB_SIGFLAG(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000155 andi a1, a1, -2
156
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000157 // Mask off the high bits of the shadow call stack pointer.
Elliott Hughes7dd38962023-04-06 14:50:31 -0700158 // We only store the low bits of gp to avoid leaking the
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000159 // shadow call stack address into memory.
160 // See the SCS commentary in pthread_internal.h for more detail.
161 li a4, SCS_MASK
Elliott Hughes7dd38962023-04-06 14:50:31 -0700162 and a4, a4, gp
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000163
Elliott Hughese1905ed2022-10-17 23:23:36 +0000164 // Save core registers.
165 mv a2, sp
166 m_mangle_registers a1, sp_reg=a2
167 sd ra, _JB_RA(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700168 sd a4, _JB_GP(a0) // a4 is the masked gp (x3) for SCS.
169 sd a2, _JB_SP(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000170 sd s0, _JB_S0(a0)
171 sd s1, _JB_S1(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700172 sd s2, _JB_S2(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000173 sd s3, _JB_S3(a0)
174 sd s4, _JB_S4(a0)
175 sd s5, _JB_S5(a0)
176 sd s6, _JB_S6(a0)
177 sd s7, _JB_S7(a0)
178 sd s8, _JB_S8(a0)
179 sd s9, _JB_S9(a0)
180 sd s10, _JB_S10(a0)
181 sd s11, _JB_S11(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000182 m_unmangle_registers a1, sp_reg=a2
183
184 // Save floating point registers.
185 fsd fs0, _JB_FS0(a0)
186 fsd fs1, _JB_FS1(a0)
187 fsd fs2, _JB_FS2(a0)
188 fsd fs3, _JB_FS3(a0)
189 fsd fs4, _JB_FS4(a0)
190 fsd fs5, _JB_FS5(a0)
191 fsd fs6, _JB_FS6(a0)
192 fsd fs7, _JB_FS7(a0)
193 fsd fs8, _JB_FS8(a0)
194 fsd fs9, _JB_FS9(a0)
195 fsd fs10, _JB_FS10(a0)
196 fsd fs11, _JB_FS11(a0)
197
198 // Calculate the checksum and save it.
199 m_calculate_checksum t0, a0, t1
200 sd t0, _JB_CHECKSUM(a0)
201
202 li a0, 0
203 ret
204END(sigsetjmp)
205
206// void siglongjmp(sigjmp_buf env, int value);
207ENTRY(siglongjmp)
208__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
209 // Check the checksum before doing anything.
210 m_calculate_checksum t0, a0, t1
211 ld t1, _JB_CHECKSUM(a0)
212 bne t0, t1, 3f
213
214 // Do we need to restore the signal mask?
215 ld a2, _JB_SIGFLAG(a0)
216 andi a3, a2, 1
217 beqz a3, 1f
218
219 addi sp, sp, -16
220 sd a0, 0(sp)
221 sd ra, 8(sp)
222
223 // Restore the signal mask.
224 mv t0, a1 // Save 'value'.
225
226 mv a2, a0
227 li a0, 2 // SIG_SETMASK
228 addi a1, a2, _JB_SIGMASK // new_mask
229 li a2, 0 // NULL
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000230 call sigprocmask
Elliott Hughese1905ed2022-10-17 23:23:36 +0000231 mv a1, t0 // Restore 'value'.
232
233 // Restore original a0 and ra.
234 ld a0, 0(sp)
235 ld ra, 8(sp)
236 addi sp, sp, 16
237
238 ld a2, _JB_SIGFLAG(a0)
2391:
240 // Restore core registers.
241 andi a2, a2, -2
242 ld ra, _JB_RA(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700243 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 +0000244 ld s0, _JB_S0(a0)
245 ld s1, _JB_S1(a0)
Elliott Hughes7dd38962023-04-06 14:50:31 -0700246 ld s2, _JB_S2(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000247 ld s3, _JB_S3(a0)
248 ld s4, _JB_S4(a0)
249 ld s5, _JB_S5(a0)
250 ld s6, _JB_S6(a0)
251 ld s7, _JB_S7(a0)
252 ld s8, _JB_S8(a0)
253 ld s9, _JB_S9(a0)
254 ld s10, _JB_S10(a0)
255 ld s11, _JB_S11(a0)
256 ld a3, _JB_SP(a0)
257 m_unmangle_registers a2, sp_reg=a3
258 mv sp, a3
259
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000260 // Restore the low bits of the shadow call stack pointer.
261 li a5, ~SCS_MASK
Elliott Hughes7dd38962023-04-06 14:50:31 -0700262 and gp, gp, a5
263 or gp, gp, a4
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000264
Elliott Hughese1905ed2022-10-17 23:23:36 +0000265 addi sp, sp, -24
266 sd ra, 0(sp)
267 sd a0, 8(sp)
268 sd a1, 16(sp)
269 ld a0, _JB_SIGFLAG(a0)
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000270 call __bionic_setjmp_cookie_check
Elliott Hughese1905ed2022-10-17 23:23:36 +0000271 ld ra, 0(sp)
272 ld a0, 8(sp)
273 ld a1, 16(sp)
274 addi sp, sp, 24
275
276 // Restore floating point registers.
277 fld fs0, _JB_FS0(a0)
278 fld fs1, _JB_FS1(a0)
279 fld fs2, _JB_FS2(a0)
280 fld fs3, _JB_FS3(a0)
281 fld fs4, _JB_FS4(a0)
282 fld fs5, _JB_FS5(a0)
283 fld fs6, _JB_FS6(a0)
284 fld fs7, _JB_FS7(a0)
285 fld fs8, _JB_FS8(a0)
286 fld fs9, _JB_FS9(a0)
287 fld fs10, _JB_FS10(a0)
288 fld fs11, _JB_FS11(a0)
289
290 // Set return value.
291 beqz a1, 2f
292 li a0, 1
2932:
294 mv a0, a1
295 ret
296
2973:
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000298 call __bionic_setjmp_checksum_mismatch
Elliott Hughese1905ed2022-10-17 23:23:36 +0000299END(siglongjmp)
300
301ALIAS_SYMBOL(longjmp, siglongjmp)
302__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
303ALIAS_SYMBOL(_longjmp, siglongjmp)
304__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)