/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/Signals.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | DisableSymbolication("disable-symbolication", |
41 | | cl::desc("Disable symbolizing crash backtraces."), |
42 | | 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 | 0 | return; |
49 | 0 | for (auto &I : *CallBacksToRun) |
50 | 0 | I.first(I.second); |
51 | 0 | CallBacksToRun->clear(); |
52 | 0 | } |
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 | 0 | static FormattedNumber format_ptr(void *PC) { |
62 | 0 | // 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 | 0 | } |
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 | | static bool printSymbolizedStackTrace(StringRef Argv0, |
74 | | void **StackTrace, int Depth, |
75 | 0 | llvm::raw_ostream &OS) { |
76 | 0 | if (DisableSymbolication) |
77 | 0 | return false; |
78 | 0 |
|
79 | 0 | // Don't recursively invoke the llvm-symbolizer binary. |
80 | 0 | if (0 Argv0.find("llvm-symbolizer") != std::string::npos0 ) |
81 | 0 | return false; |
82 | 0 |
|
83 | 0 | // FIXME: Subtract necessary number from StackTrace entries to turn return addresses |
84 | 0 | // into actual instruction addresses. |
85 | 0 | // Use llvm-symbolizer tool to symbolize the stack traces. First look for it |
86 | 0 | // alongside our binary, then in $PATH. |
87 | 0 | ErrorOr<std::string> LLVMSymbolizerPathOrErr = std::error_code(); |
88 | 0 | if (!Argv0.empty()0 ) { |
89 | 0 | StringRef Parent = llvm::sys::path::parent_path(Argv0); |
90 | 0 | if (!Parent.empty()) |
91 | 0 | LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer", Parent); |
92 | 0 | } |
93 | 0 | if (!LLVMSymbolizerPathOrErr) |
94 | 0 | LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer"); |
95 | 0 | if (!LLVMSymbolizerPathOrErr) |
96 | 0 | return false; |
97 | 0 | const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; |
98 | 0 |
|
99 | 0 | // If we don't know argv0 or the address of main() at this point, try |
100 | 0 | // to guess it anyway (it's possible on some platforms). |
101 | 0 | 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 | 0 | MainExecutableName.c_str(), StrPool)) |
110 | 0 | return false; |
111 | 0 | 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 | 0 |
|
118 | 0 | { |
119 | 0 | raw_fd_ostream Input(InputFD, true); |
120 | 0 | for (int i = 0; i < Depth0 ; i++0 ) { |
121 | 0 | if (Modules[i]) |
122 | 0 | Input << Modules[i] << " " << (void*)Offsets[i] << "\n"; |
123 | 0 | } |
124 | 0 | } |
125 | 0 |
|
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 | 0 | int RunResult = |
136 | 0 | sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects); |
137 | 0 | if (RunResult != 0) |
138 | 0 | return false; |
139 | 0 |
|
140 | 0 | // This report format is based on the sanitizer stack trace printer. See |
141 | 0 | // sanitizer_stacktrace_printer.cc in compiler-rt. |
142 | 0 | auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); |
143 | 0 | if (!OutputBuf) |
144 | 0 | 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 < Depth0 ; i++0 ) { |
151 | 0 | if (!Modules[i]0 ) { |
152 | 0 | OS << '#' << frame_no++ << ' ' << format_ptr(StackTrace[i]) << '\n'; |
153 | 0 | continue; |
154 | 0 | } |
155 | 0 | // Read pairs of lines (function name and file/line info) until we |
156 | 0 | // encounter empty line. |
157 | 0 | for (;;) 0 { |
158 | 0 | if (CurLine == Lines.end()) |
159 | 0 | return false; |
160 | 0 | StringRef FunctionName = *CurLine++; |
161 | 0 | if (FunctionName.empty()) |
162 | 0 | 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 | 0 | return false; |
168 | 0 | StringRef FileLineInfo = *CurLine++; |
169 | 0 | if (!FileLineInfo.startswith("??")) |
170 | 0 | OS << FileLineInfo; |
171 | 0 | else |
172 | 0 | OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")"; |
173 | 0 | OS << "\n"; |
174 | 0 | } |
175 | 0 | } |
176 | 0 | return true; |
177 | 0 | } |
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 |