aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ubsan_minimal
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:54 +0000
commitcdf4f3055e964bb585f294cf77cb549ead82783f (patch)
tree7bceeca766b3fbe491245bc926a083f78c35d1de /lib/ubsan_minimal
parent625108084a3ec7c19c7745004c5af0ed7aa417a9 (diff)
downloadsrc-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.txt55
-rw-r--r--lib/ubsan_minimal/ubsan.syms.extra1
-rw-r--r--lib/ubsan_minimal/ubsan_minimal_handlers.cc104
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")