Skip to content

Conversation

@fmayer
Copy link
Contributor

@fmayer fmayer commented Nov 21, 2025

This reverts commit 418204d.

Created using spr 1.3.7
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2025

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Florian Mayer (fmayer)

Changes

This reverts commit 418204d.


Full diff: https://github.com/llvm/llvm-project/pull/169091.diff

2 Files Affected:

  • (modified) compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp (+40-9)
  • (modified) compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c (+1)
diff --git a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
index ebc36a8583e05..034071f527362 100644
--- a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
+++ b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
@@ -12,6 +12,22 @@ static void message(const char *msg) { ubsan_message(msg); }
 static void message(const char *msg) { (void)write(2, msg, strlen(msg)); }
 #endif
 
+// If for some reason we cannot build the runtime with preserve_all, don't
+// emit any symbol. Programs that need them will fail to link, but that is
+// better than randomly corrupted registers.
+// Some architectures don't support preserve_all (but clang still has the)
+// attribute. For now, only support x86-64 and aarch64.
+#if defined(__clang__) && defined(__has_cpp_attribute) &&                      \
+    (defined(__x86_64__) || defined(__aarch64__))
+#if __has_cpp_attribute(clang::preserve_all)
+#define PRESERVE_HANDLERS true
+#else
+#define PRESERVE_HANDLERS false
+#endif
+#else
+#define PRESERVE_HANDLERS false
+#endif
+
 static const int kMaxCallerPcs = 20;
 static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
 // Number of elements in caller_pcs. A special value of kMaxCallerPcs + 1 means
@@ -85,6 +101,18 @@ SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error, const char *kind,
   }
 }
 
+#if PRESERVE_HANDLERS
+SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_preserve,
+                             const char *kind, uintptr_t caller)
+[[clang::preserve_all]] {
+  // Additional indirecton so the user can override this with their own
+  // preserve_all function. This would allow, e.g., a function that reports the
+  // first error only, so for all subsequent calls we can skip the register save
+  // / restore.
+  __ubsan_report_error(kind, caller);
+}
+#endif
+
 SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind,
                              uintptr_t caller) {
   // Use another handlers, in case it's already overriden.
@@ -119,6 +147,16 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
 
 #define INTERFACE extern "C" __attribute__((visibility("default")))
 
+#if PRESERVE_HANDLERS
+#define HANDLER_PRESERVE(name, kind)                                           \
+  INTERFACE void __ubsan_handle_##name##_minimal_preserve()                    \
+      [[clang::preserve_all]] {                                                \
+    __ubsan_report_error_preserve(kind, GET_CALLER_PC());                      \
+  }
+#else
+#define HANDLER_PRESERVE(name, kind)
+#endif
+
 #define HANDLER_RECOVER(name, kind)                                            \
   INTERFACE void __ubsan_handle_##name##_minimal() {                           \
     __ubsan_report_error(kind, GET_CALLER_PC());                               \
@@ -133,17 +171,10 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
 
 #define HANDLER(name, kind)                                                    \
   HANDLER_RECOVER(name, kind)                                                  \
-  HANDLER_NORECOVER(name, kind)
+  HANDLER_NORECOVER(name, kind)                                                \
+  HANDLER_PRESERVE(name, kind)
 
 HANDLER(type_mismatch, "type-mismatch")
-HANDLER(alignment_assumption, "alignment-assumption")
-HANDLER(add_overflow, "add-overflow")
-HANDLER(sub_overflow, "sub-overflow")
-HANDLER(mul_overflow, "mul-overflow")
-HANDLER(negate_overflow, "negate-overflow")
-HANDLER(divrem_overflow, "divrem-overflow")
-HANDLER(shift_out_of_bounds, "shift-out-of-bounds")
-HANDLER(out_of_bounds, "out-of-bounds")
 HANDLER(local_out_of_bounds, "local-out-of-bounds")
 HANDLER_RECOVER(builtin_unreachable, "builtin-unreachable")
 HANDLER_RECOVER(missing_return, "missing-return")
diff --git a/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c b/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c
index abc1073e02073..3c76e5aadc087 100644
--- a/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c
+++ b/compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c
@@ -4,6 +4,7 @@
 // REQUIRES: x86_64-darwin
 
 // RUN: nm -jgU `%clangxx_min_runtime -fsanitize-minimal-runtime -fsanitize=undefined %s -o %t '-###' 2>&1 | grep "libclang_rt.ubsan_minimal_osx_dynamic.dylib" | sed -e 's/.*"\(.*libclang_rt.ubsan_minimal_osx_dynamic.dylib\)".*/\1/'` | grep "^___ubsan_handle" \
+// RUN:  | grep -vE "_minimal_preserve" \
 // RUN:  | sed 's/_minimal//g' \
 // RUN:  > %t.minimal.symlist
 //

@fmayer fmayer requested a review from vitalybuka November 21, 2025 20:45
Created using spr 1.3.7
@github-actions
Copy link

🐧 Linux x64 Test Results

  • 5820 tests passed
  • 1323 tests skipped

Created using spr 1.3.7
@fmayer fmayer merged commit ff80de7 into main Nov 24, 2025
8 of 9 checks passed
@fmayer fmayer deleted the users/fmayer/spr/reapply-ubsan-compiler-rt-add-preservecc-variants-of-handlers-168973 branch November 24, 2025 20:44
aadeshps-mcw pushed a commit to aadeshps-mcw/llvm-project that referenced this pull request Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants