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_WEAK_FOR_NATIVE_BRIDGE(setjmp) 99 mov w1, #1 100 b sigsetjmp 101END(setjmp) 102 103ENTRY_WEAK_FOR_NATIVE_BRIDGE(_setjmp) 104 mov w1, #0 105 b sigsetjmp 106END(_setjmp) 107 108// int sigsetjmp(sigjmp_buf env, int save_signal_mask); 109ENTRY_WEAK_FOR_NATIVE_BRIDGE(sigsetjmp) 110 paciasp 111 .cfi_negate_ra_state 112 stp x0, x30, [sp, #-16]! 113 .cfi_def_cfa_offset 16 114 .cfi_rel_offset x0, 0 115 .cfi_rel_offset x30, 8 116 117 // Get the cookie and store it along with the signal flag. 118 mov x0, x1 119 bl __bionic_setjmp_cookie_get 120 mov x1, x0 121 ldr x0, [sp, #0] 122 str x1, [x0, #(_JB_SIGFLAG * 8)] 123 124 // Do we need to save the signal mask? 125 tbz w1, #0, 1f 126 127 // Save the cookie for later. 128 stp x1, xzr, [sp, #-16]! 129 .cfi_adjust_cfa_offset 16 130 131 // Save current signal mask. 132 // The 'how' argument is ignored if new_mask is NULL. 133 mov x1, #0 // NULL. 134 add x2, x0, #(_JB_SIGMASK * 8) // old_mask. 135 bl sigprocmask 136 137 ldp x1, xzr, [sp], #16 138 .cfi_adjust_cfa_offset -16 139 1401: 141 // Restore original x0 and lr. 142 ldp x0, x30, [sp], #16 143 .cfi_adjust_cfa_offset -16 144 .cfi_restore x0 145 .cfi_restore x30 146 147 // Mask off the signal flag bit. 148 bic x1, x1, #1 149 150 // Mask off the high bits of the shadow call stack pointer. 151 // We only store the low bits of x18 to avoid leaking the 152 // shadow call stack address into memory. 153 // See the SCS commentary in pthread_internal.h for more detail. 154 and x3, x18, #SCS_MASK 155 156 // Save core registers. 157 mov x10, sp 158 m_mangle_registers x1, sp_reg=x10 159 stp x30, x10, [x0, #(_JB_X30_SP * 8)] 160 stp x28, x29, [x0, #(_JB_X28_X29 * 8)] 161 stp x26, x27, [x0, #(_JB_X26_X27 * 8)] 162 stp x24, x25, [x0, #(_JB_X24_X25 * 8)] 163 stp x22, x23, [x0, #(_JB_X22_X23 * 8)] 164 stp x20, x21, [x0, #(_JB_X20_X21 * 8)] 165 stp x3, x19, [x0, #(_JB_SCS_X19 * 8)] 166 m_unmangle_registers x1, sp_reg=x10 167 168 // Save floating point registers. 169 stp d14, d15, [x0, #(_JB_D14_D15 * 8)] 170 stp d12, d13, [x0, #(_JB_D12_D13 * 8)] 171 stp d10, d11, [x0, #(_JB_D10_D11 * 8)] 172 stp d8, d9, [x0, #(_JB_D8_D9 * 8)] 173 174 // Calculate the checksum. 175 m_calculate_checksum x12, x0, x2 176 str x12, [x0, #(_JB_CHECKSUM * 8)] 177 178 mov w0, #0 179 autiasp 180 .cfi_negate_ra_state 181 ret 182END(sigsetjmp) 183 184// void siglongjmp(sigjmp_buf env, int value); 185ENTRY_WEAK_FOR_NATIVE_BRIDGE(siglongjmp) 186 // Check the checksum before doing anything. 187 m_calculate_checksum x12, x0, x2 188 ldr x2, [x0, #(_JB_CHECKSUM * 8)] 189 cmp x2, x12 190 bne __bionic_setjmp_checksum_mismatch 191 192 // Update stack memory tags (MTE + hwasan). 193 stp x0, x30, [sp, #-16]! 194 .cfi_adjust_cfa_offset 16 195 .cfi_rel_offset x0, 0 196 .cfi_rel_offset x30, 8 197 mov x19, x1 // Save 'value'. 198 199 // load and unmangle destination SP 200 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 201 bic x2, x2, #1 202 ldr x0, [x0, #(_JB_X30_SP * 8 + 8)] 203 eor x0, x0, x2 204 add x1, sp, #16 205 bl memtag_handle_longjmp 206 207 mov x1, x19 // Restore 'value'. 208 // Restore original x0 and lr. 209 ldp x0, x30, [sp], #16 210 .cfi_adjust_cfa_offset -16 211 .cfi_restore x0 212 .cfi_restore x30 213 214 // Do we need to restore the signal mask? 215 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 216 tbz w2, #0, 1f 217 218 stp x0, x30, [sp, #-16]! 219 .cfi_adjust_cfa_offset 16 220 .cfi_rel_offset x0, 0 221 .cfi_rel_offset x30, 8 222 223 // Restore signal mask. 224 mov x19, x1 // Save 'value'. 225 226 mov x2, x0 227 mov x0, #2 // SIG_SETMASK 228 add x1, x2, #(_JB_SIGMASK * 8) // new_mask. 229 mov x2, #0 // NULL. 230 bl sigprocmask 231 mov x1, x19 // Restore 'value'. 232 233 // Restore original x0 and lr. 234 ldp x0, x30, [sp], #16 235 .cfi_adjust_cfa_offset -16 236 .cfi_restore x0 237 .cfi_restore x30 238 239 ldr x2, [x0, #(_JB_SIGFLAG * 8)] 2401: 241 // Restore core registers. 242 bic x2, x2, #1 243 // x30 was saved with PAC to jmp_buf in sigsetjmp(). 244 ldp x30, x10, [x0, #(_JB_X30_SP * 8)] 245 .cfi_negate_ra_state 246 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 ldp x3, x19, [x0, #(_JB_SCS_X19 * 8)] 252 m_unmangle_registers x2, sp_reg=x10 253 mov sp, x10 254 255 // Restore the low bits of the shadow call stack pointer. 256 and x18, x18, #~SCS_MASK 257 orr x18, x3, x18 258 259 stp x0, x1, [sp, #-16]! 260 .cfi_adjust_cfa_offset 16 261 .cfi_rel_offset x0, 0 262 .cfi_rel_offset x1, 8 263 stp x30, xzr, [sp, #-16]! 264 .cfi_adjust_cfa_offset 16 265 .cfi_rel_offset x30, 0 266 ldr x0, [x0, #(_JB_SIGFLAG * 8)] 267 bl __bionic_setjmp_cookie_check 268 ldp x30, xzr, [sp], #16 269 .cfi_adjust_cfa_offset -16 270 .cfi_restore x30 271 ldp x0, x1, [sp], #16 272 .cfi_adjust_cfa_offset -16 273 .cfi_restore x0 274 .cfi_restore x1 275 276 // Restore floating point registers. 277 ldp d14, d15, [x0, #(_JB_D14_D15 * 8)] 278 ldp d12, d13, [x0, #(_JB_D12_D13 * 8)] 279 ldp d10, d11, [x0, #(_JB_D10_D11 * 8)] 280 ldp d8, d9, [x0, #(_JB_D8_D9 * 8)] 281 282 // Set return value. 283 cmp w1, wzr 284 csinc w0, w1, wzr, ne 285 autiasp 286 .cfi_negate_ra_state 287 ret 288END(siglongjmp) 289 290ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(longjmp, siglongjmp) 291ALIAS_SYMBOL_WEAK_FOR_NATIVE_BRIDGE(_longjmp, siglongjmp) 292 293NOTE_GNU_PROPERTY() 294