blob: 30e7e233fc4a7c5c92e197aed2a97b909237a4e6 [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 " "
61// 3 reserved (unused to allow float_base to be maximally aligned)
62// 4 float_base base of float registers (d8 to d15)
63// 20 float_state floating-point status and control register
64// 21 core_base base of core registers (r4-r11, r13-r14)
65// 31 checksum checksum of all of the core registers, to give better error messages.
66// 32 reserved reserved entries (room to grow)
Elliott Hughesb3932992014-12-05 15:39:51 -080067// 64
68//
69// NOTE: float_base must be at an even word index, since the
70// FP registers will be loaded/stored with instructions
71// that expect 8-byte alignment.
72
Elliott Hughes75096222014-12-08 16:01:20 -080073#define _JB_SIGFLAG 0
Elliott Hughes460130b2018-01-31 09:05:26 -080074#define _JB_SIGMASK (_JB_SIGFLAG + 1)
75#define _JB_FLOAT_BASE (_JB_SIGMASK + 3)
Elliott Hughesb3932992014-12-05 15:39:51 -080076#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
77#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
Josh Gaoa4c69132016-03-02 19:03:17 -080078#define _JB_CHECKSUM (_JB_CORE_BASE+10)
Elliott Hughesb3932992014-12-05 15:39:51 -080079
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080080ENTRY(setjmp)
dimitryfa432522017-10-25 13:07:45 +020081__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080082 mov r1, #1
83 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080084END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080085
Elliott Hughesb3932992014-12-05 15:39:51 -080086ENTRY(_setjmp)
dimitryfa432522017-10-25 13:07:45 +020087__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080088 mov r1, #0
89 b sigsetjmp
90END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080091
Josh Gao7fda8d22015-09-10 15:40:24 -070092#define MANGLE_REGISTERS 1
Josh Gaoa4c69132016-03-02 19:03:17 -080093#define USE_CHECKSUM 1
94
Josh Gao7fda8d22015-09-10 15:40:24 -070095.macro m_mangle_registers reg
96#if MANGLE_REGISTERS
97 eor r4, r4, \reg
98 eor r5, r5, \reg
99 eor r6, r6, \reg
100 eor r7, r7, \reg
101 eor r8, r8, \reg
102 eor r9, r9, \reg
103 eor r10, r10, \reg
104 eor r11, r11, \reg
Josh Gao7fda8d22015-09-10 15:40:24 -0700105 eor r13, r13, \reg
106 eor r14, r14, \reg
107#endif
108.endm
109
110.macro m_unmangle_registers reg
111 m_mangle_registers \reg
112.endm
113
Josh Gaoa4c69132016-03-02 19:03:17 -0800114.macro m_calculate_checksum dst, src, scratch
115 mov \dst, #0
116 .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
117 ldr \scratch, [\src, #(\i * 4)]
118 eor \dst, \dst, \scratch
119 .endr
120.endm
121
Elliott Hughesb3932992014-12-05 15:39:51 -0800122// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
123ENTRY(sigsetjmp)
dimitryfa432522017-10-25 13:07:45 +0200124__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700125 stmfd sp!, {r0, lr}
126 .cfi_def_cfa_offset 8
127 .cfi_rel_offset r0, 0
128 .cfi_rel_offset lr, 4
129
130 mov r0, r1
131 bl __bionic_setjmp_cookie_get
132 mov r1, r0
133
134 ldmfd sp, {r0}
135
136 // Save the setjmp cookie for later.
137 bic r2, r1, #1
138 stmfd sp!, {r2}
139 .cfi_adjust_cfa_offset 4
140
141 // Record the setjmp cookie and whether or not we're saving the signal mask.
Elliott Hughes75096222014-12-08 16:01:20 -0800142 str r1, [r0, #(_JB_SIGFLAG * 4)]
143
Elliott Hughesb3932992014-12-05 15:39:51 -0800144 // Do we need to save the signal mask?
Josh Gao7fda8d22015-09-10 15:40:24 -0700145 tst r1, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800146 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800147
Josh Gao7fda8d22015-09-10 15:40:24 -0700148 // Align the stack.
149 sub sp, #4
150 .cfi_adjust_cfa_offset 4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800151
Josh Gao7fda8d22015-09-10 15:40:24 -0700152 // Save the current signal mask.
153 add r2, r0, #(_JB_SIGMASK * 4)
154 mov r0, #2 // SIG_SETMASK
155 mov r1, #0
Elliott Hughes460130b2018-01-31 09:05:26 -0800156 bl sigprocmask64
Josh Gao7fda8d22015-09-10 15:40:24 -0700157
158 // Unalign the stack.
159 add sp, #4
160 .cfi_adjust_cfa_offset -4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800161
Elliott Hughesb3932992014-12-05 15:39:51 -08001621:
Josh Gao7fda8d22015-09-10 15:40:24 -0700163 ldmfd sp!, {r2}
164 .cfi_adjust_cfa_offset -4
165 ldmfd sp!, {r0, lr}
166 .cfi_adjust_cfa_offset -8
167 .cfi_restore r0
168 .cfi_restore lr
169
Elliott Hughesb3932992014-12-05 15:39:51 -0800170 // Save core registers.
171 add r1, r0, #(_JB_CORE_BASE * 4)
Josh Gao7fda8d22015-09-10 15:40:24 -0700172 m_mangle_registers r2
Josh Gaob24d7432015-10-19 12:56:50 -0700173
174 // ARM deprecates using sp in the register list for stmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800175 stmia r1, {r4-r11, lr}
176 str sp, [r1, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700177 m_unmangle_registers r2
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800178
Elliott Hughesb3932992014-12-05 15:39:51 -0800179 // Save floating-point registers.
180 add r1, r0, #(_JB_FLOAT_BASE * 4)
181 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700182
Elliott Hughesb3932992014-12-05 15:39:51 -0800183 // Save floating-point state.
184 fmrx r1, fpscr
185 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800186
Josh Gaoa4c69132016-03-02 19:03:17 -0800187#if USE_CHECKSUM
188 // Calculate the checksum.
189 m_calculate_checksum r12, r0, r2
190 str r12, [r0, #(_JB_CHECKSUM * 4)]
191#endif
192
Elliott Hughesb3932992014-12-05 15:39:51 -0800193 mov r0, #0
194 bx lr
195END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800196
Elliott Hughesb3932992014-12-05 15:39:51 -0800197// void siglongjmp(sigjmp_buf env, int value);
198ENTRY(siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200199__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700200 stmfd sp!, {r0, r1, lr}
Elliott Hughesb3932992014-12-05 15:39:51 -0800201 .cfi_def_cfa_offset 12
202 .cfi_rel_offset r0, 0
203 .cfi_rel_offset r1, 4
Josh Gao7fda8d22015-09-10 15:40:24 -0700204 .cfi_rel_offset lr, 8
Elliott Hughesb3932992014-12-05 15:39:51 -0800205
Josh Gaoa4c69132016-03-02 19:03:17 -0800206#if USE_CHECKSUM
207 // Check the checksum before doing anything.
208 m_calculate_checksum r12, r0, r3
209 ldr r2, [r0, #(_JB_CHECKSUM * 4)]
210
211 teq r2, r12
212 bne __bionic_setjmp_checksum_mismatch
213#endif
214
Josh Gao7fda8d22015-09-10 15:40:24 -0700215 // Fetch the signal flag.
216 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
217
218 // Do we need to restore the signal mask?
219 ands r1, r1, #1
220 beq 1f
221
222 // Restore the signal mask.
Elliott Hughes7ebafb32018-01-29 10:23:01 -0800223 mov r2, #0
224 add r1, r0, #(_JB_SIGMASK * 4)
225 mov r0, #2 // SIG_SETMASK
Elliott Hughes460130b2018-01-31 09:05:26 -0800226 bl sigprocmask64
Elliott Hughesb3932992014-12-05 15:39:51 -0800227
Elliott Hughesb3932992014-12-05 15:39:51 -08002281:
Josh Gao7fda8d22015-09-10 15:40:24 -0700229 ldmfd sp!, {r0, r1, lr}
230 .cfi_adjust_cfa_offset -12
231 .cfi_restore r0
232 .cfi_restore r1
233 .cfi_restore lr
234
Elliott Hughesb3932992014-12-05 15:39:51 -0800235 // Restore floating-point registers.
236 add r2, r0, #(_JB_FLOAT_BASE * 4)
237 vldmia r2, {d8-d15}
238
239 // Restore floating-point state.
240 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
241 fmxr fpscr, r2
242
Josh Gaoa4c69132016-03-02 19:03:17 -0800243 // Load the cookie.
Josh Gao7fda8d22015-09-10 15:40:24 -0700244 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
245 bic r3, r3, #1
Josh Gaoa4c69132016-03-02 19:03:17 -0800246
247 // Restore core registers.
Elliott Hughesb3932992014-12-05 15:39:51 -0800248 add r2, r0, #(_JB_CORE_BASE * 4)
Josh Gaob24d7432015-10-19 12:56:50 -0700249
250 // ARM deprecates using sp in the register list for ldmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800251 ldmia r2, {r4-r11, lr}
252 ldr sp, [r2, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700253 m_unmangle_registers r3
Elliott Hughesb3932992014-12-05 15:39:51 -0800254
Josh Gao7fda8d22015-09-10 15:40:24 -0700255 // Save the return value/address and check the setjmp cookie.
256 stmfd sp!, {r1, lr}
257 .cfi_adjust_cfa_offset 8
258 .cfi_rel_offset lr, 4
259 mov r0, r3
260 bl __bionic_setjmp_cookie_check
Elliott Hughesb3932992014-12-05 15:39:51 -0800261
Josh Gao7fda8d22015-09-10 15:40:24 -0700262 // Restore return value/address.
263 ldmfd sp!, {r0, lr}
264 .cfi_adjust_cfa_offset -8
265 .cfi_restore lr
266
Elliott Hughesb3932992014-12-05 15:39:51 -0800267 teq r0, #0
268 moveq r0, #1
269 bx lr
270END(siglongjmp)
271
Christopher Ferris24958512015-03-25 09:12:00 -0700272ALIAS_SYMBOL(longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200273__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
Christopher Ferris24958512015-03-25 09:12:00 -0700274ALIAS_SYMBOL(_longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200275__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)