mirror of
https://github.com/darlinghq/darling-compiler-rt.git
synced 2024-11-30 15:20:24 +00:00
[UBSan] Embed UBSan into ASan runtime (compiler-rt part).
Summary: Change the way we use ASan and UBSan together. Instead of keeping two separate runtimes (libclang_rt.asan and libclang_rt.ubsan), embed UBSan into ASan and get rid of libclang_rt.ubsan. If UBSan is not supported on a platform, all UBSan sources are just compiled into dummy empty object files. UBSan initialization code (e.g. flag parsing) is directly called from ASan initialization, so we are able to enforce correct initialization order. This mirrors the approach we already use for ASan+LSan. This change doesn't modify the way we use standalone UBSan. Test Plan: regression test suite Reviewers: kubabrecka, zaks.anna, rsmith, kcc Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8646 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@233861 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
06dcedbe14
commit
b05184a296
@ -305,9 +305,9 @@ if(APPLE)
|
||||
-stdlib=libc++
|
||||
-mios-simulator-version-min=7.0 -isysroot ${IOSSIM_SDK_DIR})
|
||||
set(DARWIN_osx_LINKFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}
|
||||
-stdlib=libc++ -lc++)
|
||||
-stdlib=libc++ -lc++ -lc++abi)
|
||||
set(DARWIN_iossim_LINKFLAGS
|
||||
-stdlib=libc++ -lc++
|
||||
-stdlib=libc++ -lc++ -lc++abi
|
||||
-Wl,-ios_simulator_version_min,7.0.0
|
||||
-mios-simulator-version-min=7.0
|
||||
-isysroot ${IOSSIM_SDK_DIR})
|
||||
|
@ -221,10 +221,12 @@ endfunction()
|
||||
# Architectures supported by compiler-rt libraries.
|
||||
filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH
|
||||
x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el)
|
||||
# LSan common files should be available on all architectures supported
|
||||
# LSan and UBSan common files should be available on all architectures supported
|
||||
# by other sanitizers (even if they build into dummy object files).
|
||||
filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(UBSAN_COMMON_SUPPORTED_ARCH
|
||||
${SANITIZER_COMMON_SUPPORTED_ARCH})
|
||||
filter_available_targets(ASAN_SUPPORTED_ARCH
|
||||
x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el)
|
||||
filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el)
|
||||
|
@ -8,6 +8,7 @@ if(COMPILER_RT_HAS_SANITIZER_COMMON)
|
||||
add_subdirectory(interception)
|
||||
add_subdirectory(sanitizer_common)
|
||||
add_subdirectory(lsan)
|
||||
add_subdirectory(ubsan)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_ASAN)
|
||||
@ -33,7 +34,3 @@ if(COMPILER_RT_HAS_TSAN)
|
||||
add_subdirectory(tsan/dd)
|
||||
endif()
|
||||
|
||||
if(COMPILER_RT_HAS_UBSAN)
|
||||
add_subdirectory(ubsan)
|
||||
endif()
|
||||
|
||||
|
@ -96,6 +96,7 @@ if(APPLE)
|
||||
$<TARGET_OBJECTS:RTInterception.${os}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${os}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${os}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${os}>
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_${os}_dynamic)
|
||||
@ -107,7 +108,8 @@ else()
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>)
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>)
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan-${arch} ${arch} STATIC
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_preinit.${arch}>
|
||||
@ -119,6 +121,7 @@ else()
|
||||
|
||||
add_compiler_rt_runtime(clang_rt.asan_cxx-${arch} ${arch} STATIC
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_cxx.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
CFLAGS ${ASAN_CFLAGS}
|
||||
DEFS ${ASAN_COMMON_DEFINITIONS})
|
||||
add_dependencies(asan clang_rt.asan_cxx-${arch})
|
||||
@ -137,6 +140,7 @@ else()
|
||||
add_compiler_rt_runtime(clang_rt.asan-dynamic-${arch} ${arch} SHARED
|
||||
OUTPUT_NAME ${SHARED_ASAN_NAME}
|
||||
SOURCES $<TARGET_OBJECTS:RTAsan_dynamic.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
|
||||
${ASAN_COMMON_RUNTIME_OBJECTS}
|
||||
CFLAGS ${ASAN_DYNAMIC_CFLAGS}
|
||||
DEFS ${ASAN_DYNAMIC_DEFINITIONS})
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_flag_parser.h"
|
||||
#include "ubsan/ubsan_flags.h"
|
||||
#include "ubsan/ubsan_platform.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
@ -72,8 +74,8 @@ void InitializeFlags() {
|
||||
RegisterAsanFlags(&asan_parser, f);
|
||||
RegisterCommonFlags(&asan_parser);
|
||||
|
||||
// Set the default values and prepare for parsing LSan flags (which can also
|
||||
// overwrite common flags).
|
||||
// Set the default values and prepare for parsing LSan and UBSan flags
|
||||
// (which can also overwrite common flags).
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
__lsan::Flags *lf = __lsan::flags();
|
||||
lf->SetDefaults();
|
||||
@ -83,6 +85,15 @@ void InitializeFlags() {
|
||||
RegisterCommonFlags(&lsan_parser);
|
||||
#endif
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
__ubsan::Flags *uf = __ubsan::flags();
|
||||
uf->SetDefaults();
|
||||
|
||||
FlagParser ubsan_parser;
|
||||
__ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
|
||||
RegisterCommonFlags(&ubsan_parser);
|
||||
#endif
|
||||
|
||||
// Override from ASan compile definition.
|
||||
const char *asan_compile_def = MaybeUseAsanDefaultOptionsCompileDefinition();
|
||||
asan_parser.ParseString(asan_compile_def);
|
||||
@ -90,12 +101,19 @@ void InitializeFlags() {
|
||||
// Override from user-specified string.
|
||||
const char *asan_default_options = MaybeCallAsanDefaultOptions();
|
||||
asan_parser.ParseString(asan_default_options);
|
||||
#if CAN_SANITIZE_UB
|
||||
const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
|
||||
ubsan_parser.ParseString(ubsan_default_options);
|
||||
#endif
|
||||
|
||||
// Override from command line.
|
||||
asan_parser.ParseString(GetEnv("ASAN_OPTIONS"));
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
lsan_parser.ParseString(GetEnv("LSAN_OPTIONS"));
|
||||
#endif
|
||||
#if CAN_SANITIZE_UB
|
||||
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
|
||||
#endif
|
||||
|
||||
// Let activation flags override current settings. On Android they come
|
||||
// from a system property. On other platforms this is no-op.
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_symbolizer.h"
|
||||
#include "lsan/lsan_common.h"
|
||||
#include "ubsan/ubsan_init.h"
|
||||
#include "ubsan/ubsan_platform.h"
|
||||
|
||||
int __asan_option_detect_stack_use_after_return; // Global interface symbol.
|
||||
uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan.
|
||||
@ -495,6 +497,10 @@ static void AsanInitInternal() {
|
||||
}
|
||||
#endif // CAN_SANITIZE_LEAKS
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
__ubsan::InitAsPlugin();
|
||||
#endif
|
||||
|
||||
InitializeSuppressions();
|
||||
|
||||
VReport(1, "AddressSanitizer Init done\n");
|
||||
|
@ -214,18 +214,18 @@ macro(add_asan_tests_for_arch_and_kind arch kind)
|
||||
$<TARGET_OBJECTS:RTAsan.osx>
|
||||
$<TARGET_OBJECTS:RTInterception.osx>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.osx>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>)
|
||||
$<TARGET_OBJECTS:RTLSanCommon.osx>
|
||||
$<TARGET_OBJECTS:RTUbsan.osx>)
|
||||
else()
|
||||
set(ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTAsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTAsan_cxx.${arch}>
|
||||
$<TARGET_OBJECTS:RTInterception.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>)
|
||||
if(NOT WIN32)
|
||||
list(APPEND ASAN_TEST_RUNTIME_OBJECTS
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>)
|
||||
endif()
|
||||
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
|
||||
$<TARGET_OBJECTS:RTLSanCommon.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan.${arch}>
|
||||
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>)
|
||||
endif()
|
||||
add_library(${ASAN_TEST_RUNTIME} STATIC ${ASAN_TEST_RUNTIME_OBJECTS})
|
||||
set_target_properties(${ASAN_TEST_RUNTIME} PROPERTIES
|
||||
|
@ -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_dependencies(ubsan clang_rt.ubsan_${os}_dynamic)
|
||||
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)
|
||||
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()
|
||||
|
@ -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=%)
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
|
||||
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 void CommonStandaloneInit() {
|
||||
SanitizerToolName = "UndefinedBehaviorSanitizer";
|
||||
InitializeFlags();
|
||||
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
|
||||
CommonInit();
|
||||
ubsan_mode = UBSAN_MODE_STANDALONE;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
|
34
lib/ubsan/ubsan_init_standalone.cc
Normal file
34
lib/ubsan/ubsan_init_standalone.cc
Normal file
@ -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
|
||||
|
@ -20,7 +20,6 @@
|
||||
# define CAN_SANITIZE_UB 1
|
||||
#else
|
||||
# define CAN_SANITIZE_UB 0
|
||||
# error "UBSan not supported for this platform!"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -230,7 +230,7 @@ CFLAGS.profile_ios.armv7k := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS)
|
||||
CFLAGS.profile_ios.armv7s := $(CFLAGS) $(IOS_DEPLOYMENT_ARGS)
|
||||
CFLAGS.profile_ios.arm64 := $(CFLAGS) $(IOS6_DEPLOYMENT_ARGS)
|
||||
|
||||
SANITIZER_LDFLAGS := -stdlib=libc++ -lc++
|
||||
SANITIZER_LDFLAGS := -stdlib=libc++ -lc++ -lc++abi
|
||||
|
||||
SHARED_LIBRARY.asan_osx_dynamic := 1
|
||||
LDFLAGS.asan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.asan_osx_dynamic.dylib \
|
||||
@ -241,11 +241,11 @@ LDFLAGS.asan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclan
|
||||
-Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS)
|
||||
|
||||
SHARED_LIBRARY.ubsan_osx_dynamic := 1
|
||||
LDFLAGS.ubsan_osx_dynamic := $(SANITIZER_LDFLAGS) -lc++abi -install_name @rpath/libclang_rt.ubsan_osx_dynamic.dylib \
|
||||
LDFLAGS.ubsan_osx_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_osx_dynamic.dylib \
|
||||
$(SANITIZER_MACOSX_DEPLOYMENT_ARGS)
|
||||
|
||||
SHARED_LIBRARY.ubsan_iossim_dynamic := 1
|
||||
LDFLAGS.ubsan_iossim_dynamic := $(SANITIZER_LDFLAGS) -lc++abi -install_name @rpath/libclang_rt.ubsan_iossim_dynamic.dylib \
|
||||
LDFLAGS.ubsan_iossim_dynamic := $(SANITIZER_LDFLAGS) -install_name @rpath/libclang_rt.ubsan_iossim_dynamic.dylib \
|
||||
-Wl,-ios_simulator_version_min,7.0.0 $(SANITIZER_IOSSIM_DEPLOYMENT_ARGS)
|
||||
|
||||
ifneq ($(OSX_SDK),)
|
||||
@ -275,18 +275,22 @@ FUNCTIONS.profile_ios := $(FUNCTIONS.profile_osx)
|
||||
FUNCTIONS.asan_osx_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
|
||||
$(InterceptionFunctions) \
|
||||
$(SanitizerCommonFunctions) \
|
||||
$(AsanDynamicFunctions)
|
||||
$(AsanDynamicFunctions) \
|
||||
$(UbsanFunctions) $(UbsanCXXFunctions)
|
||||
|
||||
FUNCTIONS.asan_iossim_dynamic := $(AsanFunctions) $(AsanCXXFunctions) \
|
||||
$(InterceptionFunctions) \
|
||||
$(SanitizerCommonFunctions) \
|
||||
$(AsanDynamicFunctions)
|
||||
$(AsanDynamicFunctions) \
|
||||
$(UbsanFunctions) $(UbsanCXXFunctions)
|
||||
|
||||
FUNCTIONS.ubsan_osx_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
|
||||
$(SanitizerCommonFunctions)
|
||||
$(SanitizerCommonFunctions) \
|
||||
$(UbsanStandaloneFunctions)
|
||||
|
||||
FUNCTIONS.ubsan_iossim_dynamic := $(UbsanFunctions) $(UbsanCXXFunctions) \
|
||||
$(SanitizerCommonFunctions)
|
||||
$(SanitizerCommonFunctions) \
|
||||
$(UbsanStandaloneFunctions)
|
||||
|
||||
CCKEXT_PROFILE_FUNCTIONS := \
|
||||
InstrProfiling \
|
||||
|
@ -3,16 +3,16 @@
|
||||
// RUN: mkdir -p %T/coverage-levels
|
||||
// RUN: OPT=coverage=1:verbosity=1:coverage_dir=%T/coverage-levels
|
||||
// RUN: %clangxx -fsanitize=shift -DGOOD_SHIFT=1 -O1 -fsanitize-coverage=1 %s -o %t
|
||||
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN
|
||||
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN
|
||||
// RUN: %clangxx -fsanitize=undefined -DGOOD_SHIFT=1 -O1 -fsanitize-coverage=1 %s -o %t
|
||||
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN
|
||||
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_NOWARN
|
||||
|
||||
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=1 %s -o %t
|
||||
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN
|
||||
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK1 --check-prefix=CHECK_WARN
|
||||
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=2 %s -o %t
|
||||
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN
|
||||
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK2 --check-prefix=CHECK_WARN
|
||||
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=3 %s -o %t
|
||||
// RUN: UBSAN_OPTIONS=$OPT ASAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
|
||||
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
|
||||
|
||||
volatile int sink;
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t
|
||||
// RUN: %run %t 2>&1 | FileCheck %s
|
||||
// Verify that we can disable symbolization if needed:
|
||||
// RUN: UBSAN_OPTIONS=symbolize=0 ASAN_OPTIONS=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM
|
||||
// RUN: UBSAN_OPTIONS=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM
|
||||
|
||||
// -fsanitize=function is unsupported on Darwin yet.
|
||||
// XFAIL: darwin
|
||||
|
Loading…
Reference in New Issue
Block a user