summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-07-25 22:24:34 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-07-25 22:24:34 +0000
commit6eb53d6460183b51a2cde13b30031572af65d3fe (patch)
treee324c3a92b6405f0d49bd9bcf6bcd0d1809a0c3f
parentac4b69e40bfebe502c8bee936539b352b0c14fa2 (diff)
downloadbcm5719-llvm-6eb53d6460183b51a2cde13b30031572af65d3fe.tar.gz
bcm5719-llvm-6eb53d6460183b51a2cde13b30031572af65d3fe.zip
[UBSan] Call UBSan initialization as early as possible.
Specifically, use .preinit_array initialization on Linux and dynamic global initializer on another platforms. Historically UBSan didn't have any initialization code and its runtime was stateless. This is no longer the case - UBSan relies on some non-trivial functionality from sanitizer_common (e.g. online symbolization) and is now configurable by runtime flags. Additionally, we've dropped support for enabling UBSan only for a few shared objects, so UBSan is now always linked into the main executable, so now we can use similar initialization as all the rest sanitizers. llvm-svn: 213983
-rw-r--r--compiler-rt/lib/ubsan/CMakeLists.txt1
-rw-r--r--compiler-rt/lib/ubsan/ubsan_diag.cc30
-rw-r--r--compiler-rt/lib/ubsan/ubsan_init.cc63
-rw-r--r--compiler-rt/lib/ubsan/ubsan_init.h24
4 files changed, 92 insertions, 26 deletions
diff --git a/compiler-rt/lib/ubsan/CMakeLists.txt b/compiler-rt/lib/ubsan/CMakeLists.txt
index 14e3dce2b55..7174392aa55 100644
--- a/compiler-rt/lib/ubsan/CMakeLists.txt
+++ b/compiler-rt/lib/ubsan/CMakeLists.txt
@@ -2,6 +2,7 @@
set(UBSAN_SOURCES
ubsan_diag.cc
+ ubsan_init.cc
ubsan_flags.cc
ubsan_handlers.cc
ubsan_value.cc
diff --git a/compiler-rt/lib/ubsan/ubsan_diag.cc b/compiler-rt/lib/ubsan/ubsan_diag.cc
index c19f2f5eddd..87beb625f7c 100644
--- a/compiler-rt/lib/ubsan/ubsan_diag.cc
+++ b/compiler-rt/lib/ubsan/ubsan_diag.cc
@@ -12,10 +12,8 @@
//===----------------------------------------------------------------------===//
#include "ubsan_diag.h"
+#include "ubsan_init.h"
#include "ubsan_flags.h"
-#include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_flags.h"
-#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
@@ -23,28 +21,8 @@
using namespace __ubsan;
-static void InitializeSanitizerCommonAndFlags() {
- static StaticSpinMutex init_mu;
- SpinMutexLock l(&init_mu);
- static bool initialized;
- if (initialized)
- return;
- if (0 == internal_strcmp(SanitizerToolName, "SanitizerTool")) {
- // UBSan is run in a standalone mode. Initialize it now.
- SanitizerToolName = "UndefinedBehaviorSanitizer";
- CommonFlags *cf = common_flags();
- SetCommonFlagsDefaults(cf);
- cf->print_summary = false;
- // Common flags may only be modified via UBSAN_OPTIONS.
- ParseCommonFlagsFromString(cf, GetEnv("UBSAN_OPTIONS"));
- }
- // Initialize UBSan-specific flags.
- InitializeFlags();
- initialized = true;
-}
-
void __ubsan::MaybePrintStackTrace(uptr pc, uptr bp) {
- // We assume that flags are already parsed: InitializeSanitizerCommonAndFlags
+ // We assume that flags are already parsed: InitIfNecessary
// will definitely be called when we print the first diagnostics message.
if (!flags()->print_stacktrace)
return;
@@ -82,7 +60,7 @@ Location __ubsan::getCallerLocation(uptr CallerLoc) {
Location __ubsan::getFunctionLocation(uptr Loc, const char **FName) {
if (!Loc)
return Location();
- InitializeSanitizerCommonAndFlags();
+ InitIfNecessary();
AddressInfo Info;
if (!Symbolizer::GetOrInit()->SymbolizePC(Loc, &Info, 1) ||
@@ -296,7 +274,7 @@ static void renderMemorySnippet(const Decorator &Decor, MemoryLocation Loc,
}
Diag::~Diag() {
- InitializeSanitizerCommonAndFlags();
+ InitIfNecessary();
Decorator Decor;
SpinMutexLock l(&CommonSanitizerReportMutex);
Printf(Decor.Bold());
diff --git a/compiler-rt/lib/ubsan/ubsan_init.cc b/compiler-rt/lib/ubsan/ubsan_init.cc
new file mode 100644
index 00000000000..9cfd42f3d0d
--- /dev/null
+++ b/compiler-rt/lib/ubsan/ubsan_init.cc
@@ -0,0 +1,63 @@
+//===-- ubsan_init.cc -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization of UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ubsan_init.h"
+#include "ubsan_flags.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_mutex.h"
+
+using namespace __ubsan;
+
+static bool ubsan_inited;
+
+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;
+ 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";
+ CommonFlags *cf = common_flags();
+ SetCommonFlagsDefaults(cf);
+ cf->print_summary = false;
+ // Common flags may only be modified via UBSAN_OPTIONS.
+ ParseCommonFlagsFromString(cf, GetEnv("UBSAN_OPTIONS"));
+ }
+ // Initialize UBSan-specific flags.
+ InitializeFlags();
+ ubsan_inited = true;
+}
+
+#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();
+ }
+};
+static UbsanInitializer ubsan_initializer;
+#endif // SANITIZER_CAN_USE_PREINIT_ARRAY
diff --git a/compiler-rt/lib/ubsan/ubsan_init.h b/compiler-rt/lib/ubsan/ubsan_init.h
new file mode 100644
index 00000000000..18356cfca61
--- /dev/null
+++ b/compiler-rt/lib/ubsan/ubsan_init.h
@@ -0,0 +1,24 @@
+//===-- ubsan_init.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Initialization function for UBSan runtime.
+//
+//===----------------------------------------------------------------------===//
+#ifndef UBSAN_INIT_H
+#define UBSAN_INIT_H
+
+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();
+
+} // namespace __ubsan
+
+#endif // UBSAN_INIT_H
OpenPOWER on IntegriCloud