From bc14dd46f26ae3bfe434dd56a7c12272389530f8 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 15 Jan 2015 16:26:59 +0000 Subject: [PATCH] [sanitizer] Implement include= option. Allows loading sanitizer options from file. llvm-svn: 226175 --- .../lib/sanitizer_common/sanitizer_flag_parser.cc | 19 ++++++++++++---- .../lib/sanitizer_common/sanitizer_flag_parser.h | 1 + .../lib/sanitizer_common/sanitizer_flags.cc | 26 ++++++++++++++++++++++ .../test/asan/TestCases/asan_options-include.cc | 16 +++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 compiler-rt/test/asan/TestCases/asan_options-include.cc diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc b/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc index 96ee728..4f1d0dd 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.cc @@ -71,10 +71,7 @@ void FlagParser::parse_flag() { InternalFree((void *)value); } -void FlagParser::ParseString(const char *s) { - if (!s) return; - buf_ = s; - pos_ = 0; +void FlagParser::parse_flags() { while (true) { skip_whitespace(); if (buf_[pos_] == 0) break; @@ -86,6 +83,20 @@ void FlagParser::ParseString(const char *s) { common_flags_dont_use.malloc_context_size = 1; } +void FlagParser::ParseString(const char *s) { + if (!s) return; + // Backup current parser state to allow nested ParseString() calls. + const char *old_buf_ = buf_; + uptr old_pos_ = pos_; + buf_ = s; + pos_ = 0; + + parse_flags(); + + buf_ = old_buf_; + pos_ = old_pos_; +} + bool FlagParser::run_handler(const char *name, const char *value) { for (int i = 0; i < n_flags_; ++i) { if (internal_strcmp(name, flags_[i].name) == 0) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h b/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h index fe55f7a..27b91e0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flag_parser.h @@ -101,6 +101,7 @@ class FlagParser { void fatal_error(const char *err); bool is_space(char c); void skip_whitespace(); + void parse_flags(); void parse_flag(); bool run_handler(const char *name, const char *value); }; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc index b0ae4af..5020459 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.cc @@ -45,11 +45,37 @@ void CommonFlags::CopyFrom(const CommonFlags &other) { internal_memcpy(this, &other, sizeof(*this)); } +class FlagHandlerInclude : public FlagHandlerBase { + static const uptr kMaxIncludeSize = 1 << 15; + FlagParser *parser_; + + public: + explicit FlagHandlerInclude(FlagParser *parser) : parser_(parser) {} + bool Parse(const char *value) { + char *data; + uptr data_mapped_size; + uptr len = + ReadFileToBuffer(value, &data, &data_mapped_size, kMaxIncludeSize); + if (!len) { + Printf("Failed to read options from '%s'\n", value); + return false; + } + parser_->ParseString(data); + UnmapOrDie(data, data_mapped_size); + return true; + } +}; + void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { #define COMMON_FLAG(Type, Name, DefaultValue, Description) \ RegisterFlag(parser, #Name, Description, &cf->Name); #include "sanitizer_flags.inc" #undef COMMON_FLAG + + FlagHandlerInclude *fh_include = + new (INTERNAL_ALLOC) FlagHandlerInclude(parser); // NOLINT + parser->RegisterHandler("include", fh_include, + "read more options from the given file"); } } // namespace __sanitizer diff --git a/compiler-rt/test/asan/TestCases/asan_options-include.cc b/compiler-rt/test/asan/TestCases/asan_options-include.cc new file mode 100644 index 0000000..68f0103 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/asan_options-include.cc @@ -0,0 +1,16 @@ +// RUN: %clangxx_asan -O0 %s -o %t +// RUN: echo "symbolize=1\ninclude='%t.options2.txt'" > %t.options1.txt +// RUN: echo "verbosity=1" > %t.options2.txt +// RUN: ASAN_OPTIONS="verbosity=0:include='%t.options2.txt'" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-VERBOSITY1 +// RUN: ASAN_OPTIONS="include='%t.options2.txt',verbosity=0" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-VERBOSITY0 +// RUN: ASAN_OPTIONS="include='%t.options-not-found.txt',verbosity=0" not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-FOUND + +#include + +int main() { + fprintf(stderr, "done\n"); +} + +// CHECK-VERBOSITY1: Parsed ASAN_OPTIONS: +// CHECK-VERBOSITY0-NOT: Parsed ASAN_OPTIONS: +// CHECK-NOT-FOUND: Failed to read options from -- 2.7.4