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