diff options
Diffstat (limited to 'lib/ubsan')
-rw-r--r-- | lib/ubsan/CMakeLists.txt | 53 | ||||
-rw-r--r-- | lib/ubsan/Makefile.mk | 4 | ||||
-rw-r--r-- | lib/ubsan/ubsan_diag.cc | 11 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.cc | 29 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.h | 9 | ||||
-rw-r--r-- | lib/ubsan/ubsan_init.cc | 77 | ||||
-rw-r--r-- | lib/ubsan/ubsan_init.h | 13 | ||||
-rw-r--r-- | lib/ubsan/ubsan_init_standalone.cc | 34 | ||||
-rw-r--r-- | lib/ubsan/ubsan_platform.h | 1 |
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 |