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