[compiler-rt] r213983 - [UBSan] Call UBSan initialization as early as possible.

Alexey Samsonov vonosmas at gmail.com
Fri Jul 25 15:24:34 PDT 2014


Author: samsonov
Date: Fri Jul 25 17:24:34 2014
New Revision: 213983

URL: http://llvm.org/viewvc/llvm-project?rev=213983&view=rev
Log:
[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.

Added:
    compiler-rt/trunk/lib/ubsan/ubsan_init.cc
    compiler-rt/trunk/lib/ubsan/ubsan_init.h
Modified:
    compiler-rt/trunk/lib/ubsan/CMakeLists.txt
    compiler-rt/trunk/lib/ubsan/ubsan_diag.cc

Modified: compiler-rt/trunk/lib/ubsan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/CMakeLists.txt?rev=213983&r1=213982&r2=213983&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/ubsan/CMakeLists.txt Fri Jul 25 17:24:34 2014
@@ -2,6 +2,7 @@
 
 set(UBSAN_SOURCES
   ubsan_diag.cc
+  ubsan_init.cc
   ubsan_flags.cc
   ubsan_handlers.cc
   ubsan_value.cc

Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=213983&r1=213982&r2=213983&view=diff
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
+++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Fri Jul 25 17:24:34 2014
@@ -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
 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 De
 }
 
 Diag::~Diag() {
-  InitializeSanitizerCommonAndFlags();
+  InitIfNecessary();
   Decorator Decor;
   SpinMutexLock l(&CommonSanitizerReportMutex);
   Printf(Decor.Bold());

Added: compiler-rt/trunk/lib/ubsan/ubsan_init.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_init.cc?rev=213983&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_init.cc (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_init.cc Fri Jul 25 17:24:34 2014
@@ -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

Added: compiler-rt/trunk/lib/ubsan/ubsan_init.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_init.h?rev=213983&view=auto
==============================================================================
--- compiler-rt/trunk/lib/ubsan/ubsan_init.h (added)
+++ compiler-rt/trunk/lib/ubsan/ubsan_init.h Fri Jul 25 17:24:34 2014
@@ -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





More information about the llvm-commits mailing list