blob: eea2978303cc2f81040f13bd1a3c88c03ea1b590 [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
82 xor s2, s2, \reg
83 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
154 // Save core registers.
155 mv a2, sp
156 m_mangle_registers a1, sp_reg=a2
157 sd ra, _JB_RA(a0)
158 sd s0, _JB_S0(a0)
159 sd s1, _JB_S1(a0)
160 sd s2, _JB_S2(a0)
161 sd s3, _JB_S3(a0)
162 sd s4, _JB_S4(a0)
163 sd s5, _JB_S5(a0)
164 sd s6, _JB_S6(a0)
165 sd s7, _JB_S7(a0)
166 sd s8, _JB_S8(a0)
167 sd s9, _JB_S9(a0)
168 sd s10, _JB_S10(a0)
169 sd s11, _JB_S11(a0)
Elliott Hughes45a84862022-10-18 23:04:12 +0000170 sd a2, _JB_SP(a0)
Elliott Hughese1905ed2022-10-17 23:23:36 +0000171 m_unmangle_registers a1, sp_reg=a2
172
173 // Save floating point registers.
174 fsd fs0, _JB_FS0(a0)
175 fsd fs1, _JB_FS1(a0)
176 fsd fs2, _JB_FS2(a0)
177 fsd fs3, _JB_FS3(a0)
178 fsd fs4, _JB_FS4(a0)
179 fsd fs5, _JB_FS5(a0)
180 fsd fs6, _JB_FS6(a0)
181 fsd fs7, _JB_FS7(a0)
182 fsd fs8, _JB_FS8(a0)
183 fsd fs9, _JB_FS9(a0)
184 fsd fs10, _JB_FS10(a0)
185 fsd fs11, _JB_FS11(a0)
186
187 // Calculate the checksum and save it.
188 m_calculate_checksum t0, a0, t1
189 sd t0, _JB_CHECKSUM(a0)
190
191 li a0, 0
192 ret
193END(sigsetjmp)
194
195// void siglongjmp(sigjmp_buf env, int value);
196ENTRY(siglongjmp)
197__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
198 // Check the checksum before doing anything.
199 m_calculate_checksum t0, a0, t1
200 ld t1, _JB_CHECKSUM(a0)
201 bne t0, t1, 3f
202
203 // Do we need to restore the signal mask?
204 ld a2, _JB_SIGFLAG(a0)
205 andi a3, a2, 1
206 beqz a3, 1f
207
208 addi sp, sp, -16
209 sd a0, 0(sp)
210 sd ra, 8(sp)
211
212 // Restore the signal mask.
213 mv t0, a1 // Save 'value'.
214
215 mv a2, a0
216 li a0, 2 // SIG_SETMASK
217 addi a1, a2, _JB_SIGMASK // new_mask
218 li a2, 0 // NULL
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000219 call sigprocmask
Elliott Hughese1905ed2022-10-17 23:23:36 +0000220 mv a1, t0 // Restore 'value'.
221
222 // Restore original a0 and ra.
223 ld a0, 0(sp)
224 ld ra, 8(sp)
225 addi sp, sp, 16
226
227 ld a2, _JB_SIGFLAG(a0)
2281:
229 // Restore core registers.
230 andi a2, a2, -2
231 ld ra, _JB_RA(a0)
232 ld s0, _JB_S0(a0)
233 ld s1, _JB_S1(a0)
234 ld s2, _JB_S2(a0)
235 ld s3, _JB_S3(a0)
236 ld s4, _JB_S4(a0)
237 ld s5, _JB_S5(a0)
238 ld s6, _JB_S6(a0)
239 ld s7, _JB_S7(a0)
240 ld s8, _JB_S8(a0)
241 ld s9, _JB_S9(a0)
242 ld s10, _JB_S10(a0)
243 ld s11, _JB_S11(a0)
244 ld a3, _JB_SP(a0)
245 m_unmangle_registers a2, sp_reg=a3
246 mv sp, a3
247
248 addi sp, sp, -24
249 sd ra, 0(sp)
250 sd a0, 8(sp)
251 sd a1, 16(sp)
252 ld a0, _JB_SIGFLAG(a0)
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000253 call __bionic_setjmp_cookie_check
Elliott Hughese1905ed2022-10-17 23:23:36 +0000254 ld ra, 0(sp)
255 ld a0, 8(sp)
256 ld a1, 16(sp)
257 addi sp, sp, 24
258
259 // Restore floating point registers.
260 fld fs0, _JB_FS0(a0)
261 fld fs1, _JB_FS1(a0)
262 fld fs2, _JB_FS2(a0)
263 fld fs3, _JB_FS3(a0)
264 fld fs4, _JB_FS4(a0)
265 fld fs5, _JB_FS5(a0)
266 fld fs6, _JB_FS6(a0)
267 fld fs7, _JB_FS7(a0)
268 fld fs8, _JB_FS8(a0)
269 fld fs9, _JB_FS9(a0)
270 fld fs10, _JB_FS10(a0)
271 fld fs11, _JB_FS11(a0)
272
273 // Set return value.
274 beqz a1, 2f
275 li a0, 1
2762:
277 mv a0, a1
278 ret
279
2803:
Elliott Hughes6a1dc512022-10-26 19:53:35 +0000281 call __bionic_setjmp_checksum_mismatch
Elliott Hughese1905ed2022-10-17 23:23:36 +0000282END(siglongjmp)
283
284ALIAS_SYMBOL(longjmp, siglongjmp)
285__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
286ALIAS_SYMBOL(_longjmp, siglongjmp)
287__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)