1 //===-- Implementation of longjmp for AArch64 -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/setjmp/longjmp.h" 10 #include "src/__support/common.h" 11 #include "src/__support/macros/config.h" 12 13 namespace LIBC_NAMESPACE_DECL { 14 15 // TODO: if MTE stack tagging is in use (-fsanitize=memtag-stack), we need to 16 // iterate over the region between the old and new values of sp, using STG or 17 // ST2G instructions to clear the memory tags on the invalidated region of the 18 // stack. But this requires a means of finding out that we're in that mode, and 19 // as far as I can see there isn't currently a predefined macro for that. 20 // 21 // (__ARM_FEATURE_MEMORY_TAGGING only indicates whether the target architecture 22 // supports the MTE instructions, not whether the compiler is configured to use 23 // them.) 24 25 [[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, 26 ([[maybe_unused]] jmp_buf buf, 27 [[maybe_unused]] int val)) { 28 // If BTI branch protection is in use, the compiler will automatically insert 29 // a BTI here, so we don't need to make any extra effort to do so. 30 31 // If PAC branch protection is in use, there's no need to sign the return 32 // address at the start of longjmp, because we're not going to use it anyway! 33 34 asm( 35 // Reload the callee-saved GPRs, including fp and lr. 36 R"( 37 ldp x19, x20, [x0, #0*16] 38 ldp x21, x22, [x0, #1*16] 39 ldp x23, x24, [x0, #2*16] 40 ldp x25, x26, [x0, #3*16] 41 ldp x27, x28, [x0, #4*16] 42 ldp x29, x30, [x0, #5*16] 43 )" 44 45 #if LIBC_COPT_SETJMP_AARCH64_RESTORE_PLATFORM_REGISTER 46 // Reload the stack pointer, and the platform register x18. 47 R"( 48 ldp x2, x18, [x0, #6*16] 49 mov sp, x2 50 )" 51 #else 52 // Reload just the stack pointer. 53 R"( 54 ldr x2, [x0, #6*16] 55 mov sp, x2 56 )" 57 #endif 58 59 #if __ARM_FP 60 // Reload the callee-saved FP registers. 61 R"( 62 ldp d8, d9, [x0, #7*16] 63 ldp d10, d11, [x0, #8*16] 64 ldp d12, d13, [x0, #9*16] 65 ldp d14, d15, [x0, #10*16] 66 )" 67 #endif 68 69 // Calculate the return value. 70 R"( 71 cmp w1, #0 72 cinc w0, w1, eq 73 )" 74 75 #if __ARM_FEATURE_PAC_DEFAULT & 1 76 // Authenticate the return address using the PAC A key. 77 R"( 78 autiasp 79 )" 80 #elif __ARM_FEATURE_PAC_DEFAULT & 2 81 // Authenticate the return address using the PAC B key. 82 R"( 83 autibsp 84 )" 85 #endif 86 87 R"( 88 ret 89 )"); 90 } 91 92 } // namespace LIBC_NAMESPACE_DECL 93