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