Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_flags.cc ------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "sanitizer_flags.h"
     15 
     16 #include "sanitizer_common.h"
     17 #include "sanitizer_libc.h"
     18 #include "sanitizer_list.h"
     19 #include "sanitizer_flag_parser.h"
     20 
     21 namespace __sanitizer {
     22 
     23 CommonFlags common_flags_dont_use;
     24 
     25 struct FlagDescription {
     26   const char *name;
     27   const char *description;
     28   FlagDescription *next;
     29 };
     30 
     31 IntrusiveList<FlagDescription> flag_descriptions;
     32 
     33 // If set, the tool will install its own SEGV signal handler by default.
     34 #ifndef SANITIZER_NEEDS_SEGV
     35 # define SANITIZER_NEEDS_SEGV 1
     36 #endif
     37 
     38 void CommonFlags::SetDefaults() {
     39 #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
     40 #include "sanitizer_flags.inc"
     41 #undef COMMON_FLAG
     42 }
     43 
     44 void CommonFlags::CopyFrom(const CommonFlags &other) {
     45   internal_memcpy(this, &other, sizeof(*this));
     46 }
     47 
     48 // Copy the string from "s" to "out", making the following substitutions:
     49 // %b = binary basename
     50 // %p = pid
     51 void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
     52   char *out_end = out + out_size;
     53   while (*s && out < out_end - 1) {
     54     if (s[0] != '%') {
     55       *out++ = *s++;
     56       continue;
     57     }
     58     switch (s[1]) {
     59       case 'b': {
     60         const char *base = GetProcessName();
     61         CHECK(base);
     62         while (*base && out < out_end - 1)
     63           *out++ = *base++;
     64         s += 2; // skip "%b"
     65         break;
     66       }
     67       case 'p': {
     68         int pid = internal_getpid();
     69         char buf[32];
     70         char *buf_pos = buf + 32;
     71         do {
     72           *--buf_pos = (pid % 10) + '0';
     73           pid /= 10;
     74         } while (pid);
     75         while (buf_pos < buf + 32 && out < out_end - 1)
     76           *out++ = *buf_pos++;
     77         s += 2; // skip "%p"
     78         break;
     79       }
     80       default:
     81         *out++ = *s++;
     82         break;
     83     }
     84   }
     85   CHECK(out < out_end - 1);
     86   *out = '\0';
     87 }
     88 
     89 class FlagHandlerInclude : public FlagHandlerBase {
     90   FlagParser *parser_;
     91   bool ignore_missing_;
     92 
     93  public:
     94   explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
     95       : parser_(parser), ignore_missing_(ignore_missing) {}
     96   bool Parse(const char *value) final {
     97     if (internal_strchr(value, '%')) {
     98       char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
     99       SubstituteForFlagValue(value, buf, kMaxPathLength);
    100       bool res = parser_->ParseFile(buf, ignore_missing_);
    101       UnmapOrDie(buf, kMaxPathLength);
    102       return res;
    103     }
    104     return parser_->ParseFile(value, ignore_missing_);
    105   }
    106 };
    107 
    108 void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
    109   FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT
    110       FlagHandlerInclude(parser, /*ignore_missing*/ false);
    111   parser->RegisterHandler("include", fh_include,
    112                           "read more options from the given file");
    113   FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT
    114       FlagHandlerInclude(parser, /*ignore_missing*/ true);
    115   parser->RegisterHandler(
    116       "include_if_exists", fh_include_if_exists,
    117       "read more options from the given file (if it exists)");
    118 }
    119 
    120 void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
    121 #define COMMON_FLAG(Type, Name, DefaultValue, Description) \
    122   RegisterFlag(parser, #Name, Description, &cf->Name);
    123 #include "sanitizer_flags.inc"
    124 #undef COMMON_FLAG
    125 
    126   RegisterIncludeFlags(parser, cf);
    127 }
    128 
    129 void InitializeCommonFlags(CommonFlags *cf) {
    130   // need to record coverage to generate coverage report.
    131   cf->coverage |= cf->html_cov_report;
    132   SetVerbosity(cf->verbosity);
    133 }
    134 
    135 }  // namespace __sanitizer
    136