[GWP-ASan] Configuration options [3]. am: 83c704ea07
am: 6a679601a9

Change-Id: I6bdf2c8947e0954b1e7d4efb36c16e89157df2f4
diff --git a/gwp_asan/optional/options_parser.cpp b/gwp_asan/optional/options_parser.cpp
new file mode 100644
index 0000000..ba9af49
--- /dev/null
+++ b/gwp_asan/optional/options_parser.cpp
@@ -0,0 +1,91 @@
+//===-- options_parser.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/optional/options_parser.h"
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gwp_asan/options.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
+#include "sanitizer_common/sanitizer_flags.h"
+
+namespace gwp_asan {
+namespace options {
+namespace {
+void registerGwpAsanFlags(__sanitizer::FlagParser *parser, Options *o) {
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description)                 \
+  RegisterFlag(parser, #Name, Description, &o->Name);
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+}
+
+const char *getCompileDefinitionGwpAsanDefaultOptions() {
+#ifdef GWP_ASAN_DEFAULT_OPTIONS
+  return SANITIZER_STRINGIFY(GWP_ASAN_DEFAULT_OPTIONS);
+#else
+  return "";
+#endif
+}
+
+const char *getGwpAsanDefaultOptions() {
+  return (__gwp_asan_default_options) ? __gwp_asan_default_options() : "";
+}
+
+Options *getOptionsInternal() {
+  static Options GwpAsanFlags;
+  return &GwpAsanFlags;
+}
+} // anonymous namespace
+
+void initOptions() {
+  Options *o = getOptionsInternal();
+  o->setDefaults();
+
+  __sanitizer::FlagParser Parser;
+  registerGwpAsanFlags(&Parser, o);
+
+  // Override from compile definition.
+  Parser.ParseString(getCompileDefinitionGwpAsanDefaultOptions());
+
+  // Override from user-specified string.
+  Parser.ParseString(getGwpAsanDefaultOptions());
+
+  // Override from environment.
+  Parser.ParseString(__sanitizer::GetEnv("GWP_ASAN_OPTIONS"));
+
+  __sanitizer::InitializeCommonFlags();
+  if (__sanitizer::Verbosity())
+    __sanitizer::ReportUnrecognizedFlags();
+
+  if (!o->Enabled)
+    return;
+
+  // Sanity checks for the parameters.
+  if (o->MaxSimultaneousAllocations <= 0) {
+    __sanitizer::Printf("GWP-ASan ERROR: MaxSimultaneousAllocations must be > "
+                        "0 when GWP-ASan is enabled.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  if (o->SampleRate < 1) {
+    __sanitizer::Printf(
+        "GWP-ASan ERROR: SampleRate must be > 0 when GWP-ASan is enabled.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  o->Printf = __sanitizer::Printf;
+}
+
+const Options &getOptions() { return *getOptionsInternal(); }
+
+} // namespace options
+} // namespace gwp_asan
diff --git a/gwp_asan/optional/options_parser.h b/gwp_asan/optional/options_parser.h
new file mode 100644
index 0000000..7a1d3b0
--- /dev/null
+++ b/gwp_asan/optional/options_parser.h
@@ -0,0 +1,32 @@
+//===-- options_parser.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
+#define GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
+
+#include "gwp_asan/options.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace gwp_asan {
+namespace options {
+
+// Parse the options from the GWP_ASAN_FLAGS environment variable.
+void initOptions();
+// Returns a pointer to the initialised options. Call initOptions() prior to
+// calling this function.
+const Options &getOptions();
+
+} // namespace options
+} // namespace gwp_asan
+
+extern "C" {
+SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE const char *
+__gwp_asan_default_options();
+}
+
+#endif // GWP_ASAN_OPTIONAL_OPTIONS_PARSER_H_
diff --git a/gwp_asan/options.h b/gwp_asan/options.h
new file mode 100644
index 0000000..c1b6e67
--- /dev/null
+++ b/gwp_asan/options.h
@@ -0,0 +1,41 @@
+//===-- options.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONS_H_
+#define GWP_ASAN_OPTIONS_H_
+
+namespace gwp_asan {
+namespace options {
+// The function pointer type for printf(). Follows the standard format from the
+// sanitizers library. If the supported allocator exposes printing via a
+// different function signature, please provide a wrapper which has this
+// printf() signature, and pass the wrapper instead.
+typedef void (*Printf_t)(const char *Format, ...);
+
+struct Options {
+  Printf_t Printf = nullptr;
+
+  // Read the options from the included definitions file.
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description)                 \
+  Type Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+
+  void setDefaults() {
+#define GWP_ASAN_OPTION(Type, Name, DefaultValue, Description)                 \
+  Name = DefaultValue;
+#include "gwp_asan/options.inc"
+#undef GWP_ASAN_OPTION
+
+    Printf = nullptr;
+  }
+};
+} // namespace options
+} // namespace gwp_asan
+
+#endif // GWP_ASAN_OPTIONS_H_
diff --git a/gwp_asan/options.inc b/gwp_asan/options.inc
new file mode 100644
index 0000000..9042b11
--- /dev/null
+++ b/gwp_asan/options.inc
@@ -0,0 +1,41 @@
+//===-- options.inc ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTION
+#error "Define GWP_ASAN_OPTION prior to including this file!"
+#endif
+
+GWP_ASAN_OPTION(bool, Enabled, true, "Is GWP-ASan enabled? Defaults to true.")
+
+GWP_ASAN_OPTION(
+    bool, PerfectlyRightAlign, false,
+    "When allocations are right-aligned, should we perfectly align them up to "
+    "the page boundary? By default (false), we round up allocation size to the "
+    "nearest power of two (1, 2, 4, 8, 16) up to a maximum of 16-byte "
+    "alignment for performance reasons. Setting this to true can find single "
+    "byte buffer-overflows for multibyte allocations at the cost of "
+    "performance, and may be incompatible with some architectures.")
+
+GWP_ASAN_OPTION(
+    int, MaxSimultaneousAllocations, 16,
+    "Number of usable guarded slots in the allocation pool. Defaults to 16.")
+
+GWP_ASAN_OPTION(int, SampleRate, 5000,
+                "The probability (1 / SampleRate) that an allocation is "
+                "selected for GWP-ASan sampling. Default is 5000. Sample rates "
+                "up to (2^31 - 1) are supported.")
+
+GWP_ASAN_OPTION(
+    bool, InstallSignalHandlers, true,
+    "Install GWP-ASan signal handlers for SIGSEGV during dynamic loading. This "
+    "allows better error reports by providing stack traces for allocation and "
+    "deallocation when reporting a memory error. GWP-ASan's signal handler "
+    "will forward the signal to any previously-installed handler, and user "
+    "programs that install further signal handlers should make sure they do "
+    "the same. Note, if the previously installed SIGSEGV handler is SIG_IGN, "
+    "we terminate the process after dumping the error report.")