1278497Sdim//===-- sanitizer_flag_parser.h ---------------------------------*- C++ -*-===// 2278497Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6278497Sdim// 7278497Sdim//===----------------------------------------------------------------------===// 8278497Sdim// 9278497Sdim// This file is a part of ThreadSanitizer/AddressSanitizer runtime. 10278497Sdim// 11278497Sdim//===----------------------------------------------------------------------===// 12278497Sdim 13278497Sdim#ifndef SANITIZER_FLAG_REGISTRY_H 14278497Sdim#define SANITIZER_FLAG_REGISTRY_H 15278497Sdim 16278497Sdim#include "sanitizer_internal_defs.h" 17278497Sdim#include "sanitizer_libc.h" 18278497Sdim#include "sanitizer_common.h" 19278497Sdim 20278497Sdimnamespace __sanitizer { 21278497Sdim 22278497Sdimclass FlagHandlerBase { 23278497Sdim public: 24278497Sdim virtual bool Parse(const char *value) { return false; } 25360784Sdim // Write the C string representation of the current value (truncated to fit) 26360784Sdim // into the buffer of size `size`. Returns false if truncation occurred and 27360784Sdim // returns true otherwise. 28360784Sdim virtual bool Format(char *buffer, uptr size) { 29360784Sdim if (size > 0) 30360784Sdim buffer[0] = '\0'; 31360784Sdim return false; 32360784Sdim } 33353358Sdim 34353358Sdim protected: 35360784Sdim ~FlagHandlerBase() {} 36360784Sdim 37360784Sdim inline bool FormatString(char *buffer, uptr size, const char *str_to_use) { 38360784Sdim uptr num_symbols_should_write = 39360784Sdim internal_snprintf(buffer, size, "%s", str_to_use); 40360784Sdim return num_symbols_should_write < size; 41360784Sdim } 42278497Sdim}; 43278497Sdim 44278497Sdimtemplate <typename T> 45278497Sdimclass FlagHandler : public FlagHandlerBase { 46278497Sdim T *t_; 47278497Sdim 48278497Sdim public: 49278497Sdim explicit FlagHandler(T *t) : t_(t) {} 50279194Sdim bool Parse(const char *value) final; 51360784Sdim bool Format(char *buffer, uptr size) final; 52278497Sdim}; 53278497Sdim 54321369Sdiminline bool ParseBool(const char *value, bool *b) { 55278497Sdim if (internal_strcmp(value, "0") == 0 || 56278497Sdim internal_strcmp(value, "no") == 0 || 57278497Sdim internal_strcmp(value, "false") == 0) { 58321369Sdim *b = false; 59278497Sdim return true; 60278497Sdim } 61278497Sdim if (internal_strcmp(value, "1") == 0 || 62278497Sdim internal_strcmp(value, "yes") == 0 || 63278497Sdim internal_strcmp(value, "true") == 0) { 64321369Sdim *b = true; 65278497Sdim return true; 66278497Sdim } 67321369Sdim return false; 68321369Sdim} 69321369Sdim 70321369Sdimtemplate <> 71321369Sdiminline bool FlagHandler<bool>::Parse(const char *value) { 72321369Sdim if (ParseBool(value, t_)) return true; 73278497Sdim Printf("ERROR: Invalid value for bool option: '%s'\n", value); 74278497Sdim return false; 75278497Sdim} 76278497Sdim 77278497Sdimtemplate <> 78360784Sdiminline bool FlagHandler<bool>::Format(char *buffer, uptr size) { 79360784Sdim return FormatString(buffer, size, *t_ ? "true" : "false"); 80360784Sdim} 81360784Sdim 82360784Sdimtemplate <> 83321369Sdiminline bool FlagHandler<HandleSignalMode>::Parse(const char *value) { 84321369Sdim bool b; 85321369Sdim if (ParseBool(value, &b)) { 86321369Sdim *t_ = b ? kHandleSignalYes : kHandleSignalNo; 87321369Sdim return true; 88321369Sdim } 89321369Sdim if (internal_strcmp(value, "2") == 0 || 90321369Sdim internal_strcmp(value, "exclusive") == 0) { 91321369Sdim *t_ = kHandleSignalExclusive; 92321369Sdim return true; 93321369Sdim } 94321369Sdim Printf("ERROR: Invalid value for signal handler option: '%s'\n", value); 95321369Sdim return false; 96321369Sdim} 97321369Sdim 98321369Sdimtemplate <> 99360784Sdiminline bool FlagHandler<HandleSignalMode>::Format(char *buffer, uptr size) { 100360784Sdim uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_); 101360784Sdim return num_symbols_should_write < size; 102360784Sdim} 103360784Sdim 104360784Sdimtemplate <> 105278497Sdiminline bool FlagHandler<const char *>::Parse(const char *value) { 106327952Sdim *t_ = value; 107278497Sdim return true; 108278497Sdim} 109278497Sdim 110278497Sdimtemplate <> 111360784Sdiminline bool FlagHandler<const char *>::Format(char *buffer, uptr size) { 112360784Sdim return FormatString(buffer, size, *t_); 113360784Sdim} 114360784Sdim 115360784Sdimtemplate <> 116278497Sdiminline bool FlagHandler<int>::Parse(const char *value) { 117341825Sdim const char *value_end; 118278497Sdim *t_ = internal_simple_strtoll(value, &value_end, 10); 119278497Sdim bool ok = *value_end == 0; 120278497Sdim if (!ok) Printf("ERROR: Invalid value for int option: '%s'\n", value); 121278497Sdim return ok; 122278497Sdim} 123278497Sdim 124278497Sdimtemplate <> 125360784Sdiminline bool FlagHandler<int>::Format(char *buffer, uptr size) { 126360784Sdim uptr num_symbols_should_write = internal_snprintf(buffer, size, "%d", *t_); 127360784Sdim return num_symbols_should_write < size; 128360784Sdim} 129360784Sdim 130360784Sdimtemplate <> 131278497Sdiminline bool FlagHandler<uptr>::Parse(const char *value) { 132341825Sdim const char *value_end; 133278497Sdim *t_ = internal_simple_strtoll(value, &value_end, 10); 134278497Sdim bool ok = *value_end == 0; 135278497Sdim if (!ok) Printf("ERROR: Invalid value for uptr option: '%s'\n", value); 136278497Sdim return ok; 137278497Sdim} 138278497Sdim 139353358Sdimtemplate <> 140360784Sdiminline bool FlagHandler<uptr>::Format(char *buffer, uptr size) { 141360784Sdim uptr num_symbols_should_write = internal_snprintf(buffer, size, "%p", *t_); 142360784Sdim return num_symbols_should_write < size; 143360784Sdim} 144360784Sdim 145360784Sdimtemplate <> 146353358Sdiminline bool FlagHandler<s64>::Parse(const char *value) { 147353358Sdim const char *value_end; 148353358Sdim *t_ = internal_simple_strtoll(value, &value_end, 10); 149353358Sdim bool ok = *value_end == 0; 150353358Sdim if (!ok) Printf("ERROR: Invalid value for s64 option: '%s'\n", value); 151353358Sdim return ok; 152353358Sdim} 153353358Sdim 154360784Sdimtemplate <> 155360784Sdiminline bool FlagHandler<s64>::Format(char *buffer, uptr size) { 156360784Sdim uptr num_symbols_should_write = internal_snprintf(buffer, size, "%lld", *t_); 157360784Sdim return num_symbols_should_write < size; 158360784Sdim} 159360784Sdim 160278497Sdimclass FlagParser { 161278497Sdim static const int kMaxFlags = 200; 162278497Sdim struct Flag { 163278497Sdim const char *name; 164278497Sdim const char *desc; 165278497Sdim FlagHandlerBase *handler; 166278497Sdim } *flags_; 167278497Sdim int n_flags_; 168278497Sdim 169278497Sdim const char *buf_; 170278497Sdim uptr pos_; 171278497Sdim 172278497Sdim public: 173278497Sdim FlagParser(); 174278497Sdim void RegisterHandler(const char *name, FlagHandlerBase *handler, 175278497Sdim const char *desc); 176353358Sdim void ParseString(const char *s, const char *env_name = 0); 177353358Sdim void ParseStringFromEnv(const char *env_name); 178296417Sdim bool ParseFile(const char *path, bool ignore_missing); 179278497Sdim void PrintFlagDescriptions(); 180278497Sdim 181278497Sdim static LowLevelAllocator Alloc; 182278497Sdim 183278497Sdim private: 184278497Sdim void fatal_error(const char *err); 185278497Sdim bool is_space(char c); 186278497Sdim void skip_whitespace(); 187353358Sdim void parse_flags(const char *env_option_name); 188353358Sdim void parse_flag(const char *env_option_name); 189278497Sdim bool run_handler(const char *name, const char *value); 190278497Sdim char *ll_strndup(const char *s, uptr n); 191278497Sdim}; 192278497Sdim 193278497Sdimtemplate <typename T> 194278497Sdimstatic void RegisterFlag(FlagParser *parser, const char *name, const char *desc, 195278497Sdim T *var) { 196360784Sdim FlagHandler<T> *fh = new (FlagParser::Alloc) FlagHandler<T>(var); 197278497Sdim parser->RegisterHandler(name, fh, desc); 198278497Sdim} 199278497Sdim 200278497Sdimvoid ReportUnrecognizedFlags(); 201278497Sdim 202278497Sdim} // namespace __sanitizer 203278497Sdim 204278497Sdim#endif // SANITIZER_FLAG_REGISTRY_H 205