Skip to content

Commit ff80de7

Browse files
authored
Reapply "[UBSan] [compiler-rt] add preservecc variants of handlers" (#168973) (#169091)
This reverts commit 418204d.
1 parent 1736008 commit ff80de7

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ static void message(const char *msg) { ubsan_message(msg); }
1212
static void message(const char *msg) { (void)write(2, msg, strlen(msg)); }
1313
#endif
1414

15+
// If for some reason we cannot build the runtime with preserve_all, don't
16+
// emit any symbol. Programs that need them will fail to link, but that is
17+
// better than randomly corrupted registers.
18+
// Some architectures don't support preserve_all (but clang still has the)
19+
// attribute. For now, only support x86-64 and aarch64.
20+
#if defined(__clang__) && defined(__has_cpp_attribute) && \
21+
(defined(__x86_64__) || defined(__aarch64__))
22+
#if __has_cpp_attribute(clang::preserve_all)
23+
#define PRESERVE_HANDLERS true
24+
#else
25+
#define PRESERVE_HANDLERS false
26+
#endif
27+
#else
28+
#define PRESERVE_HANDLERS false
29+
#endif
30+
1531
static const int kMaxCallerPcs = 20;
1632
static __sanitizer::atomic_uintptr_t caller_pcs[kMaxCallerPcs];
1733
// 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,
85101
}
86102
}
87103

104+
#if PRESERVE_HANDLERS
105+
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_preserve,
106+
const char *kind, uintptr_t caller)
107+
[[clang::preserve_all]] {
108+
// Additional indirecton so the user can override this with their own
109+
// preserve_all function. This would allow, e.g., a function that reports the
110+
// first error only, so for all subsequent calls we can skip the register save
111+
// / restore.
112+
__ubsan_report_error(kind, caller);
113+
}
114+
#endif
115+
88116
SANITIZER_INTERFACE_WEAK_DEF(void, __ubsan_report_error_fatal, const char *kind,
89117
uintptr_t caller) {
90118
// 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) {
119147

120148
#define INTERFACE extern "C" __attribute__((visibility("default")))
121149

150+
#if PRESERVE_HANDLERS
151+
#define HANDLER_PRESERVE(name, kind) \
152+
INTERFACE void __ubsan_handle_##name##_minimal_preserve() \
153+
[[clang::preserve_all]] { \
154+
__ubsan_report_error_preserve(kind, GET_CALLER_PC()); \
155+
}
156+
#else
157+
#define HANDLER_PRESERVE(name, kind)
158+
#endif
159+
122160
#define HANDLER_RECOVER(name, kind) \
123161
INTERFACE void __ubsan_handle_##name##_minimal() { \
124162
__ubsan_report_error(kind, GET_CALLER_PC()); \
@@ -133,7 +171,8 @@ void NORETURN CheckFailed(const char *file, int, const char *cond, u64, u64) {
133171

134172
#define HANDLER(name, kind) \
135173
HANDLER_RECOVER(name, kind) \
136-
HANDLER_NORECOVER(name, kind)
174+
HANDLER_NORECOVER(name, kind) \
175+
HANDLER_PRESERVE(name, kind)
137176

138177
HANDLER(type_mismatch, "type-mismatch")
139178
HANDLER(alignment_assumption, "alignment-assumption")

compiler-rt/test/ubsan_minimal/TestCases/test-darwin-interface.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// RUN: sed -e 's/.*"\(.*libclang_rt.ubsan_minimal_osx_dynamic.dylib\)".*/\1/' | \
99
// RUN: tr -d '\n' > %t.dylib_path1
1010
// RUN: nm -jgU %{readfile:%t.dylib_path1} | grep "^___ubsan_handle" \
11+
// RUN: | grep -vE "_minimal_preserve" \
1112
// RUN: | sed 's/_minimal//g' \
1213
// RUN: > %t.minimal.symlist
1314
//

0 commit comments

Comments
 (0)