sanitizer_flags.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //===-- sanitizer_flags.cpp -----------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_flags.h"
  13. #include "sanitizer_common.h"
  14. #include "sanitizer_flag_parser.h"
  15. #include "sanitizer_libc.h"
  16. #include "sanitizer_linux.h"
  17. #include "sanitizer_list.h"
  18. namespace __sanitizer {
  19. CommonFlags common_flags_dont_use;
  20. void CommonFlags::SetDefaults() {
  21. #define COMMON_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
  22. #include "sanitizer_flags.inc"
  23. #undef COMMON_FLAG
  24. }
  25. void CommonFlags::CopyFrom(const CommonFlags &other) {
  26. internal_memcpy(this, &other, sizeof(*this));
  27. }
  28. // Copy the string from "s" to "out", making the following substitutions:
  29. // %b = binary basename
  30. // %p = pid
  31. // %d = binary directory
  32. void SubstituteForFlagValue(const char *s, char *out, uptr out_size) {
  33. char *out_end = out + out_size;
  34. while (*s && out < out_end - 1) {
  35. if (s[0] != '%') {
  36. *out++ = *s++;
  37. continue;
  38. }
  39. switch (s[1]) {
  40. case 'b': {
  41. const char *base = GetProcessName();
  42. CHECK(base);
  43. while (*base && out < out_end - 1)
  44. *out++ = *base++;
  45. s += 2; // skip "%b"
  46. break;
  47. }
  48. case 'p': {
  49. int pid = internal_getpid();
  50. char buf[32];
  51. char *buf_pos = buf + 32;
  52. do {
  53. *--buf_pos = (pid % 10) + '0';
  54. pid /= 10;
  55. } while (pid);
  56. while (buf_pos < buf + 32 && out < out_end - 1)
  57. *out++ = *buf_pos++;
  58. s += 2; // skip "%p"
  59. break;
  60. }
  61. case 'd': {
  62. uptr len = ReadBinaryDir(out, out_end - out);
  63. out += len;
  64. s += 2; // skip "%d"
  65. break;
  66. }
  67. default:
  68. *out++ = *s++;
  69. break;
  70. }
  71. }
  72. CHECK(out < out_end - 1);
  73. *out = '\0';
  74. }
  75. class FlagHandlerInclude final : public FlagHandlerBase {
  76. FlagParser *parser_;
  77. bool ignore_missing_;
  78. const char *original_path_;
  79. public:
  80. explicit FlagHandlerInclude(FlagParser *parser, bool ignore_missing)
  81. : parser_(parser), ignore_missing_(ignore_missing), original_path_("") {}
  82. bool Parse(const char *value) final {
  83. original_path_ = value;
  84. if (internal_strchr(value, '%')) {
  85. char *buf = (char *)MmapOrDie(kMaxPathLength, "FlagHandlerInclude");
  86. SubstituteForFlagValue(value, buf, kMaxPathLength);
  87. bool res = parser_->ParseFile(buf, ignore_missing_);
  88. UnmapOrDie(buf, kMaxPathLength);
  89. return res;
  90. }
  91. return parser_->ParseFile(value, ignore_missing_);
  92. }
  93. bool Format(char *buffer, uptr size) override {
  94. // Note `original_path_` isn't actually what's parsed due to `%`
  95. // substitutions. Printing the substituted path would require holding onto
  96. // mmap'ed memory.
  97. return FormatString(buffer, size, original_path_);
  98. }
  99. };
  100. void RegisterIncludeFlags(FlagParser *parser, CommonFlags *cf) {
  101. FlagHandlerInclude *fh_include = new (FlagParser::Alloc)
  102. FlagHandlerInclude(parser, /*ignore_missing*/ false);
  103. parser->RegisterHandler("include", fh_include,
  104. "read more options from the given file");
  105. FlagHandlerInclude *fh_include_if_exists = new (FlagParser::Alloc)
  106. FlagHandlerInclude(parser, /*ignore_missing*/ true);
  107. parser->RegisterHandler(
  108. "include_if_exists", fh_include_if_exists,
  109. "read more options from the given file (if it exists)");
  110. }
  111. void RegisterCommonFlags(FlagParser *parser, CommonFlags *cf) {
  112. #define COMMON_FLAG(Type, Name, DefaultValue, Description) \
  113. RegisterFlag(parser, #Name, Description, &cf->Name);
  114. #include "sanitizer_flags.inc"
  115. #undef COMMON_FLAG
  116. RegisterIncludeFlags(parser, cf);
  117. }
  118. void InitializeCommonFlags(CommonFlags *cf) {
  119. // need to record coverage to generate coverage report.
  120. cf->coverage |= cf->html_cov_report;
  121. SetVerbosity(cf->verbosity);
  122. InitializePlatformCommonFlags(cf);
  123. }
  124. } // namespace __sanitizer