1//=-- lsan.cc -------------------------------------------------------------===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file is a part of LeakSanitizer.
9// Standalone LSan RTL.
10//
11//===----------------------------------------------------------------------===//
12
13#include "lsan.h"
14
15#include "sanitizer_common/sanitizer_flags.h"
16#include "sanitizer_common/sanitizer_flag_parser.h"
17#include "sanitizer_common/sanitizer_stacktrace.h"
18#include "lsan_allocator.h"
19#include "lsan_common.h"
20#include "lsan_thread.h"
21
22bool lsan_inited;
23bool lsan_init_is_running;
24
25namespace __lsan {
26
27///// Interface to the common LSan module. /////
28bool WordIsPoisoned(uptr addr) {
29  return false;
30}
31
32}  // namespace __lsan
33
34using namespace __lsan;  // NOLINT
35
36static void InitializeFlags() {
37  // Set all the default values.
38  SetCommonFlagsDefaults();
39  {
40    CommonFlags cf;
41    cf.CopyFrom(*common_flags());
42    cf.external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
43    cf.malloc_context_size = 30;
44    cf.intercept_tls_get_addr = true;
45    cf.detect_leaks = true;
46    cf.exitcode = 23;
47    OverrideCommonFlags(cf);
48  }
49
50  Flags *f = flags();
51  f->SetDefaults();
52
53  FlagParser parser;
54  RegisterLsanFlags(&parser, f);
55  RegisterCommonFlags(&parser);
56
57  // Override from user-specified string.
58  const char *lsan_default_options = MaybeCallLsanDefaultOptions();
59  parser.ParseString(lsan_default_options);
60  parser.ParseString(GetEnv("LSAN_OPTIONS"));
61
62  SetVerbosity(common_flags()->verbosity);
63
64  if (Verbosity()) ReportUnrecognizedFlags();
65
66  if (common_flags()->help) parser.PrintFlagDescriptions();
67
68  __sanitizer_set_report_path(common_flags()->log_path);
69}
70
71static void OnStackUnwind(const SignalContext &sig, const void *,
72                          BufferedStackTrace *stack) {
73  GetStackTrace(stack, kStackTraceMax, sig.pc, sig.bp, sig.context,
74                common_flags()->fast_unwind_on_fatal);
75}
76
77static void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
78  HandleDeadlySignal(siginfo, context, GetCurrentThread(), &OnStackUnwind,
79                     nullptr);
80}
81
82extern "C" void __lsan_init() {
83  CHECK(!lsan_init_is_running);
84  if (lsan_inited)
85    return;
86  lsan_init_is_running = true;
87  SanitizerToolName = "LeakSanitizer";
88  CacheBinaryName();
89  AvoidCVE_2016_2143();
90  InitializeFlags();
91  InitCommonLsan();
92  InitializeAllocator();
93  ReplaceSystemMalloc();
94  InitTlsSize();
95  InitializeInterceptors();
96  InitializeThreadRegistry();
97  InstallDeadlySignalHandlers(LsanOnDeadlySignal);
98  u32 tid = ThreadCreate(0, 0, true);
99  CHECK_EQ(tid, 0);
100  ThreadStart(tid, GetTid());
101  SetCurrentThread(tid);
102
103  if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
104    Atexit(DoLeakCheck);
105
106  InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
107
108  lsan_inited = true;
109  lsan_init_is_running = false;
110}
111
112extern "C" SANITIZER_INTERFACE_ATTRIBUTE
113void __sanitizer_print_stack_trace() {
114  GET_STACK_TRACE_FATAL;
115  stack.Print();
116}
117