Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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()); \
Expand All @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down