[libc-commits] [libc] Implement `sigsetjmp` and `siglongjmp` for darwin/aarch64 (PR #139555)
Aly ElAshram via libc-commits
libc-commits at lists.llvm.org
Mon May 12 07:38:03 PDT 2025
https://github.com/AlyElashram created https://github.com/llvm/llvm-project/pull/139555
None
>From f86b525eefcabaef7d2706f14eb4f8d4e222efa4 Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 16:52:21 +0300
Subject: [PATCH 1/6] Add setjmp longjmp and sigsetjmp.cpp
---
libc/src/setjmp/darwin/aarch64/longjmp.cpp | 87 +++++++++++++++++++
libc/src/setjmp/darwin/aarch64/setjmp.cpp | 89 ++++++++++++++++++++
libc/src/setjmp/darwin/aarch64/sigsetjmp.cpp | 40 +++++++++
3 files changed, 216 insertions(+)
create mode 100644 libc/src/setjmp/darwin/aarch64/longjmp.cpp
create mode 100644 libc/src/setjmp/darwin/aarch64/setjmp.cpp
create mode 100644 libc/src/setjmp/darwin/aarch64/sigsetjmp.cpp
diff --git a/libc/src/setjmp/darwin/aarch64/longjmp.cpp b/libc/src/setjmp/darwin/aarch64/longjmp.cpp
new file mode 100644
index 0000000000000..eca4303f58034
--- /dev/null
+++ b/libc/src/setjmp/darwin/aarch64/longjmp.cpp
@@ -0,0 +1,87 @@
+//===-- Implementation of longjmp for AArch64 -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/setjmp/longjmp.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// TODO: if MTE stack tagging is in use (-fsanitize=memtag-stack), we need to
+// iterate over the region between the old and new values of sp, using STG or
+// ST2G instructions to clear the memory tags on the invalidated region of the
+// stack. But this requires a means of finding out that we're in that mode, and
+// as far as I can see there isn't currently a predefined macro for that.
+//
+// (__ARM_FEATURE_MEMORY_TAGGING only indicates whether the target architecture
+// supports the MTE instructions, not whether the compiler is configured to use
+// them.)
+
+[[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp,
+ ([[maybe_unused]] jmp_buf buf,
+ [[maybe_unused]] int val)) {
+ // If BTI branch protection is in use, the compiler will automatically insert
+ // a BTI here, so we don't need to make any extra effort to do so.
+
+ // If PAC branch protection is in use, there's no need to sign the return
+ // address at the start of longjmp, because we're not going to use it anyway!
+
+ asm(
+ // Reload the callee-saved GPRs, including fp and lr.
+ R"(
+ ldp x19, x20, [x0, #0*16]
+ ldp x21, x22, [x0, #1*16]
+ ldp x23, x24, [x0, #2*16]
+ ldp x25, x26, [x0, #3*16]
+ ldp x27, x28, [x0, #4*16]
+ ldp x29, x30, [x0, #5*16]
+ )"
+ // We would usually reload the platform register x18 here
+ // but due to the apple ABI we are not allowed to use the x18 register
+ // so we reload the stack pointer only.
+ // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Respect-the-purpose-of-specific-CPU-registers
+ R"(
+ ldr x2, [x0, #6*16]
+ mov sp, x2
+ )"
+
+#if __ARM_FP
+ // Reload the callee-saved FP registers.
+ R"(
+ ldp d8, d9, [x0, #7*16]
+ ldp d10, d11, [x0, #8*16]
+ ldp d12, d13, [x0, #9*16]
+ ldp d14, d15, [x0, #10*16]
+ )"
+#endif
+
+ // Calculate the return value.
+ R"(
+ cmp w1, #0
+ cinc w0, w1, eq
+ )"
+
+#if (__ARM_FEATURE_PAC_DEFAULT & 7) == 5
+ // Authenticate the return address using the PAC A key, since the
+ // compilation options ask for PAC protection even on leaf functions.
+ R"(
+ autiasp
+ )"
+#elif (__ARM_FEATURE_PAC_DEFAULT & 7) == 6
+ // Same, but using the PAC B key.
+ R"(
+ autibsp
+ )"
+#endif
+
+ R"(
+ ret
+ )");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/darwin/aarch64/setjmp.cpp b/libc/src/setjmp/darwin/aarch64/setjmp.cpp
new file mode 100644
index 0000000000000..678203996b6d8
--- /dev/null
+++ b/libc/src/setjmp/darwin/aarch64/setjmp.cpp
@@ -0,0 +1,89 @@
+//===-- Implementation of setjmp for darwin AArch64 -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/setjmp/setjmp_impl.h"
+
+
+
+namespace LIBC_NAMESPACE_DECL {
+
+[[gnu::naked]] LLVM_LIBC_FUNCTION(int, setjmp, ([[maybe_unused]] jmp_buf buf)) {
+ // If BTI branch protection is in use, the compiler will automatically insert
+ // a BTI here, so we don't need to make any extra effort to do so.
+
+ asm(
+#if __ARM_FEATURE_PAC_DEFAULT & 1
+ // Sign the return address using the PAC A key.
+ R"(
+ paciasp
+ )"
+#elif __ARM_FEATURE_PAC_DEFAULT & 2
+ // Sign the return address using the PAC B key.
+ R"(
+ pacibsp
+ )"
+#endif
+
+ // Store all the callee-saved GPRs, including fp (x29) and also lr (x30).
+ // Of course lr isn't normally callee-saved (the call instruction itself
+ // can't help clobbering it), but we certainly need to save it for this
+ // purpose.
+ R"(
+ stp x19, x20, [x0, #0*16]
+ stp x21, x22, [x0, #1*16]
+ stp x23, x24, [x0, #2*16]
+ stp x25, x26, [x0, #3*16]
+ stp x27, x28, [x0, #4*16]
+ stp x29, x30, [x0, #5*16]
+ )"
+
+ // While we usually store the platform register x18
+ // the darwin ABI inhibts usage of it
+ // Store just the stack pointer.
+ R"(
+ add x1, sp, #0
+ str x1, [x0, #6*16]
+ )"
+
+#if __ARM_FP
+ // Store the callee-saved FP registers. AAPCS64 only requires the low 64
+ // bits of v8-v15 to be preserved, i.e. each of d8,...,d15.
+ R"(
+ stp d8, d9, [x0, #7*16]
+ stp d10, d11, [x0, #8*16]
+ stp d12, d13, [x0, #9*16]
+ stp d14, d15, [x0, #10*16]
+ )"
+#endif
+
+ // Set up return value of zero.
+ R"(
+ mov x0, #0
+ )"
+
+#if (__ARM_FEATURE_PAC_DEFAULT & 7) == 5
+ // Authenticate the return address using the PAC A key, since the
+ // compilation options ask for PAC protection even on leaf functions.
+ R"(
+ autiasp
+ )"
+#elif (__ARM_FEATURE_PAC_DEFAULT & 7) == 6
+ // Same, but using the PAC B key.
+ R"(
+ autibsp
+ )"
+#endif
+
+ R"(
+ ret
+ )");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/darwin/aarch64/sigsetjmp.cpp b/libc/src/setjmp/darwin/aarch64/sigsetjmp.cpp
new file mode 100644
index 0000000000000..88b5a28e1105d
--- /dev/null
+++ b/libc/src/setjmp/darwin/aarch64/sigsetjmp.cpp
@@ -0,0 +1,40 @@
+//===-- Implementation of darwin/aarch64 sigsetjmp ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/setjmp/sigsetjmp.h"
+#include "hdr/offsetof_macros.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/setjmp/setjmp_impl.h"
+#include "src/setjmp/sigsetjmp_epilogue.h"
+
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) {
+
+ // The difference between sigsetjmp and setjmp is storing the signal mask of
+ // the calling thread
+
+ asm(R"(
+ cbz w1, %c[setjmp]
+
+ str x30, [x0, %c[retaddr]]
+ str x19, [x0, %c[extra]]
+ mov x19, x0
+ bl %c[setjmp]
+
+ mov w1, w0
+ mov x0, x19
+ ldr x30, [x0, %c[retaddr]]
+ ldr x19, [x0, %c[extra]]
+ b %c[epilogue])" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
+ [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
+ [epilogue] "i"(sigsetjmp_epilogue)
+ : "x0", "x1", "x19", "x30");
+}
+} // namespace LIBC_NAMESPACE_DECL
>From 8c5c68ac7c8a55801f82d71dfd5f426d7dfcc6fd Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 16:52:46 +0300
Subject: [PATCH 2/6] Add setjmp to entrypoints and headers in darwin
---
libc/config/darwin/arm/entrypoints.txt | 4 ++++
libc/config/darwin/arm/headers.txt | 1 +
2 files changed, 5 insertions(+)
diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt
index 308fc49d681d7..07199db6d1ae6 100644
--- a/libc/config/darwin/arm/entrypoints.txt
+++ b/libc/config/darwin/arm/entrypoints.txt
@@ -20,6 +20,10 @@ set(TARGET_LIBC_ENTRYPOINTS
# errno.h entrypoints
libc.src.errno.errno
+ # setjmp.h entrypoints
+ libc.src.setjmp
+
+
# string.h entrypoints
libc.src.string.memccpy
libc.src.string.memchr
diff --git a/libc/config/darwin/arm/headers.txt b/libc/config/darwin/arm/headers.txt
index 86e7145972324..8f3d6029c9b6a 100644
--- a/libc/config/darwin/arm/headers.txt
+++ b/libc/config/darwin/arm/headers.txt
@@ -7,6 +7,7 @@ set(TARGET_PUBLIC_HEADERS
libc.include.inttypes
libc.include.limits
libc.include.math
+ libc.include.setjmp
libc.include.stdlib
libc.include.string
libc.include.strings
>From 174cb0b7412ad58dce5cc33190d93b29a2e92dc9 Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 17:25:04 +0300
Subject: [PATCH 3/6] Add the sigsetjmp epilogue for darwin aarch64
---
.../darwin/aarch64/sigsetjmp_epilogue.cpp | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 libc/src/setjmp/darwin/aarch64/sigsetjmp_epilogue.cpp
diff --git a/libc/src/setjmp/darwin/aarch64/sigsetjmp_epilogue.cpp b/libc/src/setjmp/darwin/aarch64/sigsetjmp_epilogue.cpp
new file mode 100644
index 0000000000000..b2ca4d99ed82b
--- /dev/null
+++ b/libc/src/setjmp/darwin/aarch64/sigsetjmp_epilogue.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of sigsetjmp_epilogue ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/setjmp/sigsetjmp_epilogue.h"
+#include "src/__support/OSUtil/syscall.h"
+#include "src/__support/common.h"
+#include "src/signal/sigprocmask.h"
+
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::returns_twice]] int sigsetjmp_epilogue(jmp_buf buffer, int retval) {
+ syscall_impl<long>(sigprocmask, SIG_SETMASK,
+ /* set= */ retval ? &buffer->sigmask : nullptr,
+ /* old_set= */ retval ? nullptr : &buffer->sigmask);
+ return retval;
+}
+} // namespace LIBC_NAMESPACE_DECL
>From b28e6b664ad23e5ba1194eea1eebb9780ac12245 Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 17:31:47 +0300
Subject: [PATCH 4/6] Formatting
---
libc/src/setjmp/darwin/aarch64/setjmp.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/libc/src/setjmp/darwin/aarch64/setjmp.cpp b/libc/src/setjmp/darwin/aarch64/setjmp.cpp
index 678203996b6d8..2842590850217 100644
--- a/libc/src/setjmp/darwin/aarch64/setjmp.cpp
+++ b/libc/src/setjmp/darwin/aarch64/setjmp.cpp
@@ -10,8 +10,6 @@
#include "src/__support/macros/config.h"
#include "src/setjmp/setjmp_impl.h"
-
-
namespace LIBC_NAMESPACE_DECL {
[[gnu::naked]] LLVM_LIBC_FUNCTION(int, setjmp, ([[maybe_unused]] jmp_buf buf)) {
>From a8589134291bbd94f6dbd8d1aadf7f0698a31848 Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 17:32:56 +0300
Subject: [PATCH 5/6] cmake file for darwin aarch64
---
libc/src/setjmp/darwin/aarch64/CMakeLists.txt | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 libc/src/setjmp/darwin/aarch64/CMakeLists.txt
diff --git a/libc/src/setjmp/darwin/aarch64/CMakeLists.txt b/libc/src/setjmp/darwin/aarch64/CMakeLists.txt
new file mode 100644
index 0000000000000..6f9d865ede7cc
--- /dev/null
+++ b/libc/src/setjmp/darwin/aarch64/CMakeLists.txt
@@ -0,0 +1,51 @@
+if(setjmp_config_options)
+ list(PREPEND setjmp_config_options "COMPILE_OPTIONS")
+endif()
+
+add_entrypoint_object(
+ setjmp
+ SRCS
+ setjmp.cpp
+ HDRS
+ ../../setjmp_impl.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ ${setjmp_config_options}
+)
+
+add_entrypoint_object(
+ longjmp
+ SRCS
+ longjmp.cpp
+ HDRS
+ ../../longjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ ${setjmp_config_options}
+)
+
+add_entrypoint_object(
+ sigsetjmp
+ SRCS
+ sigsetjmp.cpp
+ HDRS
+ ../../sigsetjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
+ libc.hdr.offsetof_macros
+ libc.src.setjmp.sigsetjmp_epilogue
+ libc.src.setjmp.setjmp
+)
+add_object_library(
+ sigsetjmp_epilogue
+ HDRS
+ ../../sigsetjmp_epilogue.h
+ SRCS
+ sigsetjmp_epilogue.cpp
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.OSUtil.osutil
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
+)
\ No newline at end of file
>From bbb0570bd7fb4807e8661d47a773157fd67b818c Mon Sep 17 00:00:00 2001
From: AlyElashram <alyahelashram at gmail.com>
Date: Mon, 12 May 2025 17:36:58 +0300
Subject: [PATCH 6/6] cmake file formatting
---
libc/src/setjmp/darwin/aarch64/CMakeLists.txt | 58 +++++++++----------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/libc/src/setjmp/darwin/aarch64/CMakeLists.txt b/libc/src/setjmp/darwin/aarch64/CMakeLists.txt
index 6f9d865ede7cc..37058e9fb905e 100644
--- a/libc/src/setjmp/darwin/aarch64/CMakeLists.txt
+++ b/libc/src/setjmp/darwin/aarch64/CMakeLists.txt
@@ -14,38 +14,38 @@ add_entrypoint_object(
)
add_entrypoint_object(
- longjmp
- SRCS
- longjmp.cpp
- HDRS
- ../../longjmp.h
- DEPENDS
- libc.hdr.types.jmp_buf
- ${setjmp_config_options}
+ longjmp
+ SRCS
+ longjmp.cpp
+ HDRS
+ ../../longjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ ${setjmp_config_options}
)
add_entrypoint_object(
- sigsetjmp
- SRCS
- sigsetjmp.cpp
- HDRS
- ../../sigsetjmp.h
- DEPENDS
- libc.hdr.types.jmp_buf
- libc.hdr.types.sigset_t
- libc.hdr.offsetof_macros
- libc.src.setjmp.sigsetjmp_epilogue
- libc.src.setjmp.setjmp
+ sigsetjmp
+ SRCS
+ sigsetjmp.cpp
+ HDRS
+ ../../sigsetjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
+ libc.hdr.offsetof_macros
+ libc.src.setjmp.sigsetjmp_epilogue
+ libc.src.setjmp.setjmp
)
add_object_library(
- sigsetjmp_epilogue
- HDRS
- ../../sigsetjmp_epilogue.h
- SRCS
- sigsetjmp_epilogue.cpp
- DEPENDS
- libc.src.__support.common
- libc.src.__support.OSUtil.osutil
- libc.hdr.types.jmp_buf
- libc.hdr.types.sigset_t
+ sigsetjmp_epilogue
+ HDRS
+ ../../sigsetjmp_epilogue.h
+ SRCS
+ sigsetjmp_epilogue.cpp
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.OSUtil.osutil
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
)
\ No newline at end of file
More information about the libc-commits
mailing list