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