blob: 5fbcaf39f931bfdc04a6505b10de7099172aeadd [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
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080078ENTRY(setjmp)
dimitryfa432522017-10-25 13:07:45 +020079__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080080 mov r1, #1
81 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080082END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080083
Elliott Hughesb3932992014-12-05 15:39:51 -080084ENTRY(_setjmp)
dimitryfa432522017-10-25 13:07:45 +020085__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080086 mov r1, #0
87 b sigsetjmp
88END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080089
Josh Gao7fda8d22015-09-10 15:40:24 -070090#define MANGLE_REGISTERS 1
Josh Gaoa4c69132016-03-02 19:03:17 -080091#define USE_CHECKSUM 1
92
Josh Gao7fda8d22015-09-10 15:40:24 -070093.macro m_mangle_registers reg
94#if MANGLE_REGISTERS
95 eor r4, r4, \reg
96 eor r5, r5, \reg
97 eor r6, r6, \reg
98 eor r7, r7, \reg
99 eor r8, r8, \reg
100 eor r9, r9, \reg
101 eor r10, r10, \reg
102 eor r11, r11, \reg
Josh Gao7fda8d22015-09-10 15:40:24 -0700103 eor r13, r13, \reg
104 eor r14, r14, \reg
105#endif
106.endm
107
108.macro m_unmangle_registers reg
109 m_mangle_registers \reg
110.endm
111
Josh Gaoa4c69132016-03-02 19:03:17 -0800112.macro m_calculate_checksum dst, src, scratch
113 mov \dst, #0
114 .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
115 ldr \scratch, [\src, #(\i * 4)]
116 eor \dst, \dst, \scratch
117 .endr
118.endm
119
Elliott Hughesb3932992014-12-05 15:39:51 -0800120// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
121ENTRY(sigsetjmp)
dimitryfa432522017-10-25 13:07:45 +0200122__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700123 stmfd sp!, {r0, lr}
124 .cfi_def_cfa_offset 8
125 .cfi_rel_offset r0, 0
126 .cfi_rel_offset lr, 4
127
128 mov r0, r1
129 bl __bionic_setjmp_cookie_get
130 mov r1, r0
131
132 ldmfd sp, {r0}
133
134 // Save the setjmp cookie for later.
135 bic r2, r1, #1
136 stmfd sp!, {r2}
137 .cfi_adjust_cfa_offset 4
138
139 // Record the setjmp cookie and whether or not we're saving the signal mask.
Elliott Hughes75096222014-12-08 16:01:20 -0800140 str r1, [r0, #(_JB_SIGFLAG * 4)]
141
Elliott Hughesb3932992014-12-05 15:39:51 -0800142 // Do we need to save the signal mask?
Josh Gao7fda8d22015-09-10 15:40:24 -0700143 tst r1, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800144 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800145
Josh Gao7fda8d22015-09-10 15:40:24 -0700146 // Align the stack.
147 sub sp, #4
148 .cfi_adjust_cfa_offset 4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800149
Josh Gao7fda8d22015-09-10 15:40:24 -0700150 // Save the current signal mask.
151 add r2, r0, #(_JB_SIGMASK * 4)
152 mov r0, #2 // SIG_SETMASK
153 mov r1, #0
Elliott Hughes460130b2018-01-31 09:05:26 -0800154 bl sigprocmask64
Josh Gao7fda8d22015-09-10 15:40:24 -0700155
156 // Unalign the stack.
157 add sp, #4
158 .cfi_adjust_cfa_offset -4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800159
Elliott Hughesb3932992014-12-05 15:39:51 -08001601:
Josh Gao7fda8d22015-09-10 15:40:24 -0700161 ldmfd sp!, {r2}
162 .cfi_adjust_cfa_offset -4
163 ldmfd sp!, {r0, lr}
164 .cfi_adjust_cfa_offset -8
165 .cfi_restore r0
166 .cfi_restore lr
167
Elliott Hughesb3932992014-12-05 15:39:51 -0800168 // Save core registers.
169 add r1, r0, #(_JB_CORE_BASE * 4)
Josh Gao7fda8d22015-09-10 15:40:24 -0700170 m_mangle_registers r2
Josh Gaob24d7432015-10-19 12:56:50 -0700171
172 // ARM deprecates using sp in the register list for stmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800173 stmia r1, {r4-r11, lr}
174 str sp, [r1, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700175 m_unmangle_registers r2
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800176
Elliott Hughesb3932992014-12-05 15:39:51 -0800177 // Save floating-point registers.
178 add r1, r0, #(_JB_FLOAT_BASE * 4)
179 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700180
Elliott Hughesb3932992014-12-05 15:39:51 -0800181 // Save floating-point state.
182 fmrx r1, fpscr
183 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800184
Josh Gaoa4c69132016-03-02 19:03:17 -0800185#if USE_CHECKSUM
186 // Calculate the checksum.
187 m_calculate_checksum r12, r0, r2
188 str r12, [r0, #(_JB_CHECKSUM * 4)]
189#endif
190
Elliott Hughesb3932992014-12-05 15:39:51 -0800191 mov r0, #0
192 bx lr
193END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800194
Elliott Hughesb3932992014-12-05 15:39:51 -0800195// void siglongjmp(sigjmp_buf env, int value);
196ENTRY(siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200197__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700198 stmfd sp!, {r0, r1, lr}
Elliott Hughesb3932992014-12-05 15:39:51 -0800199 .cfi_def_cfa_offset 12
200 .cfi_rel_offset r0, 0
201 .cfi_rel_offset r1, 4
Josh Gao7fda8d22015-09-10 15:40:24 -0700202 .cfi_rel_offset lr, 8
Elliott Hughesb3932992014-12-05 15:39:51 -0800203
Josh Gaoa4c69132016-03-02 19:03:17 -0800204#if USE_CHECKSUM
205 // Check the checksum before doing anything.
206 m_calculate_checksum r12, r0, r3
207 ldr r2, [r0, #(_JB_CHECKSUM * 4)]
208
209 teq r2, r12
210 bne __bionic_setjmp_checksum_mismatch
211#endif
212
Josh Gao7fda8d22015-09-10 15:40:24 -0700213 // Fetch the signal flag.
214 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
215
216 // Do we need to restore the signal mask?
217 ands r1, r1, #1
218 beq 1f
219
220 // Restore the signal mask.
Elliott Hughes7ebafb32018-01-29 10:23:01 -0800221 mov r2, #0
222 add r1, r0, #(_JB_SIGMASK * 4)
223 mov r0, #2 // SIG_SETMASK
Elliott Hughes460130b2018-01-31 09:05:26 -0800224 bl sigprocmask64
Elliott Hughesb3932992014-12-05 15:39:51 -0800225
Elliott Hughesb3932992014-12-05 15:39:51 -08002261:
Josh Gao7fda8d22015-09-10 15:40:24 -0700227 ldmfd sp!, {r0, r1, lr}
228 .cfi_adjust_cfa_offset -12
229 .cfi_restore r0
230 .cfi_restore r1
231 .cfi_restore lr
232
Elliott Hughesb3932992014-12-05 15:39:51 -0800233 // Restore floating-point registers.
234 add r2, r0, #(_JB_FLOAT_BASE * 4)
235 vldmia r2, {d8-d15}
236
237 // Restore floating-point state.
238 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
239 fmxr fpscr, r2
240
Josh Gaoa4c69132016-03-02 19:03:17 -0800241 // Load the cookie.
Josh Gao7fda8d22015-09-10 15:40:24 -0700242 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
243 bic r3, r3, #1
Josh Gaoa4c69132016-03-02 19:03:17 -0800244
245 // Restore core registers.
Elliott Hughesb3932992014-12-05 15:39:51 -0800246 add r2, r0, #(_JB_CORE_BASE * 4)
Josh Gaob24d7432015-10-19 12:56:50 -0700247
248 // ARM deprecates using sp in the register list for ldmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800249 ldmia r2, {r4-r11, lr}
250 ldr sp, [r2, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700251 m_unmangle_registers r3
Elliott Hughesb3932992014-12-05 15:39:51 -0800252
Josh Gao7fda8d22015-09-10 15:40:24 -0700253 // Save the return value/address and check the setjmp cookie.
254 stmfd sp!, {r1, lr}
255 .cfi_adjust_cfa_offset 8
256 .cfi_rel_offset lr, 4
257 mov r0, r3
258 bl __bionic_setjmp_cookie_check
Elliott Hughesb3932992014-12-05 15:39:51 -0800259
Josh Gao7fda8d22015-09-10 15:40:24 -0700260 // Restore return value/address.
261 ldmfd sp!, {r0, lr}
262 .cfi_adjust_cfa_offset -8
263 .cfi_restore lr
264
Elliott Hughesb3932992014-12-05 15:39:51 -0800265 teq r0, #0
266 moveq r0, #1
267 bx lr
268END(siglongjmp)
269
Christopher Ferris24958512015-03-25 09:12:00 -0700270ALIAS_SYMBOL(longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200271__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
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)