sanitizer_flags.cc revision b6246066a271e3b01732d1b4381ef745152747d2
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 19namespace __sanitizer { 20 21CommonFlags common_flags_dont_use_directly; 22 23void ParseCommonFlagsFromString(const char *str) { 24 CommonFlags *f = common_flags(); 25 ParseFlag(str, &f->malloc_context_size, "malloc_context_size"); 26 ParseFlag(str, &f->strip_path_prefix, "strip_path_prefix"); 27 ParseFlag(str, &f->fast_unwind_on_fatal, "fast_unwind_on_fatal"); 28 ParseFlag(str, &f->fast_unwind_on_malloc, "fast_unwind_on_malloc"); 29 ParseFlag(str, &f->symbolize, "symbolize"); 30 ParseFlag(str, &f->handle_ioctl, "handle_ioctl"); 31 ParseFlag(str, &f->log_path, "log_path"); 32} 33 34static bool GetFlagValue(const char *env, const char *name, 35 const char **value, int *value_length) { 36 if (env == 0) 37 return false; 38 const char *pos = 0; 39 for (;;) { 40 pos = internal_strstr(env, name); 41 if (pos == 0) 42 return false; 43 if (pos != env && ((pos[-1] >= 'a' && pos[-1] <= 'z') || pos[-1] == '_')) { 44 // Seems to be middle of another flag name or value. 45 env = pos + 1; 46 continue; 47 } 48 break; 49 } 50 pos += internal_strlen(name); 51 const char *end; 52 if (pos[0] != '=') { 53 end = pos; 54 } else { 55 pos += 1; 56 if (pos[0] == '"') { 57 pos += 1; 58 end = internal_strchr(pos, '"'); 59 } else if (pos[0] == '\'') { 60 pos += 1; 61 end = internal_strchr(pos, '\''); 62 } else { 63 // Read until the next space or colon. 64 end = pos + internal_strcspn(pos, " :"); 65 } 66 if (end == 0) 67 end = pos + internal_strlen(pos); 68 } 69 *value = pos; 70 *value_length = end - pos; 71 return true; 72} 73 74static bool StartsWith(const char *flag, int flag_length, const char *value) { 75 if (!flag || !value) 76 return false; 77 int value_length = internal_strlen(value); 78 return (flag_length >= value_length) && 79 (0 == internal_strncmp(flag, value, value_length)); 80} 81 82void ParseFlag(const char *env, bool *flag, const char *name) { 83 const char *value; 84 int value_length; 85 if (!GetFlagValue(env, name, &value, &value_length)) 86 return; 87 if (StartsWith(value, value_length, "0") || 88 StartsWith(value, value_length, "no") || 89 StartsWith(value, value_length, "false")) 90 *flag = false; 91 if (StartsWith(value, value_length, "1") || 92 StartsWith(value, value_length, "yes") || 93 StartsWith(value, value_length, "true")) 94 *flag = true; 95} 96 97void ParseFlag(const char *env, int *flag, const char *name) { 98 const char *value; 99 int value_length; 100 if (!GetFlagValue(env, name, &value, &value_length)) 101 return; 102 *flag = static_cast<int>(internal_atoll(value)); 103} 104 105static LowLevelAllocator allocator_for_flags; 106 107void ParseFlag(const char *env, const char **flag, const char *name) { 108 const char *value; 109 int value_length; 110 if (!GetFlagValue(env, name, &value, &value_length)) 111 return; 112 // Copy the flag value. Don't use locks here, as flags are parsed at 113 // tool startup. 114 char *value_copy = (char*)(allocator_for_flags.Allocate(value_length + 1)); 115 internal_memcpy(value_copy, value, value_length); 116 value_copy[value_length] = '\0'; 117 *flag = value_copy; 118} 119 120} // namespace __sanitizer 121