diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:54 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:11:54 +0000 |
commit | cdf4f3055e964bb585f294cf77cb549ead82783f (patch) | |
tree | 7bceeca766b3fbe491245bc926a083f78c35d1de /lib/ubsan_minimal | |
parent | 625108084a3ec7c19c7745004c5af0ed7aa417a9 (diff) | |
download | src-cdf4f3055e964bb585f294cf77cb549ead82783f.tar.gz src-cdf4f3055e964bb585f294cf77cb549ead82783f.zip |
Vendor import of compiler-rt trunk r321017:vendor/compiler-rt/compiler-rt-trunk-r321017
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=326943
svn path=/vendor/compiler-rt/compiler-rt-trunk-r321017/; revision=326944; tag=vendor/compiler-rt/compiler-rt-trunk-r321017
Diffstat (limited to 'lib/ubsan_minimal')
-rw-r--r-- | lib/ubsan_minimal/CMakeLists.txt | 55 | ||||
-rw-r--r-- | lib/ubsan_minimal/ubsan.syms.extra | 1 | ||||
-rw-r--r-- | lib/ubsan_minimal/ubsan_minimal_handlers.cc | 104 |
3 files changed, 160 insertions, 0 deletions
diff --git a/lib/ubsan_minimal/CMakeLists.txt b/lib/ubsan_minimal/CMakeLists.txt new file mode 100644 index 000000000000..54860a3d2764 --- /dev/null +++ b/lib/ubsan_minimal/CMakeLists.txt @@ -0,0 +1,55 @@ +# Build for the undefined behavior sanitizer runtime support library. + +set(UBSAN_MINIMAL_SOURCES + ubsan_minimal_handlers.cc + ) + +include_directories(..) + +set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) +append_rtti_flag(OFF UBSAN_CFLAGS) + +set(UBSAN_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) + +set(UBSAN_DYNAMIC_LIBS ${SANITIZER_COMMON_LINK_LIBS}) + +add_compiler_rt_component(ubsan-minimal) + +# Common parts of UBSan runtime. +add_compiler_rt_object_libraries(RTUbsan_minimal + OS ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_COMMON_SUPPORTED_ARCH} + SOURCES ${UBSAN_MINIMAL_SOURCES} CFLAGS ${UBSAN_CFLAGS}) + + +if(COMPILER_RT_HAS_UBSAN_MINIMAL) + # Initializer of standalone UBSan runtime. + + # Standalone UBSan runtimes. + add_compiler_rt_runtime(clang_rt.ubsan_minimal + STATIC + OS ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_SUPPORTED_ARCH} + OBJECT_LIBS RTUbsan_minimal + CFLAGS ${UBSAN_CFLAGS} + PARENT_TARGET ubsan-minimal) + + add_compiler_rt_runtime(clang_rt.ubsan_minimal + SHARED + OS ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_SUPPORTED_ARCH} + OBJECT_LIBS RTUbsan_minimal + CFLAGS ${UBSAN_CFLAGS} + LINK_FLAGS ${UBSAN_LINK_FLAGS} + LINK_LIBS ${UBSAN_DYNAMIC_LIBS} + PARENT_TARGET ubsan-minimal) + + if (UNIX AND NOT APPLE) + set(ARCHS_FOR_SYMBOLS ${UBSAN_SUPPORTED_ARCH}) + list(REMOVE_ITEM ARCHS_FOR_SYMBOLS i386 i686) + add_sanitizer_rt_symbols(clang_rt.ubsan_minimal + ARCHS ${ARCHS_FOR_SYMBOLS} + PARENT_TARGET ubsan-minimal + EXTRA ubsan.syms.extra) + endif() +endif() diff --git a/lib/ubsan_minimal/ubsan.syms.extra b/lib/ubsan_minimal/ubsan.syms.extra new file mode 100644 index 000000000000..7f8be694401a --- /dev/null +++ b/lib/ubsan_minimal/ubsan.syms.extra @@ -0,0 +1 @@ +__ubsan_* diff --git a/lib/ubsan_minimal/ubsan_minimal_handlers.cc b/lib/ubsan_minimal/ubsan_minimal_handlers.cc new file mode 100644 index 000000000000..5a5675c983fe --- /dev/null +++ b/lib/ubsan_minimal/ubsan_minimal_handlers.cc @@ -0,0 +1,104 @@ +#include "sanitizer_common/sanitizer_atomic.h" + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +#ifdef KERNEL_USE +extern "C" void ubsan_message(const char *msg); +static void message(const char *msg) { ubsan_message(msg); } +#else +static void message(const char *msg) { + write(2, msg, strlen(msg)); +} +#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 +// that "too many errors" has already been reported. +static __sanitizer::atomic_uint32_t caller_pcs_sz; + +__attribute__((noinline)) static bool report_this_error(void *caller_p) { + uintptr_t caller = reinterpret_cast<uintptr_t>(caller_p); + if (caller == 0) return false; + while (true) { + unsigned sz = __sanitizer::atomic_load_relaxed(&caller_pcs_sz); + if (sz > kMaxCallerPcs) return false; // early exit + // when sz==kMaxCallerPcs print "too many errors", but only when cmpxchg + // succeeds in order to not print it multiple times. + if (sz > 0 && sz < kMaxCallerPcs) { + uintptr_t p; + for (unsigned i = 0; i < sz; ++i) { + p = __sanitizer::atomic_load_relaxed(&caller_pcs[i]); + if (p == 0) break; // Concurrent update. + if (p == caller) return false; + } + if (p == 0) continue; // FIXME: yield? + } + + if (!__sanitizer::atomic_compare_exchange_strong( + &caller_pcs_sz, &sz, sz + 1, __sanitizer::memory_order_seq_cst)) + continue; // Concurrent update! Try again from the start. + + if (sz == kMaxCallerPcs) { + message("ubsan: too many errors\n"); + return false; + } + __sanitizer::atomic_store_relaxed(&caller_pcs[sz], caller); + return true; + } +} + +#if defined(__ANDROID__) +extern "C" __attribute__((weak)) void android_set_abort_message(const char *); +static void abort_with_message(const char *msg) { + if (&android_set_abort_message) android_set_abort_message(msg); + abort(); +} +#else +static void abort_with_message(const char *) { abort(); } +#endif + +#define INTERFACE extern "C" __attribute__((visibility("default"))) + +// FIXME: add caller pc to the error message (possibly as "ubsan: error-type +// @1234ABCD"). +#define HANDLER_RECOVER(name, msg) \ + INTERFACE void __ubsan_handle_##name##_minimal() { \ + if (!report_this_error(__builtin_return_address(0))) return; \ + message("ubsan: " msg "\n"); \ + } + +#define HANDLER_NORECOVER(name, msg) \ + INTERFACE void __ubsan_handle_##name##_minimal_abort() { \ + message("ubsan: " msg "\n"); \ + abort_with_message("ubsan: " msg); \ + } + +#define HANDLER(name, msg) \ + HANDLER_RECOVER(name, msg) \ + HANDLER_NORECOVER(name, msg) + +HANDLER(type_mismatch, "type-mismatch") +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_RECOVER(builtin_unreachable, "builtin-unreachable") +HANDLER_RECOVER(missing_return, "missing-return") +HANDLER(vla_bound_not_positive, "vla-bound-not-positive") +HANDLER(float_cast_overflow, "float-cast-overflow") +HANDLER(load_invalid_value, "load-invalid-value") +HANDLER(invalid_builtin, "invalid-builtin") +HANDLER(function_type_mismatch, "function-type-mismatch") +HANDLER(nonnull_arg, "nonnull-arg") +HANDLER(nonnull_return, "nonnull-return") +HANDLER(nullability_arg, "nullability-arg") +HANDLER(nullability_return, "nullability-return") +HANDLER(pointer_overflow, "pointer-overflow") +HANDLER(cfi_check_fail, "cfi-check-fail") |