summaryrefslogtreecommitdiff
path: root/lib/ubsan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ubsan')
-rw-r--r--lib/ubsan/CMakeLists.txt53
-rw-r--r--lib/ubsan/Makefile.mk4
-rw-r--r--lib/ubsan/ubsan_diag.cc11
-rw-r--r--lib/ubsan/ubsan_flags.cc29
-rw-r--r--lib/ubsan/ubsan_flags.h9
-rw-r--r--lib/ubsan/ubsan_init.cc77
-rw-r--r--lib/ubsan/ubsan_init.h13
-rw-r--r--lib/ubsan/ubsan_init_standalone.cc34
-rw-r--r--lib/ubsan/ubsan_platform.h1
9 files changed, 143 insertions, 88 deletions
diff --git a/lib/ubsan/CMakeLists.txt b/lib/ubsan/CMakeLists.txt
index a8b3f61ef..4ea0f5067 100644
--- a/lib/ubsan/CMakeLists.txt
+++ b/lib/ubsan/CMakeLists.txt
@@ -8,6 +8,10 @@ set(UBSAN_SOURCES
ubsan_value.cc
)
+set(UBSAN_STANDALONE_SOURCES
+ ubsan_init_standalone.cc
+ )
+
set(UBSAN_CXX_SOURCES
ubsan_handlers_cxx.cc
ubsan_type_hash.cc
@@ -17,64 +21,69 @@ include_directories(..)
set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS})
append_no_rtti_flag(UBSAN_CFLAGS)
+set(UBSAN_STANDALONE_CFLAGS ${SANITIZER_COMMON_CFLAGS})
+append_no_rtti_flag(UBSAN_STANDALONE_CFLAGS)
set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS})
add_custom_target(ubsan)
if(APPLE)
foreach(os ${SANITIZER_COMMON_SUPPORTED_DARWIN_OS})
+ # Common parts of UBSan runtime.
add_compiler_rt_darwin_object_library(RTUbsan ${os}
- ARCH ${UBSAN_SUPPORTED_ARCH}
+ ARCH ${UBSAN_COMMON_SUPPORTED_ARCH}
SOURCES ${UBSAN_SOURCES} ${UBSAN_CXX_SOURCES}
CFLAGS ${UBSAN_CXXFLAGS})
- add_compiler_rt_darwin_dynamic_runtime(clang_rt.ubsan_${os}_dynamic ${os}
- ARCH ${UBSAN_SUPPORTED_ARCH}
- SOURCES $<TARGET_OBJECTS:RTUbsan.${os}>
- $<TARGET_OBJECTS:RTSanitizerCommon.${os}>
- LINKFLAGS -lc++abi)
+ if(UBSAN_SUPPORTED_ARCH)
+ # Initializer of standalone UBSan runtime.
+ add_compiler_rt_darwin_object_library(RTUbsan_standalone ${os}
+ ARCH ${UBSAN_SUPPORTED_ARCH}
+ SOURCES ${UBSAN_STANDALONE_SOURCES}
+ CFLAGS ${UBSAN_STANDALONE_CFLAGS})
+
+ add_compiler_rt_darwin_dynamic_runtime(clang_rt.ubsan_${os}_dynamic ${os}
+ ARCH ${UBSAN_SUPPORTED_ARCH}
+ SOURCES $<TARGET_OBJECTS:RTUbsan.${os}>
+ $<TARGET_OBJECTS:RTUbsan_standalone.${os}>
+ $<TARGET_OBJECTS:RTSanitizerCommon.${os}>)
- add_dependencies(ubsan clang_rt.ubsan_${os}_dynamic)
+ add_dependencies(ubsan clang_rt.ubsan_${os}_dynamic)
+ endif()
endforeach()
else()
- # Build separate libraries for each target.
- foreach(arch ${UBSAN_SUPPORTED_ARCH})
+ # Common parts of UBSan runtime.
+ foreach(arch ${UBSAN_COMMON_SUPPORTED_ARCH})
add_compiler_rt_object_library(RTUbsan ${arch}
SOURCES ${UBSAN_SOURCES} CFLAGS ${UBSAN_CFLAGS})
# C++-specific parts of UBSan runtime. Requires a C++ ABI library.
add_compiler_rt_object_library(RTUbsan_cxx ${arch}
SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS})
+ endforeach()
+
+ foreach(arch ${UBSAN_SUPPORTED_ARCH})
+ # Initializer of standalone UBSan runtime.
+ add_compiler_rt_object_library(RTUbsan_standalone ${arch}
+ SOURCES ${UBSAN_STANDALONE_SOURCES} CFLAGS ${UBSAN_STANDALONE_CFLAGS})
# Standalone UBSan runtimes.
add_compiler_rt_runtime(clang_rt.ubsan_standalone-${arch} ${arch} STATIC
SOURCES $<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
$<TARGET_OBJECTS:RTUbsan.${arch}>
+ $<TARGET_OBJECTS:RTUbsan_standalone.${arch}>
CFLAGS ${UBSAN_CFLAGS})
add_compiler_rt_runtime(clang_rt.ubsan_standalone_cxx-${arch} ${arch} STATIC
SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
CFLAGS ${UBSAN_CXXFLAGS})
- # UBSan runtimes used when another sanitizer is available.
- add_compiler_rt_runtime(clang_rt.ubsan-${arch} ${arch} STATIC
- SOURCES $<TARGET_OBJECTS:RTUbsan.${arch}>
- CFLAGS ${UBSAN_CFLAGS})
- add_compiler_rt_runtime(clang_rt.ubsan_cxx-${arch} ${arch} STATIC
- SOURCES $<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
- CFLAGS ${UBSAN_CXXFLAGS})
add_dependencies(ubsan
- clang_rt.ubsan-${arch}
- clang_rt.ubsan_cxx-${arch}
clang_rt.ubsan_standalone-${arch}
clang_rt.ubsan_standalone_cxx-${arch})
if (UNIX AND NOT ${arch} MATCHES "i386|i686")
- add_sanitizer_rt_symbols(clang_rt.ubsan-${arch} ubsan.syms.extra)
- add_sanitizer_rt_symbols(clang_rt.ubsan_cxx-${arch} ubsan.syms.extra)
add_sanitizer_rt_symbols(clang_rt.ubsan_standalone-${arch} ubsan.syms.extra)
add_sanitizer_rt_symbols(clang_rt.ubsan_standalone_cxx-${arch} ubsan.syms.extra)
add_dependencies(ubsan
- clang_rt.ubsan-${arch}-symbols
- clang_rt.ubsan_cxx-${arch}-symbols
clang_rt.ubsan_standalone-${arch}-symbols
clang_rt.ubsan_standalone_cxx-${arch}-symbols)
endif()
diff --git a/lib/ubsan/Makefile.mk b/lib/ubsan/Makefile.mk
index d5561f41b..ec3f5c5da 100644
--- a/lib/ubsan/Makefile.mk
+++ b/lib/ubsan/Makefile.mk
@@ -11,8 +11,9 @@ ModuleName := ubsan
SubDirs :=
Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file)))
+StandaloneSources := ubsan_init_standalone.cc
CXXSources := ubsan_type_hash.cc ubsan_handlers_cxx.cc
-CSources := $(filter-out $(CXXSources),$(Sources))
+CSources := $(filter-out $(StandaloneSources),$(filter-out $(CXXSources),$(Sources)))
ObjNames := $(Sources:%.cc=%.o)
Implementation := Generic
@@ -24,3 +25,4 @@ Dependencies += $(wildcard $(Dir)/../sanitizer_common/*.h)
# Define a convenience variable for all the ubsan functions.
UbsanFunctions := $(CSources:%.cc=%)
UbsanCXXFunctions := $(CXXSources:%.cc=%)
+UbsanStandaloneFunctions := $(StandaloneSources:%.cc=%)
diff --git a/lib/ubsan/ubsan_diag.cc b/lib/ubsan/ubsan_diag.cc
index 2314fb6ed..6f76c6af3 100644
--- a/lib/ubsan/ubsan_diag.cc
+++ b/lib/ubsan/ubsan_diag.cc
@@ -27,7 +27,7 @@
using namespace __ubsan;
static void MaybePrintStackTrace(uptr pc, uptr bp) {
- // We assume that flags are already parsed: InitIfNecessary
+ // We assume that flags are already parsed, as UBSan runtime
// will definitely be called when we print the first diagnostics message.
if (!flags()->print_stacktrace)
return;
@@ -76,7 +76,7 @@ class Decorator : public SanitizerCommonDecorator {
}
SymbolizedStack *__ubsan::getSymbolizedLocation(uptr PC) {
- InitIfNecessary();
+ InitAsStandaloneIfNecessary();
return Symbolizer::GetOrInit()->SymbolizePC(PC);
}
@@ -330,7 +330,7 @@ Diag::~Diag() {
ScopedReport::ScopedReport(ReportOptions Opts, Location SummaryLoc)
: Opts(Opts), SummaryLoc(SummaryLoc) {
- InitIfNecessary();
+ InitAsStandaloneIfNecessary();
CommonSanitizerReportMutex.Lock();
}
@@ -355,10 +355,7 @@ void __ubsan::InitializeSuppressions() {
}
bool __ubsan::IsVptrCheckSuppressed(const char *TypeName) {
- // If .preinit_array is not used, it is possible that the UBSan runtime is not
- // initialized.
- if (!SANITIZER_CAN_USE_PREINIT_ARRAY)
- InitIfNecessary();
+ InitAsStandaloneIfNecessary();
CHECK(suppression_ctx);
Suppression *s;
return suppression_ctx->Match(TypeName, kVptrCheck, &s);
diff --git a/lib/ubsan/ubsan_flags.cc b/lib/ubsan/ubsan_flags.cc
index 49ada8a26..eda7557a0 100644
--- a/lib/ubsan/ubsan_flags.cc
+++ b/lib/ubsan/ubsan_flags.cc
@@ -20,7 +20,7 @@
namespace __ubsan {
-static const char *MaybeCallUbsanDefaultOptions() {
+const char *MaybeCallUbsanDefaultOptions() {
return (&__ubsan_default_options) ? __ubsan_default_options() : "";
}
@@ -39,31 +39,22 @@ void RegisterUbsanFlags(FlagParser *parser, Flags *f) {
#undef UBSAN_FLAG
}
-void InitializeFlags(bool standalone) {
- Flags *f = flags();
- FlagParser parser;
- RegisterUbsanFlags(&parser, f);
-
- if (standalone) {
- RegisterCommonFlags(&parser);
-
- SetCommonFlagsDefaults();
+void InitializeFlags() {
+ SetCommonFlagsDefaults();
+ {
CommonFlags cf;
cf.CopyFrom(*common_flags());
cf.print_summary = false;
OverrideCommonFlags(cf);
- } else {
- // Ignore common flags if not standalone.
- // This is inconsistent with LSan, which allows common flags in LSAN_FLAGS.
- // This is caused by undefined initialization order between ASan and UBsan,
- // which makes it impossible to make sure that common flags from ASAN_OPTIONS
- // have not been used (in __asan_init) before they are overwritten with flags
- // from UBSAN_OPTIONS.
- CommonFlags cf_ignored;
- RegisterCommonFlags(&parser, &cf_ignored);
}
+ Flags *f = flags();
f->SetDefaults();
+
+ FlagParser parser;
+ RegisterCommonFlags(&parser);
+ RegisterUbsanFlags(&parser, f);
+
// Override from user-specified string.
parser.ParseString(MaybeCallUbsanDefaultOptions());
// Override from environment variable.
diff --git a/lib/ubsan/ubsan_flags.h b/lib/ubsan/ubsan_flags.h
index b47f14e1e..18aed9b05 100644
--- a/lib/ubsan/ubsan_flags.h
+++ b/lib/ubsan/ubsan_flags.h
@@ -15,6 +15,10 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
+namespace __sanitizer {
+class FlagParser;
+}
+
namespace __ubsan {
struct Flags {
@@ -28,7 +32,10 @@ struct Flags {
extern Flags ubsan_flags;
inline Flags *flags() { return &ubsan_flags; }
-void InitializeFlags(bool standalone);
+void InitializeFlags();
+void RegisterUbsanFlags(FlagParser *parser, Flags *f);
+
+const char *MaybeCallUbsanDefaultOptions();
} // namespace __ubsan
diff --git a/lib/ubsan/ubsan_init.cc b/lib/ubsan/ubsan_init.cc
index 952726977..c3b8b6c22 100644
--- a/lib/ubsan/ubsan_init.cc
+++ b/lib/ubsan/ubsan_init.cc
@@ -23,45 +23,54 @@
using namespace __ubsan;
-static bool ubsan_inited;
+static enum {
+ UBSAN_MODE_UNKNOWN = 0,
+ UBSAN_MODE_STANDALONE,
+ UBSAN_MODE_PLUGIN
+} ubsan_mode;
+static StaticSpinMutex ubsan_init_mu;
-void __ubsan::InitIfNecessary() {
-#if !SANITIZER_CAN_USE_PREINIT_ARRAY
- // No need to lock mutex if we're initializing from preinit array.
- static StaticSpinMutex init_mu;
- SpinMutexLock l(&init_mu);
-#endif
- if (LIKELY(ubsan_inited))
- return;
- bool standalone = false;
- if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) {
- // WARNING: If this condition holds, then either UBSan runs in a standalone
- // mode, or initializer for another sanitizer hasn't run yet. In a latter
- // case, another sanitizer will overwrite "SanitizerToolName" and reparse
- // common flags. It means, that we are not allowed to *use* common flags
- // in this function.
- SanitizerToolName = "UndefinedBehaviorSanitizer";
- standalone = true;
- }
- // Initialize UBSan-specific flags.
- InitializeFlags(standalone);
+static void CommonInit() {
InitializeSuppressions();
+}
+
+static void CommonStandaloneInit() {
+ SanitizerToolName = "UndefinedBehaviorSanitizer";
+ InitializeFlags();
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
- ubsan_inited = true;
+ CommonInit();
+ ubsan_mode = UBSAN_MODE_STANDALONE;
}
-#if SANITIZER_CAN_USE_PREINIT_ARRAY
-__attribute__((section(".preinit_array"), used))
-void (*__local_ubsan_preinit)(void) = __ubsan::InitIfNecessary;
-#else
-// Use a dynamic initializer.
-class UbsanInitializer {
- public:
- UbsanInitializer() {
- InitIfNecessary();
+void __ubsan::InitAsStandalone() {
+ if (SANITIZER_CAN_USE_PREINIT_ARRAY) {
+ CHECK_EQ(UBSAN_MODE_UNKNOWN, ubsan_mode);
+ CommonStandaloneInit();
+ return;
}
-};
-static UbsanInitializer ubsan_initializer;
-#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
+ SpinMutexLock l(&ubsan_init_mu);
+ CHECK_NE(UBSAN_MODE_PLUGIN, ubsan_mode);
+ if (ubsan_mode == UBSAN_MODE_UNKNOWN)
+ CommonStandaloneInit();
+}
+
+void __ubsan::InitAsStandaloneIfNecessary() {
+ if (SANITIZER_CAN_USE_PREINIT_ARRAY) {
+ CHECK_NE(UBSAN_MODE_UNKNOWN, ubsan_mode);
+ return;
+ }
+ SpinMutexLock l(&ubsan_init_mu);
+ if (ubsan_mode == UBSAN_MODE_UNKNOWN)
+ CommonStandaloneInit();
+}
+
+void __ubsan::InitAsPlugin() {
+#if !SANITIZER_CAN_USE_PREINIT_ARRAY
+ SpinMutexLock l(&ubsan_init_mu);
+#endif
+ CHECK_EQ(UBSAN_MODE_UNKNOWN, ubsan_mode);
+ CommonInit();
+ ubsan_mode = UBSAN_MODE_PLUGIN;
+}
#endif // CAN_SANITIZE_UB
diff --git a/lib/ubsan/ubsan_init.h b/lib/ubsan/ubsan_init.h
index 18356cfca..103ae24d1 100644
--- a/lib/ubsan/ubsan_init.h
+++ b/lib/ubsan/ubsan_init.h
@@ -15,9 +15,16 @@
namespace __ubsan {
-// NOTE: This function might take a lock (if .preinit_array initialization is
-// not used). It's generally a bad idea to call it on a fast path.
-void InitIfNecessary();
+// Initialize UBSan as a standalone tool. Typically should be called early
+// during initialization.
+void InitAsStandalone();
+
+// Initialize UBSan as a standalone tool, if it hasn't been initialized before.
+void InitAsStandaloneIfNecessary();
+
+// Initializes UBSan as a plugin tool. This function should be called once
+// from "parent tool" (e.g. ASan) initialization.
+void InitAsPlugin();
} // namespace __ubsan
diff --git a/lib/ubsan/ubsan_init_standalone.cc b/lib/ubsan/ubsan_init_standalone.cc
new file mode 100644
index 000000000..cd2da1191
--- /dev/null
+++ b/lib/ubsan/ubsan_init_standalone.cc
@@ -0,0 +1,34 @@
+//===-- ubsan_init_standalone.cc ------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization of standalone UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_platform.h"
+#if !CAN_SANITIZE_UB
+# error "UBSan is not supported on this platform!
+#endif
+
+#include "ubsan_init.h"
+
+#if SANITIZER_CAN_USE_PREINIT_ARRAY
+__attribute__((section(".preinit_array"), used))
+void (*__local_ubsan_preinit)(void) = __ubsan::InitAsStandalone;
+#else
+// Use a dynamic initializer.
+class UbsanStandaloneInitializer {
+ public:
+ UbsanStandaloneInitializer() {
+ __ubsan::InitAsStandalone();
+ }
+};
+static UbsanStandaloneInitializer ubsan_standalone_initializer;
+#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
+
diff --git a/lib/ubsan/ubsan_platform.h b/lib/ubsan/ubsan_platform.h
index 83fb42b3b..8ba253bfe 100644
--- a/lib/ubsan/ubsan_platform.h
+++ b/lib/ubsan/ubsan_platform.h
@@ -20,7 +20,6 @@
# define CAN_SANITIZE_UB 1
#else
# define CAN_SANITIZE_UB 0
-# error "UBSan not supported for this platform!"
#endif
#endif