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