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
13namespace 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

source code of libc/src/setjmp/aarch64/longjmp.cpp