blob: 6ee162e0445e7ff34a955447056467b0efa603a3 [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
59// 1 sigmask signal mask (not used with _setjmp / _longjmp)
60// 2 float_base base of float registers (d8 to d15)
61// 18 float_state floating-point status and control register
Josh Gaoa4c69132016-03-02 19:03:17 -080062// 19 core_base base of core registers (r4-r11, r13-r14)
63// 29 checksum checksum of all of the core registers, to give better error messages.
Josh Gao7fda8d22015-09-10 15:40:24 -070064// 30 reserved reserved entries (room to grow)
Elliott Hughesb3932992014-12-05 15:39:51 -080065// 64
66//
67// NOTE: float_base must be at an even word index, since the
68// FP registers will be loaded/stored with instructions
69// that expect 8-byte alignment.
70
Elliott Hughes75096222014-12-08 16:01:20 -080071#define _JB_SIGFLAG 0
72#define _JB_SIGMASK (_JB_SIGFLAG+1)
Elliott Hughesb3932992014-12-05 15:39:51 -080073#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
74#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)
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 Hughesb3932992014-12-05 15:39:51 -080083ENTRY(_setjmp)
84 mov r1, #0
85 b sigsetjmp
86END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080087
Josh Gao7fda8d22015-09-10 15:40:24 -070088#define MANGLE_REGISTERS 1
Josh Gaoa4c69132016-03-02 19:03:17 -080089#define USE_CHECKSUM 1
90
Josh Gao7fda8d22015-09-10 15:40:24 -070091.macro m_mangle_registers reg
92#if MANGLE_REGISTERS
93 eor r4, r4, \reg
94 eor r5, r5, \reg
95 eor r6, r6, \reg
96 eor r7, r7, \reg
97 eor r8, r8, \reg
98 eor r9, r9, \reg
99 eor r10, r10, \reg
100 eor r11, r11, \reg
Josh Gao7fda8d22015-09-10 15:40:24 -0700101 eor r13, r13, \reg
102 eor r14, r14, \reg
103#endif
104.endm
105
106.macro m_unmangle_registers reg
107 m_mangle_registers \reg
108.endm
109
Josh Gaoa4c69132016-03-02 19:03:17 -0800110.macro m_calculate_checksum dst, src, scratch
111 mov \dst, #0
112 .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
113 ldr \scratch, [\src, #(\i * 4)]
114 eor \dst, \dst, \scratch
115 .endr
116.endm
117
Elliott Hughesb3932992014-12-05 15:39:51 -0800118// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
119ENTRY(sigsetjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700120 stmfd sp!, {r0, lr}
121 .cfi_def_cfa_offset 8
122 .cfi_rel_offset r0, 0
123 .cfi_rel_offset lr, 4
124
125 mov r0, r1
126 bl __bionic_setjmp_cookie_get
127 mov r1, r0
128
129 ldmfd sp, {r0}
130
131 // Save the setjmp cookie for later.
132 bic r2, r1, #1
133 stmfd sp!, {r2}
134 .cfi_adjust_cfa_offset 4
135
136 // Record the setjmp cookie and whether or not we're saving the signal mask.
Elliott Hughes75096222014-12-08 16:01:20 -0800137 str r1, [r0, #(_JB_SIGFLAG * 4)]
138
Elliott Hughesb3932992014-12-05 15:39:51 -0800139 // Do we need to save the signal mask?
Josh Gao7fda8d22015-09-10 15:40:24 -0700140 tst r1, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800141 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800142
Josh Gao7fda8d22015-09-10 15:40:24 -0700143 // Align the stack.
144 sub sp, #4
145 .cfi_adjust_cfa_offset 4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800146
Josh Gao7fda8d22015-09-10 15:40:24 -0700147 // Save the current signal mask.
148 add r2, r0, #(_JB_SIGMASK * 4)
149 mov r0, #2 // SIG_SETMASK
150 mov r1, #0
151 bl sigprocmask
152
153 // Unalign the stack.
154 add sp, #4
155 .cfi_adjust_cfa_offset -4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800156
Elliott Hughesb3932992014-12-05 15:39:51 -08001571:
Josh Gao7fda8d22015-09-10 15:40:24 -0700158 ldmfd sp!, {r2}
159 .cfi_adjust_cfa_offset -4
160 ldmfd sp!, {r0, lr}
161 .cfi_adjust_cfa_offset -8
162 .cfi_restore r0
163 .cfi_restore lr
164
Elliott Hughesb3932992014-12-05 15:39:51 -0800165 // Save core registers.
166 add r1, r0, #(_JB_CORE_BASE * 4)
Josh Gao7fda8d22015-09-10 15:40:24 -0700167 m_mangle_registers r2
Josh Gaob24d7432015-10-19 12:56:50 -0700168
169 // ARM deprecates using sp in the register list for stmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800170 stmia r1, {r4-r11, lr}
171 str sp, [r1, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700172 m_unmangle_registers r2
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800173
Elliott Hughesb3932992014-12-05 15:39:51 -0800174 // Save floating-point registers.
175 add r1, r0, #(_JB_FLOAT_BASE * 4)
176 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700177
Elliott Hughesb3932992014-12-05 15:39:51 -0800178 // Save floating-point state.
179 fmrx r1, fpscr
180 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800181
Josh Gaoa4c69132016-03-02 19:03:17 -0800182#if USE_CHECKSUM
183 // Calculate the checksum.
184 m_calculate_checksum r12, r0, r2
185 str r12, [r0, #(_JB_CHECKSUM * 4)]
186#endif
187
Elliott Hughesb3932992014-12-05 15:39:51 -0800188 mov r0, #0
189 bx lr
190END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800191
Elliott Hughesb3932992014-12-05 15:39:51 -0800192// void siglongjmp(sigjmp_buf env, int value);
193ENTRY(siglongjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700194 stmfd sp!, {r0, r1, lr}
Elliott Hughesb3932992014-12-05 15:39:51 -0800195 .cfi_def_cfa_offset 12
196 .cfi_rel_offset r0, 0
197 .cfi_rel_offset r1, 4
Josh Gao7fda8d22015-09-10 15:40:24 -0700198 .cfi_rel_offset lr, 8
Elliott Hughesb3932992014-12-05 15:39:51 -0800199
Josh Gaoa4c69132016-03-02 19:03:17 -0800200#if USE_CHECKSUM
201 // Check the checksum before doing anything.
202 m_calculate_checksum r12, r0, r3
203 ldr r2, [r0, #(_JB_CHECKSUM * 4)]
204
205 teq r2, r12
206 bne __bionic_setjmp_checksum_mismatch
207#endif
208
Josh Gao7fda8d22015-09-10 15:40:24 -0700209 // Fetch the signal flag.
210 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
211
212 // Do we need to restore the signal mask?
213 ands r1, r1, #1
214 beq 1f
215
216 // Restore the signal mask.
Elliott Hughesb3932992014-12-05 15:39:51 -0800217 ldr r0, [r0, #(_JB_SIGMASK * 4)]
218 bl sigsetmask
219
Elliott Hughesb3932992014-12-05 15:39:51 -08002201:
Josh Gao7fda8d22015-09-10 15:40:24 -0700221 ldmfd sp!, {r0, r1, lr}
222 .cfi_adjust_cfa_offset -12
223 .cfi_restore r0
224 .cfi_restore r1
225 .cfi_restore lr
226
Elliott Hughesb3932992014-12-05 15:39:51 -0800227 // Restore floating-point registers.
228 add r2, r0, #(_JB_FLOAT_BASE * 4)
229 vldmia r2, {d8-d15}
230
231 // Restore floating-point state.
232 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
233 fmxr fpscr, r2
234
Josh Gaoa4c69132016-03-02 19:03:17 -0800235 // Load the cookie.
Josh Gao7fda8d22015-09-10 15:40:24 -0700236 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
237 bic r3, r3, #1
Josh Gaoa4c69132016-03-02 19:03:17 -0800238
239 // Restore core registers.
Elliott Hughesb3932992014-12-05 15:39:51 -0800240 add r2, r0, #(_JB_CORE_BASE * 4)
Josh Gaob24d7432015-10-19 12:56:50 -0700241
242 // ARM deprecates using sp in the register list for ldmia.
Josh Gaoa4c69132016-03-02 19:03:17 -0800243 ldmia r2, {r4-r11, lr}
244 ldr sp, [r2, #(9 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700245 m_unmangle_registers r3
Elliott Hughesb3932992014-12-05 15:39:51 -0800246
Josh Gao7fda8d22015-09-10 15:40:24 -0700247 // Save the return value/address and check the setjmp cookie.
248 stmfd sp!, {r1, lr}
249 .cfi_adjust_cfa_offset 8
250 .cfi_rel_offset lr, 4
251 mov r0, r3
252 bl __bionic_setjmp_cookie_check
Elliott Hughesb3932992014-12-05 15:39:51 -0800253
Josh Gao7fda8d22015-09-10 15:40:24 -0700254 // Restore return value/address.
255 ldmfd sp!, {r0, lr}
256 .cfi_adjust_cfa_offset -8
257 .cfi_restore lr
258
Elliott Hughesb3932992014-12-05 15:39:51 -0800259 teq r0, #0
260 moveq r0, #1
261 bx lr
262END(siglongjmp)
263
Christopher Ferris24958512015-03-25 09:12:00 -0700264ALIAS_SYMBOL(longjmp, siglongjmp)
265ALIAS_SYMBOL(_longjmp, siglongjmp)