diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2015-01-07 00:38:00 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2015-01-07 00:38:00 +0000 |
commit | 8bb699b511904af2acc7188db146f29da94022da (patch) | |
tree | 8d6072816a80284eb43e5499cd10f23afa604fcf /lib | |
parent | df867df2d3da7451984333ebcb6b4040dbcda164 (diff) | |
download | compiler-rt-8bb699b511904af2acc7188db146f29da94022da.tar.gz |
[Sanitizer] Change the runtime flag representation.
This mirrors r225239 to all the rest sanitizers:
ASan, DFSan, LSan, MSan, TSan, UBSan.
Now the runtime flag type, name, default value and
description is located in the single place in the
.inc file.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@225327 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_activation.cc | 4 | ||||
-rw-r--r-- | lib/asan/asan_flags.cc | 190 | ||||
-rw-r--r-- | lib/asan/asan_flags.h | 45 | ||||
-rw-r--r-- | lib/asan/asan_flags.inc | 142 | ||||
-rw-r--r-- | lib/dfsan/dfsan.cc | 24 | ||||
-rw-r--r-- | lib/dfsan/dfsan.h | 17 | ||||
-rw-r--r-- | lib/dfsan/dfsan_flags.inc | 32 | ||||
-rw-r--r-- | lib/lsan/lsan_common.cc | 46 | ||||
-rw-r--r-- | lib/lsan/lsan_common.h | 37 | ||||
-rw-r--r-- | lib/lsan/lsan_flags.inc | 44 | ||||
-rw-r--r-- | lib/msan/msan.cc | 100 | ||||
-rw-r--r-- | lib/msan/msan_flags.h | 21 | ||||
-rw-r--r-- | lib/msan/msan_flags.inc | 33 | ||||
-rw-r--r-- | lib/tsan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_flags.cc | 72 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_flags.h | 65 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_flags.inc | 78 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.cc | 26 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.h | 8 | ||||
-rw-r--r-- | lib/ubsan/ubsan_flags.inc | 24 |
20 files changed, 510 insertions, 499 deletions
diff --git a/lib/asan/asan_activation.cc b/lib/asan/asan_activation.cc index df1857c69..a90484aa8 100644 --- a/lib/asan/asan_activation.cc +++ b/lib/asan/asan_activation.cc @@ -45,14 +45,14 @@ static struct AsanDeactivatedFlags { // contain any other flags. if (const char *env = GetEnv("ASAN_ACTIVATION_OPTIONS")) { cf.ParseFromString(env); - ParseFlagsFromString(&f, env); + f.ParseFromString(env); } // Override from getprop asan.options. char buf[100]; GetExtraActivationFlags(buf, sizeof(buf)); cf.ParseFromString(buf); - ParseFlagsFromString(&f, buf); + f.ParseFromString(buf); allocator_options.SetFrom(&f, &cf); malloc_context_size = cf.malloc_context_size; diff --git a/lib/asan/asan_flags.cc b/lib/asan/asan_flags.cc index 6ebdf5fd9..d6144a7a6 100644 --- a/lib/asan/asan_flags.cc +++ b/lib/asan/asan_flags.cc @@ -39,136 +39,17 @@ static const char *MaybeUseAsanDefaultOptionsCompileDefinition() { #endif } -void ParseFlagsFromString(Flags *f, const char *str) { - // Please write meaningful flag descriptions when adding new flags. - ParseFlag(str, &f->quarantine_size, "quarantine_size", - "Size (in bytes) of quarantine used to detect use-after-free " - "errors. Lower value may reduce memory usage but increase the " - "chance of false negatives."); - ParseFlag(str, &f->redzone, "redzone", - "Minimal size (in bytes) of redzones around heap objects. " - "Requirement: redzone >= 16, is a power of two."); - ParseFlag(str, &f->max_redzone, "max_redzone", - "Maximal size (in bytes) of redzones around heap objects."); - - ParseFlag(str, &f->debug, "debug", - "If set, prints some debugging information and does additional checks."); - ParseFlag(str, &f->report_globals, "report_globals", - "Controls the way to handle globals (0 - don't detect buffer overflow on " - "globals, 1 - detect buffer overflow, 2 - print data about registered " - "globals)."); - - ParseFlag(str, &f->check_initialization_order, - "check_initialization_order", - "If set, attempts to catch initialization order issues."); - - ParseFlag(str, &f->replace_str, "replace_str", - "If set, uses custom wrappers and replacements for libc string functions " - "to find more errors."); - - ParseFlag(str, &f->replace_intrin, "replace_intrin", - "If set, uses custom wrappers for memset/memcpy/memmove intinsics."); - ParseFlag(str, &f->mac_ignore_invalid_free, "mac_ignore_invalid_free", - "Ignore invalid free() calls to work around some bugs. Used on OS X " - "only."); - ParseFlag(str, &f->detect_stack_use_after_return, - "detect_stack_use_after_return", - "Enables stack-use-after-return checking at run-time."); - ParseFlag(str, &f->min_uar_stack_size_log, "min_uar_stack_size_log", - "Minimum fake stack size log."); - ParseFlag(str, &f->max_uar_stack_size_log, "max_uar_stack_size_log", - "Maximum fake stack size log."); - ParseFlag(str, &f->uar_noreserve, "uar_noreserve", - "Use mmap with 'norserve' flag to allocate fake stack."); - ParseFlag(str, &f->max_malloc_fill_size, "max_malloc_fill_size", - "ASan allocator flag. max_malloc_fill_size is the maximal amount of " - "bytes that will be filled with malloc_fill_byte on malloc."); - ParseFlag(str, &f->malloc_fill_byte, "malloc_fill_byte", - "Value used to fill the newly allocated memory."); - ParseFlag(str, &f->exitcode, "exitcode", - "Override the program exit status if the tool found an error."); - ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning", - "If set, user may manually mark memory regions as poisoned or " - "unpoisoned."); - ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying", - "Number of seconds to sleep between printing an error report and " - "terminating the program. Useful for debugging purposes (e.g. when one " - "needs to attach gdb)."); - - ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size", - "Allows the users to work around the bug in Nvidia drivers prior to " - "295.*."); - - ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit", - "If set, explicitly unmaps the (huge) shadow at exit."); - ParseFlag(str, &f->abort_on_error, "abort_on_error", - "If set, the tool calls abort() instead of _exit() after printing the " - "error report."); - ParseFlag(str, &f->print_stats, "print_stats", - "Print various statistics after printing an error message or if " - "atexit=1."); - ParseFlag(str, &f->print_legend, "print_legend", - "Print the legend for the shadow bytes."); - ParseFlag(str, &f->atexit, "atexit", - "If set, prints ASan exit stats even after program terminates " - "successfully."); - - ParseFlag(str, &f->print_full_thread_history, - "print_full_thread_history", - "If set, prints thread creation stacks for the threads involved in the " - "report and their ancestors up to the main thread."); - - ParseFlag(str, &f->poison_heap, "poison_heap", - "Poison (or not) the heap memory on [de]allocation. Zero value is useful " - "for benchmarking the allocator or instrumentator."); - - ParseFlag(str, &f->poison_array_cookie, "poison_array_cookie", - "Poison (or not) the array cookie after operator new[]."); - - ParseFlag(str, &f->poison_partial, "poison_partial", - "If true, poison partially addressable 8-byte aligned words " - "(default=true). This flag affects heap and global buffers, but not " - "stack buffers."); - - ParseFlag(str, &f->alloc_dealloc_mismatch, "alloc_dealloc_mismatch", - "Report errors on malloc/delete, new/free, new/delete[], etc."); - - ParseFlag(str, &f->new_delete_type_mismatch, "new_delete_type_mismatch", - "Report errors on mismatch betwen size of new and delete."); - - ParseFlag(str, &f->strict_memcmp, "strict_memcmp", - "If true, assume that memcmp(p1, p2, n) always reads n bytes before " - "comparing p1 and p2."); - - ParseFlag(str, &f->strict_init_order, "strict_init_order", - "If true, assume that dynamic initializers can never access globals from " - "other modules, even if the latter are already initialized."); - - ParseFlag(str, &f->start_deactivated, "start_deactivated", - "If true, ASan tweaks a bunch of other flags (quarantine, redzone, heap " - "poisoning) to reduce memory consumption as much as possible, and " - "restores them to original values when the first instrumented module is " - "loaded into the process. This is mainly intended to be used on " - "Android. "); - - ParseFlag(str, &f->detect_invalid_pointer_pairs, - "detect_invalid_pointer_pairs", - "If non-zero, try to detect operations like <, <=, >, >= and - on " - "invalid pointer pairs (e.g. when pointers belong to different objects). " - "The bigger the value the harder we try."); - - ParseFlag(str, &f->detect_container_overflow, - "detect_container_overflow", - "If true, honor the container overflow annotations. " - "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow"); - - ParseFlag(str, &f->detect_odr_violation, "detect_odr_violation", - "If >=2, detect violation of One-Definition-Rule (ODR); " - "If ==1, detect ODR-violation only if the two variables " - "have different sizes"); +void Flags::SetDefaults() { +#define ASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "asan_flags.inc" +#undef ASAN_FLAG +} - ParseFlag(str, &f->dump_instruction_bytes, "dump_instruction_bytes", - "If true, dump 16 bytes starting at the instruction that caused SEGV"); +void Flags::ParseFromString(const char *str) { +#define ASAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "asan_flags.inc" +#undef ASAN_FLAG } void InitializeFlags(Flags *f) { @@ -183,65 +64,24 @@ void InitializeFlags(Flags *f) { OverrideCommonFlags(cf); } - internal_memset(f, 0, sizeof(*f)); - f->quarantine_size = (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28; - f->redzone = 16; - f->max_redzone = 2048; - f->debug = false; - f->report_globals = 1; - f->check_initialization_order = false; - f->replace_str = true; - f->replace_intrin = true; - f->mac_ignore_invalid_free = false; - f->detect_stack_use_after_return = false; // Also needs the compiler flag. - f->min_uar_stack_size_log = 16; // We can't do smaller anyway. - f->max_uar_stack_size_log = 20; // 1Mb per size class, i.e. ~11Mb per thread. - f->uar_noreserve = false; - f->max_malloc_fill_size = 0x1000; // By default, fill only the first 4K. - f->malloc_fill_byte = 0xbe; - f->exitcode = ASAN_DEFAULT_FAILURE_EXITCODE; - f->allow_user_poisoning = true; - f->sleep_before_dying = 0; - f->check_malloc_usable_size = true; - f->unmap_shadow_on_exit = false; - f->abort_on_error = false; - f->print_stats = false; - f->print_legend = true; - f->atexit = false; - f->print_full_thread_history = true; - f->poison_heap = true; - f->poison_array_cookie = true; - f->poison_partial = true; - // Turn off alloc/dealloc mismatch checker on Mac and Windows for now. - // https://code.google.com/p/address-sanitizer/issues/detail?id=131 - // https://code.google.com/p/address-sanitizer/issues/detail?id=309 - // TODO(glider,timurrrr): Fix known issues and enable this back. - f->alloc_dealloc_mismatch = (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0); - f->new_delete_type_mismatch = true; - f->strict_memcmp = true; - f->strict_init_order = false; - f->start_deactivated = false; - f->detect_invalid_pointer_pairs = 0; - f->detect_container_overflow = true; - f->detect_odr_violation = 2; - f->dump_instruction_bytes = false; + f->SetDefaults(); // Override from compile definition. const char *compile_def = MaybeUseAsanDefaultOptionsCompileDefinition(); ParseCommonFlagsFromString(compile_def); - ParseFlagsFromString(f, compile_def); + f->ParseFromString(compile_def); // Override from user-specified string. const char *default_options = MaybeCallAsanDefaultOptions(); ParseCommonFlagsFromString(default_options); - ParseFlagsFromString(f, default_options); + f->ParseFromString(default_options); VReport(1, "Using the defaults from __asan_default_options: %s\n", MaybeCallAsanDefaultOptions()); // Override from command line. if (const char *env = GetEnv("ASAN_OPTIONS")) { ParseCommonFlagsFromString(env); - ParseFlagsFromString(f, env); + f->ParseFromString(env); VReport(1, "Parsed ASAN_OPTIONS: %s\n", env); } @@ -251,7 +91,7 @@ void InitializeFlags(Flags *f) { char buf[100]; GetExtraActivationFlags(buf, sizeof(buf)); ParseCommonFlagsFromString(buf); - ParseFlagsFromString(f, buf); + f->ParseFromString(buf); if (buf[0] != '\0') VReport(1, "Parsed activation flags: %s\n", buf); } diff --git a/lib/asan/asan_flags.h b/lib/asan/asan_flags.h index 386be7ef6..32937e837 100644 --- a/lib/asan/asan_flags.h +++ b/lib/asan/asan_flags.h @@ -24,47 +24,17 @@ // 3) overriden from string returned by user-specified function // __asan_default_options(). // 4) overriden from env variable ASAN_OPTIONS. +// 5) overriden during ASan activation (for now used on Android only). namespace __asan { struct Flags { - // Flag descriptions are in asan_rtl.cc. - int quarantine_size; - int redzone; - int max_redzone; - bool debug; - int report_globals; - bool check_initialization_order; - bool replace_str; - bool replace_intrin; - bool mac_ignore_invalid_free; - bool detect_stack_use_after_return; - int min_uar_stack_size_log; - int max_uar_stack_size_log; - bool uar_noreserve; - int max_malloc_fill_size, malloc_fill_byte; - int exitcode; - bool allow_user_poisoning; - int sleep_before_dying; - bool check_malloc_usable_size; - bool unmap_shadow_on_exit; - bool abort_on_error; - bool print_stats; - bool print_legend; - bool atexit; - bool print_full_thread_history; - bool poison_heap; - bool poison_partial; - bool poison_array_cookie; - bool alloc_dealloc_mismatch; - bool new_delete_type_mismatch; - bool strict_memcmp; - bool strict_init_order; - bool start_deactivated; - int detect_invalid_pointer_pairs; - bool detect_container_overflow; - int detect_odr_violation; - bool dump_instruction_bytes; +#define ASAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "asan_flags.inc" +#undef ASAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); }; extern Flags asan_flags_dont_use_directly; @@ -72,7 +42,6 @@ inline Flags *flags() { return &asan_flags_dont_use_directly; } void InitializeFlags(Flags *f); -void ParseFlagsFromString(Flags *f, const char *str); } // namespace __asan diff --git a/lib/asan/asan_flags.inc b/lib/asan/asan_flags.inc new file mode 100644 index 000000000..066b47aec --- /dev/null +++ b/lib/asan/asan_flags.inc @@ -0,0 +1,142 @@ +//===-- asan_flags.inc ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ASan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef ASAN_FLAG +# error "Define ASAN_FLAG prior to including this file!" +#endif + +// ASAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +ASAN_FLAG(int, quarantine_size, (ASAN_LOW_MEMORY) ? 1UL << 26 : 1UL << 28, + "Size (in bytes) of quarantine used to detect use-after-free " + "errors. Lower value may reduce memory usage but increase the " + "chance of false negatives.") +ASAN_FLAG(int, redzone, 16, + "Minimal size (in bytes) of redzones around heap objects. " + "Requirement: redzone >= 16, is a power of two.") +ASAN_FLAG(int, max_redzone, 2048, + "Maximal size (in bytes) of redzones around heap objects.") +ASAN_FLAG( + bool, debug, false, + "If set, prints some debugging information and does additional checks.") +ASAN_FLAG( + int, report_globals, 1, + "Controls the way to handle globals (0 - don't detect buffer overflow on " + "globals, 1 - detect buffer overflow, 2 - print data about registered " + "globals).") +ASAN_FLAG(bool, check_initialization_order, false, + "If set, attempts to catch initialization order issues.") +ASAN_FLAG( + bool, replace_str, true, + "If set, uses custom wrappers and replacements for libc string functions " + "to find more errors.") +ASAN_FLAG(bool, replace_intrin, true, + "If set, uses custom wrappers for memset/memcpy/memmove intinsics.") +ASAN_FLAG(bool, mac_ignore_invalid_free, false, + "Ignore invalid free() calls to work around some bugs. Used on OS X " + "only.") +ASAN_FLAG(bool, detect_stack_use_after_return, false, + "Enables stack-use-after-return checking at run-time.") +ASAN_FLAG(int, min_uar_stack_size_log, 16, // We can't do smaller anyway. + "Minimum fake stack size log.") +ASAN_FLAG(int, max_uar_stack_size_log, + 20, // 1Mb per size class, i.e. ~11Mb per thread + "Maximum fake stack size log.") +ASAN_FLAG(bool, uar_noreserve, false, + "Use mmap with 'noreserve' flag to allocate fake stack.") +ASAN_FLAG( + int, max_malloc_fill_size, 0x1000, // By default, fill only the first 4K. + "ASan allocator flag. max_malloc_fill_size is the maximal amount of " + "bytes that will be filled with malloc_fill_byte on malloc.") +ASAN_FLAG(int, malloc_fill_byte, 0xbe, + "Value used to fill the newly allocated memory.") +ASAN_FLAG(int, exitcode, ASAN_DEFAULT_FAILURE_EXITCODE, + "Override the program exit status if the tool found an error.") +ASAN_FLAG(bool, allow_user_poisoning, true, + "If set, user may manually mark memory regions as poisoned or " + "unpoisoned.") +ASAN_FLAG( + int, sleep_before_dying, 0, + "Number of seconds to sleep between printing an error report and " + "terminating the program. Useful for debugging purposes (e.g. when one " + "needs to attach gdb).") +ASAN_FLAG(bool, check_malloc_usable_size, true, + "Allows the users to work around the bug in Nvidia drivers prior to " + "295.*.") +ASAN_FLAG(bool, unmap_shadow_on_exit, false, + "If set, explicitly unmaps the (huge) shadow at exit.") +ASAN_FLAG( + bool, abort_on_error, false, + "If set, the tool calls abort() instead of _exit() after printing the " + "error report.") +ASAN_FLAG(bool, print_stats, false, + "Print various statistics after printing an error message or if " + "atexit=1.") +ASAN_FLAG(bool, print_legend, true, "Print the legend for the shadow bytes.") +ASAN_FLAG(bool, atexit, false, + "If set, prints ASan exit stats even after program terminates " + "successfully.") +ASAN_FLAG( + bool, print_full_thread_history, true, + "If set, prints thread creation stacks for the threads involved in the " + "report and their ancestors up to the main thread.") +ASAN_FLAG( + bool, poison_heap, true, + "Poison (or not) the heap memory on [de]allocation. Zero value is useful " + "for benchmarking the allocator or instrumentator.") +ASAN_FLAG(bool, poison_partial, true, + "If true, poison partially addressable 8-byte aligned words " + "(default=true). This flag affects heap and global buffers, but not " + "stack buffers.") +ASAN_FLAG(bool, poison_array_cookie, true, + "Poison (or not) the array cookie after operator new[].") + +// Turn off alloc/dealloc mismatch checker on Mac and Windows for now. +// https://code.google.com/p/address-sanitizer/issues/detail?id=131 +// https://code.google.com/p/address-sanitizer/issues/detail?id=309 +// TODO(glider,timurrrr): Fix known issues and enable this back. +ASAN_FLAG(bool, alloc_dealloc_mismatch, + (SANITIZER_MAC == 0) && (SANITIZER_WINDOWS == 0), + "Report errors on malloc/delete, new/free, new/delete[], etc.") + +ASAN_FLAG(bool, new_delete_type_mismatch, true, + "Report errors on mismatch betwen size of new and delete.") +ASAN_FLAG(bool, strict_memcmp, true, + "If true, assume that memcmp(p1, p2, n) always reads n bytes before " + "comparing p1 and p2.") +ASAN_FLAG( + bool, strict_init_order, false, + "If true, assume that dynamic initializers can never access globals from " + "other modules, even if the latter are already initialized.") +ASAN_FLAG( + bool, start_deactivated, false, + "If true, ASan tweaks a bunch of other flags (quarantine, redzone, heap " + "poisoning) to reduce memory consumption as much as possible, and " + "restores them to original values when the first instrumented module is " + "loaded into the process. This is mainly intended to be used on " + "Android. ") +ASAN_FLAG( + int, detect_invalid_pointer_pairs, 0, + "If non-zero, try to detect operations like <, <=, >, >= and - on " + "invalid pointer pairs (e.g. when pointers belong to different objects). " + "The bigger the value the harder we try.") +ASAN_FLAG( + bool, detect_container_overflow, true, + "If true, honor the container overflow annotations. " + "See https://code.google.com/p/address-sanitizer/wiki/ContainerOverflow") +ASAN_FLAG(int, detect_odr_violation, 2, + "If >=2, detect violation of One-Definition-Rule (ODR); " + "If ==1, detect ODR-violation only if the two variables " + "have different sizes") +ASAN_FLAG(bool, dump_instruction_bytes, false, + "If true, dump 16 bytes starting at the instruction that caused SEGV") diff --git a/lib/dfsan/dfsan.cc b/lib/dfsan/dfsan.cc index 941edc5eb..72abee7ef 100644 --- a/lib/dfsan/dfsan.cc +++ b/lib/dfsan/dfsan.cc @@ -310,16 +310,22 @@ dfsan_dump_labels(int fd) { } } +void Flags::SetDefaults() { +#define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "dfsan_flags.inc" +#undef DFSAN_FLAG +} + +void Flags::ParseFromString(const char *str) { +#define DFSAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "dfsan_flags.inc" +#undef DFSAN_FLAG +} + static void InitializeFlags(Flags &f, const char *env) { - f.warn_unimplemented = true; - f.warn_nonzero_labels = false; - f.strict_data_dependencies = true; - f.dump_labels_at_exit = ""; - - ParseFlag(env, &f.warn_unimplemented, "warn_unimplemented", ""); - ParseFlag(env, &f.warn_nonzero_labels, "warn_nonzero_labels", ""); - ParseFlag(env, &f.strict_data_dependencies, "strict_data_dependencies", ""); - ParseFlag(env, &f.dump_labels_at_exit, "dump_labels_at_exit", ""); + f.SetDefaults(); + f.ParseFromString(env); } static void dfsan_fini() { diff --git a/lib/dfsan/dfsan.h b/lib/dfsan/dfsan.h index bc38be08c..8f242197f 100644 --- a/lib/dfsan/dfsan.h +++ b/lib/dfsan/dfsan.h @@ -56,17 +56,12 @@ inline const dfsan_label *shadow_for(const void *ptr) { } struct Flags { - // Whether to warn on unimplemented functions. - bool warn_unimplemented; - // Whether to warn on non-zero labels. - bool warn_nonzero_labels; - // Whether to propagate labels only when there is an obvious data dependency - // (e.g., when comparing strings, ignore the fact that the output of the - // comparison might be data-dependent on the content of the strings). This - // applies only to the custom functions defined in 'custom.c'. - bool strict_data_dependencies; - // The path of the file where to dump the labels when the program terminates. - const char* dump_labels_at_exit; +#define DFSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "dfsan_flags.inc" +#undef DFSAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); }; extern Flags flags_data; diff --git a/lib/dfsan/dfsan_flags.inc b/lib/dfsan/dfsan_flags.inc new file mode 100644 index 000000000..24fbfcb9e --- /dev/null +++ b/lib/dfsan/dfsan_flags.inc @@ -0,0 +1,32 @@ +//===-- dfsan_flags.inc -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// DFSan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef DFSAN_FLAG +# error "Define DFSAN_FLAG prior to including this file!" +#endif + +// DFSAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +DFSAN_FLAG(bool, warn_unimplemented, true, + "Whether to warn on unimplemented functions.") +DFSAN_FLAG(bool, warn_nonzero_labels, false, + "Whether to warn on unimplemented functions.") +DFSAN_FLAG( + bool, strict_data_dependencies, true, + "Whether to propagate labels only when there is an obvious data dependency" + "(e.g., when comparing strings, ignore the fact that the output of the" + "comparison might be data-dependent on the content of the strings). This" + "applies only to the custom functions defined in 'custom.c'.") +DFSAN_FLAG(const char *, dump_labels_at_exit, "", "The path of the file where " + "to dump the labels when the " + "program terminates.") diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index 1c431122d..7c52526a5 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -36,41 +36,25 @@ bool DisabledInThisThread() { return disable_counter > 0; } Flags lsan_flags; +void Flags::SetDefaults() { +#define LSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "lsan_flags.inc" +#undef LSAN_FLAG +} + +void Flags::ParseFromString(const char *str) { +#define LSAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "lsan_flags.inc" +#undef LSAN_FLAG +} + static void InitializeFlags(bool standalone) { Flags *f = flags(); - // Default values. - f->report_objects = false; - f->resolution = 0; - f->max_leaks = 0; - f->exitcode = 23; - f->use_registers = true; - f->use_globals = true; - f->use_stacks = true; - f->use_tls = true; - f->use_root_regions = true; - f->use_unaligned = false; - f->use_poisoned = false; - f->log_pointers = false; - f->log_threads = false; + f->SetDefaults(); const char *options = GetEnv("LSAN_OPTIONS"); - if (options) { - ParseFlag(options, &f->use_registers, "use_registers", ""); - ParseFlag(options, &f->use_globals, "use_globals", ""); - ParseFlag(options, &f->use_stacks, "use_stacks", ""); - ParseFlag(options, &f->use_tls, "use_tls", ""); - ParseFlag(options, &f->use_root_regions, "use_root_regions", ""); - ParseFlag(options, &f->use_unaligned, "use_unaligned", ""); - ParseFlag(options, &f->use_poisoned, "use_poisoned", ""); - ParseFlag(options, &f->report_objects, "report_objects", ""); - ParseFlag(options, &f->resolution, "resolution", ""); - CHECK_GE(&f->resolution, 0); - ParseFlag(options, &f->max_leaks, "max_leaks", ""); - CHECK_GE(&f->max_leaks, 0); - ParseFlag(options, &f->log_pointers, "log_pointers", ""); - ParseFlag(options, &f->log_threads, "log_threads", ""); - ParseFlag(options, &f->exitcode, "exitcode", ""); - } + f->ParseFromString(options); // Set defaults for common flags (only in standalone mode) and parse // them from LSAN_OPTIONS. diff --git a/lib/lsan/lsan_common.h b/lib/lsan/lsan_common.h index 86ff12da6..b82b9a727 100644 --- a/lib/lsan/lsan_common.h +++ b/lib/lsan/lsan_common.h @@ -38,40 +38,15 @@ enum ChunkTag { }; struct Flags { +#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "lsan_flags.inc" +#undef LSAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); uptr pointer_alignment() const { return use_unaligned ? 1 : sizeof(uptr); } - - // Print addresses of leaked objects after main leak report. - bool report_objects; - // Aggregate two objects into one leak if this many stack frames match. If - // zero, the entire stack trace must match. - int resolution; - // The number of leaks reported. - int max_leaks; - // If nonzero kill the process with this exit code upon finding leaks. - int exitcode; - - // Flags controlling the root set of reachable memory. - // Global variables (.data and .bss). - bool use_globals; - // Thread stacks. - bool use_stacks; - // Thread registers. - bool use_registers; - // TLS and thread-specific storage. - bool use_tls; - // Regions added via __lsan_register_root_region(). - bool use_root_regions; - - // Consider unaligned pointers valid. - bool use_unaligned; - // Consider pointers found in poisoned memory to be valid. - bool use_poisoned; - - // Debug logging. - bool log_pointers; - bool log_threads; }; extern Flags lsan_flags; diff --git a/lib/lsan/lsan_flags.inc b/lib/lsan/lsan_flags.inc new file mode 100644 index 000000000..7f00acbf9 --- /dev/null +++ b/lib/lsan/lsan_flags.inc @@ -0,0 +1,44 @@ +//===-- lsan_flags.inc ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// LSan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef LSAN_FLAG +# error "Define LSAN_FLAG prior to including this file!" +#endif + +// LSAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +LSAN_FLAG(bool, report_objects, false, + "Print addresses of leaked objects after main leak report.") +LSAN_FLAG( + int, resolution, 0, + "Aggregate two objects into one leak if this many stack frames match. If " + "zero, the entire stack trace must match.") +LSAN_FLAG(int, max_leaks, 0, "The number of leaks reported.") +LSAN_FLAG(int, exitcode, 23, + "If nonzero kill the process with this exit code upon finding leaks.") + +// Flags controlling the root set of reachable memory. +LSAN_FLAG(bool, use_globals, true, + "Root set: include global variables (.data and .bss)") +LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks") +LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers") +LSAN_FLAG(bool, use_tls, true, + "Root set: include TLS and thread-specific storage") +LSAN_FLAG(bool, use_root_regions, true, + "Root set: include regions added via __lsan_register_root_region().") + +LSAN_FLAG(bool, use_unaligned, false, "Consider unaligned pointers valid.") +LSAN_FLAG(bool, use_poisoned, false, + "Consider pointers found in poisoned memory to be valid.") +LSAN_FLAG(bool, log_pointers, false, "Debug logging") +LSAN_FLAG(bool, log_threads, false, "Debug logging") diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc index cb0ffd60e..6eccb5bf6 100644 --- a/lib/msan/msan.cc +++ b/lib/msan/msan.cc @@ -96,51 +96,23 @@ static const char *StackOriginDescr[kNumStackOriginDescrs]; static uptr StackOriginPC[kNumStackOriginDescrs]; static atomic_uint32_t NumStackOriginDescrs; -static void ParseFlagsFromString(Flags *f, const char *str) { - ParseFlag(str, &f->poison_heap_with_zeroes, "poison_heap_with_zeroes", ""); - ParseFlag(str, &f->poison_stack_with_zeroes, "poison_stack_with_zeroes", ""); - ParseFlag(str, &f->poison_in_malloc, "poison_in_malloc", ""); - ParseFlag(str, &f->poison_in_free, "poison_in_free", ""); - ParseFlag(str, &f->exit_code, "exit_code", ""); - if (f->exit_code < 0 || f->exit_code > 127) { - Printf("Exit code not in [0, 128) range: %d\n", f->exit_code); - Die(); - } - ParseFlag(str, &f->origin_history_size, "origin_history_size", ""); - if (f->origin_history_size < 0 || - f->origin_history_size > Origin::kMaxDepth) { - Printf( - "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " - "range.\n", - f->origin_history_size, Origin::kMaxDepth); - Die(); - } - ParseFlag(str, &f->origin_history_per_stack_limit, - "origin_history_per_stack_limit", ""); - // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in - // StackDepotHandle::inc_use_count_unsafe. - if (f->origin_history_per_stack_limit < 0 || - f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { - Printf( - "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " - "%d] range.\n", - f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); - Die(); - } - - ParseFlag(str, &f->report_umrs, "report_umrs", ""); - ParseFlag(str, &f->wrap_signals, "wrap_signals", ""); - ParseFlag(str, &f->print_stats, "print_stats", ""); - ParseFlag(str, &f->atexit, "atexit", ""); - ParseFlag(str, &f->store_context_size, "store_context_size", ""); - if (f->store_context_size < 1) f->store_context_size = 1; +void Flags::SetDefaults() { +#define MSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "msan_flags.inc" +#undef MSAN_FLAG +} +void Flags::ParseFromString(const char *str) { // keep_going is an old name for halt_on_error, // and it has inverse meaning. - f->halt_on_error = !f->halt_on_error; - ParseFlag(str, &f->halt_on_error, "keep_going", ""); - f->halt_on_error = !f->halt_on_error; - ParseFlag(str, &f->halt_on_error, "halt_on_error", ""); + halt_on_error = !halt_on_error; + ParseFlag(str, &halt_on_error, "keep_going", ""); + halt_on_error = !halt_on_error; + +#define MSAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "msan_flags.inc" +#undef MSAN_FLAG } static void InitializeFlags(Flags *f, const char *options) { @@ -157,29 +129,41 @@ static void InitializeFlags(Flags *f, const char *options) { OverrideCommonFlags(cf); } - internal_memset(f, 0, sizeof(*f)); - f->poison_heap_with_zeroes = false; - f->poison_stack_with_zeroes = false; - f->poison_in_malloc = true; - f->poison_in_free = true; - f->exit_code = 77; - f->origin_history_size = Origin::kMaxDepth; - f->origin_history_per_stack_limit = 20000; - f->report_umrs = true; - f->wrap_signals = true; - f->print_stats = false; - f->atexit = false; - f->halt_on_error = !&__msan_keep_going; - f->store_context_size = 20; + f->SetDefaults(); // Override from user-specified string. if (__msan_default_options) { - ParseFlagsFromString(f, __msan_default_options()); + f->ParseFromString(__msan_default_options()); ParseCommonFlagsFromString(__msan_default_options()); } - ParseFlagsFromString(f, options); + f->ParseFromString(options); ParseCommonFlagsFromString(options); + + // Check flag values: + if (f->exit_code < 0 || f->exit_code > 127) { + Printf("Exit code not in [0, 128) range: %d\n", f->exit_code); + Die(); + } + if (f->origin_history_size < 0 || + f->origin_history_size > Origin::kMaxDepth) { + Printf( + "Origin history size invalid: %d. Must be 0 (unlimited) or in [1, %d] " + "range.\n", + f->origin_history_size, Origin::kMaxDepth); + Die(); + } + // Limiting to kStackDepotMaxUseCount / 2 to avoid overflow in + // StackDepotHandle::inc_use_count_unsafe. + if (f->origin_history_per_stack_limit < 0 || + f->origin_history_per_stack_limit > kStackDepotMaxUseCount / 2) { + Printf( + "Origin per-stack limit invalid: %d. Must be 0 (unlimited) or in [1, " + "%d] range.\n", + f->origin_history_per_stack_limit, kStackDepotMaxUseCount / 2); + Die(); + } + if (f->store_context_size < 1) f->store_context_size = 1; } void GetStackTrace(BufferedStackTrace *stack, uptr max_s, uptr pc, uptr bp, diff --git a/lib/msan/msan_flags.h b/lib/msan/msan_flags.h index 9b93f118a..5ec684dfc 100644 --- a/lib/msan/msan_flags.h +++ b/lib/msan/msan_flags.h @@ -9,28 +9,19 @@ // // This file is a part of MemorySanitizer. // -// MemorySanitizer allocator. //===----------------------------------------------------------------------===// #ifndef MSAN_FLAGS_H #define MSAN_FLAGS_H namespace __msan { -// Flags. struct Flags { - int exit_code; - int origin_history_size; - int origin_history_per_stack_limit; - bool poison_heap_with_zeroes; // default: false - bool poison_stack_with_zeroes; // default: false - bool poison_in_malloc; // default: true - bool poison_in_free; // default: true - bool report_umrs; - bool wrap_signals; - bool print_stats; - bool halt_on_error; - bool atexit; - int store_context_size; // like malloc_context_size, but for uninit stores +#define MSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "msan_flags.inc" +#undef MSAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); }; Flags *flags(); diff --git a/lib/msan/msan_flags.inc b/lib/msan/msan_flags.inc new file mode 100644 index 000000000..cb58ffc4a --- /dev/null +++ b/lib/msan/msan_flags.inc @@ -0,0 +1,33 @@ +//===-- msan_flags.inc ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// MSan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef MSAN_FLAG +# error "Define MSAN_FLAG prior to including this file!" +#endif + +// MSAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +MSAN_FLAG(int, exit_code, 77, "") +MSAN_FLAG(int, origin_history_size, Origin::kMaxDepth, "") +MSAN_FLAG(int, origin_history_per_stack_limit, 20000, "") +MSAN_FLAG(bool, poison_heap_with_zeroes, false, "") +MSAN_FLAG(bool, poison_stack_with_zeroes, false, "") +MSAN_FLAG(bool, poison_in_malloc, true, "") +MSAN_FLAG(bool, poison_in_free, true, "") +MSAN_FLAG(bool, report_umrs, true, "") +MSAN_FLAG(bool, wrap_signals, true, "") +MSAN_FLAG(bool, print_stats, false, "") +MSAN_FLAG(bool, halt_on_error, !&__msan_keep_going, "") +MSAN_FLAG(bool, atexit, false, "") +MSAN_FLAG(int, store_context_size, 20, + "Like malloc_context_size, but for uninit stores.") diff --git a/lib/tsan/CMakeLists.txt b/lib/tsan/CMakeLists.txt index 58f9c41f2..50f11f026 100644 --- a/lib/tsan/CMakeLists.txt +++ b/lib/tsan/CMakeLists.txt @@ -54,6 +54,7 @@ set(TSAN_HEADERS rtl/tsan_dense_alloc.h rtl/tsan_fd.h rtl/tsan_flags.h + rtl/tsan_flags.inc rtl/tsan_ignoreset.h rtl/tsan_interface_ann.h rtl/tsan_interface.h diff --git a/lib/tsan/rtl/tsan_flags.cc b/lib/tsan/rtl/tsan_flags.cc index 71fee3eaa..77677ebba 100644 --- a/lib/tsan/rtl/tsan_flags.cc +++ b/lib/tsan/rtl/tsan_flags.cc @@ -33,65 +33,25 @@ const char *WEAK __tsan_default_options() { } #endif -static void ParseFlags(Flags *f, const char *env) { - ParseFlag(env, &f->enable_annotations, "enable_annotations", ""); - ParseFlag(env, &f->suppress_equal_stacks, "suppress_equal_stacks", ""); - ParseFlag(env, &f->suppress_equal_addresses, "suppress_equal_addresses", ""); - ParseFlag(env, &f->report_bugs, "report_bugs", ""); - ParseFlag(env, &f->report_thread_leaks, "report_thread_leaks", ""); - ParseFlag(env, &f->report_destroy_locked, "report_destroy_locked", ""); - ParseFlag(env, &f->report_mutex_bugs, "report_mutex_bugs", ""); - ParseFlag(env, &f->report_signal_unsafe, "report_signal_unsafe", ""); - ParseFlag(env, &f->report_atomic_races, "report_atomic_races", ""); - ParseFlag(env, &f->force_seq_cst_atomics, "force_seq_cst_atomics", ""); - ParseFlag(env, &f->print_benign, "print_benign", ""); - ParseFlag(env, &f->exitcode, "exitcode", ""); - ParseFlag(env, &f->halt_on_error, "halt_on_error", ""); - ParseFlag(env, &f->atexit_sleep_ms, "atexit_sleep_ms", ""); - ParseFlag(env, &f->profile_memory, "profile_memory", ""); - ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms", ""); - ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms", ""); - ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb", ""); - ParseFlag(env, &f->stop_on_start, "stop_on_start", ""); - ParseFlag(env, &f->running_on_valgrind, "running_on_valgrind", ""); - ParseFlag(env, &f->history_size, "history_size", ""); - ParseFlag(env, &f->io_sync, "io_sync", ""); - ParseFlag(env, &f->die_after_fork, "die_after_fork", ""); +void Flags::SetDefaults() { +#define TSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "tsan_flags.inc" +#undef TSAN_FLAG + // DDFlags + second_deadlock_stack = false; +} +void Flags::ParseFromString(const char *str) { +#define TSAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "tsan_flags.inc" +#undef TSAN_FLAG // DDFlags - ParseFlag(env, &f->second_deadlock_stack, "second_deadlock_stack", ""); + ParseFlag(str, &second_deadlock_stack, "second_deadlock_stack", ""); } void InitializeFlags(Flags *f, const char *env) { - internal_memset(f, 0, sizeof(*f)); - - // Default values. - f->enable_annotations = true; - f->suppress_equal_stacks = true; - f->suppress_equal_addresses = true; - f->report_bugs = true; - f->report_thread_leaks = true; - f->report_destroy_locked = true; - f->report_mutex_bugs = true; - f->report_signal_unsafe = true; - f->report_atomic_races = true; - f->force_seq_cst_atomics = false; - f->print_benign = false; - f->exitcode = 66; - f->halt_on_error = false; - f->atexit_sleep_ms = 1000; - f->profile_memory = ""; - f->flush_memory_ms = 0; - f->flush_symbolizer_ms = 5000; - f->memory_limit_mb = 0; - f->stop_on_start = false; - f->running_on_valgrind = false; - f->history_size = kGoMode ? 1 : 2; // There are a lot of goroutines in Go. - f->io_sync = 1; - f->die_after_fork = true; - - // DDFlags - f->second_deadlock_stack = false; + f->SetDefaults(); SetCommonFlagsDefaults(); { @@ -106,10 +66,10 @@ void InitializeFlags(Flags *f, const char *env) { } // Let a frontend override. - ParseFlags(f, __tsan_default_options()); + f->ParseFromString(__tsan_default_options()); ParseCommonFlagsFromString(__tsan_default_options()); // Override from command line. - ParseFlags(f, env); + f->ParseFromString(env); ParseCommonFlagsFromString(env); // Sanity check. diff --git a/lib/tsan/rtl/tsan_flags.h b/lib/tsan/rtl/tsan_flags.h index 621ca1392..e2f6b3c9f 100644 --- a/lib/tsan/rtl/tsan_flags.h +++ b/lib/tsan/rtl/tsan_flags.h @@ -20,65 +20,12 @@ namespace __tsan { struct Flags : DDFlags { - // Enable dynamic annotations, otherwise they are no-ops. - bool enable_annotations; - // Suppress a race report if we've already output another race report - // with the same stack. - bool suppress_equal_stacks; - // Suppress a race report if we've already output another race report - // on the same address. - bool suppress_equal_addresses; - // Turns off bug reporting entirely (useful for benchmarking). - bool report_bugs; - // Report thread leaks at exit? - bool report_thread_leaks; - // Report destruction of a locked mutex? - bool report_destroy_locked; - // Report incorrect usages of mutexes and mutex annotations? - bool report_mutex_bugs; - // Report violations of async signal-safety - // (e.g. malloc() call from a signal handler). - bool report_signal_unsafe; - // Report races between atomic and plain memory accesses. - bool report_atomic_races; - // If set, all atomics are effectively sequentially consistent (seq_cst), - // regardless of what user actually specified. - bool force_seq_cst_atomics; - // Print matched "benign" races at exit. - bool print_benign; - // Override exit status if something was reported. - int exitcode; - // Exit after first reported error. - bool halt_on_error; - // Sleep in main thread before exiting for that many ms - // (useful to catch "at exit" races). - int atexit_sleep_ms; - // If set, periodically write memory profile to that file. - const char *profile_memory; - // Flush shadow memory every X ms. - int flush_memory_ms; - // Flush symbolizer caches every X ms. - int flush_symbolizer_ms; - // Resident memory limit in MB to aim at. - // If the process consumes more memory, then TSan will flush shadow memory. - int memory_limit_mb; - // Stops on start until __tsan_resume() is called (for debugging). - bool stop_on_start; - // Controls whether RunningOnValgrind() returns true or false. - bool running_on_valgrind; - // Per-thread history size, controls how many previous memory accesses - // are remembered per thread. Possible values are [0..7]. - // history_size=0 amounts to 32K memory accesses. Each next value doubles - // the amount of memory accesses, up to history_size=7 that amounts to - // 4M memory accesses. The default value is 2 (128K memory accesses). - int history_size; - // Controls level of synchronization implied by IO operations. - // 0 - no synchronization - // 1 - reasonable level of synchronization (write->read) - // 2 - global synchronization of all IO operations - int io_sync; - // Die after multi-threaded fork if the child creates new threads. - bool die_after_fork; +#define TSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "tsan_flags.inc" +#undef TSAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); }; Flags *flags(); diff --git a/lib/tsan/rtl/tsan_flags.inc b/lib/tsan/rtl/tsan_flags.inc new file mode 100644 index 000000000..2925f3848 --- /dev/null +++ b/lib/tsan/rtl/tsan_flags.inc @@ -0,0 +1,78 @@ +//===-- tsan_flags.inc ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TSan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef TSAN_FLAG +# error "Define TSAN_FLAG prior to including this file!" +#endif + +// TSAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +TSAN_FLAG(bool, enable_annotations, true, + "Enable dynamic annotations, otherwise they are no-ops.") +// Suppress a race report if we've already output another race report +// with the same stack. +TSAN_FLAG(bool, suppress_equal_stacks, true, + "Suppress a race report if we've already output another race report " + "with the same stack.") +TSAN_FLAG(bool, suppress_equal_addresses, true, + "Suppress a race report if we've already output another race report " + "on the same address.") + +TSAN_FLAG(bool, report_bugs, true, + "Turns off bug reporting entirely (useful for benchmarking).") +TSAN_FLAG(bool, report_thread_leaks, true, "Report thread leaks at exit?") +TSAN_FLAG(bool, report_destroy_locked, true, + "Report destruction of a locked mutex?") +TSAN_FLAG(bool, report_mutex_bugs, true, + "Report incorrect usages of mutexes and mutex annotations?") +TSAN_FLAG(bool, report_signal_unsafe, true, + "Report violations of async signal-safety " + "(e.g. malloc() call from a signal handler).") +TSAN_FLAG(bool, report_atomic_races, true, + "Report races between atomic and plain memory accesses.") +TSAN_FLAG( + bool, force_seq_cst_atomics, false, + "If set, all atomics are effectively sequentially consistent (seq_cst), " + "regardless of what user actually specified.") +TSAN_FLAG(bool, print_benign, false, "Print matched \"benign\" races at exit.") +TSAN_FLAG(int, exitcode, 66, "Override exit status if something was reported.") +TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.") +TSAN_FLAG(int, atexit_sleep_ms, 1000, + "Sleep in main thread before exiting for that many ms " + "(useful to catch \"at exit\" races).") +TSAN_FLAG(const char *, profile_memory, "", + "If set, periodically write memory profile to that file.") +TSAN_FLAG(int, flush_memory_ms, 0, "Flush shadow memory every X ms.") +TSAN_FLAG(int, flush_symbolizer_ms, 5000, "Flush symbolizer caches every X ms.") +TSAN_FLAG( + int, memory_limit_mb, 0, + "Resident memory limit in MB to aim at." + "If the process consumes more memory, then TSan will flush shadow memory.") +TSAN_FLAG(bool, stop_on_start, false, + "Stops on start until __tsan_resume() is called (for debugging).") +TSAN_FLAG(bool, running_on_valgrind, false, + "Controls whether RunningOnValgrind() returns true or false.") +TSAN_FLAG( + int, history_size, kGoMode ? 1 : 2, // There are a lot of goroutines in Go. + "Per-thread history size, controls how many previous memory accesses " + "are remembered per thread. Possible values are [0..7]. " + "history_size=0 amounts to 32K memory accesses. Each next value doubles " + "the amount of memory accesses, up to history_size=7 that amounts to " + "4M memory accesses. The default value is 2 (128K memory accesses).") +TSAN_FLAG(int, io_sync, 1, + "Controls level of synchronization implied by IO operations. " + "0 - no synchronization " + "1 - reasonable level of synchronization (write->read)" + "2 - global synchronization of all IO operations.") +TSAN_FLAG(bool, die_after_fork, true, + "Die after multi-threaded fork if the child creates new threads.") diff --git a/lib/ubsan/ubsan_flags.cc b/lib/ubsan/ubsan_flags.cc index d0fa889ea..d25481e73 100644 --- a/lib/ubsan/ubsan_flags.cc +++ b/lib/ubsan/ubsan_flags.cc @@ -35,24 +35,26 @@ void InitializeCommonFlags() { Flags ubsan_flags; -static void ParseFlagsFromString(Flags *f, const char *str) { - if (!str) - return; - ParseFlag(str, &f->halt_on_error, "halt_on_error", - "Crash the program after printing the first error report"); - ParseFlag(str, &f->print_stacktrace, "print_stacktrace", - "Include full stacktrace into an error report"); +void Flags::SetDefaults() { +#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; +#include "ubsan_flags.inc" +#undef UBSAN_FLAG +} + +void Flags::ParseFromString(const char *str) { +#define UBSAN_FLAG(Type, Name, DefaultValue, Description) \ + ParseFlag(str, &Name, #Name, Description); +#include "ubsan_flags.inc" +#undef UBSAN_FLAG } void InitializeFlags() { Flags *f = flags(); - // Default values. - f->halt_on_error = false; - f->print_stacktrace = false; + f->SetDefaults(); // Override from user-specified string. - ParseFlagsFromString(f, MaybeCallUbsanDefaultOptions()); + f->ParseFromString(MaybeCallUbsanDefaultOptions()); // Override from environment variable. - ParseFlagsFromString(f, GetEnv("UBSAN_OPTIONS")); + f->ParseFromString(GetEnv("UBSAN_OPTIONS")); } } // namespace __ubsan diff --git a/lib/ubsan/ubsan_flags.h b/lib/ubsan/ubsan_flags.h index c496469f5..44c287e3d 100644 --- a/lib/ubsan/ubsan_flags.h +++ b/lib/ubsan/ubsan_flags.h @@ -18,8 +18,12 @@ namespace __ubsan { struct Flags { - bool halt_on_error; - bool print_stacktrace; +#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Type Name; +#include "ubsan_flags.inc" +#undef UBSAN_FLAG + + void SetDefaults(); + void ParseFromString(const char *str); }; extern Flags ubsan_flags; diff --git a/lib/ubsan/ubsan_flags.inc b/lib/ubsan/ubsan_flags.inc new file mode 100644 index 000000000..3260e8e13 --- /dev/null +++ b/lib/ubsan/ubsan_flags.inc @@ -0,0 +1,24 @@ +//===-- ubsan_flags.inc -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// UBSan runtime flags. +// +//===----------------------------------------------------------------------===// +#ifndef UBSAN_FLAG +# error "Define UBSAN_FLAG prior to including this file!" +#endif + +// UBSAN_FLAG(Type, Name, DefaultValue, Description) +// See COMMON_FLAG in sanitizer_flags.inc for more details. + +UBSAN_FLAG(bool, halt_on_error, false, + "Crash the program after printing the first error report") +UBSAN_FLAG(bool, print_stacktrace, false, + "Include full stacktrace into an error report") + |