blob: a2b23702a4fb4961a86e6983b63f13794901b261 [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>
Peter Collingbourne734beec2018-11-14 12:41:41 -080030#include <private/bionic_constants.h>
Serban Constantinescue2104882013-09-26 11:37:10 +010031
Elliott Hughes9fb536d2014-12-05 12:17:25 -080032// According to AARCH64 PCS document we need to save the following
33// registers:
34//
35// Core x19 - x30, sp (see section 5.1.1)
36// VFP d8 - d15 (see section 5.1.2)
37//
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080038// NOTE: All the registers saved here will have 64 bit vales.
Elliott Hughes9fb536d2014-12-05 12:17:25 -080039// AAPCS mandates that the higher part of q registers do not need to
40// be saved by the callee.
Josh Gao0c3655a2016-03-02 19:45:29 -080041//
42// The internal structure of a jmp_buf is totally private.
43// Current layout (changes from release to release):
44//
45// word name description
46// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
47// 1 sigmask signal mask (not used with _setjmp / _longjmp)
Peter Collingbourne734beec2018-11-14 12:41:41 -080048// 2 core_base base of core registers (x18-x30, sp)
49// (We only store the low bits of x18 to avoid leaking the
50// shadow call stack address into memory.)
51// 16 float_base base of float registers (d8-d15)
52// 24 checksum checksum of core registers
53// 25 reserved reserved entries (room to grow)
Josh Gao0c3655a2016-03-02 19:45:29 -080054// 32
Elliott Hughes9fb536d2014-12-05 12:17:25 -080055
Elliott Hughes75096222014-12-08 16:01:20 -080056#define _JB_SIGFLAG 0
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080057#define _JB_SIGMASK (_JB_SIGFLAG + 1)
58#define _JB_X30_SP (_JB_SIGMASK + 1)
59#define _JB_X28_X29 (_JB_X30_SP + 2)
60#define _JB_X26_X27 (_JB_X28_X29 + 2)
61#define _JB_X24_X25 (_JB_X26_X27 + 2)
62#define _JB_X22_X23 (_JB_X24_X25 + 2)
63#define _JB_X20_X21 (_JB_X22_X23 + 2)
Peter Collingbourne734beec2018-11-14 12:41:41 -080064#define _JB_SCS_X19 (_JB_X20_X21 + 2)
65#define _JB_D14_D15 (_JB_SCS_X19 + 2)
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -080066#define _JB_D12_D13 (_JB_D14_D15 + 2)
Duane Sanddbaab262015-01-26 16:20:05 -080067#define _JB_D10_D11 (_JB_D12_D13 + 2)
68#define _JB_D8_D9 (_JB_D10_D11 + 2)
Josh Gao0c3655a2016-03-02 19:45:29 -080069#define _JB_CHECKSUM (_JB_D8_D9 + 2)
Serban Constantinescue2104882013-09-26 11:37:10 +010070
Peter Collingbourne734beec2018-11-14 12:41:41 -080071#define SCS_MASK (SCS_SIZE - 1)
Josh Gao54db0df2015-09-11 15:23:32 -070072#define MANGLE_REGISTERS 1
Josh Gao0c3655a2016-03-02 19:45:29 -080073#define USE_CHECKSUM 1
74
Josh Gao54db0df2015-09-11 15:23:32 -070075.macro m_mangle_registers reg, sp_reg
76#if MANGLE_REGISTERS
Peter Collingbourne734beec2018-11-14 12:41:41 -080077 eor x3, x3, \reg
Josh Gao54db0df2015-09-11 15:23:32 -070078 eor x19, x19, \reg
79 eor x20, x20, \reg
80 eor x21, x21, \reg
81 eor x22, x22, \reg
82 eor x23, x23, \reg
83 eor x24, x24, \reg
84 eor x25, x25, \reg
85 eor x26, x26, \reg
86 eor x27, x27, \reg
87 eor x28, x28, \reg
88 eor x29, x29, \reg
89 eor x30, x30, \reg
90 eor \sp_reg, \sp_reg, \reg
91#endif
92.endm
93
Josh Gao0c3655a2016-03-02 19:45:29 -080094.macro m_calculate_checksum dst, src, scratch
95 mov \dst, #0
Peter Collingbourne734beec2018-11-14 12:41:41 -080096 .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
Josh Gao0c3655a2016-03-02 19:45:29 -080097 ldr \scratch, [\src, #(\i * 8)]
98 eor \dst, \dst, \scratch
99 .endr
100.endm
101
Josh Gao54db0df2015-09-11 15:23:32 -0700102.macro m_unmangle_registers reg, sp_reg
103 m_mangle_registers \reg, sp_reg=\sp_reg
104.endm
105
Serban Constantinescue2104882013-09-26 11:37:10 +0100106ENTRY(setjmp)
dimitryfa432522017-10-25 13:07:45 +0200107__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800108 mov w1, #1
109 b sigsetjmp
Serban Constantinescue2104882013-09-26 11:37:10 +0100110END(setjmp)
111
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800112ENTRY(_setjmp)
dimitryfa432522017-10-25 13:07:45 +0200113__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800114 mov w1, #0
115 b sigsetjmp
116END(_setjmp)
Serban Constantinescue2104882013-09-26 11:37:10 +0100117
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800118// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
119ENTRY(sigsetjmp)
dimitryfa432522017-10-25 13:07:45 +0200120__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
Josh Gao54db0df2015-09-11 15:23:32 -0700121 stp x0, x30, [sp, #-16]!
122 .cfi_def_cfa_offset 16
123 .cfi_rel_offset x0, 0
124 .cfi_rel_offset x30, 8
125
126 // Get the cookie and store it along with the signal flag.
127 mov x0, x1
128 bl __bionic_setjmp_cookie_get
129 mov x1, x0
130 ldr x0, [sp, #0]
131 str x1, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes75096222014-12-08 16:01:20 -0800132
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800133 // Do we need to save the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700134 tbz w1, #0, 1f
135
136 // Save the cookie for later.
137 stp x1, xzr, [sp, #-16]!
138 .cfi_adjust_cfa_offset 16
Serban Constantinescue2104882013-09-26 11:37:10 +0100139
Elliott Hughes7b78e812014-12-05 22:57:55 -0800140 // Save current signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800141 // The 'how' argument is ignored if new_mask is NULL.
142 mov x1, #0 // NULL.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800143 add x2, x0, #(_JB_SIGMASK * 8) // old_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800144 bl sigprocmask
Josh Gao54db0df2015-09-11 15:23:32 -0700145
146 ldp x1, xzr, [sp], #16
147 .cfi_adjust_cfa_offset -16
Serban Constantinescue2104882013-09-26 11:37:10 +0100148
Elliott Hughes9fb536d2014-12-05 12:17:25 -08001491:
Josh Gao54db0df2015-09-11 15:23:32 -0700150 // Restore original x0 and lr.
151 ldp x0, x30, [sp], #16
152 .cfi_adjust_cfa_offset -16
153 .cfi_restore x0
154 .cfi_restore x30
155
156 // Mask off the signal flag bit.
157 bic x1, x1, #1
158
Peter Collingbourne734beec2018-11-14 12:41:41 -0800159 // Mask off the high bits of the shadow call stack pointer.
160 and x3, x18, #SCS_MASK
161
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800162 // Save core registers.
163 mov x10, sp
Josh Gao54db0df2015-09-11 15:23:32 -0700164 m_mangle_registers x1, sp_reg=x10
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800165 stp x30, x10, [x0, #(_JB_X30_SP * 8)]
166 stp x28, x29, [x0, #(_JB_X28_X29 * 8)]
167 stp x26, x27, [x0, #(_JB_X26_X27 * 8)]
168 stp x24, x25, [x0, #(_JB_X24_X25 * 8)]
169 stp x22, x23, [x0, #(_JB_X22_X23 * 8)]
170 stp x20, x21, [x0, #(_JB_X20_X21 * 8)]
Peter Collingbourne734beec2018-11-14 12:41:41 -0800171 stp x3, x19, [x0, #(_JB_SCS_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700172 m_unmangle_registers x1, sp_reg=x10
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800173
174 // Save floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800175 stp d14, d15, [x0, #(_JB_D14_D15 * 8)]
176 stp d12, d13, [x0, #(_JB_D12_D13 * 8)]
177 stp d10, d11, [x0, #(_JB_D10_D11 * 8)]
178 stp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800179
Josh Gao0c3655a2016-03-02 19:45:29 -0800180#if USE_CHECKSUM
181 // Calculate the checksum.
182 m_calculate_checksum x12, x0, x2
183 str x12, [x0, #(_JB_CHECKSUM * 8)]
184#endif
185
Elliott Hughes75096222014-12-08 16:01:20 -0800186 mov w0, #0
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800187 ret
188END(sigsetjmp)
189
190// void siglongjmp(sigjmp_buf env, int value);
191ENTRY(siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200192__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
Josh Gao0c3655a2016-03-02 19:45:29 -0800193#if USE_CHECKSUM
194 // Check the checksum before doing anything.
195 m_calculate_checksum x12, x0, x2
196 ldr x2, [x0, #(_JB_CHECKSUM * 8)]
197
198 cmp x2, x12
199 bne __bionic_setjmp_checksum_mismatch
200#endif
201
Evgenii Stepanovb16e9ce2018-08-31 13:02:06 -0700202#if __has_feature(hwaddress_sanitizer)
203 stp x0, x30, [sp, #-16]!
204 .cfi_adjust_cfa_offset 16
205 .cfi_rel_offset x0, 0
206 .cfi_rel_offset x30, 8
207 mov x19, x1 // Save 'value'.
208
209 // load and unmangle destination SP
210 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
211 bic x2, x2, #1
212 ldr x0, [x0, #(_JB_X30_SP * 8 + 8)]
213 eor x0, x0, x2
214 bl __hwasan_handle_longjmp
215
216 mov x1, x19 // Restore 'value'.
217 // Restore original x0 and lr.
218 ldp x0, x30, [sp], #16
219 .cfi_adjust_cfa_offset -16
220 .cfi_restore x0
221 .cfi_restore x30
222#endif
223
Elliott Hughes75096222014-12-08 16:01:20 -0800224 // Do we need to restore the signal mask?
Josh Gao54db0df2015-09-11 15:23:32 -0700225 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
226 tbz w2, #0, 1f
227
228 stp x0, x30, [sp, #-16]!
229 .cfi_adjust_cfa_offset 16
230 .cfi_rel_offset x0, 0
231 .cfi_rel_offset x30, 8
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800232
233 // Restore signal mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800234 mov x19, x1 // Save 'value'.
Josh Gao54db0df2015-09-11 15:23:32 -0700235
Elliott Hughes7b78e812014-12-05 22:57:55 -0800236 mov x2, x0
237 mov x0, #2 // SIG_SETMASK
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800238 add x1, x2, #(_JB_SIGMASK * 8) // new_mask.
Elliott Hughes7b78e812014-12-05 22:57:55 -0800239 mov x2, #0 // NULL.
240 bl sigprocmask
241 mov x1, x19 // Restore 'value'.
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800242
Josh Gao54db0df2015-09-11 15:23:32 -0700243 // Restore original x0 and lr.
244 ldp x0, x30, [sp], #16
245 .cfi_adjust_cfa_offset -16
246 .cfi_restore x0
247 .cfi_restore x30
248
249 ldr x2, [x0, #(_JB_SIGFLAG * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -08002501:
251 // Restore core registers.
Josh Gao54db0df2015-09-11 15:23:32 -0700252 bic x2, x2, #1
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800253 ldp x30, x10, [x0, #(_JB_X30_SP * 8)]
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800254 ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
255 ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
256 ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
257 ldp x22, x23, [x0, #(_JB_X22_X23 * 8)]
258 ldp x20, x21, [x0, #(_JB_X20_X21 * 8)]
Peter Collingbourne734beec2018-11-14 12:41:41 -0800259 ldp x3, x19, [x0, #(_JB_SCS_X19 * 8)]
Josh Gao54db0df2015-09-11 15:23:32 -0700260 m_unmangle_registers x2, sp_reg=x10
261 mov sp, x10
262
Peter Collingbourne734beec2018-11-14 12:41:41 -0800263 // Restore the low bits of the shadow call stack pointer.
264 and x18, x18, #~SCS_MASK
265 orr x18, x3, x18
266
Josh Gao54db0df2015-09-11 15:23:32 -0700267 stp x0, x1, [sp, #-16]!
268 .cfi_adjust_cfa_offset 16
269 .cfi_rel_offset x0, 0
270 .cfi_rel_offset x1, 8
271 stp x30, xzr, [sp, #-16]!
272 .cfi_adjust_cfa_offset 16
273 .cfi_rel_offset x30, 0
274 ldr x0, [x0, #(_JB_SIGFLAG * 8)]
275 bl __bionic_setjmp_cookie_check
276 ldp x30, xzr, [sp], #16
277 .cfi_adjust_cfa_offset -16
278 .cfi_restore x30
279 ldp x0, x1, [sp], #16
280 .cfi_adjust_cfa_offset -16
281 .cfi_restore x0
282 .cfi_restore x1
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800283
284 // Restore floating point registers.
Elliott Hughes9fa2cfb2014-12-08 16:23:10 -0800285 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)]
286 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)]
287 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)]
288 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)]
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800289
Elliott Hughes9fb536d2014-12-05 12:17:25 -0800290 // Set return value.
291 cmp w1, wzr
292 csinc w0, w1, wzr, ne
293 ret
294END(siglongjmp)
295
Christopher Ferris24958512015-03-25 09:12:00 -0700296ALIAS_SYMBOL(longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200297__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
Christopher Ferris24958512015-03-25 09:12:00 -0700298ALIAS_SYMBOL(_longjmp, siglongjmp)
dimitryfa432522017-10-25 13:07:45 +0200299__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)