-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc] implement sigsetjmp/siglongjmp for x86-64 #136072
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Schrodinger ZHU Yifan (SchrodingerZhu) ChangesThis PR adds The behavior of this implementation aligns with Full diff: https://github.com/llvm/llvm-project/pull/136072.diff 15 Files Affected:
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 73dfeae1a2c94..e3a96da615056 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1049,6 +1049,8 @@ if(LLVM_LIBC_FULL_BUILD)
# setjmp.h entrypoints
libc.src.setjmp.longjmp
libc.src.setjmp.setjmp
+ libc.src.setjmp.siglongjmp
+ libc.src.setjmp.sigsetjmp
# stdio.h entrypoints
libc.src.stdio.clearerr
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 861b983b34219..26a3ed06b6f05 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -39,7 +39,6 @@ add_header(gid_t HDR gid_t.h)
add_header(uid_t HDR uid_t.h)
add_header(imaxdiv_t HDR imaxdiv_t.h)
add_header(ino_t HDR ino_t.h)
-add_header(jmp_buf HDR jmp_buf.h)
add_header(mbstate_t HDR mbstate_t.h)
add_header(mode_t HDR mode_t.h)
add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type)
@@ -83,6 +82,7 @@ add_header(union_sigval HDR union_sigval.h)
add_header(siginfo_t HDR siginfo_t.h DEPENDS .union_sigval .pid_t .uid_t .clock_t)
add_header(sig_atomic_t HDR sig_atomic_t.h)
add_header(sigset_t HDR sigset_t.h DEPENDS libc.include.llvm-libc-macros.signal_macros)
+add_header(jmp_buf HDR jmp_buf.h DEPENDS .sigset_t)
add_header(struct_sigaction HDR struct_sigaction.h DEPENDS .sigset_t .siginfo_t)
add_header(struct_timespec HDR struct_timespec.h DEPENDS .time_t)
add_header(
diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index f246e6491cf55..ccfe249c8ee91 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -9,6 +9,8 @@
#ifndef LLVM_LIBC_TYPES_JMP_BUF_H
#define LLVM_LIBC_TYPES_JMP_BUF_H
+#include "llvm-libc-types/sigset_t.h"
+
typedef struct {
#ifdef __x86_64__
__UINT64_TYPE__ rbx;
@@ -50,8 +52,15 @@ typedef struct {
#else
#error "__jmp_buf not available for your target architecture."
#endif
+ // return address
+ void *sig_retaddr;
+ // extra register buffer to avoid indefinite stack growth in sigsetjmp
+ void *sig_extra;
+ // signal masks
+ sigset_t sigmask;
} __jmp_buf;
typedef __jmp_buf jmp_buf[1];
+typedef __jmp_buf sigjmp_buf[1];
#endif // LLVM_LIBC_TYPES_JMP_BUF_H
diff --git a/libc/include/setjmp.yaml b/libc/include/setjmp.yaml
index 5fbb9eb2a47e5..65eb51c2b17be 100644
--- a/libc/include/setjmp.yaml
+++ b/libc/include/setjmp.yaml
@@ -21,3 +21,19 @@ functions:
- _Returns_twice
arguments:
- type: jmp_buf
+ - name: sigsetjmp
+ standards:
+ - stdc
+ return_type: int
+ attributes:
+ - _Returns_twice
+ arguments:
+ - type: sigjmp_buf
+ - type: int
+ - name: siglongjmp
+ standards:
+ - stdc
+ return_type: _Noreturn void
+ arguments:
+ - type: sigjmp_buf
+ - type: int
diff --git a/libc/src/setjmp/CMakeLists.txt b/libc/src/setjmp/CMakeLists.txt
index d85c532e8636c..3a3628bafe7ca 100644
--- a/libc/src/setjmp/CMakeLists.txt
+++ b/libc/src/setjmp/CMakeLists.txt
@@ -1,3 +1,14 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_object_library(
+ sigsetjmp_epilogue
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sigsetjmp_epilogue
+)
+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
endif()
@@ -15,3 +26,20 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_ARCHITECTURE}.longjmp
)
+
+add_entrypoint_object(
+ siglongjmp
+ SRCS
+ siglongjmp.cpp
+ HDRS
+ siglongjmp.h
+ DEPENDS
+ .longjmp
+)
+
+add_entrypoint_object(
+ sigsetjmp
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.sigsetjmp
+)
diff --git a/libc/src/setjmp/linux/CMakeLists.txt b/libc/src/setjmp/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..fdf6cf3d4ee62
--- /dev/null
+++ b/libc/src/setjmp/linux/CMakeLists.txt
@@ -0,0 +1,15 @@
+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
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+ -fomit-frame-pointer
+)
diff --git a/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp b/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp
new file mode 100644
index 0000000000000..4718623c488ec
--- /dev/null
+++ b/libc/src/setjmp/linux/sigsetjmp_epilogue.cpp
@@ -0,0 +1,25 @@
+//===-- 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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::returns_twice]] int sigsetjmp_epilogue(jmp_buf buffer, int retval) {
+ // If set is NULL, then the signal mask is unchanged (i.e., how is
+ // ignored), but the current value of the signal mask is nevertheless
+ // returned in oldset (if it is not NULL).
+ syscall_impl<long>(SYS_rt_sigprocmask, SIG_SETMASK,
+ /* set= */ retval ? &buffer->sigmask : nullptr,
+ /* old_set= */ retval ? nullptr : &buffer->sigmask,
+ sizeof(sigset_t));
+ return retval;
+}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/siglongjmp.cpp b/libc/src/setjmp/siglongjmp.cpp
new file mode 100644
index 0000000000000..1641fd9ae5522
--- /dev/null
+++ b/libc/src/setjmp/siglongjmp.cpp
@@ -0,0 +1,21 @@
+//===-- Implementation of lsigongjmp --------------------------------------===//
+//
+// 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/siglongjmp.h"
+#include "src/__support/common.h"
+#include "src/setjmp/longjmp.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+// siglongjmp is the same as longjmp. The additional recovery work is done in
+// the epilogue of the sigsetjmp function.
+LLVM_LIBC_FUNCTION(void, siglongjmp, (jmp_buf buf, int val)) {
+ return longjmp(buf, val);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/siglongjmp.h b/libc/src/setjmp/siglongjmp.h
new file mode 100644
index 0000000000000..ea5bbb91df2ec
--- /dev/null
+++ b/libc/src/setjmp/siglongjmp.h
@@ -0,0 +1,25 @@
+//===-- Implementation header for siglongjmp --------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SETJMP_SIGLONGJMP_H
+#define LLVM_LIBC_SRC_SETJMP_SIGLONGJMP_H
+
+#include "hdr/types/jmp_buf.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifdef LIBC_COMPILER_IS_GCC
+[[gnu::nothrow]]
+#endif
+void siglongjmp(jmp_buf buf, int val);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SETJMP_SIGLONGJMP_H
diff --git a/libc/src/setjmp/sigsetjmp.h b/libc/src/setjmp/sigsetjmp.h
new file mode 100644
index 0000000000000..5c6d143c3a7a3
--- /dev/null
+++ b/libc/src/setjmp/sigsetjmp.h
@@ -0,0 +1,25 @@
+//===-- Implementation header for sigsetjmp ---------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SETJMP_SIGSETJMP_H
+#define LLVM_LIBC_SRC_SETJMP_SIGSETJMP_H
+
+#include "hdr/types/jmp_buf.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/compiler.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifdef LIBC_COMPILER_IS_GCC
+[[gnu::nothrow]]
+#endif
+__attribute__((returns_twice)) int sigsetjmp(sigjmp_buf buf, int savesigs);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SETJMP_SIGSETJMP_H
diff --git a/libc/src/setjmp/sigsetjmp_epilogue.h b/libc/src/setjmp/sigsetjmp_epilogue.h
new file mode 100644
index 0000000000000..88702b743940f
--- /dev/null
+++ b/libc/src/setjmp/sigsetjmp_epilogue.h
@@ -0,0 +1,19 @@
+//===-- Implementation header for sigsetjmp epilogue ------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SETJMP_SIGSETJMP_EPILOGUE_H
+#define LLVM_LIBC_SRC_SETJMP_SIGSETJMP_EPILOGUE_H
+
+#include "hdr/types/jmp_buf.h"
+#include "src/__support/common.h"
+
+namespace LIBC_NAMESPACE_DECL {
+[[gnu::returns_twice]] int sigsetjmp_epilogue(jmp_buf buffer, int retval);
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SETJMP_SIGSETJMP_EPILOGUE_H
diff --git a/libc/src/setjmp/x86_64/CMakeLists.txt b/libc/src/setjmp/x86_64/CMakeLists.txt
index 96d5751bc81dd..f831cc584838f 100644
--- a/libc/src/setjmp/x86_64/CMakeLists.txt
+++ b/libc/src/setjmp/x86_64/CMakeLists.txt
@@ -10,6 +10,21 @@ add_entrypoint_object(
${libc_opt_high_flag}
)
+add_entrypoint_object(
+ sigsetjmp
+ SRCS
+ sigsetjmp.cpp
+ HDRS
+ ../sigsetjmp.h
+ DEPENDS
+ libc.hdr.types.jmp_buf
+ libc.hdr.types.sigset_t
+ libc.src.setjmp.sigsetjmp_epilogue
+ libc.src.setjmp.setjmp
+ COMPILE_OPTIONS
+ ${libc_opt_high_flag}
+)
+
add_entrypoint_object(
longjmp
SRCS
diff --git a/libc/src/setjmp/x86_64/sigsetjmp.cpp b/libc/src/setjmp/x86_64/sigsetjmp.cpp
new file mode 100644
index 0000000000000..8b2ebb5af227c
--- /dev/null
+++ b/libc/src/setjmp/x86_64/sigsetjmp.cpp
@@ -0,0 +1,70 @@
+//===-- Implementation of setjmp ------------------------------------------===//
+//
+// 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 "include/llvm-libc-macros/offsetof-macro.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/setjmp/setjmp_impl.h"
+#include "src/setjmp/sigsetjmp_epilogue.h"
+
+#if !defined(LIBC_TARGET_ARCH_IS_X86)
+#error "Invalid file include"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+#ifdef __i386__
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf buf)) {
+ asm(R"(
+ mov 8(%%esp), %%ecx
+ jecxz .Lnosave
+
+ mov 4(%%esp), %%eax
+ pop %c[retaddr](%%eax)
+ mov %%ebx, %c[extra](%%eax)
+ mov %%eax, %%ebx
+ call %P[setjmp]
+ push %c[retaddr](%%ebx)
+ mov %%ebx,4(%%esp)
+ mov %%eax,8(%%esp)
+ mov %c[extra](%%ebx), %%ebx
+ jmp %P[epilogue]
+
+.Lnosave:
+ jmp %P[setjmp])" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
+ [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
+ [epilogue] "i"(sigsetjmp_epilogue)
+ : "rax", "rbx");
+}
+#endif
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) {
+ asm(R"(
+ test %%esi, %%esi
+ jz .Lnosave
+
+ pop %c[retaddr](%%rdi)
+ mov %%rbx, %c[extra](%%rdi)
+ mov %%rdi, %%rbx
+ call %P[setjmp]
+ push %c[retaddr](%%rbx)
+ mov %%rbx, %%rdi
+ mov %%eax, %%esi
+ mov %c[extra](%%rdi), %%rbx
+ jmp %P[epilogue]
+
+.Lnosave:
+ jmp %P[setjmp])" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
+ [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
+ [epilogue] "i"(sigsetjmp_epilogue)
+ : "rax", "rbx");
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/setjmp/CMakeLists.txt b/libc/test/src/setjmp/CMakeLists.txt
index 392230784bd99..7c81ee366b67f 100644
--- a/libc/test/src/setjmp/CMakeLists.txt
+++ b/libc/test/src/setjmp/CMakeLists.txt
@@ -17,3 +17,20 @@ add_libc_unittest(
libc.src.setjmp.longjmp
libc.src.setjmp.setjmp
)
+
+add_libc_unittest(
+ sigsetjmp_test
+ SUITE
+ libc_setjmp_unittests
+ SRCS
+ sigsetjmp_test.cpp
+ CXX_STANDARD
+ 20
+ DEPENDS
+ libc.src.setjmp.sigsetjmp
+ libc.src.setjmp.siglongjmp
+ libc.src.signal.sigprocmask
+ libc.src.string.memory_utils.inline_memset
+ libc.src.string.memory_utils.inline_memcmp
+ libc.hdr.types.sigset_t
+)
diff --git a/libc/test/src/setjmp/sigsetjmp_test.cpp b/libc/test/src/setjmp/sigsetjmp_test.cpp
new file mode 100644
index 0000000000000..b11070a6f0f48
--- /dev/null
+++ b/libc/test/src/setjmp/sigsetjmp_test.cpp
@@ -0,0 +1,76 @@
+//===-- Unittests for sigsetjmp and siglongjmp ----------------------------===//
+//
+// 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/siglongjmp.h"
+#include "src/setjmp/sigsetjmp.h"
+#include "src/signal/sigprocmask.h"
+#include "src/string/memory_utils/inline_memcmp.h"
+#include "src/string/memory_utils/inline_memset.h"
+#include "test/UnitTest/Test.h"
+
+constexpr int MAX_LOOP = 123;
+int longjmp_called = 0;
+
+void jump_back(jmp_buf buf, int n) {
+ longjmp_called++;
+ LIBC_NAMESPACE::siglongjmp(buf, n); // Will return |n| out of setjmp
+}
+
+#define SMOKE_TESTS(SUFFIX, FLAG) \
+ TEST(LlvmLibcSetJmpTest, SigSetAndJumpBack##SUFFIX) { \
+ jmp_buf buf; \
+ longjmp_called = 0; \
+ volatile int n = 0; \
+ sigset_t old; \
+ sigset_t mask_all; \
+ sigset_t recovered; \
+ LIBC_NAMESPACE::inline_memset(&mask_all, 0xFF, sizeof(mask_all)); \
+ LIBC_NAMESPACE::inline_memset(&old, 0, sizeof(old)); \
+ LIBC_NAMESPACE::inline_memset(&recovered, 0, sizeof(recovered)); \
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &old); \
+ if (LIBC_NAMESPACE::sigsetjmp(buf, FLAG) <= MAX_LOOP) { \
+ if (FLAG) { \
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered); \
+ ASSERT_EQ( \
+ 0, LIBC_NAMESPACE::inline_memcmp(&old, &recovered, sizeof(old))); \
+ } \
+ n = n + 1; \
+ if (FLAG) \
+ LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &mask_all, nullptr); \
+ jump_back(buf, n); \
+ } \
+ ASSERT_EQ(longjmp_called, n); \
+ ASSERT_EQ(n, MAX_LOOP + 1); \
+ } \
+ TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackValOne##SUFFIX) { \
+ jmp_buf buf; \
+ longjmp_called = 0; \
+ sigset_t old; \
+ sigset_t mask_all; \
+ sigset_t recovered; \
+ LIBC_NAMESPACE::inline_memset(&mask_all, 0xFF, sizeof(mask_all)); \
+ LIBC_NAMESPACE::inline_memset(&old, 0, sizeof(old)); \
+ LIBC_NAMESPACE::inline_memset(&recovered, 0, sizeof(recovered)); \
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &old); \
+ int val = LIBC_NAMESPACE::sigsetjmp(buf, FLAG); \
+ if (val == 0) { \
+ if (FLAG) \
+ LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &mask_all, nullptr); \
+ jump_back(buf, val); \
+ } \
+ if (FLAG) { \
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered); \
+ ASSERT_EQ(0, \
+ LIBC_NAMESPACE::inline_memcmp(&old, &recovered, sizeof(old))); \
+ } \
+ ASSERT_EQ(longjmp_called, 1); \
+ ASSERT_EQ(val, 1); \
+ }
+
+SMOKE_TESTS(SaveSigs, 1)
+SMOKE_TESTS(NoSaveSigs, 0)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements sigsetjmp and siglongjmp for the x86-64 target to provide signal-safe non-local jumps following the musl and mlibc behavior. Key changes include:
- Adding new test cases in libc/test/src/setjmp/sigsetjmp_test.cpp to validate the sigsetjmp/siglongjmp behavior.
- Introducing assembly implementations for sigsetjmp in libc/src/setjmp/x86_64/sigsetjmp.cpp, along with its epilogue in both architecture-specific and Linux-specific files.
- Updating header files, YAML configuration, and entrypoints to expose the new functions.
Reviewed Changes
Copilot reviewed 10 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
libc/test/src/setjmp/sigsetjmp_test.cpp | Added unit tests for sigsetjmp and siglongjmp |
libc/src/setjmp/x86_64/sigsetjmp.cpp | Implemented sigsetjmp with inline assembly for x86-64 |
libc/src/setjmp/sigsetjmp_epilogue.h, linux/sigsetjmp_epilogue.cpp | Provided epilogue support for sigsetjmp |
libc/src/setjmp/sigsetjmp.h and siglongjmp.h | Declared the new functions |
libc/src/setjmp/siglongjmp.cpp | Implemented siglongjmp as an alias for longjmp |
libc/include/setjmp.yaml and jmp_buf.h | Updated type definitions and configuration for new functions |
libc/config/linux/x86_64/entrypoints.txt | Added sigsetjmp and siglongjmp entrypoints |
Files not reviewed (5)
- libc/include/llvm-libc-types/CMakeLists.txt: Language not supported
- libc/src/setjmp/CMakeLists.txt: Language not supported
- libc/src/setjmp/linux/CMakeLists.txt: Language not supported
- libc/src/setjmp/x86_64/CMakeLists.txt: Language not supported
- libc/test/src/setjmp/CMakeLists.txt: Language not supported
Co-authored-by: Copilot <[email protected]>
✅ With the latest revision this PR passed the C/C++ code formatter. |
Looks pretty much done, one last fix then I'll approve |
Co-authored-by: Michael Jones <[email protected]>
libc/hdr/CMakeLists.txt
Outdated
# offsetof is a macro inside compiler resource header stddef.h | ||
# defining it directly as a header library | ||
add_header_library(offsetof_macros HDRS offsetof_macros.h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this also needs to be a proxy header library now
039613b
to
0b62f8a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for implementing this
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/131/builds/20499 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/10/builds/4007 Here is the relevant piece of the build log for the reference
|
@SchrodingerZhu Are you investigating the GPU failure?
|
Hi there, this PR breaks our buildbot. Would you please take a look? Thanks! |
Looking into it now. |
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) | ||
endif() | ||
|
||
add_object_library( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't do this, object libraries are built by default. Entrypoint libraries are only enabled if the corresponding entrypoint is present. This is why every target is now trying to build this and failing if it's not present.
We also started seeing a failure on our bots:
Could you please revert this change while investigating the issue since there are multiple breakage reports? |
I reverted the change via #137077. Before relanding, please make sure that it fixes the reported issues. I can test it on our builders when you have the fix if you need my help. |
Sorry but I am a bit confused. f07511a should have fixed
Does this still reproduce under f07511a? |
Yes, it still reproduces with |
- **[libc][aarch64] implement sigsetjmp** On top of #136072 See also #137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm#136072 See also llvm#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm#136072 See also llvm#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm#136072 See also llvm#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm/llvm-project#136072 See also llvm/llvm-project#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm#136072 See also llvm#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
- **[libc][aarch64] implement sigsetjmp** On top of llvm#136072 See also llvm#137055 for remarks on naked attributes. ```c++ //===-- Implementation of setjmp ------------------------------------------===// // // 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)) { 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 ```
This PR adds
siglongjmp
andsigsetjmp
forx86-64
targets.The behavior of this implementation aligns with
musl
andmlibc
where thesiglongjmp
is the same aslongjmp
and the signal mask saving and recovering is handledby an epilogue trampoline inside
sigsetjmp
. Whensavesigs=1
,sigsetjmp
acts as a callee ofsetjmp
and stores the real return address in extra fields of the jumpbuffer. Otherwise, it tail calls
setjmp
directly.sigsetjmp
does not spill anything to the stack which makes it safer to use in signal handlers.