Reapply "[UBSan] [compiler-rt] add preservecc variants of handlers" (#168973) (#169091)

This reverts commit 418204d9c108351340fe21194ace0e31157b7189.
This commit is contained in:
Florian Mayer 2025-11-24 12:44:32 -08:00 committed by GitHub
parent 173600880b
commit ff80de72c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

View File

@ -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,7 +171,8 @@ 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")

View File

@ -8,6 +8,7 @@
// RUN: sed -e 's/.*"\(.*libclang_rt.ubsan_minimal_osx_dynamic.dylib\)".*/\1/' | \
// RUN: tr -d '\n' > %t.dylib_path1
// RUN: nm -jgU %{readfile:%t.dylib_path1} | grep "^___ubsan_handle" \
// RUN: | grep -vE "_minimal_preserve" \
// RUN: | sed 's/_minimal//g' \
// RUN: > %t.minimal.symlist
//