blob: d3d25d429943580800546deb6310eb1e9fe47c95 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
2 * Copyright (c) 1997 Mark Brinicombe
Elliott Hughesdfb74c52016-10-24 12:53:17 -07003 * Copyright (C) 2010 The Android Open Source Project
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Mark Brinicombe
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
Elliott Hughes851e68a2014-02-19 16:53:20 -080034#include <private/bionic_asm.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080035
Elliott Hughesb3932992014-12-05 15:39:51 -080036// According to the ARM AAPCS document, we only need to save
37// the following registers:
38//
Josh Gaoa4c69132016-03-02 19:03:17 -080039// Core r4-r11, sp, lr
40// AAPCS 5.1.1:
41// A subroutine must preserve the contents of the registers r4-r8, r10, r11
42// and SP (and r9 in PCS variants that designate r9 as v6).
Elliott Hughesb3932992014-12-05 15:39:51 -080043//
Josh Gaoa4c69132016-03-02 19:03:17 -080044// VFP d8-d15
45// AAPCS 5.1.2.1:
Elliott Hughesb3932992014-12-05 15:39:51 -080046// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
47// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
48// (and can be used for passing arguments or returning results in standard
49// procedure-call variants). Registers d16-d31 (q8-q15), if present, do
50// not need to be preserved.
51//
52// FPSCR saved because glibc does.
53
54// The internal structure of a jmp_buf is totally private.
Josh Gaoa4c69132016-03-02 19:03:17 -080055// Current layout (changes from release to release):
Elliott Hughesb3932992014-12-05 15:39:51 -080056//
Josh Gao7fda8d22015-09-10 15:40:24 -070057// word name description
58// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
Elliott Hughes460130b2018-01-31 09:05:26 -080059// 1 sigmask 64-bit signal mask (not used with _setjmp / _longjmp)
60// 2 " "
Elliott Hughese58d49e2018-02-05 13:36:02 -080061// 3 reserved (unused to allow float_base to be maximally aligned;
62// this avoids software emulation of unaligned loads/stores)
Elliott Hughes460130b2018-01-31 09:05:26 -080063// 4 float_base base of float registers (d8 to d15)
64// 20 float_state floating-point status and control register
65// 21 core_base base of core registers (r4-r11, r13-r14)
Elliott Hughese58d49e2018-02-05 13:36:02 -080066// 31 checksum checksum of all of the core registers, to give better error messages
Elliott Hughes460130b2018-01-31 09:05:26 -080067// 32 reserved reserved entries (room to grow)
Elliott Hughese58d49e2018-02-05 13:36:02 -080068// ...
69// 63 " "
Elliott Hughesb3932992014-12-05 15:39:51 -080070
Elliott Hughes75096222014-12-08 16:01:20 -080071#define _JB_SIGFLAG 0
Elliott Hughes460130b2018-01-31 09:05:26 -080072#define _JB_SIGMASK (_JB_SIGFLAG + 1)
73#define _JB_FLOAT_BASE (_JB_SIGMASK + 3)
Elliott Hughesb3932992014-12-05 15:39:51 -080074#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
75#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
Josh Gaoa4c69132016-03-02 19:03:17 -080076#define _JB_CHECKSUM (_JB_CORE_BASE+10)
Elliott Hughesb3932992014-12-05 15:39:51 -080077
Elliott Hughesd7831202024-01-19 20:55:31 +000078ENTRY_WEAK_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080079 mov r1, #1
80 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080081END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080082
Elliott Hughesd7831202024-01-19 20:55:31 +000083ENTRY_WEAK_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080084 mov r1, #0
85 b sigsetjmp
86END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080087
Josh Gaoa4c69132016-03-02 19:03:17 -080088.macro m_calculate_checksum dst, src, scratch
89 mov \dst, #0
90 .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
91 ldr \scratch, [\src, #(\i * 4)]
92 eor \dst, \dst, \scratch
93 .endr
94.endm
95
Elliott Hughesb3932992014-12-05 15:39:51 -080096// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
Elliott Hughesd7831202024-01-19 20:55:31 +000097ENTRY_WEAK_FOR_NATIVE_BRIDGE(sigsetjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -070098 stmfd sp!, {r0, lr}
99 .cfi_def_cfa_offset 8
100 .cfi_rel_offset r0, 0
101 .cfi_rel_offset lr, 4
102
103 mov r0, r1
104 bl __bionic_setjmp_cookie_get
105 mov r1, r0
106
107 ldmfd sp, {r0}
108
109 // Save the setjmp cookie for later.
110 bic r2, r1, #1
111 stmfd sp!, {r2}
112 .cfi_adjust_cfa_offset 4
113
114 // Record the setjmp cookie and whether or not we're saving the signal mask.
Elliott Hughes75096222014-12-08 16:01:20 -0800115 str r1, [r0, #(_JB_SIGFLAG * 4)]
116
Elliott Hughesb3932992014-12-05 15:39:51 -0800117 // Do we need to save the signal mask?
Josh Gao7fda8d22015-09-10 15:40:24 -0700118 tst r1, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800119 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800120
Josh Gao7fda8d22015-09-10 15:40:24 -0700121 // Align the stack.
122 sub sp, #4
123 .cfi_adjust_cfa_offset 4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800124
Josh Gao7fda8d22015-09-10 15:40:24 -0700125 // Save the current signal mask.
126 add r2, r0, #(_JB_SIGMASK * 4)
127 mov r0, #2 // SIG_SETMASK
128 mov r1, #0
Elliott Hughes460130b2018-01-31 09:05:26 -0800129 bl sigprocmask64
Josh Gao7fda8d22015-09-10 15:40:24 -0700130
131 // Unalign the stack.
132 add sp, #4
133 .cfi_adjust_cfa_offset -4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800134
Elliott Hughesb3932992014-12-05 15:39:51 -08001351:
Josh Gao7fda8d22015-09-10 15:40:24 -0700136 ldmfd sp!, {r2}
137 .cfi_adjust_cfa_offset -4
138 ldmfd sp!, {r0, lr}
139 .cfi_adjust_cfa_offset -8
140 .cfi_restore r0
141 .cfi_restore lr
142
Elliott Hughesb3932992014-12-05 15:39:51 -0800143 // Save core registers.
144 add r1, r0, #(_JB_CORE_BASE * 4)
Elliott Hughesc0d41db2021-04-02 18:02:38 -0700145 // Mangle the easy registers in-place, write them out in one go, and unmangle
146 // them again.
147 eor r4, r4, r2
148 eor r5, r5, r2
149 eor r6, r6, r2
150 eor r7, r7, r2
151 eor r8, r8, r2
152 eor r9, r9, r2
153 eor r10, r10, r2
154 eor r11, r11, r2
155 stmia r1, {r4-r11}
156 eor r4, r4, r2
157 eor r5, r5, r2
158 eor r6, r6, r2
159 eor r7, r7, r2
160 eor r8, r8, r2
161 eor r9, r9, r2
162 eor r10, r10, r2
163 eor r11, r11, r2
164 // We need to avoid invalid values in sp or lr (http://b/152210274).
165 eor r3, lr, r2
166 str r3, [r1, #(8 * 4)]
167 eor r3, sp, r2
168 str r3, [r1, #(9 * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800169
Elliott Hughesb3932992014-12-05 15:39:51 -0800170 // Save floating-point registers.
171 add r1, r0, #(_JB_FLOAT_BASE * 4)
172 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700173
Elliott Hughesb3932992014-12-05 15:39:51 -0800174 // Save floating-point state.
175 fmrx r1, fpscr
176 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800177
Josh Gaoa4c69132016-03-02 19:03:17 -0800178 // Calculate the checksum.
179 m_calculate_checksum r12, r0, r2
180 str r12, [r0, #(_JB_CHECKSUM * 4)]
Josh Gaoa4c69132016-03-02 19:03:17 -0800181
Elliott Hughesb3932992014-12-05 15:39:51 -0800182 mov r0, #0
183 bx lr
184END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800185
Elliott Hughesb3932992014-12-05 15:39:51 -0800186// void siglongjmp(sigjmp_buf env, int value);
Elliott Hughesd7831202024-01-19 20:55:31 +0000187ENTRY_WEAK_FOR_NATIVE_BRIDGE(siglongjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700188 stmfd sp!, {r0, r1, lr}
Elliott Hughesb3932992014-12-05 15:39:51 -0800189 .cfi_def_cfa_offset 12
190 .cfi_rel_offset r0, 0
191 .cfi_rel_offset r1, 4
Josh Gao7fda8d22015-09-10 15:40:24 -0700192 .cfi_rel_offset lr, 8
Elliott Hughesb3932992014-12-05 15:39:51 -0800193
Josh Gaoa4c69132016-03-02 19:03:17 -0800194 // Check the checksum before doing anything.
195 m_calculate_checksum r12, r0, r3
196 ldr r2, [r0, #(_JB_CHECKSUM * 4)]
Josh Gaoa4c69132016-03-02 19:03:17 -0800197 teq r2, r12
198 bne __bionic_setjmp_checksum_mismatch
Josh Gaoa4c69132016-03-02 19:03:17 -0800199
Josh Gao7fda8d22015-09-10 15:40:24 -0700200 // Fetch the signal flag.
201 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
202
203 // Do we need to restore the signal mask?
204 ands r1, r1, #1
205 beq 1f
206
207 // Restore the signal mask.
Elliott Hughes7ebafb32018-01-29 10:23:01 -0800208 mov r2, #0
209 add r1, r0, #(_JB_SIGMASK * 4)
210 mov r0, #2 // SIG_SETMASK
Elliott Hughes460130b2018-01-31 09:05:26 -0800211 bl sigprocmask64
Elliott Hughesb3932992014-12-05 15:39:51 -0800212
Elliott Hughesb3932992014-12-05 15:39:51 -08002131:
Josh Gao7fda8d22015-09-10 15:40:24 -0700214 ldmfd sp!, {r0, r1, lr}
215 .cfi_adjust_cfa_offset -12
216 .cfi_restore r0
217 .cfi_restore r1
218 .cfi_restore lr
219
Elliott Hughesb3932992014-12-05 15:39:51 -0800220 // Restore floating-point registers.
221 add r2, r0, #(_JB_FLOAT_BASE * 4)
222 vldmia r2, {d8-d15}
223
224 // Restore floating-point state.
225 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
226 fmxr fpscr, r2
227
Josh Gaoa4c69132016-03-02 19:03:17 -0800228 // Load the cookie.
Josh Gao7fda8d22015-09-10 15:40:24 -0700229 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
230 bic r3, r3, #1
Josh Gaoa4c69132016-03-02 19:03:17 -0800231
232 // Restore core registers.
Elliott Hughesb3932992014-12-05 15:39:51 -0800233 add r2, r0, #(_JB_CORE_BASE * 4)
Josh Gaob24d7432015-10-19 12:56:50 -0700234
Elliott Hughesc0d41db2021-04-02 18:02:38 -0700235 // Do all the easy registers in one go.
236 ldmia r2, {r4-r11}
237 eor r4, r4, r3
238 eor r5, r5, r3
239 eor r6, r6, r3
240 eor r7, r7, r3
241 eor r8, r8, r3
242 eor r9, r9, r3
243 eor r10, r10, r3
244 eor r11, r11, r3
245 // We need to avoid invalid values in sp or lr (http://b/152210274).
246 ldr r0, [r2, #(8 * 4)]
247 eor lr, r0, r3
248 ldr r0, [r2, #(9 * 4)]
249 eor sp, r0, r3
Elliott Hughesb3932992014-12-05 15:39:51 -0800250
Josh Gao7fda8d22015-09-10 15:40:24 -0700251 // Save the return value/address and check the setjmp cookie.
252 stmfd sp!, {r1, lr}
253 .cfi_adjust_cfa_offset 8
254 .cfi_rel_offset lr, 4
255 mov r0, r3
256 bl __bionic_setjmp_cookie_check
Elliott Hughesb3932992014-12-05 15:39:51 -0800257
Josh Gao7fda8d22015-09-10 15:40:24 -0700258 // Restore return value/address.
259 ldmfd sp!, {r0, lr}
260 .cfi_adjust_cfa_offset -8
261 .cfi_restore lr
262
Elliott Hughesb3932992014-12-05 15:39:51 -0800263 teq r0, #0
264 moveq r0, #1
265 bx lr
266END(siglongjmp)
267
Elliott Hughesd7831202024-01-19 20:55:31 +0000268ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(longjmp, siglongjmp)
269ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(_longjmp, siglongjmp)