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 21namespace __sanitizer { 22 23CommonFlags common_flags_dont_use; 24 25struct FlagDescription { 26 const char *name; 27 const char *description; 28 FlagDescription *next; 29}; 30 31IntrusiveList<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 38void CommonFlags::SetDefaults() { 39#define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 40#include "sanitizer_flags.inc" 41#undef COMMON_FLAG 42} 43 44void CommonFlags::CopyFrom(const CommonFlags &other) { 45 internal_memcpy(this, &other, sizeof(*this)); 46} 47 48// Copy the string from "s" to "out", replacing "%b" with the binary basename. 49static void SubstituteBinaryName(const char *s, char *out, uptr out_size) { 50 char *out_end = out + out_size; 51 while (*s && out < out_end - 1) { 52 if (s[0] != '%' || s[1] != 'b') { *out++ = *s++; continue; } 53 const char *base = GetProcessName(); 54 CHECK(base); 55 while (*base && out < out_end - 1) 56 *out++ = *base++; 57 s += 2; // skip "%b" 58 } 59 *out = '\0'; 60} 61 62class FlagHandlerInclude : public FlagHandlerBase { 63 FlagParser *parser_; 64 bool ignore_missing_; 65 66 public: 67 explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing) 68 : parser_(parser), ignore_missing_(ignore_missing) {} 69 bool Parse(const char *value) final { 70 if (internal_strchr(value, '%')) { 71 char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude"); 72 SubstituteBinaryName(value, buf, kMaxPathLength); 73 bool res = parser_->ParseFile(buf, ignore_missing_); 74 UnmapOrDie(buf, kMaxPathLength); 75 return res; 76 } 77 return parser_->ParseFile(value, ignore_missing_); 78 } 79}; 80 81void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) { 82 FlagHandlerInclude *fh_include = new (FlagParser::Alloc) // NOLINT 83 FlagHandlerInclude(parser, /*ignore_missing*/ false); 84 parser->RegisterHandler("include", fh_include, 85 "read more options from the given file"); 86 FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc) // NOLINT 87 FlagHandlerInclude(parser, /*ignore_missing*/ true); 88 parser->RegisterHandler( 89 "include_if_exists", fh_include_if_exists, 90 "read more options from the given file (if it exists)"); 91} 92 93void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) { 94#define COMMON_FLAG(Type, Name, DefaultValue, Description) \ 95 RegisterFlag(parser, #Name, Description, &cf->Name); 96#include "sanitizer_flags.inc" 97#undef COMMON_FLAG 98 99 RegisterIncludeFlags(parser, cf); 100} 101 102} // namespace __sanitizer 103