xref: /freebsd/contrib/llvm-project/compiler-rt/lib/lsan/lsan.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
1 //=-- lsan.cpp ------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of LeakSanitizer.
10 // Standalone LSan RTL.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "lsan.h"
15 
16 #include "sanitizer_common/sanitizer_flags.h"
17 #include "sanitizer_common/sanitizer_flag_parser.h"
18 #include "lsan_allocator.h"
19 #include "lsan_common.h"
20 #include "lsan_thread.h"
21 
22 bool lsan_inited;
23 bool lsan_init_is_running;
24 
25 namespace __lsan {
26 
27 ///// Interface to the common LSan module. /////
28 bool WordIsPoisoned(uptr addr) {
29   return false;
30 }
31 
32 }  // namespace __lsan
33 
34 void __sanitizer::BufferedStackTrace::UnwindImpl(
35     uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
36   using namespace __lsan;
37   uptr stack_top = 0, stack_bottom = 0;
38   ThreadContext *t;
39   if (StackTrace::WillUseFastUnwind(request_fast) &&
40       (t = CurrentThreadContext())) {
41     stack_top = t->stack_end();
42     stack_bottom = t->stack_begin();
43   }
44   if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) {
45     if (StackTrace::WillUseFastUnwind(request_fast))
46       Unwind(max_depth, pc, bp, nullptr, stack_top, stack_bottom, true);
47     else
48       Unwind(max_depth, pc, 0, context, 0, 0, false);
49   }
50 }
51 
52 using namespace __lsan;
53 
54 static void InitializeFlags() {
55   // Set all the default values.
56   SetCommonFlagsDefaults();
57   {
58     CommonFlags cf;
59     cf.CopyFrom(*common_flags());
60     cf.external_symbolizer_path = GetEnv("LSAN_SYMBOLIZER_PATH");
61     cf.malloc_context_size = 30;
62     cf.intercept_tls_get_addr = true;
63     cf.detect_leaks = true;
64     cf.exitcode = 23;
65     OverrideCommonFlags(cf);
66   }
67 
68   Flags *f = flags();
69   f->SetDefaults();
70 
71   FlagParser parser;
72   RegisterLsanFlags(&parser, f);
73   RegisterCommonFlags(&parser);
74 
75   // Override from user-specified string.
76   const char *lsan_default_options = MaybeCallLsanDefaultOptions();
77   parser.ParseString(lsan_default_options);
78   parser.ParseStringFromEnv("LSAN_OPTIONS");
79 
80   SetVerbosity(common_flags()->verbosity);
81 
82   if (Verbosity()) ReportUnrecognizedFlags();
83 
84   if (common_flags()->help) parser.PrintFlagDescriptions();
85 
86   __sanitizer_set_report_path(common_flags()->log_path);
87 }
88 
89 extern "C" void __lsan_init() {
90   CHECK(!lsan_init_is_running);
91   if (lsan_inited)
92     return;
93   lsan_init_is_running = true;
94   SanitizerToolName = "LeakSanitizer";
95   CacheBinaryName();
96   AvoidCVE_2016_2143();
97   InitializeFlags();
98   InitCommonLsan();
99   InitializeAllocator();
100   ReplaceSystemMalloc();
101   InitTlsSize();
102   InitializeInterceptors();
103   InitializeThreadRegistry();
104   InstallDeadlySignalHandlers(LsanOnDeadlySignal);
105   InitializeMainThread();
106 
107   if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
108     Atexit(DoLeakCheck);
109 
110   InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
111 
112   lsan_inited = true;
113   lsan_init_is_running = false;
114 }
115 
116 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
117 void __sanitizer_print_stack_trace() {
118   GET_STACK_TRACE_FATAL;
119   stack.Print();
120 }
121