brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · c851dbb Raw
198 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Implementation of weak hooks from sanitizer_symbolizer_posix_libcdep.cpp.10//11//===----------------------------------------------------------------------===//12 13#include <inttypes.h>14#include <stdio.h>15 16#include <string>17 18#include "llvm/DebugInfo/Symbolize/DIPrinter.h"19#include "llvm/DebugInfo/Symbolize/Symbolize.h"20#include "llvm/Demangle/Demangle.h"21 22static llvm::symbolize::LLVMSymbolizer *Symbolizer = nullptr;23static bool Demangle = true;24static bool InlineFrames = true;25 26static llvm::symbolize::LLVMSymbolizer *getDefaultSymbolizer() {27  if (Symbolizer)28    return Symbolizer;29  llvm::symbolize::LLVMSymbolizer::Options Opts;30  Opts.Demangle = Demangle;31  Opts.UntagAddresses = true;32  Symbolizer = new llvm::symbolize::LLVMSymbolizer(Opts);33  return Symbolizer;34}35 36static llvm::symbolize::PrinterConfig getDefaultPrinterConfig() {37  llvm::symbolize::PrinterConfig Config;38  Config.Pretty = false;39  Config.Verbose = false;40  Config.PrintFunctions = true;41  Config.PrintAddress = false;42  Config.SourceContextLines = 0;43  return Config;44}45 46static llvm::symbolize::ErrorHandler symbolize_error_handler(47    llvm::raw_string_ostream &OS) {48  return49      [&](const llvm::ErrorInfoBase &ErrorInfo, llvm::StringRef ErrorBanner) {50        OS << ErrorBanner;51        ErrorInfo.log(OS);52        OS << '\n';53      };54}55 56namespace __sanitizer {57int internal_snprintf(char *buffer, uintptr_t length, const char *format, ...);58}  // namespace __sanitizer59 60extern "C" {61 62typedef uint64_t u64;63 64bool __sanitizer_symbolize_code(const char *ModuleName, uint64_t ModuleOffset,65                                char *Buffer, int MaxLength) {66  std::string Result;67  {68    llvm::raw_string_ostream OS(Result);69    llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig();70    llvm::symbolize::Request Request{ModuleName, ModuleOffset};71    auto Printer = std::make_unique<llvm::symbolize::LLVMPrinter>(72        OS, symbolize_error_handler(OS), Config);73 74    // TODO: it is necessary to set proper SectionIndex here.75    // object::SectionedAddress::UndefSection works for only absolute addresses.76    if (InlineFrames) {77      auto ResOrErr = getDefaultSymbolizer()->symbolizeInlinedCode(78          ModuleName,79          {ModuleOffset, llvm::object::SectionedAddress::UndefSection});80      if (!ResOrErr)81        return false;82      Printer->print(Request, ResOrErr.get());83    } else {84      auto ResOrErr = getDefaultSymbolizer()->symbolizeCode(85          ModuleName,86          {ModuleOffset, llvm::object::SectionedAddress::UndefSection});87      if (!ResOrErr)88        return false;89      Printer->print(Request, ResOrErr.get());90    }91  }92  return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",93                                        Result.c_str()) < MaxLength;94}95 96bool __sanitizer_symbolize_data(const char *ModuleName, uint64_t ModuleOffset,97                                char *Buffer, int MaxLength) {98  std::string Result;99  {100    llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig();101    llvm::raw_string_ostream OS(Result);102    llvm::symbolize::Request Request{ModuleName, ModuleOffset};103    auto Printer = std::make_unique<llvm::symbolize::LLVMPrinter>(104        OS, symbolize_error_handler(OS), Config);105 106    // TODO: it is necessary to set proper SectionIndex here.107    // object::SectionedAddress::UndefSection works for only absolute addresses.108    auto ResOrErr = getDefaultSymbolizer()->symbolizeData(109        ModuleName,110        {ModuleOffset, llvm::object::SectionedAddress::UndefSection});111    if (!ResOrErr)112      return false;113    Printer->print(Request, ResOrErr.get());114  }115  return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",116                                        Result.c_str()) < MaxLength;117}118 119bool __sanitizer_symbolize_frame(const char *ModuleName, uint64_t ModuleOffset,120                                 char *Buffer, int MaxLength) {121  std::string Result;122  {123    llvm::symbolize::PrinterConfig Config = getDefaultPrinterConfig();124    llvm::raw_string_ostream OS(Result);125    llvm::symbolize::Request Request{ModuleName, ModuleOffset};126    auto Printer = std::make_unique<llvm::symbolize::LLVMPrinter>(127        OS, symbolize_error_handler(OS), Config);128 129    // TODO: it is necessary to set proper SectionIndex here.130    // object::SectionedAddress::UndefSection works for only absolute addresses.131    auto ResOrErr = getDefaultSymbolizer()->symbolizeFrame(132        ModuleName,133        {ModuleOffset, llvm::object::SectionedAddress::UndefSection});134    if (!ResOrErr)135      return false;136    Printer->print(Request, ResOrErr.get());137  }138  return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",139                                        Result.c_str()) < MaxLength;140}141 142void __sanitizer_symbolize_flush() {143  if (Symbolizer)144    Symbolizer->flush();145}146 147bool __sanitizer_symbolize_demangle(const char *Name, char *Buffer,148                                    int MaxLength) {149  std::string Result;150  if (!llvm::nonMicrosoftDemangle(Name, Result))151    return false;152  return __sanitizer::internal_snprintf(Buffer, MaxLength, "%s",153                                        Result.c_str()) < MaxLength;154}155 156bool __sanitizer_symbolize_set_demangle(bool Value) {157  // Must be called before LLVMSymbolizer created.158  if (Symbolizer)159    return false;160  Demangle = Value;161  return true;162}163 164bool __sanitizer_symbolize_set_inline_frames(bool Value) {165  InlineFrames = Value;166  return true;167}168 169// Override __cxa_atexit and ignore callbacks.170// This prevents crashes in a configuration when the symbolizer171// is built into sanitizer runtime and consequently into the test process.172// LLVM libraries have some global objects destroyed during exit,173// so if the test process triggers any bugs after that, the symbolizer crashes.174// An example stack trace of such crash:175//176// #1  __cxa_throw177// #2  std::__u::__throw_system_error178// #3  std::__u::recursive_mutex::lock179// #4  __sanitizer_llvm::ManagedStaticBase::RegisterManagedStatic180// #5  __sanitizer_llvm::errorToErrorCode181// #6  __sanitizer_llvm::getFileAux182// #7  __sanitizer_llvm::MemoryBuffer::getFileOrSTDIN183// #10 __sanitizer_llvm::symbolize::LLVMSymbolizer::getOrCreateModuleInfo184// #13 __sanitizer::Symbolizer::SymbolizeData185// #14 __tsan::SymbolizeData186// #16 __tsan::ReportRace187// #18 __tsan_write4188// #19 race() () at test/tsan/atexit4.cpp189// #20 cxa_at_exit_wrapper190// #21 __cxa_finalize191// #22 __do_fini192//193// For the standalone llvm-symbolizer this does not hurt,194// we just don't destroy few global objects on exit.195int __cxa_atexit(void (*f)(void *a), void *arg, void *dso) { return 0; }196 197}  // extern "C"198