blob: 5e62c2825ea56d317ae3964bf2f957c10dfad827 [file] [log] [blame]
Serban Constantinescue2104882013-09-26 11:37:10 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Elliott Hughes54a74942014-01-03 16:40:37 -08003 * All rights reserved.
Serban Constantinescue2104882013-09-26 11:37:10 +01004 *
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
Elliott Hughes851e68a2014-02-19 16:53:20 -080029#include <private/bionic_asm.h>
Serban Constantinescue2104882013-09-26 11:37:10 +010030
Elliott Hughes9fb536d2014-12-05 12:17:25 -080031// According to AARCH64 PCS document we need to save the following
32// registers:
33//
34// Core x19 - x30, sp (see section 5.1.1)
35// VFP d8 - d15 (see section 5.1.2)
36//
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080037// NOTE: All the registers saved here will have 64 bit vales.
Elliott Hughes9fb536d2014-12-05 12:17:25 -080038// AAPCS mandates that the higher part of q registers do not need to
39// be saved by the callee.
Josh Gao0c3655a2016-03-02 19:45:29 -080040//
41// The internal structure of a jmp_buf is totally private.
42// Current layout (changes from release to release):
43//
44// word name description
45// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
46// 1 sigmask signal mask (not used with _setjmp / _longjmp)
47// 2 core_base base of core registers (x19-x30, sp)
48// 15 float_base base of float registers (d8-d15)
49// 23 checksum checksum of core registers
50// 24 reserved reserved entries (room to grow)
51// 32
Elliott Hughes9fb536d2014-12-05 12:17:25 -080052
Elliott Hughes75096222014-12-08 16:01:20 -080053#define _JB_SIGFLAG 0
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080054#define _JB_SIGMASK (_JB_SIGFLAG + 1)
55#define _JB_X30_SP (_JB_SIGMASK + 1)
56#define _JB_X28_X29 (_JB_X30_SP + 2)
57#define _JB_X26_X27 (_JB_X28_X29 + 2)
58#define _JB_X24_X25 (_JB_X26_X27 + 2)
59#define _JB_X22_X23 (_JB_X24_X25 + 2)
60#define _JB_X20_X21 (_JB_X22_X23 + 2)
61#define _JB_X19 (_JB_X20_X21 + 2)
62#define _JB_D14_D15 (_JB_X19 + 1)
63#define _JB_D12_D13 (_JB_D14_D15 + 2)
Duane Sanddbaab262015-01-26 16:20:05 -080064#define _JB_D10_D11 (_JB_D12_D13 + 2)
65#define _JB_D8_D9 (_JB_D10_D11 + 2)
Josh Gao0c3655a2016-03-02 19:45:29 -080066#define _JB_CHECKSUM (_JB_D8_D9 + 2)
Serban Constantinescue2104882013-09-26 11:37:10 +010067
Josh Gao54db0df2015-09-11 15:23:32 -070068#define MANGLE_REGISTERS 1
Josh Gao0c3655a2016-03-02 19:45:29 -080069#define USE_CHECKSUM 1
70
Josh Gao54db0df2015-09-11 15:23:32 -070071.macro m_mangle_registers reg, sp_reg
72#if MANGLE_REGISTERS
73 eor x19, x19, \reg
74 eor x20, x20, \reg
75 eor x21, x21, \reg
76 eor x22, x22, \reg
77 eor x23, x23, \reg
78 eor x24, x24, \reg
79 eor x25, x25, \reg
80 eor x26, x26, \reg
81 eor x27, x27, \reg
82 eor x28, x28, \reg
83 eor x29, x29, \reg
84 eor x30, x30, \reg
85 eor \sp_reg, \sp_reg, \reg
86#endif
87.endm
88
Josh Gao0c3655a2016-03-02 19:45:29 -080089.macro m_calculate_checksum dst, src, scratch
90 mov \dst, #0
91 .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
92 ldr \scratch, [\src, #(\i * 8)]
93 eor \dst, \dst, \scratch
94 .endr
95.endm
96
Josh Gao54db0df2015-09-11 15:23:32 -070097.macro m_unmangle_registers reg, sp_reg
98 m_mangle_registers \reg, sp_reg=\sp_reg
99.endm
100
Serban Constantinescue2104882013-09-26 11:37:10 +0100101ENTRY(setjmp)
dimitryfa432522017-10-25 13:07:45 +0200102__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800103 mov w1, #1
104 b sigsetjmp
Serban Constantinescue2104882013-09-26 11:37:10 +0100105END(setjmp)
106
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800107ENTRY(_setjmp)
dimitryfa432522017-10-25 13:07:45 +0200108__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800109 mov w1, #0
110 b sigsetjmp
111END(_setjmp)
Serban Constantinescue2104882013-09-26 11:37:10 +0100112
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800113// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
114ENTRY(sigsetjmp)
dimitryfa432522017-10-25 13:07:45 +0200115__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
Josh Gao54db0df2015-09-11 15:23:32 -0700116 stp x0, x30, [sp, #-16]!
117 .cfi_def_cfa_offset 16
118 .cfi_rel_offset x0, 0
119 .cfi_rel_offset x30, 8
120
121 // Get the cookie and store it along with the signal flag.
122 mov x0, x1
123 bl __bionic_setjmp_cookie_get
124 mov x1, x0
125 ldr x0, [sp, #0]
126 str x1, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes75096222014-12-08 16:01:20 -0800127
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800128 // Do we need to save the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700129 tbz w1, #0, 1f
130
131 // Save the cookie for later.
132 stp x1, xzr, [sp, #-16]!
133 .cfi_adjust_cfa_offset 16
Serban Constantinescue2104882013-09-26 11:37:10 +0100134
Elliott Hughes7b78e812014-12-05 22:57:55 -0800135 // Save current signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800136 // The 'how' argument is ignored if new_mask is NULL.
137 mov x1, #0 // NULL.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800138 add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800139 bl sigprocmask
Josh Gao54db0df2015-09-11 15:23:32 -0700140
141 ldp x1, xzr, [sp], #16
142 .cfi_adjust_cfa_offset -16
Serban Constantinescue2104882013-09-26 11:37:10 +0100143
Elliott Hughes9fb536d2014-12-05 12:17:25 -08001441:
Josh Gao54db0df2015-09-11 15:23:32 -0700145 // Restore original x0 and lr.
146 ldp x0, x30, [sp], #16
147 .cfi_adjust_cfa_offset -16
148 .cfi_restore x0
149 .cfi_restore x30
150
151 // Mask off the signal flag bit.
152 bic x1, x1, #1
153
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800154 // Save core registers.
155 mov x10, sp
Josh Gao54db0df2015-09-11 15:23:32 -0700156 m_mangle_registers x1, sp_reg=x10
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800157 stp x30, x10, [x0, #(_JB_X30_SP * 8)]
158 stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
159 stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
160 stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
161 stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
162 stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
163 str x19, [x0, #(_JB_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700164 m_unmangle_registers x1, sp_reg=x10
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800165
166 // Save floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800167 stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
168 stp d12, d13, [x0, #(_JB_D12_D13 * 8)]
169 stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
170 stp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800171
Josh Gao0c3655a2016-03-02 19:45:29 -0800172#if USE_CHECKSUM
173 // Calculate the checksum.
174 m_calculate_checksum x12, x0, x2
175 str x12, [x0, #(_JB_CHECKSUM * 8)]
176#endif
177
Elliott Hughes75096222014-12-08 16:01:20 -0800178 mov w0, #0
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800179 ret
180END(sigsetjmp)
181
182// void siglongjmp(sigjmp_buf env, int value);
183ENTRY(siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200184__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
Josh Gao0c3655a2016-03-02 19:45:29 -0800185#if USE_CHECKSUM
186 // Check the checksum before doing anything.
187 m_calculate_checksum x12, x0, x2
188 ldr x2, [x0, #(_JB_CHECKSUM * 8)]
189
190 cmp x2, x12
191 bne __bionic_setjmp_checksum_mismatch
192#endif
193
Evgenii Stepanovb16e9ce2018-08-31 13:02:06 -0700194#if __has_feature(hwaddress_sanitizer)
195 stp x0, x30, [sp, #-16]!
196 .cfi_adjust_cfa_offset 16
197 .cfi_rel_offset x0, 0
198 .cfi_rel_offset x30, 8
199 mov x19, x1 // Save 'value'.
200
201 // load and unmangle destination SP
202 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
203 bic x2, x2, #1
204 ldr x0, [x0, #(_JB_X30_SP * 8 + 8)]
205 eor x0, x0, x2
206 bl __hwasan_handle_longjmp
207
208 mov x1, x19 // Restore 'value'.
209 // Restore original x0 and lr.
210 ldp x0, x30, [sp], #16
211 .cfi_adjust_cfa_offset -16
212 .cfi_restore x0
213 .cfi_restore x30
214#endif
215
Elliott Hughes75096222014-12-08 16:01:20 -0800216 // Do we need to restore the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700217 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
218 tbz w2, #0, 1f
219
220 stp x0, x30, [sp, #-16]!
221 .cfi_adjust_cfa_offset 16
222 .cfi_rel_offset x0, 0
223 .cfi_rel_offset x30, 8
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800224
225 // Restore signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800226 mov x19, x1 // Save 'value'.
Josh Gao54db0df2015-09-11 15:23:32 -0700227
Elliott Hughes7b78e812014-12-05 22:57:55 -0800228 mov x2, x0
229 mov x0, #2 // SIG_SETMASK
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800230 add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800231 mov x2, #0 // NULL.
232 bl sigprocmask
233 mov x1, x19 // Restore 'value'.
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800234
Josh Gao54db0df2015-09-11 15:23:32 -0700235 // Restore original x0 and lr.
236 ldp x0, x30, [sp], #16
237 .cfi_adjust_cfa_offset -16
238 .cfi_restore x0
239 .cfi_restore x30
240
241 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -08002421:
243 // Restore core registers.
Josh Gao54db0df2015-09-11 15:23:32 -0700244 bic x2, x2, #1
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800245 ldp x30, x10, [x0, #(_JB_X30_SP * 8)]
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800246 ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
247 ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
248 ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
249 ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
250 ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
251 ldr x19, [x0, #(_JB_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700252 m_unmangle_registers x2, sp_reg=x10
253 mov sp, x10
254
255 stp x0, x1, [sp, #-16]!
256 .cfi_adjust_cfa_offset 16
257 .cfi_rel_offset x0, 0
258 .cfi_rel_offset x1, 8
259 stp x30, xzr, [sp, #-16]!
260 .cfi_adjust_cfa_offset 16
261 .cfi_rel_offset x30, 0
262 ldr x0, [x0, #(_JB_SIGFLAG * 8)]
263 bl __bionic_setjmp_cookie_check
264 ldp x30, xzr, [sp], #16
265 .cfi_adjust_cfa_offset -16
266 .cfi_restore x30
267 ldp x0, x1, [sp], #16
268 .cfi_adjust_cfa_offset -16
269 .cfi_restore x0
270 .cfi_restore x1
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800271
272 // Restore floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800273 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
274 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)]
275 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
276 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800277
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800278 // Set return value.
279 cmp w1, wzr
280 csinc w0, w1, wzr, ne
281 ret
282END(siglongjmp)
283
Christopher Ferris24958512015-03-25 09:12:00 -0700284ALIAS_SYMBOL(longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200285__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
Christopher Ferris24958512015-03-25 09:12:00 -0700286ALIAS_SYMBOL(_longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200287__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)