[vm] Create builds for LeakSanitizer, MemorySanitizer and ThreadSanitizer.

Change-Id: I65905ec76fcde8b7f4063cb5b80a3d034b453153
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120323
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Chinmay Garde <chinmaygarde@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Ryan Macnak 2019-10-07 16:24:22 +00:00 committed by commit-bot@chromium.org
parent 8c5236f55e
commit d5feab0c53
11 changed files with 151 additions and 8 deletions

View file

@ -16,7 +16,7 @@ config("sdk") {
"-Wl,--exclude-libs=libc++.a",
]
if (is_asan) {
if (is_asan || is_lsan || is_msan || is_tsan) {
ldflags += [ "-lrt" ]
}

View file

@ -6,7 +6,7 @@ declare_args() {
# Use libc++ (buildtools/third_party/libc++ and
# buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
# This is intended to be used for instrumented builds.
use_custom_libcxx = (is_asan && is_linux) || is_tsan || is_msan
use_custom_libcxx = (is_asan && is_linux) || is_lsan || is_msan || is_tsan
# Track where uninitialized memory originates from. From fastest to slowest:
# 0 - no tracking, 1 - track only the initial allocation site, 2 - track the

View file

@ -186,6 +186,9 @@ config("dart_config") {
if (defined(is_asan) && is_asan) {
ldflags += [ "-fsanitize=address" ]
}
if (defined(is_lsan) && is_lsan) {
ldflags += [ "-fsanitize=leak" ]
}
if (defined(is_msan) && is_msan) {
ldflags += [ "-fsanitize=memory" ]
}

View file

@ -11,16 +11,24 @@
// told about areas that are initialized by generated code.
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
extern "C" void __msan_poison(const volatile void*, size_t);
extern "C" void __msan_unpoison(const volatile void*, size_t);
#define MSAN_POISON(ptr, len) __msan_poison(ptr, len)
#define MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len)
#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
#else // __has_feature(memory_sanitizer)
#define MSAN_POISON(ptr, len) \
do { \
} while (false && (ptr) == 0 && (len) == 0)
#define MSAN_UNPOISON(ptr, len) \
do { \
} while (false && (ptr) == 0 && (len) == 0)
#define NO_SANITIZE_MEMORY
#endif // __has_feature(memory_sanitizer)
#else // defined(__has_feature)
#define MSAN_POISON(ptr, len) \
do { \
} while (false && (ptr) == 0 && (len) == 0)
#define MSAN_UNPOISON(ptr, len) \
do { \
} while (false && (ptr) == 0 && (len) == 0)

View file

@ -2,6 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Customize ASAN options for this test with 'allocator_may_return_null=1' as
// it tries to allocate a large memory buffer.
// Environment=ASAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
// Environment=MSAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
// Test that ensures correct exception when running out of memory for
// really large transferable.

View file

@ -283,6 +283,10 @@ void HierarchyInfo::BuildRangesForJIT(ClassTable* table,
qsort(cids_array, cids.length(), sizeof(intptr_t),
[](const void* a, const void* b) {
// MSAN seems unaware of allocations inside qsort. The linker flag
// -fsanitize=memory should give us a MSAN-aware version of libc...
MSAN_UNPOISON(static_cast<const intptr_t*>(a), sizeof(intptr_t));
MSAN_UNPOISON(static_cast<const intptr_t*>(b), sizeof(intptr_t));
return static_cast<int>(*static_cast<const intptr_t*>(a) -
*static_cast<const intptr_t*>(b));
});

View file

@ -375,6 +375,8 @@ SemiSpace* SemiSpace::New(intptr_t size_in_words, const char* name) {
#ifdef DEBUG
result->reserved_->Protect(VirtualMemory::kReadWrite);
#endif
// Initialized by generated code.
MSAN_UNPOISON(result->reserved_->address(), size_in_words << kWordSizeLog2);
return result;
}
@ -392,18 +394,21 @@ SemiSpace* SemiSpace::New(intptr_t size_in_words, const char* name) {
#if defined(DEBUG)
memset(memory->address(), Heap::kZapByte, size_in_bytes);
#endif // defined(DEBUG)
// Initialized by generated code.
MSAN_UNPOISON(memory->address(), size_in_bytes);
return new SemiSpace(memory);
}
}
void SemiSpace::Delete() {
#ifdef DEBUG
if (reserved_ != nullptr) {
const intptr_t size_in_bytes = size_in_words() << kWordSizeLog2;
#ifdef DEBUG
memset(reserved_->address(), Heap::kZapByte, size_in_bytes);
reserved_->Protect(VirtualMemory::kNoAccess);
}
#endif
MSAN_POISON(reserved_->address(), size_in_bytes);
}
SemiSpace* old_cache = nullptr;
{
MutexLocker locker(mutex_);

View file

@ -263,7 +263,7 @@ class Interpreter {
}
#ifndef PRODUCT
bool is_debugging_;
bool is_debugging_ = false;
#endif // !PRODUCT
bool supports_unboxed_doubles_;

View file

@ -7,6 +7,7 @@
// Customize ASAN options for this test with 'allocator_may_return_null=1' as
// it tries to allocate a large memory buffer.
// Environment=ASAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
// Environment=MSAN_OPTIONS=handle_segv=0:detect_stack_use_after_return=1:allocator_may_return_null=1
import "dart:io";

View file

@ -285,6 +285,21 @@
"builder-tag": "asan",
"timeout": 240
}},
"dartk-lsan-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"builder-tag": "lsan",
"timeout": 240
}},
"dartk-msan-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
"options": {
"builder-tag": "msan",
"timeout": 240
}},
"dartk-tsan-(linux|mac|win)-(debug|product|release)-x64": {
"options": {
"builder-tag": "tsan",
"timeout": 240
}},
"dart2js-(linux|mac|win)-chrome": {
"options": {
"use-sdk": true
@ -788,7 +803,7 @@
"arguments": ["runtime"],
"environment": {
"DART_USE_ASAN": 1,
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0",
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
},
@ -797,12 +812,101 @@
"arguments": [
"-ndartk-asan-linux-release-${arch}"],
"environment": {
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0",
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
]
},
{
"builders": [
"vm-kernel-lsan-linux-release-ia32",
"vm-kernel-lsan-linux-release-x64"
],
"meta": {
"description": "This configuration is used by the vm builders with leak sanitizing (lsan). We have to run gn.py with the DART_USE_LSAN options, which we do by running generate_buildfiles."
},
"steps": [
{
"name": "build dart",
"script": "tools/build.py",
"arguments": ["runtime"],
"environment": {
"DART_USE_LSAN": 1,
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
},
{
"name": "vm tests",
"arguments": [
"-ndartk-lsan-linux-release-${arch}"],
"environment": {
"ASAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
]
},
{
"builders": [
"vm-kernel-msan-linux-release-ia32",
"vm-kernel-msan-linux-release-x64"
],
"meta": {
"description": "This configuration is used by the vm builders with memory sanitizing (msan). We have to run gn.py with the DART_USE_MSAN options, which we do by running generate_buildfiles."
},
"steps": [
{
"name": "build dart",
"script": "tools/build.py",
"arguments": ["runtime"],
"environment": {
"DART_USE_MSAN": 1,
"MSAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"MSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
},
{
"name": "vm tests",
"arguments": [
"-ndartk-msan-linux-release-${arch}"],
"environment": {
"MSAN_OPTIONS": "handle_segv=0:detect_leaks=1:detect_stack_use_after_return=0:disable_coredump=0:abort_on_error=1",
"MSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
]
},
{
"builders": [
"vm-kernel-tsan-linux-release-x64"
],
"meta": {
"description": "This configuration is used by the vm builders with thread sanitizing (tsan). We have to run gn.py with the DART_USE_TSAN options, which we do by running generate_buildfiles."
},
"steps": [
{
"name": "build dart",
"script": "tools/build.py",
"arguments": ["runtime"],
"environment": {
"DART_USE_TSAN": 1,
"TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1",
"TSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
},
{
"name": "vm tests",
"arguments": [
"-ndartk-tsan-linux-release-${arch}"],
"environment": {
"TSAN_OPTIONS": "handle_segv=0:disable_coredump=0:abort_on_error=1",
"TSAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
}
}
]
},
{
"builders": [
"vm-kernel-linux-release-simarm",

View file

@ -20,6 +20,7 @@ GN = os.path.join(DART_ROOT, 'buildtools', 'gn')
# Environment variables for default settings.
DART_USE_ASAN = "DART_USE_ASAN" # Use instead of --asan
DART_USE_LSAN = "DART_USE_LSAN" # Use instead of --lsan
DART_USE_MSAN = "DART_USE_MSAN" # Use instead of --msan
DART_USE_TSAN = "DART_USE_TSAN" # Use instead of --tsan
DART_USE_TOOLCHAIN = "DART_USE_TOOLCHAIN" # Use instread of --toolchain-prefix
@ -35,6 +36,10 @@ def UseASAN():
return DART_USE_ASAN in os.environ
def UseLSAN():
return DART_USE_LSAN in os.environ
def UseMSAN():
return DART_USE_MSAN in os.environ
@ -152,7 +157,7 @@ def ParseStringMap(key, string_map):
def UseSanitizer(args):
return args.asan or args.msan or args.tsan
return args.asan or args.lsan or args.msan or args.tsan
def DontUseClang(args, target_os, host_cpu, target_cpu):
@ -249,6 +254,7 @@ def ToGnArgs(args, mode, arch, target_os, use_nnbd):
gn_args['dart_vm_code_coverage'] = enable_code_coverage
gn_args['is_asan'] = args.asan and gn_args['is_clang']
gn_args['is_lsan'] = args.lsan and gn_args['is_clang']
gn_args['is_msan'] = args.msan and gn_args['is_clang']
gn_args['is_tsan'] = args.tsan and gn_args['is_clang']
@ -460,6 +466,13 @@ def parse_args(args):
default=False,
dest='exclude_kernel_service',
action='store_true')
other_group.add_argument(
'--lsan',
help='Build with LSAN',
default=UseLSAN(),
action='store_true')
other_group.add_argument(
'--no-lsan', help='Disable LSAN', dest='lsan', action='store_false')
other_group.add_argument(
'--msan',
help='Build with MSAN',