1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * All rights reserved. 4 * 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 29#include <private/bionic_asm.h> 30#include <private/bionic_constants.h> 31 32// 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// 38// NOTE: All the registers saved here will have 64 bit vales. 39// AAPCS mandates that the higher part of q registers do not need to 40// be saved by the callee. 41// 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) 48// 2 core_base base of core registers (x18-x30, sp) 49// 16 float_base base of float registers (d8-d15) 50// 24 checksum checksum of core registers 51// 25 reserved reserved entries (room to grow) 52// 32 53 54#define _JB_SIGFLAG 0 55#define _JB_SIGMASK (_JB_SIGFLAG + 1) 56#define _JB_X30_SP (_JB_SIGMASK + 1) 57#define _JB_X28_X29 (_JB_X30_SP + 2) 58#define _JB_X26_X27 (_JB_X28_X29 + 2) 59#define _JB_X24_X25 (_JB_X26_X27 + 2) 60#define _JB_X22_X23 (_JB_X24_X25 + 2) 61#define _JB_X20_X21 (_JB_X22_X23 + 2) 62#define _JB_SCS_X19 (_JB_X20_X21 + 2) 63#define _JB_D14_D15 (_JB_SCS_X19 + 2) 64#define _JB_D12_D13 (_JB_D14_D15 + 2) 65#define _JB_D10_D11 (_JB_D12_D13 + 2) 66#define _JB_D8_D9 (_JB_D10_D11 + 2) 67#define _JB_CHECKSUM (_JB_D8_D9 + 2) 68 69.macro m_mangle_registers reg, sp_reg 70 eor x3, x3, \reg 71 eor x19, x19, \reg 72 eor x20, x20, \reg 73 eor x21, x21, \reg 74 eor x22, x22, \reg 75 eor x23, x23, \reg 76 eor x24, x24, \reg 77 eor x25, x25, \reg 78 eor x26, x26, \reg 79 eor x27, x27, \reg 80 eor x28, x28, \reg 81 eor x29, x29, \reg 82 eor x30, x30, \reg 83 eor \sp_reg, \sp_reg, \reg 84.endm 85 86.macro m_calculate_checksum dst, src, scratch 87 mov \dst, #0 88 .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 89 ldr \scratch, [\src, #(\i * 8)] 90 eor \dst, \dst, \scratch 91 .endr 92.endm 93 94.macro m_unmangle_registers reg, sp_reg 95 m_mangle_registers \reg, sp_reg=\sp_reg 96.endm 97 98ENTRY(setjmp) 99__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp) 100 mov w1, #1 101 b sigsetjmp 102END(setjmp) 103 104ENTRY(_setjmp) 105__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp) 106 mov w1, #0 107 b sigsetjmp 108END(_setjmp) 109 110// int sigsetjmp(sigjmp_buf env, int save_signal_mask); 111ENTRY(sigsetjmp) 112__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp) 113 paciasp 114 .cfi_negate_ra_state 115 stp x0, x30, [sp, #-16]! 116 .cfi_def_cfa_offset 16 117 .cfi_rel_offset x0, 0 118 .cfi_rel_offset x30, 8 119 120 // Get the cookie and store it along with the signal flag. 121 mov x0, x1 122 bl __bionic_setjmp_cookie_get 123 mov x1, x0 124 ldr x0, [sp, #0] 125 str x1, [x0, #(_JB_SIGFLAG * 8)] 126 127 // Do we need to save the signal mask? 128 tbz w1, #0, 1f 129 130 // Save the cookie for later. 131 stp x1, xzr, [sp, #-16]! 132 .cfi_adjust_cfa_offset 16 133 134 // Save current signal mask. 135 // The 'how' argument is ignored if new_mask is NULL. 136 mov x1, #0 // NULL. 137 add x2, x0, #(_JB_SIGMASK * 8) // old_mask. 138 bl sigprocmask 139 140 ldp x1, xzr, [sp], #16 141 .cfi_adjust_cfa_offset -16 142 1431: 144 // Restore original x0 and lr. 145 ldp x0, x30, [sp], #16 146 .cfi_adjust_cfa_offset -16 147 .cfi_restore x0 148 .cfi_restore x30 149 150 // Mask off the signal flag bit. 151 bic x1, x1, #1 152 153 // Mask off the high bits of the shadow call stack pointer. 154 // We only store the low bits of x18 to avoid leaking the 155 // shadow call stack address into memory. 156 // See the SCS commentary in pthread_internal.h for more detail. 157 and x3, x18, #SCS_MASK 158 159 // Save core registers. 160 mov x10, sp 161 m_mangle_registers x1, sp_reg=x10 162 stp x30, x10, [x0, #(_JB_X30_SP * 8)] 163 stp x28, x29, [x0, #(_JB_X28_X29 * 8)] 164 stp x26, x27, [x0, #(_JB_X26_X27 * 8)] 165 stp x24, x25, [x0, #(_JB_X24_X25 * 8)] 166 stp x22, x23, [x0, #(_JB_X22_X23 * 8)] 167 stp x20, x21, [x0, #(_JB_X20_X21 * 8)] 168 stp x3, x19, [x0, #(_JB_SCS_X19 * 8)] 169 m_unmangle_registers x1, sp_reg=x10 170 171 // Save floating point registers. 172 stp d14, d15, [x0, #(_JB_D14_D15 * 8)] 173 stp d12, d13, [x0, #(_JB_D12_D13 * 8)] 174 stp d10, d11, [x0, #(_JB_D10_D11 * 8)] 175 stp d8, d9, [x0, #(_JB_D8_D9 * 8)] 176 177 // Calculate the checksum. 178 m_calculate_checksum x12, x0, x2 179 str x12, [x0, #(_JB_CHECKSUM * 8)] 180 181 mov w0, #0 182 autiasp 183 .cfi_negate_ra_state 184 ret 185END(sigsetjmp) 186 187// void siglongjmp(sigjmp_buf env, int value); 188ENTRY(siglongjmp) 189__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp) 190 // Check the checksum before doing anything. 191 m_calculate_checksum x12, x0, x2 192 ldr x2, [x0, #(_JB_CHECKSUM * 8)] 193 cmp x2, x12 194 bne __bionic_setjmp_checksum_mismatch 195 196 // Update stack memory tags (MTE + hwasan). 197 stp x0, x30, [sp, #-16]! 198 .cfi_adjust_cfa_offset 16 199 .cfi_rel_offset x0, 0 200 .cfi_rel_offset x30, 8 201 mov x19, x1 // Save 'value'. 202 203 // load and unmangle destination SP 204 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 205 bic x2, x2, #1 206 ldr x0, [x0, #(_JB_X30_SP * 8 + 8)] 207 eor x0, x0, x2 208 bl memtag_handle_longjmp 209 210 mov x1, x19 // Restore 'value'. 211 // Restore original x0 and lr. 212 ldp x0, x30, [sp], #16 213 .cfi_adjust_cfa_offset -16 214 .cfi_restore x0 215 .cfi_restore x30 216 217 // Do we need to restore the signal mask? 218 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 219 tbz w2, #0, 1f 220 221 stp x0, x30, [sp, #-16]! 222 .cfi_adjust_cfa_offset 16 223 .cfi_rel_offset x0, 0 224 .cfi_rel_offset x30, 8 225 226 // Restore signal mask. 227 mov x19, x1 // Save 'value'. 228 229 mov x2, x0 230 mov x0, #2 // SIG_SETMASK 231 add x1, x2, #(_JB_SIGMASK * 8) // new_mask. 232 mov x2, #0 // NULL. 233 bl sigprocmask 234 mov x1, x19 // Restore 'value'. 235 236 // Restore original x0 and lr. 237 ldp x0, x30, [sp], #16 238 .cfi_adjust_cfa_offset -16 239 .cfi_restore x0 240 .cfi_restore x30 241 242 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 2431: 244 // Restore core registers. 245 bic x2, x2, #1 246 // x30 was saved with PAC to jmp_buf in sigsetjmp(). 247 ldp x30, x10, [x0, #(_JB_X30_SP * 8)] 248 .cfi_negate_ra_state 249 ldp x28, x29, [x0, #(_JB_X28_X29 * 8)] 250 ldp x26, x27, [x0, #(_JB_X26_X27 * 8)] 251 ldp x24, x25, [x0, #(_JB_X24_X25 * 8)] 252 ldp x22, x23, [x0, #(_JB_X22_X23 * 8)] 253 ldp x20, x21, [x0, #(_JB_X20_X21 * 8)] 254 ldp x3, x19, [x0, #(_JB_SCS_X19 * 8)] 255 m_unmangle_registers x2, sp_reg=x10 256 mov sp, x10 257 258 // Restore the low bits of the shadow call stack pointer. 259 and x18, x18, #~SCS_MASK 260 orr x18, x3, x18 261 262 stp x0, x1, [sp, #-16]! 263 .cfi_adjust_cfa_offset 16 264 .cfi_rel_offset x0, 0 265 .cfi_rel_offset x1, 8 266 stp x30, xzr, [sp, #-16]! 267 .cfi_adjust_cfa_offset 16 268 .cfi_rel_offset x30, 0 269 ldr x0, [x0, #(_JB_SIGFLAG * 8)] 270 bl __bionic_setjmp_cookie_check 271 ldp x30, xzr, [sp], #16 272 .cfi_adjust_cfa_offset -16 273 .cfi_restore x30 274 ldp x0, x1, [sp], #16 275 .cfi_adjust_cfa_offset -16 276 .cfi_restore x0 277 .cfi_restore x1 278 279 // Restore floating point registers. 280 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)] 281 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)] 282 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)] 283 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)] 284 285 // Set return value. 286 cmp w1, wzr 287 csinc w0, w1, wzr, ne 288 autiasp 289 .cfi_negate_ra_state 290 ret 291END(siglongjmp) 292 293ALIAS_SYMBOL(longjmp, siglongjmp) 294__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp) 295ALIAS_SYMBOL(_longjmp, siglongjmp) 296__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp) 297 298NOTE_GNU_PROPERTY() 299