Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 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 | // The internal structure of a jmp_buf is totally private. |
| 33 | // Current layout (changes from release to release): |
| 34 | // |
| 35 | // word name description |
| 36 | // 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit |
| 37 | // 1 sigmask 64-bit signal mask |
| 38 | // 2 ra |
| 39 | // 3 s0 |
| 40 | // ...... |
| 41 | // 14 s11 |
| 42 | // 15 sp |
| 43 | // 16 fs0 |
| 44 | // ...... |
| 45 | // 27 fs11 |
| 46 | // 28 checksum |
| 47 | // _JBLEN: defined in bionic/libc/include/setjmp.h |
| 48 | |
| 49 | #define _JB_SIGFLAG 0 |
| 50 | #define _JB_SIGMASK 1 * 8 |
| 51 | #define _JB_RA 2 * 8 |
| 52 | #define _JB_S0 3 * 8 |
| 53 | #define _JB_S1 4 * 8 |
| 54 | #define _JB_S2 5 * 8 |
| 55 | #define _JB_S3 6 * 8 |
| 56 | #define _JB_S4 7 * 8 |
| 57 | #define _JB_S5 8 * 8 |
| 58 | #define _JB_S6 9 * 8 |
| 59 | #define _JB_S7 10 * 8 |
| 60 | #define _JB_S8 11 * 8 |
| 61 | #define _JB_S9 12 * 8 |
| 62 | #define _JB_S10 13 * 8 |
| 63 | #define _JB_S11 14 * 8 |
| 64 | #define _JB_SP 15 * 8 |
| 65 | #define _JB_FS0 16 * 8 |
| 66 | #define _JB_FS1 17 * 8 |
| 67 | #define _JB_FS2 18 * 8 |
| 68 | #define _JB_FS3 19 * 8 |
| 69 | #define _JB_FS4 20 * 8 |
| 70 | #define _JB_FS5 21 * 8 |
| 71 | #define _JB_FS6 22 * 8 |
| 72 | #define _JB_FS7 23 * 8 |
| 73 | #define _JB_FS8 24 * 8 |
| 74 | #define _JB_FS9 25 * 8 |
| 75 | #define _JB_FS10 26 * 8 |
| 76 | #define _JB_FS11 27 * 8 |
| 77 | #define _JB_CHECKSUM 28 * 8 |
| 78 | |
| 79 | .macro m_mangle_registers reg, sp_reg |
| 80 | xor s0, s0, \reg |
| 81 | xor s1, s1, \reg |
Elliott Hughes | 9a7155d | 2023-02-10 02:00:03 +0000 | [diff] [blame] | 82 | xor a4, a4, \reg // a4 is the masked s2 (x18) for SCS. |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 83 | xor s3, s3, \reg |
| 84 | xor s4, s4, \reg |
| 85 | xor s5, s5, \reg |
| 86 | xor s6, s6, \reg |
| 87 | xor s7, s7, \reg |
| 88 | xor s8, s8, \reg |
| 89 | xor s9, s9, \reg |
| 90 | xor s10, s10, \reg |
| 91 | xor s11, s11, \reg |
| 92 | xor \sp_reg, \sp_reg, \reg |
| 93 | .endm |
| 94 | |
| 95 | .macro m_calculate_checksum dst, src, scratch |
| 96 | li \dst, 0 |
| 97 | .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 |
| 98 | ld \scratch, (\i * 8)(\src) |
| 99 | xor \dst, \dst, \scratch |
| 100 | .endr |
| 101 | .endm |
| 102 | |
| 103 | .macro m_unmangle_registers reg, sp_reg |
| 104 | m_mangle_registers \reg, sp_reg=\sp_reg |
| 105 | .endm |
| 106 | |
| 107 | ENTRY(setjmp) |
| 108 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp) |
| 109 | li a1, 1 |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 110 | tail sigsetjmp |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 111 | END(setjmp) |
| 112 | |
| 113 | ENTRY(_setjmp) |
| 114 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp) |
| 115 | li a1, 0 |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 116 | tail sigsetjmp |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 117 | END(_setjmp) |
| 118 | |
| 119 | // int sigsetjmp(sigjmp_buf env, int save_signal_mask); |
| 120 | ENTRY(sigsetjmp) |
| 121 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp) |
| 122 | addi sp, sp, -24 |
| 123 | sd a0, 0(sp) |
| 124 | sd a1, 8(sp) |
| 125 | sd ra, 16(sp) |
| 126 | |
| 127 | // Get the cookie and store it along with the signal flag. |
| 128 | mv a0, a1 |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 129 | call __bionic_setjmp_cookie_get |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 130 | mv a1, a0 |
| 131 | ld a0, 0(sp) |
| 132 | sd a1, _JB_SIGFLAG(a0) |
| 133 | |
| 134 | // Do we need to save the signal mask? |
| 135 | andi a1, a1, 1 |
| 136 | beqz a1, 1f |
| 137 | |
| 138 | // Save current signal mask. |
| 139 | // The 'how'/a0 argument is ignored if set is NULL. |
| 140 | li a1, 0 // NULL |
| 141 | addi a2, a0, _JB_SIGMASK // old_mask. |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 142 | call sigprocmask |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 143 | |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 144 | 1: |
Elliott Hughes | 45a8486 | 2022-10-18 23:04:12 +0000 | [diff] [blame] | 145 | // Restore original a0/ra. |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 146 | ld a0, 0(sp) |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 147 | ld ra, 16(sp) |
| 148 | addi sp, sp, 24 |
| 149 | |
Elliott Hughes | 45a8486 | 2022-10-18 23:04:12 +0000 | [diff] [blame] | 150 | // Get the cookie. |
| 151 | ld a1, _JB_SIGFLAG(a0) |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 152 | andi a1, a1, -2 |
| 153 | |
Elliott Hughes | 9a7155d | 2023-02-10 02:00:03 +0000 | [diff] [blame] | 154 | // Mask off the high bits of the shadow call stack pointer. |
| 155 | // We only store the low bits of x18 to avoid leaking the |
| 156 | // shadow call stack address into memory. |
| 157 | // See the SCS commentary in pthread_internal.h for more detail. |
| 158 | li a4, SCS_MASK |
| 159 | and a4, a4, x18 |
| 160 | |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 161 | // Save core registers. |
| 162 | mv a2, sp |
| 163 | m_mangle_registers a1, sp_reg=a2 |
| 164 | sd ra, _JB_RA(a0) |
| 165 | sd s0, _JB_S0(a0) |
| 166 | sd s1, _JB_S1(a0) |
Elliott Hughes | 9a7155d | 2023-02-10 02:00:03 +0000 | [diff] [blame] | 167 | sd a4, _JB_S2(a0) // a4 is the masked s2 (x18) for SCS. |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 168 | sd s3, _JB_S3(a0) |
| 169 | sd s4, _JB_S4(a0) |
| 170 | sd s5, _JB_S5(a0) |
| 171 | sd s6, _JB_S6(a0) |
| 172 | sd s7, _JB_S7(a0) |
| 173 | sd s8, _JB_S8(a0) |
| 174 | sd s9, _JB_S9(a0) |
| 175 | sd s10, _JB_S10(a0) |
| 176 | sd s11, _JB_S11(a0) |
Elliott Hughes | 45a8486 | 2022-10-18 23:04:12 +0000 | [diff] [blame] | 177 | sd a2, _JB_SP(a0) |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 178 | m_unmangle_registers a1, sp_reg=a2 |
| 179 | |
| 180 | // Save floating point registers. |
| 181 | fsd fs0, _JB_FS0(a0) |
| 182 | fsd fs1, _JB_FS1(a0) |
| 183 | fsd fs2, _JB_FS2(a0) |
| 184 | fsd fs3, _JB_FS3(a0) |
| 185 | fsd fs4, _JB_FS4(a0) |
| 186 | fsd fs5, _JB_FS5(a0) |
| 187 | fsd fs6, _JB_FS6(a0) |
| 188 | fsd fs7, _JB_FS7(a0) |
| 189 | fsd fs8, _JB_FS8(a0) |
| 190 | fsd fs9, _JB_FS9(a0) |
| 191 | fsd fs10, _JB_FS10(a0) |
| 192 | fsd fs11, _JB_FS11(a0) |
| 193 | |
| 194 | // Calculate the checksum and save it. |
| 195 | m_calculate_checksum t0, a0, t1 |
| 196 | sd t0, _JB_CHECKSUM(a0) |
| 197 | |
| 198 | li a0, 0 |
| 199 | ret |
| 200 | END(sigsetjmp) |
| 201 | |
| 202 | // void siglongjmp(sigjmp_buf env, int value); |
| 203 | ENTRY(siglongjmp) |
| 204 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp) |
| 205 | // Check the checksum before doing anything. |
| 206 | m_calculate_checksum t0, a0, t1 |
| 207 | ld t1, _JB_CHECKSUM(a0) |
| 208 | bne t0, t1, 3f |
| 209 | |
| 210 | // Do we need to restore the signal mask? |
| 211 | ld a2, _JB_SIGFLAG(a0) |
| 212 | andi a3, a2, 1 |
| 213 | beqz a3, 1f |
| 214 | |
| 215 | addi sp, sp, -16 |
| 216 | sd a0, 0(sp) |
| 217 | sd ra, 8(sp) |
| 218 | |
| 219 | // Restore the signal mask. |
| 220 | mv t0, a1 // Save 'value'. |
| 221 | |
| 222 | mv a2, a0 |
| 223 | li a0, 2 // SIG_SETMASK |
| 224 | addi a1, a2, _JB_SIGMASK // new_mask |
| 225 | li a2, 0 // NULL |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 226 | call sigprocmask |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 227 | mv a1, t0 // Restore 'value'. |
| 228 | |
| 229 | // Restore original a0 and ra. |
| 230 | ld a0, 0(sp) |
| 231 | ld ra, 8(sp) |
| 232 | addi sp, sp, 16 |
| 233 | |
| 234 | ld a2, _JB_SIGFLAG(a0) |
| 235 | 1: |
| 236 | // Restore core registers. |
| 237 | andi a2, a2, -2 |
| 238 | ld ra, _JB_RA(a0) |
| 239 | ld s0, _JB_S0(a0) |
| 240 | ld s1, _JB_S1(a0) |
Elliott Hughes | 9a7155d | 2023-02-10 02:00:03 +0000 | [diff] [blame] | 241 | ld a4, _JB_S2(a0) // Don't clobber s2 (x18) used for SCS yet. |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 242 | ld s3, _JB_S3(a0) |
| 243 | ld s4, _JB_S4(a0) |
| 244 | ld s5, _JB_S5(a0) |
| 245 | ld s6, _JB_S6(a0) |
| 246 | ld s7, _JB_S7(a0) |
| 247 | ld s8, _JB_S8(a0) |
| 248 | ld s9, _JB_S9(a0) |
| 249 | ld s10, _JB_S10(a0) |
| 250 | ld s11, _JB_S11(a0) |
| 251 | ld a3, _JB_SP(a0) |
| 252 | m_unmangle_registers a2, sp_reg=a3 |
| 253 | mv sp, a3 |
| 254 | |
Elliott Hughes | 9a7155d | 2023-02-10 02:00:03 +0000 | [diff] [blame] | 255 | // Restore the low bits of the shadow call stack pointer. |
| 256 | li a5, ~SCS_MASK |
| 257 | and x18, x18, a5 |
| 258 | or x18, a4, x18 |
| 259 | |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 260 | addi sp, sp, -24 |
| 261 | sd ra, 0(sp) |
| 262 | sd a0, 8(sp) |
| 263 | sd a1, 16(sp) |
| 264 | ld a0, _JB_SIGFLAG(a0) |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 265 | call __bionic_setjmp_cookie_check |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 266 | ld ra, 0(sp) |
| 267 | ld a0, 8(sp) |
| 268 | ld a1, 16(sp) |
| 269 | addi sp, sp, 24 |
| 270 | |
| 271 | // Restore floating point registers. |
| 272 | fld fs0, _JB_FS0(a0) |
| 273 | fld fs1, _JB_FS1(a0) |
| 274 | fld fs2, _JB_FS2(a0) |
| 275 | fld fs3, _JB_FS3(a0) |
| 276 | fld fs4, _JB_FS4(a0) |
| 277 | fld fs5, _JB_FS5(a0) |
| 278 | fld fs6, _JB_FS6(a0) |
| 279 | fld fs7, _JB_FS7(a0) |
| 280 | fld fs8, _JB_FS8(a0) |
| 281 | fld fs9, _JB_FS9(a0) |
| 282 | fld fs10, _JB_FS10(a0) |
| 283 | fld fs11, _JB_FS11(a0) |
| 284 | |
| 285 | // Set return value. |
| 286 | beqz a1, 2f |
| 287 | li a0, 1 |
| 288 | 2: |
| 289 | mv a0, a1 |
| 290 | ret |
| 291 | |
| 292 | 3: |
Elliott Hughes | 6a1dc51 | 2022-10-26 19:53:35 +0000 | [diff] [blame] | 293 | call __bionic_setjmp_checksum_mismatch |
Elliott Hughes | e1905ed | 2022-10-17 23:23:36 +0000 | [diff] [blame] | 294 | END(siglongjmp) |
| 295 | |
| 296 | ALIAS_SYMBOL(longjmp, siglongjmp) |
| 297 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp) |
| 298 | ALIAS_SYMBOL(_longjmp, siglongjmp) |
| 299 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp) |