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 |
| 82 | xor s2, s2, \reg |
| 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 |
| 110 | tail PIC_PLT(sigsetjmp) |
| 111 | END(setjmp) |
| 112 | |
| 113 | ENTRY(_setjmp) |
| 114 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp) |
| 115 | li a1, 0 |
| 116 | tail PIC_PLT(sigsetjmp) |
| 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 |
| 129 | call PIC_PLT(__bionic_setjmp_cookie_get) |
| 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. |
| 142 | call PIC_PLT(sigprocmask) |
| 143 | |
| 144 | ld a1, 8(sp) |
| 145 | |
| 146 | 1: |
| 147 | // Restore original a0/a1/ra. |
| 148 | ld a0, 0(sp) |
| 149 | ld a1, 8(sp) |
| 150 | ld ra, 16(sp) |
| 151 | addi sp, sp, 24 |
| 152 | |
| 153 | // Mask off the signal flag bit. |
| 154 | andi a1, a1, -2 |
| 155 | |
| 156 | // Save core registers. |
| 157 | mv a2, sp |
| 158 | m_mangle_registers a1, sp_reg=a2 |
| 159 | sd ra, _JB_RA(a0) |
| 160 | sd s0, _JB_S0(a0) |
| 161 | sd s1, _JB_S1(a0) |
| 162 | sd s2, _JB_S2(a0) |
| 163 | sd s3, _JB_S3(a0) |
| 164 | sd s4, _JB_S4(a0) |
| 165 | sd s5, _JB_S5(a0) |
| 166 | sd s6, _JB_S6(a0) |
| 167 | sd s7, _JB_S7(a0) |
| 168 | sd s8, _JB_S8(a0) |
| 169 | sd s9, _JB_S9(a0) |
| 170 | sd s10, _JB_S10(a0) |
| 171 | sd s11, _JB_S11(a0) |
| 172 | sd sp, _JB_SP(a0) |
| 173 | m_unmangle_registers a1, sp_reg=a2 |
| 174 | |
| 175 | // Save floating point registers. |
| 176 | fsd fs0, _JB_FS0(a0) |
| 177 | fsd fs1, _JB_FS1(a0) |
| 178 | fsd fs2, _JB_FS2(a0) |
| 179 | fsd fs3, _JB_FS3(a0) |
| 180 | fsd fs4, _JB_FS4(a0) |
| 181 | fsd fs5, _JB_FS5(a0) |
| 182 | fsd fs6, _JB_FS6(a0) |
| 183 | fsd fs7, _JB_FS7(a0) |
| 184 | fsd fs8, _JB_FS8(a0) |
| 185 | fsd fs9, _JB_FS9(a0) |
| 186 | fsd fs10, _JB_FS10(a0) |
| 187 | fsd fs11, _JB_FS11(a0) |
| 188 | |
| 189 | // Calculate the checksum and save it. |
| 190 | m_calculate_checksum t0, a0, t1 |
| 191 | sd t0, _JB_CHECKSUM(a0) |
| 192 | |
| 193 | li a0, 0 |
| 194 | ret |
| 195 | END(sigsetjmp) |
| 196 | |
| 197 | // void siglongjmp(sigjmp_buf env, int value); |
| 198 | ENTRY(siglongjmp) |
| 199 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp) |
| 200 | // Check the checksum before doing anything. |
| 201 | m_calculate_checksum t0, a0, t1 |
| 202 | ld t1, _JB_CHECKSUM(a0) |
| 203 | bne t0, t1, 3f |
| 204 | |
| 205 | // Do we need to restore the signal mask? |
| 206 | ld a2, _JB_SIGFLAG(a0) |
| 207 | andi a3, a2, 1 |
| 208 | beqz a3, 1f |
| 209 | |
| 210 | addi sp, sp, -16 |
| 211 | sd a0, 0(sp) |
| 212 | sd ra, 8(sp) |
| 213 | |
| 214 | // Restore the signal mask. |
| 215 | mv t0, a1 // Save 'value'. |
| 216 | |
| 217 | mv a2, a0 |
| 218 | li a0, 2 // SIG_SETMASK |
| 219 | addi a1, a2, _JB_SIGMASK // new_mask |
| 220 | li a2, 0 // NULL |
| 221 | call PIC_PLT(sigprocmask) |
| 222 | mv a1, t0 // Restore 'value'. |
| 223 | |
| 224 | // Restore original a0 and ra. |
| 225 | ld a0, 0(sp) |
| 226 | ld ra, 8(sp) |
| 227 | addi sp, sp, 16 |
| 228 | |
| 229 | ld a2, _JB_SIGFLAG(a0) |
| 230 | 1: |
| 231 | // Restore core registers. |
| 232 | andi a2, a2, -2 |
| 233 | ld ra, _JB_RA(a0) |
| 234 | ld s0, _JB_S0(a0) |
| 235 | ld s1, _JB_S1(a0) |
| 236 | ld s2, _JB_S2(a0) |
| 237 | ld s3, _JB_S3(a0) |
| 238 | ld s4, _JB_S4(a0) |
| 239 | ld s5, _JB_S5(a0) |
| 240 | ld s6, _JB_S6(a0) |
| 241 | ld s7, _JB_S7(a0) |
| 242 | ld s8, _JB_S8(a0) |
| 243 | ld s9, _JB_S9(a0) |
| 244 | ld s10, _JB_S10(a0) |
| 245 | ld s11, _JB_S11(a0) |
| 246 | ld a3, _JB_SP(a0) |
| 247 | m_unmangle_registers a2, sp_reg=a3 |
| 248 | mv sp, a3 |
| 249 | |
| 250 | addi sp, sp, -24 |
| 251 | sd ra, 0(sp) |
| 252 | sd a0, 8(sp) |
| 253 | sd a1, 16(sp) |
| 254 | ld a0, _JB_SIGFLAG(a0) |
| 255 | call PIC_PLT(__bionic_setjmp_cookie_check) |
| 256 | ld ra, 0(sp) |
| 257 | ld a0, 8(sp) |
| 258 | ld a1, 16(sp) |
| 259 | addi sp, sp, 24 |
| 260 | |
| 261 | // Restore floating point registers. |
| 262 | fld fs0, _JB_FS0(a0) |
| 263 | fld fs1, _JB_FS1(a0) |
| 264 | fld fs2, _JB_FS2(a0) |
| 265 | fld fs3, _JB_FS3(a0) |
| 266 | fld fs4, _JB_FS4(a0) |
| 267 | fld fs5, _JB_FS5(a0) |
| 268 | fld fs6, _JB_FS6(a0) |
| 269 | fld fs7, _JB_FS7(a0) |
| 270 | fld fs8, _JB_FS8(a0) |
| 271 | fld fs9, _JB_FS9(a0) |
| 272 | fld fs10, _JB_FS10(a0) |
| 273 | fld fs11, _JB_FS11(a0) |
| 274 | |
| 275 | // Set return value. |
| 276 | beqz a1, 2f |
| 277 | li a0, 1 |
| 278 | 2: |
| 279 | mv a0, a1 |
| 280 | ret |
| 281 | |
| 282 | 3: |
| 283 | call PIC_PLT(__bionic_setjmp_checksum_mismatch) |
| 284 | END(siglongjmp) |
| 285 | |
| 286 | ALIAS_SYMBOL(longjmp, siglongjmp) |
| 287 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp) |
| 288 | ALIAS_SYMBOL(_longjmp, siglongjmp) |
| 289 | __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp) |