Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 1 | //===-- sanitizer_symbolize.cpp ---------------------------------*- C++ -*-===// |
| 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 | // Implementation of weak hooks from sanitizer_symbolizer_posix_libcdep.cpp. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include <stdio.h> |
Thiébaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 14 | |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 15 | #include <string> |
| 16 | |
| 17 | #include "llvm/DebugInfo/Symbolize/DIPrinter.h" |
| 18 | #include "llvm/DebugInfo/Symbolize/Symbolize.h" |
| 19 | |
| 20 | static llvm::symbolize::LLVMSymbolizer *getDefaultSymbolizer() { |
| 21 | static llvm::symbolize::LLVMSymbolizer *DefaultSymbolizer = |
| 22 | new llvm::symbolize::LLVMSymbolizer(); |
| 23 | return DefaultSymbolizer; |
| 24 | } |
| 25 | |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 26 | static llvm::symbolize::PrinterConfig getDefaultPrinterConfig() { |
| 27 | llvm::symbolize::PrinterConfig Config; |
| 28 | Config.Pretty = false; |
| 29 | Config.Verbose = false; |
| 30 | Config.PrintFunctions = true; |
| 31 | Config.PrintAddress = false; |
| 32 | Config.SourceContextLines = 0; |
| 33 | return Config; |
| 34 | } |
| 35 | |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 36 | namespace __sanitizer { |
| 37 | int internal_snprintf(char *buffer, unsigned long length, const char *format, |
| 38 | ...); |
| 39 | } // namespace __sanitizer |
| 40 | |
| 41 | extern "C" { |
| 42 | |
| 43 | typedef uint64_t u64; |
| 44 | |
| 45 | bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset, |
Thiébaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 46 | char *Buffer, int MaxLength, |
| 47 | bool SymbolizeInlineFrames) { |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 48 | std::string Result; |
| 49 | { |
| 50 | llvm::raw_string_ostream OS(Result); |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 51 | llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig(); |
| 52 | llvm::symbolize::Request Request{ModuleName, ModuleOffset}; |
| 53 | auto Printer = |
| 54 | std::make_unique<llvm::symbolize::LLVMPrinter>(OS, OS, Config); |
| 55 | |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 56 | // TODO: it is neccessary to set proper SectionIndex here. |
| 57 | // object::SectionedAddress::UndefSection works for only absolute addresses. |
Thiébaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 58 | if (SymbolizeInlineFrames) { |
| 59 | auto ResOrErr = getDefaultSymbolizer()->symbolizeInlinedCode( |
| 60 | ModuleName, |
| 61 | {ModuleOffset, llvm::object::SectionedAddress::UndefSection}); |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 62 | Printer->print(Request, |
| 63 | ResOrErr ? ResOrErr.get() : llvm::DIInliningInfo()); |
Thiébaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 64 | } else { |
| 65 | auto ResOrErr = getDefaultSymbolizer()->symbolizeCode( |
| 66 | ModuleName, |
| 67 | {ModuleOffset, llvm::object::SectionedAddress::UndefSection}); |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 68 | Printer->print(Request, ResOrErr ? ResOrErr.get() : llvm::DILineInfo()); |
Thiébaud Weksteen | e40e736 | 2020-10-28 15:03:00 +0100 | [diff] [blame] | 69 | } |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 70 | } |
| 71 | return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s", |
| 72 | Result.c_str()) < MaxLength; |
| 73 | } |
| 74 | |
| 75 | bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset, |
| 76 | char *Buffer, int MaxLength) { |
| 77 | std::string Result; |
| 78 | { |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 79 | llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig(); |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 80 | llvm::raw_string_ostream OS(Result); |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 81 | llvm::symbolize::Request Request{ModuleName, ModuleOffset}; |
| 82 | auto Printer = |
| 83 | std::make_unique<llvm::symbolize::LLVMPrinter>(OS, OS, Config); |
| 84 | |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 85 | // TODO: it is neccessary to set proper SectionIndex here. |
| 86 | // object::SectionedAddress::UndefSection works for only absolute addresses. |
| 87 | auto ResOrErr = getDefaultSymbolizer()->symbolizeData( |
| 88 | ModuleName, |
| 89 | {ModuleOffset, llvm::object::SectionedAddress::UndefSection}); |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 90 | Printer->print(Request, ResOrErr ? ResOrErr.get() : llvm::DIGlobal()); |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 91 | } |
| 92 | return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s", |
| 93 | Result.c_str()) < MaxLength; |
| 94 | } |
| 95 | |
| 96 | void __sanitizer_symbolize_flush() { getDefaultSymbolizer()->flush(); } |
| 97 | |
| 98 | int __sanitizer_symbolize_demangle(const char *Name, char *Buffer, |
| 99 | int MaxLength) { |
| 100 | std::string Result = |
| 101 | llvm::symbolize::LLVMSymbolizer::DemangleName(Name, nullptr); |
| 102 | return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s", |
| 103 | Result.c_str()) < MaxLength |
| 104 | ? static_cast<int>(Result.size() + 1) |
| 105 | : 0; |
| 106 | } |
| 107 | |
Chris Wailes | bcf972c | 2021-10-21 11:03:28 -0700 | [diff] [blame^] | 108 | // Override __cxa_atexit and ignore callbacks. |
| 109 | // This prevents crashes in a configuration when the symbolizer |
| 110 | // is built into sanitizer runtime and consequently into the test process. |
| 111 | // LLVM libraries have some global objects destroyed during exit, |
| 112 | // so if the test process triggers any bugs after that, the symbolizer crashes. |
| 113 | // An example stack trace of such crash: |
| 114 | // |
| 115 | // #1 __cxa_throw |
| 116 | // #2 std::__u::__throw_system_error |
| 117 | // #3 std::__u::recursive_mutex::lock |
| 118 | // #4 __sanitizer_llvm::ManagedStaticBase::RegisterManagedStatic |
| 119 | // #5 __sanitizer_llvm::errorToErrorCode |
| 120 | // #6 __sanitizer_llvm::getFileAux |
| 121 | // #7 __sanitizer_llvm::MemoryBuffer::getFileOrSTDIN |
| 122 | // #10 __sanitizer_llvm::symbolize::LLVMSymbolizer::getOrCreateModuleInfo |
| 123 | // #13 __sanitizer::Symbolizer::SymbolizeData |
| 124 | // #14 __tsan::SymbolizeData |
| 125 | // #16 __tsan::ReportRace |
| 126 | // #18 __tsan_write4 |
| 127 | // #19 race() () at test/tsan/atexit4.cpp |
| 128 | // #20 cxa_at_exit_wrapper |
| 129 | // #21 __cxa_finalize |
| 130 | // #22 __do_fini |
| 131 | // |
| 132 | // For the standalone llvm-symbolizer this does not hurt, |
| 133 | // we just don't destroy few global objects on exit. |
| 134 | int __cxa_atexit(void (*f)(void *a), void *arg, void *dso) { return 0; } |
| 135 | |
Jeff Vander Stoep | 247d86b | 2020-08-11 14:27:44 +0200 | [diff] [blame] | 136 | } // extern "C" |