Allow UBSan+MSan and UBSan+TSan combinations (Clang part).

Embed UBSan runtime into TSan and MSan runtimes in the same as we do
in ASan. Extend UBSan test suite to also run tests for these
combinations.

llvm-svn: 235954
This commit is contained in:
Alexey Samsonov 2015-04-28 00:56:48 +00:00
parent d60832eade
commit b3053d9cbe
13 changed files with 109 additions and 36 deletions

View File

@ -32,9 +32,11 @@ foreach(arch ${MSAN_SUPPORTED_ARCH})
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
$<TARGET_OBJECTS:RTUbsan.${arch}>
CFLAGS ${MSAN_RTL_CFLAGS})
add_compiler_rt_runtime(clang_rt.msan_cxx-${arch} ${arch} STATIC
SOURCES ${MSAN_RTL_CXX_SOURCES}
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
CFLAGS ${MSAN_RTL_CFLAGS})
add_dependencies(msan clang_rt.msan-${arch}
clang_rt.msan_cxx-${arch})

View File

@ -26,6 +26,8 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "ubsan/ubsan_flags.h"
#include "ubsan/ubsan_init.h"
// ACHTUNG! No system header includes in this file.
@ -133,11 +135,6 @@ static void RegisterMsanFlags(FlagParser *parser, Flags *f) {
}
static void InitializeFlags() {
Flags *f = flags();
FlagParser parser;
RegisterMsanFlags(&parser, f);
RegisterCommonFlags(&parser);
SetCommonFlagsDefaults();
{
CommonFlags cf;
@ -151,14 +148,35 @@ static void InitializeFlags() {
OverrideCommonFlags(cf);
}
Flags *f = flags();
f->SetDefaults();
FlagParser parser;
RegisterMsanFlags(&parser, f);
RegisterCommonFlags(&parser);
#if MSAN_CONTAINS_UBSAN
__ubsan::Flags *uf = __ubsan::flags();
uf->SetDefaults();
FlagParser ubsan_parser;
__ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
RegisterCommonFlags(&ubsan_parser);
#endif
// Override from user-specified string.
if (__msan_default_options)
parser.ParseString(__msan_default_options());
#if MSAN_CONTAINS_UBSAN
const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
ubsan_parser.ParseString(ubsan_default_options);
#endif
const char *msan_options = GetEnv("MSAN_OPTIONS");
parser.ParseString(msan_options);
#if MSAN_CONTAINS_UBSAN
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
#endif
VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>");
SetVerbosity(common_flags()->verbosity);
@ -392,6 +410,10 @@ void __msan_init() {
SetCurrentThread(main_thread);
main_thread->ThreadStart();
#if MSAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
#endif
VPrintf(1, "MemorySanitizer init done\n");
msan_init_is_running = 0;

View File

@ -20,11 +20,16 @@
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "msan_interface_internal.h"
#include "msan_flags.h"
#include "ubsan/ubsan_platform.h"
#ifndef MSAN_REPLACE_OPERATORS_NEW_AND_DELETE
# define MSAN_REPLACE_OPERATORS_NEW_AND_DELETE 1
#endif
#ifndef MSAN_CONTAINS_UBSAN
# define MSAN_CONTAINS_UBSAN CAN_SANITIZE_UB
#endif
struct MappingDesc {
uptr start;
uptr end;

View File

@ -107,9 +107,11 @@ if(UNIX AND NOT APPLE)
$<TARGET_OBJECTS:RTInterception.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
$<TARGET_OBJECTS:RTUbsan.${arch}>
CFLAGS ${TSAN_RTL_CFLAGS})
add_compiler_rt_runtime(clang_rt.tsan_cxx-${arch} ${arch} STATIC
SOURCES ${TSAN_CXX_SOURCES}
$<TARGET_OBJECTS:RTUbsan_cxx.${arch}>
CFLAGS ${TSAN_RTL_CFLAGS})
list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch}
clang_rt.tsan_cxx-${arch})

View File

@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "tsan_stat.h"
#include "ubsan/ubsan_platform.h"
// Setup defaults for compile definitions.
#ifndef TSAN_NO_HISTORY
@ -27,6 +28,10 @@
# define TSAN_COLLECT_STATS 0
#endif
#ifndef TSAN_CONTAINS_UBSAN
# define TSAN_CONTAINS_UBSAN (CAN_SANITIZE_UB && !defined(SANITIZER_GO))
#endif
namespace __tsan {
#ifdef SANITIZER_GO

View File

@ -17,6 +17,7 @@
#include "tsan_flags.h"
#include "tsan_rtl.h"
#include "tsan_mman.h"
#include "ubsan/ubsan_flags.h"
namespace __tsan {
@ -54,12 +55,6 @@ void RegisterTsanFlags(FlagParser *parser, Flags *f) {
}
void InitializeFlags(Flags *f, const char *env) {
FlagParser parser;
RegisterTsanFlags(&parser, f);
RegisterCommonFlags(&parser);
f->SetDefaults();
SetCommonFlagsDefaults();
{
// Override some common flags defaults.
@ -74,10 +69,32 @@ void InitializeFlags(Flags *f, const char *env) {
OverrideCommonFlags(cf);
}
f->SetDefaults();
FlagParser parser;
RegisterTsanFlags(&parser, f);
RegisterCommonFlags(&parser);
#if TSAN_CONTAINS_UBSAN
__ubsan::Flags *uf = __ubsan::flags();
uf->SetDefaults();
FlagParser ubsan_parser;
__ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
RegisterCommonFlags(&ubsan_parser);
#endif
// Let a frontend override.
parser.ParseString(__tsan_default_options());
#if TSAN_CONTAINS_UBSAN
const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
ubsan_parser.ParseString(ubsan_default_options);
#endif
// Override from command line.
parser.ParseString(env);
#if TSAN_CONTAINS_UBSAN
ubsan_parser.ParseString(GetEnv("UBSAN_OPTIONS"));
#endif
// Sanity check.
if (!f->report_bugs) {

View File

@ -24,6 +24,7 @@
#include "tsan_mman.h"
#include "tsan_suppressions.h"
#include "tsan_symbolize.h"
#include "ubsan/ubsan_init.h"
#ifdef __SSE3__
// <emmintrin.h> transitively includes <stdlib.h>,
@ -350,6 +351,9 @@ void Initialize(ThreadState *thr) {
int tid = ThreadCreate(thr, 0, 0, true);
CHECK_EQ(tid, 0);
ThreadStart(thr, tid, internal_getpid());
#if TSAN_CONTAINS_UBSAN
__ubsan::InitAsPlugin();
#endif
ctx->initialized = true;
if (flags()->stop_on_start) {

View File

@ -1,6 +1,20 @@
set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(UBSAN_TESTSUITES)
set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
macro(add_ubsan_testsuite test_mode sanitizer arch)
set(UBSAN_LIT_TEST_MODE "${test_mode}")
set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND UBSAN_TEST_DEPS ${sanitizer})
endif()
endmacro()
foreach(arch ${UBSAN_SUPPORTED_ARCH})
set(UBSAN_TEST_TARGET_ARCH ${arch})
if(${arch} MATCHES "arm|aarch64")
@ -9,28 +23,19 @@ foreach(arch ${UBSAN_SUPPORTED_ARCH})
else()
get_target_flags_for_arch(${arch} UBSAN_TEST_TARGET_CFLAGS)
endif()
set(UBSAN_LIT_TEST_MODE "Standalone")
set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
add_ubsan_testsuite("Standalone" ubsan ${arch})
if(COMPILER_RT_HAS_ASAN)
set(UBSAN_LIT_TEST_MODE "AddressSanitizer")
set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch})
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg)
list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME})
if(";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
add_ubsan_testsuite("AddressSanitizer" asan ${arch})
endif()
if(";${MSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
add_ubsan_testsuite("MemorySanitizer" msan ${arch})
endif()
if(";${TSAN_SUPPORTED_ARCH};" MATCHES ";${arch};")
add_ubsan_testsuite("ThreadSanitizer" tsan ${arch})
endif()
endforeach()
set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND UBSAN_TEST_DEPS ubsan asan)
endif()
add_lit_testsuite(check-ubsan "Running UndefinedBehaviorSanitizer tests"
${UBSAN_TESTSUITES}
DEPENDS ${UBSAN_TEST_DEPS})

View File

@ -14,6 +14,9 @@
// RUN: %clangxx -fsanitize=shift -O1 -fsanitize-coverage=3 %s -o %t
// RUN: UBSAN_OPTIONS=$OPT %run %t 2>&1 | FileCheck %s --check-prefix=CHECK3 --check-prefix=CHECK_WARN
// Coverage is not yet implemented in TSan.
// XFAIL: ubsan-tsan
volatile int sink;
int main(int argc, char **argv) {
int shift = argc * 32;

View File

@ -6,8 +6,8 @@
int f() {
// Slow stack unwinding is disabled on Darwin for now, see
// https://code.google.com/p/address-sanitizer/issues/detail?id=137
// CHECK-Linux-STACKTRACE: #0 {{.*}} in f(){{.*}}missing_return.cpp:[[@LINE-3]]
// CHECK-FreeBSD-STACKTRACE: #0 {{.*}} in f(void){{.*}}missing_return.cpp:[[@LINE-4]]
// CHECK-Linux-STACKTRACE: #0 {{.*}}f(){{.*}}missing_return.cpp:[[@LINE-3]]
// CHECK-FreeBSD-STACKTRACE: #0 {{.*}}f(void){{.*}}missing_return.cpp:[[@LINE-4]]
// Check for already checked line to avoid lit error reports.
// CHECK-Darwin-STACKTRACE: missing_return.cpp
}

View File

@ -45,7 +45,7 @@ int main(int, char **argv) {
return *p && 0;
// Slow stack unwinding is disabled on Darwin for now, see
// https://code.google.com/p/address-sanitizer/issues/detail?id=137
// CHECK-Linux-STACK-LOAD: #0 {{.*}} in main{{.*}}misaligned.cpp
// CHECK-Linux-STACK-LOAD: #0 {{.*}}main{{.*}}misaligned.cpp
// Check for the already checked line to avoid lit error reports.
// CHECK-Darwin-STACK-LOAD: {{ }}

View File

@ -128,7 +128,7 @@ int access_p(T *p, char type) {
// CHECK-MEMBER-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-MEMBER-NEXT: {{^ vptr for}} [[DYN_TYPE]]
// CHECK-MEMBER-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
// CHECK-MEMBER-NEXT: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return p->b;
// CHECK-NULL-MEMBER: vptr.cpp:[[@LINE-2]]:15: runtime error: member access within address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
@ -136,7 +136,7 @@ int access_p(T *p, char type) {
// CHECK-NULL-MEMBER-NEXT: {{^ ?.. .. .. .. ?00 00 00 00 ?00 00 00 00 ?}}
// CHECK-NULL-MEMBER-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-NULL-MEMBER-NEXT: {{^ invalid vptr}}
// CHECK-NULL-MEMBER-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE-7]]
// CHECK-NULL-MEMBER-NEXT: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE-7]]
case 'f':
// CHECK-MEMFUN: vptr.cpp:[[@LINE+6]]:12: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'T'
@ -153,7 +153,7 @@ int access_p(T *p, char type) {
// CHECK-OFFSET-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-OFFSET-NEXT: {{^ \^ ( ~~~~~~~~~~~~)?~~~~~~~~~~~ *$}}
// CHECK-OFFSET-NEXT: {{^ ( )?vptr for}} 'T' base class of [[DYN_TYPE]]
// CHECK-OFFSET-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
// CHECK-OFFSET-NEXT: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
return reinterpret_cast<U*>(p)->v() - 2;
case 'c':
@ -162,7 +162,7 @@ int access_p(T *p, char type) {
// CHECK-DOWNCAST-NEXT: {{^ .. .. .. .. .. .. .. .. .. .. .. .. }}
// CHECK-DOWNCAST-NEXT: {{^ \^~~~~~~~~~~(~~~~~~~~~~~~)? *$}}
// CHECK-DOWNCAST-NEXT: {{^ vptr for}} [[DYN_TYPE]]
// CHECK-DOWNCAST-NEXT: #0 {{.*}} in access_p{{.*}}vptr.cpp:[[@LINE+1]]
// CHECK-DOWNCAST-NEXT: #0 {{.*}}access_p{{.*}}vptr.cpp:[[@LINE+1]]
static_cast<T*>(reinterpret_cast<S*>(p));
return 0;
}

View File

@ -25,6 +25,14 @@ elif ubsan_lit_test_mode == "AddressSanitizer":
config.available_features.add("ubsan-asan")
clang_ubsan_cflags = ["-fsanitize=address"]
config.environment['ASAN_OPTIONS'] = 'detect_leaks=0'
elif ubsan_lit_test_mode == "MemorySanitizer":
config.name = 'UBSan-MSan-' + config.target_arch
config.available_features.add("ubsan-msan")
clang_ubsan_cflags = ["-fsanitize=memory"]
elif ubsan_lit_test_mode == "ThreadSanitizer":
config.name = 'UBSan-TSan-' + config.target_arch
config.available_features.add("ubsan-tsan")
clang_ubsan_cflags = ["-fsanitize=thread"]
else:
lit_config.fatal("Unknown UBSan test mode: %r" % ubsan_lit_test_mode)