Home | History | Annotate | Download | only in sanitizer_common
      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