sanitizer_flag_parser.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===//
  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. #ifndef SANITIZER_FLAG_REGISTRY_H
  13. #define SANITIZER_FLAG_REGISTRY_H
  14. #include "sanitizer_internal_defs.h"
  15. #include "sanitizer_libc.h"
  16. #include "sanitizer_common.h"
  17. namespace __sanitizer {
  18. class FlagHandlerBase {
  19. public:
  20. virtual bool Parse(const char *value) { return false; }
  21. // Write the C string representation of the current value (truncated to fit)
  22. // into the buffer of size `size`. Returns false if truncation occurred and
  23. // returns true otherwise.
  24. virtual bool Format(char *buffer, uptr size) {
  25. if (size > 0)
  26. buffer[0] = '\0';
  27. return false;
  28. }
  29. protected:
  30. ~FlagHandlerBase() {}
  31. inline bool FormatString(char *buffer, uptr size, const char *str_to_use) {
  32. uptr num_symbols_should_write =
  33. internal_snprintf(buffer, size, "%s", str_to_use);
  34. return num_symbols_should_write < size;
  35. }
  36. };
  37. template <typename T>
  38. class FlagHandler final : public FlagHandlerBase {
  39. T *t_;
  40. public:
  41. explicit FlagHandler(T *t) : t_(t) {}
  42. bool Parse(const char *value) final;
  43. bool Format(char *buffer, uptr size) final;
  44. };
  45. inline bool ParseBool(const char *value, bool *b) {
  46. if (internal_strcmp(value, "0") == 0 ||
  47. internal_strcmp(value, "no") == 0 ||
  48. internal_strcmp(value, "false") == 0) {
  49. *b = false;
  50. return true;
  51. }
  52. if (internal_strcmp(value, "1") == 0 ||
  53. internal_strcmp(value, "yes") == 0 ||
  54. internal_strcmp(value, "true") == 0) {
  55. *b = true;
  56. return true;
  57. }
  58. return false;
  59. }
  60. template <>
  61. inline bool FlagHandler<bool>::Parse(const char *value) {
  62. if (ParseBool(value, t_)) return true;
  63. Printf("ERROR: Invalid value for bool option: '%s'\n", value);
  64. return false;
  65. }
  66. template <>
  67. inline bool FlagHandler<bool>::Format(char *buffer, uptr size) {
  68. return FormatString(buffer, size, *t_ ? "true" : "false");
  69. }
  70. template <>
  71. inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) {
  72. bool b;
  73. if (ParseBool(value, &b)) {
  74. *t_ = b ? kHandleSignalYes : kHandleSignalNo;
  75. return true;
  76. }
  77. if (internal_strcmp(value, "2") == 0 ||
  78. internal_strcmp(value, "exclusive") == 0) {
  79. *t_ = kHandleSignalExclusive;
  80. return true;
  81. }
  82. Printf("ERROR: Invalid value for signal handler option: '%s'\n", value);
  83. return false;
  84. }
  85. template <>
  86. inline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) {
  87. uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
  88. return num_symbols_should_write < size;
  89. }
  90. template <>
  91. inline bool FlagHandler<const char *>::Parse(const char *value) {
  92. *t_ = value;
  93. return true;
  94. }
  95. template <>
  96. inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) {
  97. return FormatString(buffer, size, *t_);
  98. }
  99. template <>
  100. inline bool FlagHandler<int>::Parse(const char *value) {
  101. const char *value_end;
  102. *t_ = internal_simple_strtoll(value, &value_end, 10);
  103. bool ok = *value_end == 0;
  104. if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value);
  105. return ok;
  106. }
  107. template <>
  108. inline bool FlagHandler<int>::Format(char *buffer, uptr size) {
  109. uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_);
  110. return num_symbols_should_write < size;
  111. }
  112. template <>
  113. inline bool FlagHandler<uptr>::Parse(const char *value) {
  114. const char *value_end;
  115. *t_ = internal_simple_strtoll(value, &value_end, 10);
  116. bool ok = *value_end == 0;
  117. if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value);
  118. return ok;
  119. }
  120. template <>
  121. inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) {
  122. uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_);
  123. return num_symbols_should_write < size;
  124. }
  125. template <>
  126. inline bool FlagHandler<s64>::Parse(const char *value) {
  127. const char *value_end;
  128. *t_ = internal_simple_strtoll(value, &value_end, 10);
  129. bool ok = *value_end == 0;
  130. if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value);
  131. return ok;
  132. }
  133. template <>
  134. inline bool FlagHandler<s64>::Format(char *buffer, uptr size) {
  135. uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_);
  136. return num_symbols_should_write < size;
  137. }
  138. class FlagParser {
  139. static const int kMaxFlags = 200;
  140. struct Flag {
  141. const char *name;
  142. const char *desc;
  143. FlagHandlerBase *handler;
  144. } *flags_;
  145. int n_flags_;
  146. const char *buf_;
  147. uptr pos_;
  148. public:
  149. FlagParser();
  150. void RegisterHandler(const char *name, FlagHandlerBase *handler,
  151. const char *desc);
  152. void ParseString(const char *s, const char *env_name = 0);
  153. void ParseStringFromEnv(const char *env_name);
  154. bool ParseFile(const char *path, bool ignore_missing);
  155. void PrintFlagDescriptions();
  156. static LowLevelAllocator Alloc;
  157. private:
  158. void fatal_error(const char *err);
  159. bool is_space(char c);
  160. void skip_whitespace();
  161. void parse_flags(const char *env_option_name);
  162. void parse_flag(const char *env_option_name);
  163. bool run_handler(const char *name, const char *value);
  164. char *ll_strndup(const char *s, uptr n);
  165. };
  166. template <typename T>
  167. static void RegisterFlag(FlagParser *parser, const char *name, const char *desc,
  168. T *var) {
  169. FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var);
  170. parser->RegisterHandler(name, fh, desc);
  171. }
  172. void ReportUnrecognizedFlags();
  173. } // namespace __sanitizer
  174. #endif // SANITIZER_FLAG_REGISTRY_H