summaryrefslogtreecommitdiff
path: root/lib/lsan
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lsan')
-rw-r--r--lib/lsan/lsan.cc3
-rw-r--r--lib/lsan/lsan_allocator.cc2
-rw-r--r--lib/lsan/lsan_common.cc77
-rw-r--r--lib/lsan/lsan_common.h36
-rw-r--r--lib/lsan/lsan_flags.inc44
5 files changed, 91 insertions, 71 deletions
diff --git a/lib/lsan/lsan.cc b/lib/lsan/lsan.cc
index 1598fcac4a764..1509b2a7d342a 100644
--- a/lib/lsan/lsan.cc
+++ b/lib/lsan/lsan.cc
@@ -52,6 +52,9 @@ extern "C" void __lsan_init() {
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
Atexit(DoLeakCheck);
+
+ InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
+
lsan_inited = true;
lsan_init_is_running = false;
}
diff --git a/lib/lsan/lsan_allocator.cc b/lib/lsan/lsan_allocator.cc
index 8be2a2ad92245..96a2b0428a612 100644
--- a/lib/lsan/lsan_allocator.cc
+++ b/lib/lsan/lsan_allocator.cc
@@ -47,7 +47,7 @@ static Allocator allocator;
static THREADLOCAL AllocatorCache cache;
void InitializeAllocator() {
- allocator.Init();
+ allocator.InitLinkerInitialized(common_flags()->allocator_may_return_null);
}
void AllocatorThreadFinish() {
diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc
index c2ba52e46911c..7b3cd16397613 100644
--- a/lib/lsan/lsan_common.cc
+++ b/lib/lsan/lsan_common.cc
@@ -16,6 +16,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
+#include "sanitizer_common/sanitizer_flag_parser.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_procmaps.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@@ -36,52 +37,50 @@ bool DisabledInThisThread() { return disable_counter > 0; }
Flags lsan_flags;
+void Flags::SetDefaults() {
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
+#include "lsan_flags.inc"
+#undef LSAN_FLAG
+}
+
+static void RegisterLsanFlags(FlagParser *parser, Flags *f) {
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) \
+ RegisterFlag(parser, #Name, Description, &f->Name);
+#include "lsan_flags.inc"
+#undef LSAN_FLAG
+}
+
static void InitializeFlags(bool standalone) {
Flags *f = flags();
- // Default values.
- f->report_objects = false;
- f->resolution = 0;
- f->max_leaks = 0;
- f->exitcode = 23;
- f->use_registers = true;
- f->use_globals = true;
- f->use_stacks = true;
- f->use_tls = true;
- f->use_root_regions = true;
- f->use_unaligned = false;
- f->use_poisoned = false;
- f->log_pointers = false;
- f->log_threads = false;
+ FlagParser parser;
+ RegisterLsanFlags(&parser, f);
+ RegisterCommonFlags(&parser);
- const char *options = GetEnv("LSAN_OPTIONS");
- if (options) {
- ParseFlag(options, &f->use_registers, "use_registers", "");
- ParseFlag(options, &f->use_globals, "use_globals", "");
- ParseFlag(options, &f->use_stacks, "use_stacks", "");
- ParseFlag(options, &f->use_tls, "use_tls", "");
- ParseFlag(options, &f->use_root_regions, "use_root_regions", "");
- ParseFlag(options, &f->use_unaligned, "use_unaligned", "");
- ParseFlag(options, &f->use_poisoned, "use_poisoned", "");
- ParseFlag(options, &f->report_objects, "report_objects", "");
- ParseFlag(options, &f->resolution, "resolution", "");
- CHECK_GE(&f->resolution, 0);
- ParseFlag(options, &f->max_leaks, "max_leaks", "");
- CHECK_GE(&f->max_leaks, 0);
- ParseFlag(options, &f->log_pointers, "log_pointers", "");
- ParseFlag(options, &f->log_threads, "log_threads", "");
- ParseFlag(options, &f->exitcode, "exitcode", "");
- }
+ f->SetDefaults();
// Set defaults for common flags (only in standalone mode) and parse
// them from LSAN_OPTIONS.
- CommonFlags *cf = common_flags();
if (standalone) {
- SetCommonFlagsDefaults(cf);
- cf->external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
- cf->malloc_context_size = 30;
- cf->detect_leaks = true;
+ SetCommonFlagsDefaults();
+ CommonFlags cf;
+ cf.CopyFrom(*common_flags());
+ cf.external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
+ cf.malloc_context_size = 30;
+ cf.detect_leaks = true;
+ OverrideCommonFlags(cf);
}
- ParseCommonFlagsFromString(cf, options);
+
+ bool help_before = common_flags()->help;
+
+ const char *options = GetEnv("LSAN_OPTIONS");
+ parser.ParseString(options);
+
+ SetVerbosity(common_flags()->verbosity);
+
+ if (Verbosity()) ReportUnrecognizedFlags();
+
+ if (!help_before && common_flags()->help)
+ parser.PrintFlagDescriptions();
}
#define LOG_POINTERS(...) \
@@ -367,7 +366,7 @@ static void CollectLeaksCb(uptr chunk, void *arg) {
LsanMetadata m(chunk);
if (!m.allocated()) return;
if (m.tag() == kDirectlyLeaked || m.tag() == kIndirectlyLeaked) {
- uptr resolution = flags()->resolution;
+ u32 resolution = flags()->resolution;
u32 stack_trace_id = 0;
if (resolution > 0) {
StackTrace stack = StackDepotGet(m.stack_trace_id());
diff --git a/lib/lsan/lsan_common.h b/lib/lsan/lsan_common.h
index 86ff12da6e0fb..64cbef38c7a68 100644
--- a/lib/lsan/lsan_common.h
+++ b/lib/lsan/lsan_common.h
@@ -38,40 +38,14 @@ enum ChunkTag {
};
struct Flags {
+#define LSAN_FLAG(Type, Name, DefaultValue, Description) Type Name;
+#include "lsan_flags.inc"
+#undef LSAN_FLAG
+
+ void SetDefaults();
uptr pointer_alignment() const {
return use_unaligned ? 1 : sizeof(uptr);
}
-
- // Print addresses of leaked objects after main leak report.
- bool report_objects;
- // Aggregate two objects into one leak if this many stack frames match. If
- // zero, the entire stack trace must match.
- int resolution;
- // The number of leaks reported.
- int max_leaks;
- // If nonzero kill the process with this exit code upon finding leaks.
- int exitcode;
-
- // Flags controlling the root set of reachable memory.
- // Global variables (.data and .bss).
- bool use_globals;
- // Thread stacks.
- bool use_stacks;
- // Thread registers.
- bool use_registers;
- // TLS and thread-specific storage.
- bool use_tls;
- // Regions added via __lsan_register_root_region().
- bool use_root_regions;
-
- // Consider unaligned pointers valid.
- bool use_unaligned;
- // Consider pointers found in poisoned memory to be valid.
- bool use_poisoned;
-
- // Debug logging.
- bool log_pointers;
- bool log_threads;
};
extern Flags lsan_flags;
diff --git a/lib/lsan/lsan_flags.inc b/lib/lsan/lsan_flags.inc
new file mode 100644
index 0000000000000..7f00acbf91194
--- /dev/null
+++ b/lib/lsan/lsan_flags.inc
@@ -0,0 +1,44 @@
+//===-- lsan_flags.inc ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// LSan runtime flags.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LSAN_FLAG
+# error "Define LSAN_FLAG prior to including this file!"
+#endif
+
+// LSAN_FLAG(Type, Name, DefaultValue, Description)
+// See COMMON_FLAG in sanitizer_flags.inc for more details.
+
+LSAN_FLAG(bool, report_objects, false,
+ "Print addresses of leaked objects after main leak report.")
+LSAN_FLAG(
+ int, resolution, 0,
+ "Aggregate two objects into one leak if this many stack frames match. If "
+ "zero, the entire stack trace must match.")
+LSAN_FLAG(int, max_leaks, 0, "The number of leaks reported.")
+LSAN_FLAG(int, exitcode, 23,
+ "If nonzero kill the process with this exit code upon finding leaks.")
+
+// Flags controlling the root set of reachable memory.
+LSAN_FLAG(bool, use_globals, true,
+ "Root set: include global variables (.data and .bss)")
+LSAN_FLAG(bool, use_stacks, true, "Root set: include thread stacks")
+LSAN_FLAG(bool, use_registers, true, "Root set: include thread registers")
+LSAN_FLAG(bool, use_tls, true,
+ "Root set: include TLS and thread-specific storage")
+LSAN_FLAG(bool, use_root_regions, true,
+ "Root set: include regions added via __lsan_register_root_region().")
+
+LSAN_FLAG(bool, use_unaligned, false, "Consider unaligned pointers valid.")
+LSAN_FLAG(bool, use_poisoned, false,
+ "Consider pointers found in poisoned memory to be valid.")
+LSAN_FLAG(bool, log_pointers, false, "Debug logging")
+LSAN_FLAG(bool, log_threads, false, "Debug logging")