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