blob: ba3cacf44d5f4cc302ebb0eff6dbaf409ce9c36d [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
39// 3 s0
40// ......
41// 14 s11
42// 15 sp
43// 16 fs0
44// ......
45// 27 fs11
46// 28 checksum
47// _JBLEN: defined in bionic/libc/include/setjmp.h
48
49#define _JB_SIGFLAG 0
50#define _JB_SIGMASK 1 * 8
51#define _JB_RA 2 * 8
52#define _JB_S0 3 * 8
53#define _JB_S1 4 * 8
54#define _JB_S2 5 * 8
55#define _JB_S3 6 * 8
56#define _JB_S4 7 * 8
57#define _JB_S5 8 * 8
58#define _JB_S6 9 * 8
59#define _JB_S7 10 * 8
60#define _JB_S8 11 * 8
61#define _JB_S9 12 * 8
62#define _JB_S10 13 * 8
63#define _JB_S11 14 * 8
64#define _JB_SP 15 * 8
65#define _JB_FS0 16 * 8
66#define _JB_FS1 17 * 8
67#define _JB_FS2 18 * 8
68#define _JB_FS3 19 * 8
69#define _JB_FS4 20 * 8
70#define _JB_FS5 21 * 8
71#define _JB_FS6 22 * 8
72#define _JB_FS7 23 * 8
73#define _JB_FS8 24 * 8
74#define _JB_FS9 25 * 8
75#define _JB_FS10 26 * 8
76#define _JB_FS11 27 * 8
77#define _JB_CHECKSUM 28 * 8
78
79.macro m_mangle_registers reg, sp_reg
80 xor s0, s0, \reg
81 xor s1, s1, \reg
Elliott Hughes9a7155d2023-02-10 02:00:03 +000082 xor a4, a4, \reg // a4 is the masked s2 (x18) for SCS.
Elliott Hughese1905ed2022-10-17 23:23:36 +000083 xor s3, s3, \reg
84 xor s4, s4, \reg
85 xor s5, s5, \reg
86 xor s6, s6, \reg
87 xor s7, s7, \reg
88 xor s8, s8, \reg
89 xor s9, s9, \reg
90 xor s10, s10, \reg
91 xor s11, s11, \reg
92 xor \sp_reg, \sp_reg, \reg
93.endm
94
95.macro m_calculate_checksum dst, src, scratch
96 li \dst, 0
97 .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
98 ld \scratch, (\i * 8)(\src)
99 xor \dst, \dst, \scratch
100 .endr
101.endm
102
103.macro m_unmangle_registers reg, sp_reg
104 m_mangle_registers \reg, sp_reg=\sp_reg
105.endm
106
107ENTRY(setjmp)
108__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
109 li a1, 1
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000110 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000111END(setjmp)
112
113ENTRY(_setjmp)
114__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
115 li a1, 0
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000116 tail sigsetjmp
Elliott Hughese1905ed2022-10-17 23:23:36 +0000117END(_setjmp)
118
119// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
120ENTRY(sigsetjmp)
121__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
122 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.
155 // We only store the low bits of x18 to avoid leaking the
156 // shadow call stack address into memory.
157 // See the SCS commentary in pthread_internal.h for more detail.
158 li a4, SCS_MASK
159 and a4, a4, x18
160
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)
165 sd s0, _JB_S0(a0)
166 sd s1, _JB_S1(a0)
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000167 sd a4, _JB_S2(a0) // a4 is the masked s2 (x18) for SCS.
Elliott Hughese1905ed2022-10-17 23:23:36 +0000168 sd s3, _JB_S3(a0)
169 sd s4, _JB_S4(a0)
170 sd s5, _JB_S5(a0)
171 sd s6, _JB_S6(a0)
172 sd s7, _JB_S7(a0)
173 sd s8, _JB_S8(a0)
174 sd s9, _JB_S9(a0)
175 sd s10, _JB_S10(a0)
176 sd s11, _JB_S11(a0)
Elliott Hughes45a84862022-10-18 23:04:12 +0000177 sd a2, _JB_SP(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000178 m_unmangle_registers a1, sp_reg=a2
179
180 // Save floating point registers.
181 fsd fs0, _JB_FS0(a0)
182 fsd fs1, _JB_FS1(a0)
183 fsd fs2, _JB_FS2(a0)
184 fsd fs3, _JB_FS3(a0)
185 fsd fs4, _JB_FS4(a0)
186 fsd fs5, _JB_FS5(a0)
187 fsd fs6, _JB_FS6(a0)
188 fsd fs7, _JB_FS7(a0)
189 fsd fs8, _JB_FS8(a0)
190 fsd fs9, _JB_FS9(a0)
191 fsd fs10, _JB_FS10(a0)
192 fsd fs11, _JB_FS11(a0)
193
194 // Calculate the checksum and save it.
195 m_calculate_checksum t0, a0, t1
196 sd t0, _JB_CHECKSUM(a0)
197
198 li a0, 0
199 ret
200END(sigsetjmp)
201
202// void siglongjmp(sigjmp_buf env, int value);
203ENTRY(siglongjmp)
204__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
205 // Check the checksum before doing anything.
206 m_calculate_checksum t0, a0, t1
207 ld t1, _JB_CHECKSUM(a0)
208 bne t0, t1, 3f
209
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)
239 ld s0, _JB_S0(a0)
240 ld s1, _JB_S1(a0)
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000241 ld a4, _JB_S2(a0) // Don't clobber s2 (x18) used for SCS yet.
Elliott Hughese1905ed2022-10-17 23:23:36 +0000242 ld s3, _JB_S3(a0)
243 ld s4, _JB_S4(a0)
244 ld s5, _JB_S5(a0)
245 ld s6, _JB_S6(a0)
246 ld s7, _JB_S7(a0)
247 ld s8, _JB_S8(a0)
248 ld s9, _JB_S9(a0)
249 ld s10, _JB_S10(a0)
250 ld s11, _JB_S11(a0)
251 ld a3, _JB_SP(a0)
252 m_unmangle_registers a2, sp_reg=a3
253 mv sp, a3
254
Elliott Hughes9a7155d2023-02-10 02:00:03 +0000255 // Restore the low bits of the shadow call stack pointer.
256 li a5, ~SCS_MASK
257 and x18, x18, a5
258 or x18, a4, x18
259
Elliott Hughese1905ed2022-10-17 23:23:36 +0000260 addi sp, sp, -24
261 sd ra, 0(sp)
262 sd a0, 8(sp)
263 sd a1, 16(sp)
264 ld a0, _JB_SIGFLAG(a0)
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000265 call __bionic_setjmp_cookie_check
Elliott Hughese1905ed2022-10-17 23:23:36 +0000266 ld ra, 0(sp)
267 ld a0, 8(sp)
268 ld a1, 16(sp)
269 addi sp, sp, 24
270
271 // Restore floating point registers.
272 fld fs0, _JB_FS0(a0)
273 fld fs1, _JB_FS1(a0)
274 fld fs2, _JB_FS2(a0)
275 fld fs3, _JB_FS3(a0)
276 fld fs4, _JB_FS4(a0)
277 fld fs5, _JB_FS5(a0)
278 fld fs6, _JB_FS6(a0)
279 fld fs7, _JB_FS7(a0)
280 fld fs8, _JB_FS8(a0)
281 fld fs9, _JB_FS9(a0)
282 fld fs10, _JB_FS10(a0)
283 fld fs11, _JB_FS11(a0)
284
285 // Set return value.
286 beqz a1, 2f
287 li a0, 1
2882:
289 mv a0, a1
290 ret
291
2923:
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000293 call __bionic_setjmp_checksum_mismatch
Elliott Hughese1905ed2022-10-17 23:23:36 +0000294END(siglongjmp)
295
296ALIAS_SYMBOL(longjmp, siglongjmp)
297__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
298ALIAS_SYMBOL(_longjmp, siglongjmp)
299__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)