-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Reland "[libc] build fix for sigsetjmp (#137047)" #137214
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
base: main
Are you sure you want to change the base?
Conversation
@gulfemsavrun could you check if this fix addresses the build issue? thank you! |
@llvm/pr-subscribers-libc Author: Schrodinger ZHU Yifan (SchrodingerZhu) ChangesReland We wrap every target replying on the epilogue library into conditional checks. Full diff: https://github.com/llvm/llvm-project/pull/137214.diff 19 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/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index db2dac9ff2822..209fcb965242f 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -223,5 +223,14 @@ add_proxy_header_library(
libc.include.wchar
)
+# offsetof is a macro inside compiler resource header stddef.h
+add_proxy_header_library(
+ offsetof_macros
+ HDRS
+ offsetof_macros.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-macros.offsetof_macro
+)
+
add_subdirectory(types)
add_subdirectory(func)
diff --git a/libc/hdr/offsetof_macros.h b/libc/hdr/offsetof_macros.h
new file mode 100644
index 0000000000000..42e853ffa92e5
--- /dev/null
+++ b/libc/hdr/offsetof_macros.h
@@ -0,0 +1,23 @@
+//===-- Definition of macros for offsetof ---------------------------------===//
+//
+// 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_HDR_OFFSETOF_MACROS_H
+#define LLVM_LIBC_HDR_OFFSETOF_MACROS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-macros/offsetof-macro.h"
+
+#else // Overlay mode
+
+#define __need_offsetof
+#include <stddef.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_OFFSETOF_MACROS_H
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..1e7791610857d 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 "sigset_t.h"
+
typedef struct {
#ifdef __x86_64__
__UINT64_TYPE__ rbx;
@@ -49,9 +51,22 @@ typedef struct {
#endif
#else
#error "__jmp_buf not available for your target architecture."
+#endif
+ // TODO: implement sigjmp_buf related functions for other architectures
+ // Issue: https://github.com/llvm/llvm-project/issues/136358
+#if defined(__i386__) || defined(__x86_64__)
+ // return address
+ void *sig_retaddr;
+ // extra register buffer to avoid indefinite stack growth in sigsetjmp
+ void *sig_extra;
+ // signal masks
+ sigset_t sigmask;
#endif
} __jmp_buf;
typedef __jmp_buf jmp_buf[1];
+#if defined(__i386__) || defined(__x86_64__)
+typedef __jmp_buf sigjmp_buf[1];
+#endif
#endif // LLVM_LIBC_TYPES_JMP_BUF_H
diff --git a/libc/include/setjmp.yaml b/libc/include/setjmp.yaml
index 5fbb9eb2a47e5..00049e58c86c8 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:
+ - POSIX
+ return_type: int
+ attributes:
+ - _Returns_twice
+ arguments:
+ - type: sigjmp_buf
+ - type: int
+ - name: siglongjmp
+ standards:
+ - POSIX
+ 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..239254fa57dc6 100644
--- a/libc/src/setjmp/CMakeLists.txt
+++ b/libc/src/setjmp/CMakeLists.txt
@@ -1,3 +1,13 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_object_library(
+ sigsetjmp_epilogue
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sigsetjmp_epilogue
+ )
+endif()
+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE})
endif()
@@ -15,3 +25,22 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_ARCHITECTURE}.longjmp
)
+
+if (TARGET libc.src.setjmp.sigsetjmp_epilogue)
+ add_entrypoint_object(
+ siglongjmp
+ SRCS
+ siglongjmp.cpp
+ HDRS
+ siglongjmp.h
+ DEPENDS
+ .longjmp
+ )
+
+ add_entrypoint_object(
+ sigsetjmp
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_ARCHITECTURE}.sigsetjmp
+ )
+endif()
diff --git a/libc/src/setjmp/linux/CMakeLists.txt b/libc/src/setjmp/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..b844c8c5ee55a
--- /dev/null
+++ b/libc/src/setjmp/linux/CMakeLists.txt
@@ -0,0 +1,12 @@
+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
+)
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/setjmp_impl.h b/libc/src/setjmp/setjmp_impl.h
index 669f720bda5d3..c89d6bc07c900 100644
--- a/libc/src/setjmp/setjmp_impl.h
+++ b/libc/src/setjmp/setjmp_impl.h
@@ -29,7 +29,8 @@ namespace LIBC_NAMESPACE_DECL {
#ifdef LIBC_COMPILER_IS_GCC
[[gnu::nothrow]]
#endif
-__attribute__((returns_twice)) int setjmp(jmp_buf buf);
+[[gnu::returns_twice]] int
+setjmp(jmp_buf buf);
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/siglongjmp.cpp b/libc/src/setjmp/siglongjmp.cpp
new file mode 100644
index 0000000000000..e372a6fa37503
--- /dev/null
+++ b/libc/src/setjmp/siglongjmp.cpp
@@ -0,0 +1,23 @@
+//===-- Implementation of 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/__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.
+// TODO: move this inside the TU of longjmp and making it an alias after
+// sigsetjmp is implemented for all architectures.
+LLVM_LIBC_FUNCTION(void, siglongjmp, (jmp_buf buf, int val)) {
+ return LIBC_NAMESPACE::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..ef060c8b344a6
--- /dev/null
+++ b/libc/src/setjmp/sigsetjmp.h
@@ -0,0 +1,26 @@
+//===-- 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
+[[gnu::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..03ed5fb647084 100644
--- a/libc/src/setjmp/x86_64/CMakeLists.txt
+++ b/libc/src/setjmp/x86_64/CMakeLists.txt
@@ -5,10 +5,24 @@ add_entrypoint_object(
HDRS
../setjmp_impl.h
DEPENDS
+ libc.hdr.offsetof_macros
libc.hdr.types.jmp_buf
- COMPILE_OPTIONS
- ${libc_opt_high_flag}
)
+if (TARGET libc.src.setjmp.sigsetjmp_epilogue)
+ 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
+ )
+endif()
add_entrypoint_object(
longjmp
@@ -18,7 +32,4 @@ add_entrypoint_object(
../longjmp.h
DEPENDS
libc.hdr.types.jmp_buf
- COMPILE_OPTIONS
- ${libc_opt_high_flag}
- -fomit-frame-pointer
)
diff --git a/libc/src/setjmp/x86_64/setjmp.cpp b/libc/src/setjmp/x86_64/setjmp.cpp
index 5ac10fa87b39a..28e52712c785d 100644
--- a/libc/src/setjmp/x86_64/setjmp.cpp
+++ b/libc/src/setjmp/x86_64/setjmp.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "include/llvm-libc-macros/offsetof-macro.h"
+#include "hdr/offsetof_macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/setjmp/setjmp_impl.h"
diff --git a/libc/src/setjmp/x86_64/sigsetjmp.cpp b/libc/src/setjmp/x86_64/sigsetjmp.cpp
new file mode 100644
index 0000000000000..4c97a01822679
--- /dev/null
+++ b/libc/src/setjmp/x86_64/sigsetjmp.cpp
@@ -0,0 +1,68 @@
+//===-- Implementation of 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"
+
+#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] "X"(setjmp),
+ [epilogue] "X"(sigsetjmp_epilogue)
+ : "eax", "ebx", "ecx");
+}
+#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] "X"(setjmp),
+ [epilogue] "X"(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..e95476e00e54b 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.memset
+ libc.src.string.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..cf8d2f2fab347
--- /dev/null
+++ b/libc/test/src/setjmp/sigsetjmp_test.cpp
@@ -0,0 +1,88 @@
+//===-- 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/memcmp.h"
+#include "src/string/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
+}
+
+TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackSaveSigs) {
+ jmp_buf buf;
+ longjmp_called = 0;
+ volatile int n = 0;
+ sigset_t old;
+ sigset_t mask_all;
+ sigset_t recovered;
+ LIBC_NAMESPACE::memset(&mask_all, 0xFF, sizeof(mask_all));
+ LIBC_NAMESPACE::memset(&old, 0, sizeof(old));
+ LIBC_NAMESPACE::memset(&recovered, 0, sizeof(recovered));
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &old);
+ if (LIBC_NAMESPACE::sigsetjmp(buf, 1) <= MAX_LOOP) {
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered);
+ ASSERT_EQ(0, LIBC_NAMESPACE::memcmp(&old, &recovered, sizeof(old)));
+ n = n + 1;
+ 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, SigSetAndJumpBackValOneSaveSigs) {
+ jmp_buf buf;
+ longjmp_called = 0;
+ sigset_t old;
+ sigset_t mask_all;
+ sigset_t recovered;
+ LIBC_NAMESPACE::memset(&mask_all, 0xFF, sizeof(mask_all));
+ LIBC_NAMESPACE::memset(&old, 0, sizeof(old));
+ LIBC_NAMESPACE::memset(&recovered, 0, sizeof(recovered));
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &old);
+ int val = LIBC_NAMESPACE::sigsetjmp(buf, 1);
+ if (val == 0) {
+ LIBC_NAMESPACE::sigprocmask(SIG_BLOCK, &mask_all, nullptr);
+ jump_back(buf, val);
+ }
+ LIBC_NAMESPACE::sigprocmask(0, nullptr, &recovered);
+ ASSERT_EQ(0, LIBC_NAMESPACE::memcmp(&old, &recovered, sizeof(old)));
+ ASSERT_EQ(longjmp_called, 1);
+ ASSERT_EQ(val, 1);
+}
+
+TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackNoSaveSigs) {
+ jmp_buf buf;
+ longjmp_called = 0;
+ volatile int n = 0;
+ if (LIBC_NAMESPACE::sigsetjmp(buf, 0) <= MAX_LOOP) {
+ n = n + 1;
+ jump_back(buf, n);
+ }
+ ASSERT_EQ(longjmp_called, n);
+ ASSERT_EQ(n, MAX_LOOP + 1);
+}
+
+TEST(LlvmLibcSetJmpTest, SigSetAndJumpBackValOneNoSaveSigs) {
+ jmp_buf buf;
+ longjmp_called = 0;
+ int val = LIBC_NAMESPACE::sigsetjmp(buf, 0);
+ if (val == 0) {
+ jump_back(buf, val);
+ }
+ ASSERT_EQ(longjmp_called, 1);
+ ASSERT_EQ(val, 1);
+}
|
No, unfortunately it still has an issue. The issue seems to be different though.
|
Should be fixed by 3591028 |
With the above fix, the issue is resolved. |
#endif | ||
// TODO: implement sigjmp_buf related functions for other architectures | ||
// Issue: https://github.com/llvm/llvm-project/issues/136358 | ||
#if defined(__i386__) || defined(__x86_64__) |
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.
Rather than conditionally enabling this based on architecture, we should do it based on the standards enabled in hdrgen
. Specifically, this should only be enabled for POSIX
and should never be included elsewhere regardless of the architecture.
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.
Ideally, we will need _POSIX_SOURCE
but I don't think this system is implemented in libc currently.
Reland
sigsetjmp
patches with build fixes.We wrap every target replying on the epilogue library into conditional checks.