LCOV - code coverage report
Current view: top level - lib/Support - Signals.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 3 66 4.5 %
Date: 2017-09-14 15:23:50 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file defines some helpful functions for dealing with the possibility of
      11             : // Unix signals occurring while your program is running.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/Support/Signals.h"
      16             : #include "llvm/ADT/STLExtras.h"
      17             : #include "llvm/ADT/StringRef.h"
      18             : #include "llvm/Config/config.h"
      19             : #include "llvm/Support/ErrorOr.h"
      20             : #include "llvm/Support/FileSystem.h"
      21             : #include "llvm/Support/FileUtilities.h"
      22             : #include "llvm/Support/Format.h"
      23             : #include "llvm/Support/ManagedStatic.h"
      24             : #include "llvm/Support/MemoryBuffer.h"
      25             : #include "llvm/Support/Mutex.h"
      26             : #include "llvm/Support/Program.h"
      27             : #include "llvm/Support/StringSaver.h"
      28             : #include "llvm/Support/raw_ostream.h"
      29             : #include "llvm/Support/Options.h"
      30             : #include <vector>
      31             : 
      32             : //===----------------------------------------------------------------------===//
      33             : //=== WARNING: Implementation here must contain only TRULY operating system
      34             : //===          independent code.
      35             : //===----------------------------------------------------------------------===//
      36             : 
      37             : using namespace llvm;
      38             : 
      39             : static cl::opt<bool>
      40      121345 :     DisableSymbolication("disable-symbolication",
      41      364035 :                          cl::desc("Disable symbolizing crash backtraces."),
      42      485380 :                          cl::init(false), cl::Hidden);
      43             : 
      44             : static ManagedStatic<std::vector<std::pair<void (*)(void *), void *>>>
      45             :     CallBacksToRun;
      46           0 : void sys::RunSignalHandlers() {
      47           0 :   if (!CallBacksToRun.isConstructed())
      48             :     return;
      49           0 :   for (auto &I : *CallBacksToRun)
      50           0 :     I.first(I.second);
      51           0 :   CallBacksToRun->clear();
      52             : }
      53             : 
      54             : static bool findModulesAndOffsets(void **StackTrace, int Depth,
      55             :                                   const char **Modules, intptr_t *Offsets,
      56             :                                   const char *MainExecutableName,
      57             :                                   StringSaver &StrPool);
      58             : 
      59             : /// Format a pointer value as hexadecimal. Zero pad it out so its always the
      60             : /// same width.
      61             : static FormattedNumber format_ptr(void *PC) {
      62             :   // Each byte is two hex digits plus 2 for the 0x prefix.
      63           0 :   unsigned PtrWidth = 2 + 2 * sizeof(void *);
      64           0 :   return format_hex((uint64_t)PC, PtrWidth);
      65             : }
      66             : 
      67             : static bool printSymbolizedStackTrace(StringRef Argv0,
      68             :                                       void **StackTrace, int Depth,
      69             :                                       llvm::raw_ostream &OS)
      70             :   LLVM_ATTRIBUTE_USED;
      71             : 
      72             : /// Helper that launches llvm-symbolizer and symbolizes a backtrace.
      73           0 : static bool printSymbolizedStackTrace(StringRef Argv0,
      74             :                                       void **StackTrace, int Depth,
      75             :                                       llvm::raw_ostream &OS) {
      76           0 :   if (DisableSymbolication)
      77             :     return false;
      78             : 
      79             :   // Don't recursively invoke the llvm-symbolizer binary.
      80           0 :   if (Argv0.find("llvm-symbolizer") != std::string::npos)
      81             :     return false;
      82             : 
      83             :   // FIXME: Subtract necessary number from StackTrace entries to turn return addresses
      84             :   // into actual instruction addresses.
      85             :   // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
      86             :   // alongside our binary, then in $PATH.
      87           0 :   ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
      88           0 :   if (!Argv0.empty()) {
      89           0 :     StringRef Parent = llvm::sys::path::parent_path(Argv0);
      90           0 :     if (!Parent.empty())
      91           0 :       LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
      92             :   }
      93           0 :   if (!LLVMSymbolizerPathOrErr)
      94           0 :     LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
      95           0 :   if (!LLVMSymbolizerPathOrErr)
      96             :     return false;
      97           0 :   const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
      98             : 
      99             :   // If we don't know argv0 or the address of main() at this point, try
     100             :   // to guess it anyway (it's possible on some platforms).
     101             :   std::string MainExecutableName =
     102           0 :       Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr)
     103           0 :                     : (std::string)Argv0;
     104           0 :   BumpPtrAllocator Allocator;
     105           0 :   StringSaver StrPool(Allocator);
     106           0 :   std::vector<const char *> Modules(Depth, nullptr);
     107           0 :   std::vector<intptr_t> Offsets(Depth, 0);
     108           0 :   if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(),
     109             :                              MainExecutableName.c_str(), StrPool))
     110             :     return false;
     111             :   int InputFD;
     112           0 :   SmallString<32> InputFile, OutputFile;
     113           0 :   sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile);
     114           0 :   sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
     115           0 :   FileRemover InputRemover(InputFile.c_str());
     116           0 :   FileRemover OutputRemover(OutputFile.c_str());
     117             : 
     118             :   {
     119           0 :     raw_fd_ostream Input(InputFD, true);
     120           0 :     for (int i = 0; i < Depth; i++) {
     121           0 :       if (Modules[i])
     122           0 :         Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
     123             :     }
     124             :   }
     125             : 
     126           0 :   Optional<StringRef> Redirects[] = {InputFile.str(), OutputFile.str(), llvm::None};
     127           0 :   const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
     128             : #ifdef LLVM_ON_WIN32
     129             :                         // Pass --relative-address on Windows so that we don't
     130             :                         // have to add ImageBase from PE file.
     131             :                         // FIXME: Make this the default for llvm-symbolizer.
     132             :                         "--relative-address",
     133             : #endif
     134             :                         "--demangle", nullptr};
     135             :   int RunResult =
     136           0 :       sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
     137           0 :   if (RunResult != 0)
     138             :     return false;
     139             : 
     140             :   // This report format is based on the sanitizer stack trace printer.  See
     141             :   // sanitizer_stacktrace_printer.cc in compiler-rt.
     142           0 :   auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
     143           0 :   if (!OutputBuf)
     144             :     return false;
     145           0 :   StringRef Output = OutputBuf.get()->getBuffer();
     146           0 :   SmallVector<StringRef, 32> Lines;
     147           0 :   Output.split(Lines, "\n");
     148           0 :   auto CurLine = Lines.begin();
     149           0 :   int frame_no = 0;
     150           0 :   for (int i = 0; i < Depth; i++) {
     151           0 :     if (!Modules[i]) {
     152           0 :       OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n';
     153           0 :       continue;
     154             :     }
     155             :     // Read pairs of lines (function name and file/line info) until we
     156             :     // encounter empty line.
     157             :     for (;;) {
     158           0 :       if (CurLine == Lines.end())
     159             :         return false;
     160           0 :       StringRef FunctionName = *CurLine++;
     161           0 :       if (FunctionName.empty())
     162             :         break;
     163           0 :       OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << ' ';
     164           0 :       if (!FunctionName.startswith("??"))
     165           0 :         OS << FunctionName << ' ';
     166           0 :       if (CurLine == Lines.end())
     167             :         return false;
     168           0 :       StringRef FileLineInfo = *CurLine++;
     169           0 :       if (!FileLineInfo.startswith("??"))
     170           0 :         OS << FileLineInfo;
     171             :       else
     172           0 :         OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")";
     173           0 :       OS << "\n";
     174           0 :     }
     175             :   }
     176             :   return true;
     177             : }
     178             : 
     179             : // Include the platform-specific parts of this class.
     180             : #ifdef LLVM_ON_UNIX
     181             : #include "Unix/Signals.inc"
     182             : #endif
     183             : #ifdef LLVM_ON_WIN32
     184             : #include "Windows/Signals.inc"
     185             : #endif

Generated by: LCOV version 1.13