LLVM  4.0.0
Signals.cpp
Go to the documentation of this file.
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/ADT/STLExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Config/config.h"
18 #include "llvm/Support/ErrorOr.h"
21 #include "llvm/Support/Format.h"
24 #include "llvm/Support/Mutex.h"
25 #include "llvm/Support/Program.h"
26 #include "llvm/Support/Signals.h"
29 #include <vector>
30 
31 namespace llvm {
32 using namespace sys;
33 
34 //===----------------------------------------------------------------------===//
35 //=== WARNING: Implementation here must contain only TRULY operating system
36 //=== independent code.
37 //===----------------------------------------------------------------------===//
38 
42  if (!CallBacksToRun.isConstructed())
43  return;
44  for (auto &I : *CallBacksToRun)
45  I.first(I.second);
46  CallBacksToRun->clear();
47 }
48 }
49 
50 using namespace llvm;
51 
52 static bool findModulesAndOffsets(void **StackTrace, int Depth,
53  const char **Modules, intptr_t *Offsets,
54  const char *MainExecutableName,
55  StringSaver &StrPool);
56 
57 /// Format a pointer value as hexadecimal. Zero pad it out so its always the
58 /// same width.
59 static FormattedNumber format_ptr(void *PC) {
60  // Each byte is two hex digits plus 2 for the 0x prefix.
61  unsigned PtrWidth = 2 + 2 * sizeof(void *);
62  return format_hex((uint64_t)PC, PtrWidth);
63 }
64 
65 static bool printSymbolizedStackTrace(StringRef Argv0,
66  void **StackTrace, int Depth,
69 
70 /// Helper that launches llvm-symbolizer and symbolizes a backtrace.
72  void **StackTrace, int Depth,
73  llvm::raw_ostream &OS) {
74  // Don't recursively invoke the llvm-symbolizer binary.
75  if (Argv0.find("llvm-symbolizer") != std::string::npos)
76  return false;
77 
78  // FIXME: Subtract necessary number from StackTrace entries to turn return addresses
79  // into actual instruction addresses.
80  // Use llvm-symbolizer tool to symbolize the stack traces. First look for it
81  // alongside our binary, then in $PATH.
82  ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code();
83  if (!Argv0.empty()) {
85  if (!Parent.empty())
86  LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent);
87  }
88  if (!LLVMSymbolizerPathOrErr)
89  LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer");
90  if (!LLVMSymbolizerPathOrErr)
91  return false;
92  const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr;
93 
94  // If we don't know argv0 or the address of main() at this point, try
95  // to guess it anyway (it's possible on some platforms).
96  std::string MainExecutableName =
97  Argv0.empty() ? sys::fs::getMainExecutable(nullptr, nullptr)
98  : (std::string)Argv0;
100  StringSaver StrPool(Allocator);
101  std::vector<const char *> Modules(Depth, nullptr);
102  std::vector<intptr_t> Offsets(Depth, 0);
103  if (!findModulesAndOffsets(StackTrace, Depth, Modules.data(), Offsets.data(),
104  MainExecutableName.c_str(), StrPool))
105  return false;
106  int InputFD;
107  SmallString<32> InputFile, OutputFile;
108  sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile);
109  sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile);
110  FileRemover InputRemover(InputFile.c_str());
111  FileRemover OutputRemover(OutputFile.c_str());
112 
113  {
114  raw_fd_ostream Input(InputFD, true);
115  for (int i = 0; i < Depth; i++) {
116  if (Modules[i])
117  Input << Modules[i] << " " << (void*)Offsets[i] << "\n";
118  }
119  }
120 
121  StringRef InputFileStr(InputFile);
122  StringRef OutputFileStr(OutputFile);
123  StringRef StderrFileStr;
124  const StringRef *Redirects[] = {&InputFileStr, &OutputFileStr,
125  &StderrFileStr};
126  const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
127 #ifdef LLVM_ON_WIN32
128  // Pass --relative-address on Windows so that we don't
129  // have to add ImageBase from PE file.
130  // FIXME: Make this the default for llvm-symbolizer.
131  "--relative-address",
132 #endif
133  "--demangle", nullptr};
134  int RunResult =
135  sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
136  if (RunResult != 0)
137  return false;
138 
139  // This report format is based on the sanitizer stack trace printer. See
140  // sanitizer_stacktrace_printer.cc in compiler-rt.
141  auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str());
142  if (!OutputBuf)
143  return false;
144  StringRef Output = OutputBuf.get()->getBuffer();
146  Output.split(Lines, "\n");
147  auto CurLine = Lines.begin();
148  int frame_no = 0;
149  for (int i = 0; i < Depth; i++) {
150  if (!Modules[i]) {
151  OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n';
152  continue;
153  }
154  // Read pairs of lines (function name and file/line info) until we
155  // encounter empty line.
156  for (;;) {
157  if (CurLine == Lines.end())
158  return false;
159  StringRef FunctionName = *CurLine++;
160  if (FunctionName.empty())
161  break;
162  OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << ' ';
163  if (!FunctionName.startswith("??"))
164  OS << FunctionName << ' ';
165  if (CurLine == Lines.end())
166  return false;
167  StringRef FileLineInfo = *CurLine++;
168  if (!FileLineInfo.startswith("??"))
169  OS << FileLineInfo;
170  else
171  OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")";
172  OS << "\n";
173  }
174  }
175  return true;
176 }
177 
178 // Include the platform-specific parts of this class.
179 #ifdef LLVM_ON_UNIX
180 #include "Unix/Signals.inc"
181 #endif
182 #ifdef LLVM_ON_WIN32
183 #include "Windows/Signals.inc"
184 #endif
Represents either an error or a value T.
Definition: ErrorOr.h:68
size_t i
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition: Format.h:177
Offsets
Offsets in bytes from the start of the input buffer.
Definition: SIInstrInfo.h:777
static FILE * OutputFile
Definition: FuzzerIO.cpp:24
static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, const char *MainExecutableName, StringSaver &StrPool)
FileRemover - This class is a simple object meant to be stack allocated.
Definition: FileUtilities.h:40
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:264
int ExecuteAndWait(StringRef Program, const char **args, const char **env=nullptr, const StringRef **redirects=nullptr, unsigned secondsToWait=0, unsigned memoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr)
This function executes the program using the arguments provided.
Definition: Program.cpp:30
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
void RunSignalHandlers()
Definition: Signals.cpp:41
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:295
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:138
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
Greedy Register Allocator
static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, int Depth, llvm::raw_ostream &OS) LLVM_ATTRIBUTE_USED
Helper that launches llvm-symbolizer and symbolizes a backtrace.
Definition: Signals.cpp:71
This is a helper class used for format_hex() and format_decimal().
Definition: Format.h:155
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:843
StringRef parent_path(StringRef path)
Get parent path.
Definition: Path.cpp:493
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:716
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:130
Saves strings in the inheritor's stable storage and returns a StringRef with a stable character point...
Definition: StringSaver.h:21
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:357
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
Definition: Path.cpp:794
const char * c_str()
Definition: SmallString.h:270
#define I(x, y, z)
Definition: MD5.cpp:54
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths=None)
Find the first executable file Name in Paths.
Provides ErrorOr<T> smart pointer.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
static FormattedNumber format_ptr(void *PC)
Format a pointer value as hexadecimal.
Definition: Signals.cpp:59
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:63
static ManagedStatic< std::vector< std::pair< void(*)(void *), void * > > > CallBacksToRun
Definition: Signals.cpp:40
char * PC
#define LLVM_ATTRIBUTE_USED
Definition: Compiler.h:123