29 # include <execinfo.h>
41 #include <mach/mach.h>
46 #ifdef HAVE__UNWIND_BACKTRACE
54 #undef HAVE__UNWIND_BACKTRACE
60 static RETSIGTYPE SignalHandler(
int Sig);
65 static void (*InterruptFunction)() =
nullptr;
74 static const int IntSigs[] = {
75 SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
80 static const int KillSigs[] = {
81 SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
96 static unsigned NumRegisteredSignals = 0;
103 static void RegisterHandler(
int Signal) {
105 "Out of space for signal handlers!");
107 struct sigaction NewHandler;
109 NewHandler.sa_handler = SignalHandler;
110 NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
111 sigemptyset(&NewHandler.sa_mask);
114 sigaction(Signal, &NewHandler,
115 &RegisteredSignalInfo[NumRegisteredSignals].SA);
116 RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal;
117 ++NumRegisteredSignals;
120 #if defined(HAVE_SIGALTSTACK)
125 static stack_t OldAltStack;
126 static void* NewAltStackPointer;
128 static void CreateSigAltStack() {
129 const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
135 if (sigaltstack(
nullptr, &OldAltStack) != 0 ||
136 OldAltStack.ss_flags & SS_ONSTACK ||
137 (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
140 stack_t AltStack = {};
141 AltStack.ss_sp =
reinterpret_cast<char *
>(malloc(AltStackSize));
142 NewAltStackPointer = AltStack.ss_sp;
143 AltStack.ss_size = AltStackSize;
144 if (sigaltstack(&AltStack, &OldAltStack) != 0)
145 free(AltStack.ss_sp);
148 static void CreateSigAltStack() {}
151 static void RegisterHandlers() {
159 if (NumRegisteredSignals != 0)
return;
165 for (
auto S : IntSigs) RegisterHandler(S);
166 for (
auto S : KillSigs) RegisterHandler(S);
169 static void UnregisterHandlers() {
171 for (
unsigned i = 0, e = NumRegisteredSignals;
i != e; ++
i)
172 sigaction(RegisteredSignalInfo[
i].SigNo,
173 &RegisteredSignalInfo[
i].SA,
nullptr);
174 NumRegisteredSignals = 0;
182 static void RemoveFilesToRemove() {
185 if (!FilesToRemove.isConstructed())
190 std::vector<std::string>& FilesToRemoveRef = *FilesToRemove;
191 for (
unsigned i = 0, e = FilesToRemoveRef.size();
i != e; ++
i) {
192 const char *path = FilesToRemoveRef[
i].c_str();
197 if (stat(path, &buf) != 0)
203 if (!S_ISREG(buf.st_mode))
213 static RETSIGTYPE SignalHandler(
int Sig) {
218 UnregisterHandlers();
222 sigfillset(&SigMask);
223 sigprocmask(SIG_UNBLOCK, &SigMask,
nullptr);
227 RemoveFilesToRemove();
231 if (InterruptFunction) {
232 void (*IF)() = InterruptFunction;
234 InterruptFunction =
nullptr;
253 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
260 RemoveFilesToRemove();
266 InterruptFunction = IF;
273 std::string* ErrMsg) {
276 FilesToRemove->push_back(Filename);
286 std::vector<std::string>::reverse_iterator RI =
288 std::vector<std::string>::iterator
I = FilesToRemove->end();
289 if (RI != FilesToRemove->rend())
290 I = FilesToRemove->erase(RI.base()-1);
301 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H && \
302 (defined(__linux__) || defined(__FreeBSD__) || \
303 defined(__FreeBSD_kernel__) || defined(__NetBSD__))
304 struct DlIteratePhdrData {
308 const char **modules;
310 const char *main_exec_name;
313 static int dl_iterate_phdr_cb(dl_phdr_info *
info,
size_t size,
void *arg) {
314 DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
315 const char *
name = data->first ? data->main_exec_name : info->dlpi_name;
317 for (
int i = 0;
i < info->dlpi_phnum;
i++) {
318 const auto *phdr = &info->dlpi_phdr[
i];
321 intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
323 for (
int j = 0; j < data->depth; j++) {
324 if (data->modules[j])
327 if (beg <= addr && addr < end) {
328 data->modules[j] =
name;
329 data->offsets[j] = addr - info->dlpi_addr;
340 const char *MainExecutableName,
342 DlIteratePhdrData data = {StackTrace,
Depth,
true,
343 Modules,
Offsets, MainExecutableName};
344 dl_iterate_phdr(dl_iterate_phdr_cb, &data);
352 const char *MainExecutableName,
356 #endif // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && ...
358 #if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
359 static int unwindBacktrace(
void **StackTrace,
int MaxEntries) {
366 auto HandleFrame = [&](_Unwind_Context *
Context) -> _Unwind_Reason_Code {
368 void *
IP = (
void *)_Unwind_GetIP(
Context);
370 return _URC_END_OF_STACK;
372 assert(Entries < MaxEntries &&
"recursively called after END_OF_STACK?");
374 StackTrace[Entries] = IP;
376 if (++Entries == MaxEntries)
377 return _URC_END_OF_STACK;
378 return _URC_NO_REASON;
382 [](_Unwind_Context *
Context,
void *Handler) {
383 return (*
static_cast<decltype(HandleFrame) *
>(Handler))(Context);
385 static_cast<void *
>(&HandleFrame));
386 return std::max(Entries, 0);
396 #if ENABLE_BACKTRACES
397 static void *StackTrace[256];
399 #if defined(HAVE_BACKTRACE)
402 depth = backtrace(StackTrace, static_cast<int>(
array_lengthof(StackTrace)));
404 #if defined(HAVE__UNWIND_BACKTRACE)
407 depth = unwindBacktrace(StackTrace,
415 #if HAVE_DLFCN_H && __GNUG__ && !defined(__CYGWIN__)
417 for (
int i = 0;
i < depth; ++
i) {
419 dladdr(StackTrace[
i], &dlinfo);
420 const char* name = strrchr(dlinfo.dli_fname,
'/');
423 if (!name) nwidth = strlen(dlinfo.dli_fname);
424 else nwidth = strlen(name) - 1;
426 if (nwidth > width) width = nwidth;
429 for (
int i = 0;
i < depth; ++
i) {
431 dladdr(StackTrace[
i], &dlinfo);
435 const char* name = strrchr(dlinfo.dli_fname,
'/');
436 if (!name) OS <<
format(
" %-*s", width, dlinfo.dli_fname);
437 else OS <<
format(
" %-*s", width, name+1);
439 OS <<
format(
" %#0*lx", (
int)(
sizeof(
void*) * 2) + 2,
440 (
unsigned long)StackTrace[
i]);
442 if (dlinfo.dli_sname !=
nullptr) {
446 if (!d) OS << dlinfo.dli_sname;
453 OS <<
format(
" + %u",(
unsigned)((
char*)StackTrace[
i]-
454 (
char*)dlinfo.dli_saddr));
458 #elif defined(HAVE_BACKTRACE)
459 backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
464 static void PrintStackTraceSignalHandler(
void *) {
473 bool DisableCrashReporting) {
478 #if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
480 if (DisableCrashReporting || getenv(
"LLVM_DISABLE_CRASH_REPORT")) {
481 mach_port_t
self = mach_task_self();
483 exception_mask_t mask = EXC_MASK_CRASH;
485 kern_return_t ret = task_set_exception_ports(
self,
488 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
const_iterator end(StringRef path)
Get end iterator over path.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
char * itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status)
This is a llvm local version of __cxa_demangle.
void DisableSystemDialogsOnCrash()
Disable all system dialog boxes that appear when the process crashes.
const_iterator begin(StringRef path)
Get begin iterator over path.
static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, const char *MainExecutableName, StringSaver &StrPool)
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
void PrintStackTraceOnErrorSignal(StringRef Argv0, bool DisableCrashReporting=false)
When an error signal (such as SIBABRT or SIGSEGV) is delivered to the process, print a stack trace an...
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void PrintStackTrace(raw_ostream &OS)
Print the stack trace using the given raw_ostream object.
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
A pared-down imitation of std::unique_lock from C++11.
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
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.
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
Saves strings in the inheritor's stable storage and returns a StringRef with a stable character point...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
void SetInterruptFunction(void(*IF)())
This function registers a function to be called when the user "interrupts" the program (typically by ...
static ManagedStatic< std::vector< std::pair< void(*)(void *), void * > > > CallBacksToRun
void AddSignalHandler(void(*FnPtr)(void *), void *Cookie)
AddSignalHandler - Add a function to be called when an abort/kill signal is delivered to the process...