mirror of
https://github.com/dart-lang/sdk
synced 2024-09-04 16:03:44 +00:00
[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:
parent
8c5236f55e
commit
d5feab0c53
|
@ -16,7 +16,7 @@ config("sdk") {
|
||||||
"-Wl,--exclude-libs=libc++.a",
|
"-Wl,--exclude-libs=libc++.a",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (is_asan) {
|
if (is_asan || is_lsan || is_msan || is_tsan) {
|
||||||
ldflags += [ "-lrt" ]
|
ldflags += [ "-lrt" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ declare_args() {
|
||||||
# Use libc++ (buildtools/third_party/libc++ and
|
# Use libc++ (buildtools/third_party/libc++ and
|
||||||
# buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
|
# buildtools/third_party/libc++abi) instead of stdlibc++ as standard library.
|
||||||
# This is intended to be used for instrumented builds.
|
# 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:
|
# Track where uninitialized memory originates from. From fastest to slowest:
|
||||||
# 0 - no tracking, 1 - track only the initial allocation site, 2 - track the
|
# 0 - no tracking, 1 - track only the initial allocation site, 2 - track the
|
||||||
|
|
|
@ -186,6 +186,9 @@ config("dart_config") {
|
||||||
if (defined(is_asan) && is_asan) {
|
if (defined(is_asan) && is_asan) {
|
||||||
ldflags += [ "-fsanitize=address" ]
|
ldflags += [ "-fsanitize=address" ]
|
||||||
}
|
}
|
||||||
|
if (defined(is_lsan) && is_lsan) {
|
||||||
|
ldflags += [ "-fsanitize=leak" ]
|
||||||
|
}
|
||||||
if (defined(is_msan) && is_msan) {
|
if (defined(is_msan) && is_msan) {
|
||||||
ldflags += [ "-fsanitize=memory" ]
|
ldflags += [ "-fsanitize=memory" ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,24 @@
|
||||||
// told about areas that are initialized by generated code.
|
// told about areas that are initialized by generated code.
|
||||||
#if defined(__has_feature)
|
#if defined(__has_feature)
|
||||||
#if __has_feature(memory_sanitizer)
|
#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);
|
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 MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len)
|
||||||
#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
|
||||||
#else // __has_feature(memory_sanitizer)
|
#else // __has_feature(memory_sanitizer)
|
||||||
|
#define MSAN_POISON(ptr, len) \
|
||||||
|
do { \
|
||||||
|
} while (false && (ptr) == 0 && (len) == 0)
|
||||||
#define MSAN_UNPOISON(ptr, len) \
|
#define MSAN_UNPOISON(ptr, len) \
|
||||||
do { \
|
do { \
|
||||||
} while (false && (ptr) == 0 && (len) == 0)
|
} while (false && (ptr) == 0 && (len) == 0)
|
||||||
#define NO_SANITIZE_MEMORY
|
#define NO_SANITIZE_MEMORY
|
||||||
#endif // __has_feature(memory_sanitizer)
|
#endif // __has_feature(memory_sanitizer)
|
||||||
#else // defined(__has_feature)
|
#else // defined(__has_feature)
|
||||||
|
#define MSAN_POISON(ptr, len) \
|
||||||
|
do { \
|
||||||
|
} while (false && (ptr) == 0 && (len) == 0)
|
||||||
#define MSAN_UNPOISON(ptr, len) \
|
#define MSAN_UNPOISON(ptr, len) \
|
||||||
do { \
|
do { \
|
||||||
} while (false && (ptr) == 0 && (len) == 0)
|
} while (false && (ptr) == 0 && (len) == 0)
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// 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.
|
// 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
|
// Test that ensures correct exception when running out of memory for
|
||||||
// really large transferable.
|
// really large transferable.
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,10 @@ void HierarchyInfo::BuildRangesForJIT(ClassTable* table,
|
||||||
|
|
||||||
qsort(cids_array, cids.length(), sizeof(intptr_t),
|
qsort(cids_array, cids.length(), sizeof(intptr_t),
|
||||||
[](const void* a, const void* b) {
|
[](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) -
|
return static_cast<int>(*static_cast<const intptr_t*>(a) -
|
||||||
*static_cast<const intptr_t*>(b));
|
*static_cast<const intptr_t*>(b));
|
||||||
});
|
});
|
||||||
|
|
|
@ -375,6 +375,8 @@ SemiSpace* SemiSpace::New(intptr_t size_in_words, const char* name) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
result->reserved_->Protect(VirtualMemory::kReadWrite);
|
result->reserved_->Protect(VirtualMemory::kReadWrite);
|
||||||
#endif
|
#endif
|
||||||
|
// Initialized by generated code.
|
||||||
|
MSAN_UNPOISON(result->reserved_->address(), size_in_words << kWordSizeLog2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,18 +394,21 @@ SemiSpace* SemiSpace::New(intptr_t size_in_words, const char* name) {
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
memset(memory->address(), Heap::kZapByte, size_in_bytes);
|
memset(memory->address(), Heap::kZapByte, size_in_bytes);
|
||||||
#endif // defined(DEBUG)
|
#endif // defined(DEBUG)
|
||||||
|
// Initialized by generated code.
|
||||||
|
MSAN_UNPOISON(memory->address(), size_in_bytes);
|
||||||
return new SemiSpace(memory);
|
return new SemiSpace(memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SemiSpace::Delete() {
|
void SemiSpace::Delete() {
|
||||||
#ifdef DEBUG
|
|
||||||
if (reserved_ != nullptr) {
|
if (reserved_ != nullptr) {
|
||||||
const intptr_t size_in_bytes = size_in_words() << kWordSizeLog2;
|
const intptr_t size_in_bytes = size_in_words() << kWordSizeLog2;
|
||||||
|
#ifdef DEBUG
|
||||||
memset(reserved_->address(), Heap::kZapByte, size_in_bytes);
|
memset(reserved_->address(), Heap::kZapByte, size_in_bytes);
|
||||||
reserved_->Protect(VirtualMemory::kNoAccess);
|
reserved_->Protect(VirtualMemory::kNoAccess);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
MSAN_POISON(reserved_->address(), size_in_bytes);
|
||||||
|
}
|
||||||
SemiSpace* old_cache = nullptr;
|
SemiSpace* old_cache = nullptr;
|
||||||
{
|
{
|
||||||
MutexLocker locker(mutex_);
|
MutexLocker locker(mutex_);
|
||||||
|
|
|
@ -263,7 +263,7 @@ class Interpreter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
bool is_debugging_;
|
bool is_debugging_ = false;
|
||||||
#endif // !PRODUCT
|
#endif // !PRODUCT
|
||||||
|
|
||||||
bool supports_unboxed_doubles_;
|
bool supports_unboxed_doubles_;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
// Customize ASAN options for this test with 'allocator_may_return_null=1' as
|
// Customize ASAN options for this test with 'allocator_may_return_null=1' as
|
||||||
// it tries to allocate a large memory buffer.
|
// 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=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";
|
import "dart:io";
|
||||||
|
|
||||||
|
|
|
@ -285,6 +285,21 @@
|
||||||
"builder-tag": "asan",
|
"builder-tag": "asan",
|
||||||
"timeout": 240
|
"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": {
|
"dart2js-(linux|mac|win)-chrome": {
|
||||||
"options": {
|
"options": {
|
||||||
"use-sdk": true
|
"use-sdk": true
|
||||||
|
@ -788,7 +803,7 @@
|
||||||
"arguments": ["runtime"],
|
"arguments": ["runtime"],
|
||||||
"environment": {
|
"environment": {
|
||||||
"DART_USE_ASAN": 1,
|
"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"
|
"ASAN_SYMBOLIZER_PATH": "buildtools/linux-x64/clang/bin/llvm-symbolizer"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -797,12 +812,101 @@
|
||||||
"arguments": [
|
"arguments": [
|
||||||
"-ndartk-asan-linux-release-${arch}"],
|
"-ndartk-asan-linux-release-${arch}"],
|
||||||
"environment": {
|
"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"
|
"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": [
|
"builders": [
|
||||||
"vm-kernel-linux-release-simarm",
|
"vm-kernel-linux-release-simarm",
|
||||||
|
|
15
tools/gn.py
15
tools/gn.py
|
@ -20,6 +20,7 @@ GN = os.path.join(DART_ROOT, 'buildtools', 'gn')
|
||||||
|
|
||||||
# Environment variables for default settings.
|
# Environment variables for default settings.
|
||||||
DART_USE_ASAN = "DART_USE_ASAN" # Use instead of --asan
|
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_MSAN = "DART_USE_MSAN" # Use instead of --msan
|
||||||
DART_USE_TSAN = "DART_USE_TSAN" # Use instead of --tsan
|
DART_USE_TSAN = "DART_USE_TSAN" # Use instead of --tsan
|
||||||
DART_USE_TOOLCHAIN = "DART_USE_TOOLCHAIN" # Use instread of --toolchain-prefix
|
DART_USE_TOOLCHAIN = "DART_USE_TOOLCHAIN" # Use instread of --toolchain-prefix
|
||||||
|
@ -35,6 +36,10 @@ def UseASAN():
|
||||||
return DART_USE_ASAN in os.environ
|
return DART_USE_ASAN in os.environ
|
||||||
|
|
||||||
|
|
||||||
|
def UseLSAN():
|
||||||
|
return DART_USE_LSAN in os.environ
|
||||||
|
|
||||||
|
|
||||||
def UseMSAN():
|
def UseMSAN():
|
||||||
return DART_USE_MSAN in os.environ
|
return DART_USE_MSAN in os.environ
|
||||||
|
|
||||||
|
@ -152,7 +157,7 @@ def ParseStringMap(key, string_map):
|
||||||
|
|
||||||
|
|
||||||
def UseSanitizer(args):
|
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):
|
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['dart_vm_code_coverage'] = enable_code_coverage
|
||||||
|
|
||||||
gn_args['is_asan'] = args.asan and gn_args['is_clang']
|
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_msan'] = args.msan and gn_args['is_clang']
|
||||||
gn_args['is_tsan'] = args.tsan 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,
|
default=False,
|
||||||
dest='exclude_kernel_service',
|
dest='exclude_kernel_service',
|
||||||
action='store_true')
|
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(
|
other_group.add_argument(
|
||||||
'--msan',
|
'--msan',
|
||||||
help='Build with MSAN',
|
help='Build with MSAN',
|
||||||
|
|
Loading…
Reference in a new issue