blob: 812cfd1ac11022186eaeee3246a659b66a2b84e6 [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
110 tail PIC_PLT(sigsetjmp)
111END(setjmp)
112
113ENTRY(_setjmp)
114__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
115 li a1, 0
116 tail PIC_PLT(sigsetjmp)
117END(_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
129 call PIC_PLT(__bionic_setjmp_cookie_get)
130 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.
142 call PIC_PLT(sigprocmask)
143
144 ld a1, 8(sp)
145
1461:
147 // Restore original a0/a1/ra.
148 ld a0, 0(sp)
149 ld a1, 8(sp)
150 ld ra, 16(sp)
151 addi sp, sp, 24
152
153 // Mask off the signal flag bit.
154 andi a1, a1, -2
155
156 // Save core registers.
157 mv a2, sp
158 m_mangle_registers a1, sp_reg=a2
159 sd ra, _JB_RA(a0)
160 sd s0, _JB_S0(a0)
161 sd s1, _JB_S1(a0)
162 sd s2, _JB_S2(a0)
163 sd s3, _JB_S3(a0)
164 sd s4, _JB_S4(a0)
165 sd s5, _JB_S5(a0)
166 sd s6, _JB_S6(a0)
167 sd s7, _JB_S7(a0)
168 sd s8, _JB_S8(a0)
169 sd s9, _JB_S9(a0)
170 sd s10, _JB_S10(a0)
171 sd s11, _JB_S11(a0)
172 sd sp, _JB_SP(a0)
173 m_unmangle_registers a1, sp_reg=a2
174
175 // Save floating point registers.
176 fsd fs0, _JB_FS0(a0)
177 fsd fs1, _JB_FS1(a0)
178 fsd fs2, _JB_FS2(a0)
179 fsd fs3, _JB_FS3(a0)
180 fsd fs4, _JB_FS4(a0)
181 fsd fs5, _JB_FS5(a0)
182 fsd fs6, _JB_FS6(a0)
183 fsd fs7, _JB_FS7(a0)
184 fsd fs8, _JB_FS8(a0)
185 fsd fs9, _JB_FS9(a0)
186 fsd fs10, _JB_FS10(a0)
187 fsd fs11, _JB_FS11(a0)
188
189 // Calculate the checksum and save it.
190 m_calculate_checksum t0, a0, t1
191 sd t0, _JB_CHECKSUM(a0)
192
193 li a0, 0
194 ret
195END(sigsetjmp)
196
197// void siglongjmp(sigjmp_buf env, int value);
198ENTRY(siglongjmp)
199__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
200 // Check the checksum before doing anything.
201 m_calculate_checksum t0, a0, t1
202 ld t1, _JB_CHECKSUM(a0)
203 bne t0, t1, 3f
204
205 // Do we need to restore the signal mask?
206 ld a2, _JB_SIGFLAG(a0)
207 andi a3, a2, 1
208 beqz a3, 1f
209
210 addi sp, sp, -16
211 sd a0, 0(sp)
212 sd ra, 8(sp)
213
214 // Restore the signal mask.
215 mv t0, a1 // Save 'value'.
216
217 mv a2, a0
218 li a0, 2 // SIG_SETMASK
219 addi a1, a2, _JB_SIGMASK // new_mask
220 li a2, 0 // NULL
221 call PIC_PLT(sigprocmask)
222 mv a1, t0 // Restore 'value'.
223
224 // Restore original a0 and ra.
225 ld a0, 0(sp)
226 ld ra, 8(sp)
227 addi sp, sp, 16
228
229 ld a2, _JB_SIGFLAG(a0)
2301:
231 // Restore core registers.
232 andi a2, a2, -2
233 ld ra, _JB_RA(a0)
234 ld s0, _JB_S0(a0)
235 ld s1, _JB_S1(a0)
236 ld s2, _JB_S2(a0)
237 ld s3, _JB_S3(a0)
238 ld s4, _JB_S4(a0)
239 ld s5, _JB_S5(a0)
240 ld s6, _JB_S6(a0)
241 ld s7, _JB_S7(a0)
242 ld s8, _JB_S8(a0)
243 ld s9, _JB_S9(a0)
244 ld s10, _JB_S10(a0)
245 ld s11, _JB_S11(a0)
246 ld a3, _JB_SP(a0)
247 m_unmangle_registers a2, sp_reg=a3
248 mv sp, a3
249
250 addi sp, sp, -24
251 sd ra, 0(sp)
252 sd a0, 8(sp)
253 sd a1, 16(sp)
254 ld a0, _JB_SIGFLAG(a0)
255 call PIC_PLT(__bionic_setjmp_cookie_check)
256 ld ra, 0(sp)
257 ld a0, 8(sp)
258 ld a1, 16(sp)
259 addi sp, sp, 24
260
261 // Restore floating point registers.
262 fld fs0, _JB_FS0(a0)
263 fld fs1, _JB_FS1(a0)
264 fld fs2, _JB_FS2(a0)
265 fld fs3, _JB_FS3(a0)
266 fld fs4, _JB_FS4(a0)
267 fld fs5, _JB_FS5(a0)
268 fld fs6, _JB_FS6(a0)
269 fld fs7, _JB_FS7(a0)
270 fld fs8, _JB_FS8(a0)
271 fld fs9, _JB_FS9(a0)
272 fld fs10, _JB_FS10(a0)
273 fld fs11, _JB_FS11(a0)
274
275 // Set return value.
276 beqz a1, 2f
277 li a0, 1
2782:
279 mv a0, a1
280 ret
281
2823:
283 call PIC_PLT(__bionic_setjmp_checksum_mismatch)
284END(siglongjmp)
285
286ALIAS_SYMBOL(longjmp, siglongjmp)
287__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
288ALIAS_SYMBOL(_longjmp, siglongjmp)
289__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)