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