1 //===-- sanitizer_symbolize.cpp ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Implementation of weak hooks from sanitizer_symbolizer_posix_libcdep.cpp.
11 //===----------------------------------------------------------------------===//
17 #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
18 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
20 static llvm::symbolize::LLVMSymbolizer
*Symbolizer
= nullptr;
21 static bool Demangle
= true;
22 static bool InlineFrames
= true;
24 static llvm::symbolize::LLVMSymbolizer
*getDefaultSymbolizer() {
27 llvm::symbolize::LLVMSymbolizer::Options Opts
;
28 Opts
.Demangle
= Demangle
;
29 Symbolizer
= new llvm::symbolize::LLVMSymbolizer(Opts
);
33 static llvm::symbolize::PrinterConfig
getDefaultPrinterConfig() {
34 llvm::symbolize::PrinterConfig Config
;
35 Config
.Pretty
= false;
36 Config
.Verbose
= false;
37 Config
.PrintFunctions
= true;
38 Config
.PrintAddress
= false;
39 Config
.SourceContextLines
= 0;
43 namespace __sanitizer
{
44 int internal_snprintf(char *buffer
, unsigned long length
, const char *format
,
46 } // namespace __sanitizer
52 bool __sanitizer_symbolize_code(const char *ModuleName
, uint64_t ModuleOffset
,
53 char *Buffer
, int MaxLength
) {
56 llvm::raw_string_ostream
OS(Result
);
57 llvm::symbolize::PrinterConfig Config
= getDefaultPrinterConfig();
58 llvm::symbolize::Request Request
{ModuleName
, ModuleOffset
};
60 std::make_unique
<llvm::symbolize::LLVMPrinter
>(OS
, OS
, Config
);
62 // TODO: it is neccessary to set proper SectionIndex here.
63 // object::SectionedAddress::UndefSection works for only absolute addresses.
65 auto ResOrErr
= getDefaultSymbolizer()->symbolizeInlinedCode(
67 {ModuleOffset
, llvm::object::SectionedAddress::UndefSection
});
68 Printer
->print(Request
,
69 ResOrErr
? ResOrErr
.get() : llvm::DIInliningInfo());
71 auto ResOrErr
= getDefaultSymbolizer()->symbolizeCode(
73 {ModuleOffset
, llvm::object::SectionedAddress::UndefSection
});
74 Printer
->print(Request
, ResOrErr
? ResOrErr
.get() : llvm::DILineInfo());
77 return __sanitizer::internal_snprintf(Buffer
, MaxLength
, "%s",
78 Result
.c_str()) < MaxLength
;
81 bool __sanitizer_symbolize_data(const char *ModuleName
, uint64_t ModuleOffset
,
82 char *Buffer
, int MaxLength
) {
85 llvm::symbolize::PrinterConfig Config
= getDefaultPrinterConfig();
86 llvm::raw_string_ostream
OS(Result
);
87 llvm::symbolize::Request Request
{ModuleName
, ModuleOffset
};
89 std::make_unique
<llvm::symbolize::LLVMPrinter
>(OS
, OS
, Config
);
91 // TODO: it is neccessary to set proper SectionIndex here.
92 // object::SectionedAddress::UndefSection works for only absolute addresses.
93 auto ResOrErr
= getDefaultSymbolizer()->symbolizeData(
95 {ModuleOffset
, llvm::object::SectionedAddress::UndefSection
});
96 Printer
->print(Request
, ResOrErr
? ResOrErr
.get() : llvm::DIGlobal());
98 return __sanitizer::internal_snprintf(Buffer
, MaxLength
, "%s",
99 Result
.c_str()) < MaxLength
;
102 void __sanitizer_symbolize_flush() {
107 int __sanitizer_symbolize_demangle(const char *Name
, char *Buffer
,
110 llvm::symbolize::LLVMSymbolizer::DemangleName(Name
, nullptr);
111 return __sanitizer::internal_snprintf(Buffer
, MaxLength
, "%s",
112 Result
.c_str()) < MaxLength
113 ? static_cast<int>(Result
.size() + 1)
117 bool __sanitizer_symbolize_set_demangle(bool Value
) {
118 // Must be called before LLVMSymbolizer created.
125 bool __sanitizer_symbolize_set_inline_frames(bool Value
) {
126 InlineFrames
= Value
;
130 // Override __cxa_atexit and ignore callbacks.
131 // This prevents crashes in a configuration when the symbolizer
132 // is built into sanitizer runtime and consequently into the test process.
133 // LLVM libraries have some global objects destroyed during exit,
134 // so if the test process triggers any bugs after that, the symbolizer crashes.
135 // An example stack trace of such crash:
138 // #2 std::__u::__throw_system_error
139 // #3 std::__u::recursive_mutex::lock
140 // #4 __sanitizer_llvm::ManagedStaticBase::RegisterManagedStatic
141 // #5 __sanitizer_llvm::errorToErrorCode
142 // #6 __sanitizer_llvm::getFileAux
143 // #7 __sanitizer_llvm::MemoryBuffer::getFileOrSTDIN
144 // #10 __sanitizer_llvm::symbolize::LLVMSymbolizer::getOrCreateModuleInfo
145 // #13 __sanitizer::Symbolizer::SymbolizeData
146 // #14 __tsan::SymbolizeData
147 // #16 __tsan::ReportRace
149 // #19 race() () at test/tsan/atexit4.cpp
150 // #20 cxa_at_exit_wrapper
151 // #21 __cxa_finalize
154 // For the standalone llvm-symbolizer this does not hurt,
155 // we just don't destroy few global objects on exit.
156 int __cxa_atexit(void (*f
)(void *a
), void *arg
, void *dso
) { return 0; }