Viewing file: sanitizer_flag_parser.h (5.72 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file is a part of ThreadSanitizer/AddressSanitizer runtime. // //===----------------------------------------------------------------------===//
#ifndef SANITIZER_FLAG_REGISTRY_H #define SANITIZER_FLAG_REGISTRY_H
#include "sanitizer_internal_defs.h" #include "sanitizer_libc.h" #include "sanitizer_common.h"
namespace __sanitizer {
class FlagHandlerBase { public: virtual bool Parse(const char *value) { return false; } // Write the C string representation of the current value (truncated to fit) // into the buffer of size `size`. Returns false if truncation occurred and // returns true otherwise. virtual bool Format(char *buffer, uptr size) { if (size > 0) buffer[0] = '\0'; return false; }
protected: ~FlagHandlerBase() {}
inline bool FormatString(char *buffer, uptr size, const char *str_to_use) { uptr num_symbols_should_write = internal_snprintf(buffer, size, "%s", str_to_use); return num_symbols_should_write < size; } };
template <typename T> class FlagHandler final : public FlagHandlerBase { T *t_;
public: explicit FlagHandler(T *t) : t_(t) {} bool Parse(const char *value) final; bool Format(char *buffer, uptr size) final; };
inline bool ParseBool(const char *value, bool *b) { if (internal_strcmp(value, "0") == 0 || internal_strcmp(value, "no") == 0 || internal_strcmp(value, "false") == 0) { *b = false; return true; } if (internal_strcmp(value, "1") == 0 || internal_strcmp(value, "yes") == 0 || internal_strcmp(value, "true") == 0) { *b = true; return true; } return false; }
template <> inline bool FlagHandler<bool>::Parse(const char *value) { if (ParseBool(value, t_)) return true; Printf("ERROR: Invalid value for bool option: '%s'\n", value); return false; }
template <> inline bool FlagHandler<bool>::Format(char *buffer, uptr size) { return FormatString(buffer, size, *t_ ? "true" : "false"); }
template <> inline bool FlagHandler<HandleSignalMode>::Parse(const char *value) { bool b; if (ParseBool(value, &b)) { *t_ = b ? kHandleSignalYes : kHandleSignalNo; return true; } if (internal_strcmp(value, "2") == 0 || internal_strcmp(value, "exclusive") == 0) { *t_ = kHandleSignalExclusive; return true; } Printf("ERROR: Invalid value for signal handler option: '%s'\n", value); return false; }
template <> inline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) { uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_); return num_symbols_should_write < size; }
template <> inline bool FlagHandler<const char *>::Parse(const char *value) { *t_ = value; return true; }
template <> inline bool FlagHandler<const char *>::Format(char *buffer, uptr size) { return FormatString(buffer, size, *t_); }
template <> inline bool FlagHandler<int>::Parse(const char *value) { const char *value_end; *t_ = internal_simple_strtoll(value, &value_end, 10); bool ok = *value_end == 0; if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value); return ok; }
template <> inline bool FlagHandler<int>::Format(char *buffer, uptr size) { uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_); return num_symbols_should_write < size; }
template <> inline bool FlagHandler<uptr>::Parse(const char *value) { const char *value_end; *t_ = internal_simple_strtoll(value, &value_end, 10); bool ok = *value_end == 0; if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value); return ok; }
template <> inline bool FlagHandler<uptr>::Format(char *buffer, uptr size) { uptr num_symbols_should_write = internal_snprintf(buffer, size, "0x%zx", *t_); return num_symbols_should_write < size; }
template <> inline bool FlagHandler<s64>::Parse(const char *value) { const char *value_end; *t_ = internal_simple_strtoll(value, &value_end, 10); bool ok = *value_end == 0; if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value); return ok; }
template <> inline bool FlagHandler<s64>::Format(char *buffer, uptr size) { uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_); return num_symbols_should_write < size; }
class FlagParser { static const int kMaxFlags = 200; struct Flag { const char *name; const char *desc; FlagHandlerBase *handler; } *flags_; int n_flags_;
const char *buf_; uptr pos_;
public: FlagParser(); void RegisterHandler(const char *name, FlagHandlerBase *handler, const char *desc); void ParseString(const char *s, const char *env_name = 0); void ParseStringFromEnv(const char *env_name); bool ParseFile(const char *path, bool ignore_missing); void PrintFlagDescriptions();
static LowLevelAllocator Alloc;
private: void fatal_error(const char *err); bool is_space(char c); void skip_whitespace(); void parse_flags(const char *env_option_name); void parse_flag(const char *env_option_name); bool run_handler(const char *name, const char *value); char *ll_strndup(const char *s, uptr n); };
template <typename T> static void RegisterFlag(FlagParser *parser, const char *name, const char *desc, T *var) { FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); parser->RegisterHandler(name, fh, desc); }
void ReportUnrecognizedFlags();
} // namespace __sanitizer
#endif // SANITIZER_FLAG_REGISTRY_H
|