LLVM 23.0.0git
Signals.inc
Go to the documentation of this file.
1//===- Signals.cpp - Generic Unix Signals Implementation -----*- 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines some helpful functions for dealing with the possibility of
10// Unix signals occurring while your program is running.
11//
12//===----------------------------------------------------------------------===//
13//
14// This file is extremely careful to only do signal-safe things while in a
15// signal handler. In particular, memory allocation and acquiring a mutex
16// while in a signal handler should never occur. ManagedStatic isn't usable from
17// a signal handler for 2 reasons:
18//
19// 1. Creating a new one allocates.
20// 2. The signal handler could fire while llvm_shutdown is being processed, in
21// which case the ManagedStatic is in an unknown state because it could
22// already have been destroyed, or be in the process of being destroyed.
23//
24// Modifying the behavior of the signal handlers (such as registering new ones)
25// can acquire a mutex, but all this guarantees is that the signal handler
26// behavior is only modified by one thread at a time. A signal handler can still
27// fire while this occurs!
28//
29// Adding work to a signal handler requires lock-freedom (and assume atomics are
30// always lock-free) because the signal handler could fire while new work is
31// being added.
32//
33//===----------------------------------------------------------------------===//
34
35#include "Unix.h"
36#include "llvm/ADT/STLExtras.h"
37#include "llvm/Config/config.h"
42#include "llvm/Support/Format.h"
44#include "llvm/Support/Mutex.h"
48#include <algorithm>
49#include <string>
50#ifdef HAVE_BACKTRACE
51#include BACKTRACE_HEADER // For backtrace().
52#endif
53#include <signal.h>
54#include <sys/stat.h>
55#include <dlfcn.h>
56#if HAVE_MACH_MACH_H
57#include <mach/mach.h>
58#endif
59#ifdef __APPLE__
60#include <mach-o/dyld.h>
61#endif
62#if __has_include(<link.h>)
63#include <link.h>
64#endif
65#ifdef HAVE__UNWIND_BACKTRACE
66// FIXME: We should be able to use <unwind.h> for any target that has an
67// _Unwind_Backtrace function, but on FreeBSD the configure test passes
68// despite the function not existing, and on Android, <unwind.h> conflicts
69// with <link.h>.
70#ifdef __GLIBC__
71#include <unwind.h>
72#else
73#undef HAVE__UNWIND_BACKTRACE
74#endif
75#endif
76#if ENABLE_BACKTRACES && defined(__MVS__)
78#include <__le_cwi.h>
79#endif
80
81#if defined(__linux__)
82#include <sys/syscall.h>
83#endif
84
85using namespace llvm;
86
87static void SignalHandler(int Sig, siginfo_t *Info, void *Context);
88static void SignalHandlerTerminate(int Sig, siginfo_t *Info, void *Context);
89static void InfoSignalHandler(int Sig); // defined below.
90static void InfoSignalHandlerTerminate(int Sig); // defined below.
91
92using SignalHandlerFunctionType = void (*)();
93/// The function to call if ctrl-c is pressed.
94static std::atomic<SignalHandlerFunctionType> InterruptFunction = nullptr;
95static std::atomic<SignalHandlerFunctionType> InfoSignalFunction = nullptr;
96/// The function to call on SIGPIPE (one-time use only).
97static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction =
98 nullptr;
99
100namespace {
101/// Sentinel stored in a node after the signal handler has removed the file;
102/// not a valid path, never freed.
103static char InvalidPathSentinel[] = "\01\02\03\04";
104
105/// Signal-safe removal of files.
106/// Inserting and erasing from the list isn't signal-safe, but removal of files
107/// themselves is signal-safe. Memory is freed when the head is freed, deletion
108/// is therefore not signal-safe either.
109class FileToRemoveList {
110 std::atomic<char *> Filename = nullptr;
111 std::atomic<FileToRemoveList *> Next = nullptr;
112
113 FileToRemoveList() = default;
114 // Takes ownership of \p filename.
115 FileToRemoveList(char *filename) : Filename(filename) {}
116
117public:
118 // Not signal-safe.
119 ~FileToRemoveList() {
120 if (FileToRemoveList *N = Next.exchange(nullptr))
121 delete N;
122 if (char *F = Filename.exchange(nullptr))
123 if (F != InvalidPathSentinel)
124 free(F);
125 }
126
127 // Not signal-safe.
128 static void insert(std::atomic<FileToRemoveList *> &Head,
129 const std::string &Filename) {
130 // Reuse a node with a null filename (left behind by erase) if one exists.
131 // There are two cases where Filename can be special:
132 // - nullptr: a node left behind by a previous file that we had to remove
133 // - InvalidPathSentinel: a node whose file is actively being removed by a
134 // signal handler right now, in which case it's OK if this file doesn't
135 // get removed.
136 char *NewFilename = strdup(Filename.c_str());
137 std::atomic<FileToRemoveList *> *InsertionPoint = &Head;
138 for (FileToRemoveList *Current = Head.load(); Current;
139 Current = Current->Next.load()) {
140 char *NullFilename = nullptr;
141 if (Current->Filename.compare_exchange_strong(NullFilename, NewFilename))
142 return; // Reused a slot.
143 InsertionPoint = &Current->Next;
144 }
145
146 // Append the new node at the end; on CAS failure, advance to the new tail.
147 FileToRemoveList *NewNode = new FileToRemoveList(NewFilename);
148 FileToRemoveList *OldNext = nullptr;
149 while (!InsertionPoint->compare_exchange_strong(OldNext, NewNode)) {
150 InsertionPoint = &OldNext->Next;
151 OldNext = nullptr;
152 }
153 }
154
155 // Not signal-safe.
156 static void erase(std::atomic<FileToRemoveList *> &Head,
157 const std::string &Filename) {
158 // Use a lock to avoid concurrent erase: the comparison would access
159 // free'd memory.
160 static ManagedStatic<sys::SmartMutex<true>> Lock;
161 sys::SmartScopedLock<true> Writer(*Lock);
162
163 for (FileToRemoveList *Current = Head.load(); Current;
164 Current = Current->Next.load()) {
165 if (char *OldFilename = Current->Filename.load()) {
166 if (OldFilename != Filename)
167 continue;
168 // Leave an empty filename. Use CAS to avoid racing with the signal
169 // handler (which can't take the writer lock); only clear and free
170 // if we still own the pointer.
171 char *Expected = OldFilename;
172 while (!Current->Filename.compare_exchange_strong(Expected, nullptr)) {
173 if (Expected == nullptr || Expected == InvalidPathSentinel)
174 break;
175 }
176 if (Expected == OldFilename)
177 free(OldFilename);
178 }
179 }
180 }
181
182 static void removeFile(char *path) {
183 // Get the status so we can determine if it's a file or directory. If we
184 // can't stat the file, ignore it.
185 struct stat buf;
186 if (stat(path, &buf) != 0)
187 return;
188
189 // If this is not a regular file, ignore it. We want to prevent removal
190 // of special files like /dev/null, even if the compiler is being run
191 // with the super-user permissions.
192 if (!S_ISREG(buf.st_mode))
193 return;
194
195 // Otherwise, remove the file. We ignore any errors here as there is
196 // nothing else we can do.
197 unlink(path);
198 }
199
200 // Signal-safe.
201 static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) {
202 // This signal-safe code cannot acquire the writer lock, and needs to defend
203 // against racing writes from the `erase` method above.
204 FileToRemoveList *OldHead = Head.exchange(nullptr);
205
206 for (FileToRemoveList *currentFile = OldHead; currentFile;
207 currentFile = currentFile->Next.load()) {
208 // Take exclusive ownership by swapping in the sentinel (signal-safe: no
209 // allocation or free). Then put the path back so we don't leak.
210 char *Path = currentFile->Filename.exchange(InvalidPathSentinel);
211 if (!Path) {
212 // Restore an empty slot so future insertions can reuse it.
213 currentFile->Filename.exchange(nullptr);
214 } else if (Path != InvalidPathSentinel) {
215 removeFile(Path);
216 // Add the path back to the list to create a global root referencing the
217 // heap allocation, which will pacify leak checkers that run at exit.
218 currentFile->Filename.exchange(Path);
219 }
220 }
221
222 // We're done removing files, cleanup can safely proceed.
223 Head.exchange(OldHead);
224 }
225};
226static std::atomic<FileToRemoveList *> FilesToRemove = nullptr;
227
228/// Clean up the list in a signal-friendly manner.
229/// Recall that signals can fire during llvm_shutdown. If this occurs we should
230/// either clean something up or nothing at all, but we shouldn't crash!
231struct FilesToRemoveCleanup {
232 // Not signal-safe.
233 ~FilesToRemoveCleanup() {
234 FileToRemoveList *Head = FilesToRemove.exchange(nullptr);
235 if (Head)
236 delete Head;
237 }
238};
239} // namespace
240
241static StringRef Argv0;
242
243/// Signals that represent requested termination. There's no bug or failure, or
244/// if there is, it's not our direct responsibility. For whatever reason, our
245/// continued execution is no longer desirable.
246static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2};
247
248/// Signals that represent that we have a bug, and our prompt termination has
249/// been ordered.
250static const int KillSigs[] = {SIGILL,
251 SIGTRAP,
252 SIGABRT,
253 SIGFPE,
254 SIGBUS,
255 SIGSEGV,
256 SIGQUIT
257#ifdef SIGSYS
258 ,
259 SIGSYS
260#endif
261#ifdef SIGXCPU
262 ,
263 SIGXCPU
264#endif
265#ifdef SIGXFSZ
266 ,
267 SIGXFSZ
268#endif
269#ifdef SIGEMT
270 ,
271 SIGEMT
272#endif
273};
274
275/// Signals that represent requests for status.
276static const int InfoSigs[] = {SIGUSR1
277#ifdef SIGINFO
278 ,
279 SIGINFO
280#endif
281};
282
283static const size_t NumSigs = std::size(IntSigs) + std::size(KillSigs) +
284 std::size(InfoSigs) + 1 /* SIGPIPE */;
285
286static std::atomic<unsigned> NumRegisteredSignals = 0;
287static struct {
288 struct sigaction SA;
289 int SigNo;
290} RegisteredSignalInfo[NumSigs];
291
292#if defined(HAVE_SIGALTSTACK)
293// Hold onto both the old and new alternate signal stack so that it's not
294// reported as a leak. We don't make any attempt to remove our alt signal
295// stack if we remove our signal handlers; that can't be done reliably if
296// someone else is also trying to do the same thing.
297static stack_t OldAltStack;
298LLVM_ATTRIBUTE_USED static void *NewAltStackPointer;
299
300static void CreateSigAltStack() {
301 const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
302
303 // If we're executing on the alternate stack, or we already have an alternate
304 // signal stack that we're happy with, there's nothing for us to do. Don't
305 // reduce the size, some other part of the process might need a larger stack
306 // than we do.
307 if (sigaltstack(nullptr, &OldAltStack) != 0 ||
308 OldAltStack.ss_flags & SS_ONSTACK ||
309 (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
310 return;
311
312 stack_t AltStack = {};
313 AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
314 NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
315 AltStack.ss_size = AltStackSize;
316 if (sigaltstack(&AltStack, &OldAltStack) != 0)
317 free(AltStack.ss_sp);
318}
319#else
320static void CreateSigAltStack() {}
321#endif
322
323static void RegisterHandlers(
324 bool NeedsPOSIXUtilitySignalHandling = false) { // Not signal-safe.
325 // The mutex prevents other threads from registering handlers while we're
326 // doing it. We also have to protect the handlers and their count because
327 // a signal handler could fire while we're registering handlers.
328 static ManagedStatic<sys::SmartMutex<true>> SignalHandlerRegistrationMutex;
329 sys::SmartScopedLock<true> Guard(*SignalHandlerRegistrationMutex);
330
331 // If the handlers are already registered, we're done.
332 if (NumRegisteredSignals.load() != 0)
333 return;
334
335 // Create an alternate stack for signal handling. This is necessary for us to
336 // be able to reliably handle signals due to stack overflow.
337 CreateSigAltStack();
338
339 enum class SignalKind { IsKill, IsInfo };
340 auto registerHandler = [&](int Signal, SignalKind Kind) {
341 unsigned Index = NumRegisteredSignals.load();
342 assert(Index < std::size(RegisteredSignalInfo) &&
343 "Out of space for signal handlers!");
344
345 struct sigaction NewHandler;
346
347 switch (Kind) {
348 case SignalKind::IsKill:
349 if (NeedsPOSIXUtilitySignalHandling)
350 // If POSIX signal-handling semantics are followed, the signal handler
351 // resignal itself to terminate after handling the signal.
352 NewHandler.sa_sigaction = SignalHandlerTerminate;
353 else
354 NewHandler.sa_sigaction = SignalHandler;
355 NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO;
356 break;
357 case SignalKind::IsInfo:
358 if (NeedsPOSIXUtilitySignalHandling)
359 // If POSIX signal-handling semantics are followed, the signal handler
360 // resignal itself to terminate after handling the signal.
361 NewHandler.sa_handler = InfoSignalHandlerTerminate;
362 else
363 NewHandler.sa_handler = InfoSignalHandler;
364 NewHandler.sa_flags = SA_ONSTACK;
365 break;
366 }
367 sigemptyset(&NewHandler.sa_mask);
368
369 if (NeedsPOSIXUtilitySignalHandling) {
370 // Don't install the new handler if the signal disposition is SIG_IGN.
371 struct sigaction act;
372 if (sigaction(Signal, NULL, &act) == 0 && act.sa_handler != SIG_IGN)
373 sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
374 } else {
375 sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
376 }
377 RegisteredSignalInfo[Index].SigNo = Signal;
378 ++NumRegisteredSignals;
379 };
380
381 for (auto S : IntSigs)
382 registerHandler(S, SignalKind::IsKill);
383 for (auto S : KillSigs)
384 registerHandler(S, SignalKind::IsKill);
385 if (OneShotPipeSignalFunction)
386 registerHandler(SIGPIPE, SignalKind::IsKill);
387 for (auto S : InfoSigs)
388 registerHandler(S, SignalKind::IsInfo);
389}
390
392 // Restore all of the signal handlers to how they were before we showed up.
393 for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) {
394 sigaction(RegisteredSignalInfo[i].SigNo, &RegisteredSignalInfo[i].SA,
395 nullptr);
396 --NumRegisteredSignals;
397 }
398}
399
400/// Process the FilesToRemove list.
401static void RemoveFilesToRemove() {
402 FileToRemoveList::removeAllFiles(FilesToRemove);
403}
404
405void sys::CleanupOnSignal(uintptr_t Context) {
406 // Let's not interfere with stack trace symbolication and friends.
407 auto BypassSandbox = sandbox::scopedDisable();
408
409 int Sig = (int)Context;
410
411 if (llvm::is_contained(InfoSigs, Sig)) {
412 InfoSignalHandler(Sig);
413 return;
414 }
415
416 RemoveFilesToRemove();
417
418 if (llvm::is_contained(IntSigs, Sig) || Sig == SIGPIPE)
419 return;
420
422}
423
424// The signal handler that runs.
425static void SignalHandler(int Sig, siginfo_t *Info, void *Context) {
426 // Restore the signal behavior to default, so that the program actually
427 // crashes when we return and the signal reissues. This also ensures that if
428 // we crash in our signal handler that the program will terminate immediately
429 // instead of recursing in the signal handler.
431
432 // Unmask all potentially blocked kill signals.
433 sigset_t SigMask;
434 sigfillset(&SigMask);
435 sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
436
437 {
438 RemoveFilesToRemove();
439
440 if (Sig == SIGPIPE)
441 if (auto OldOneShotPipeFunction =
442 OneShotPipeSignalFunction.exchange(nullptr))
443 return OldOneShotPipeFunction();
444
445 bool IsIntSig = llvm::is_contained(IntSigs, Sig);
446 if (IsIntSig)
447 if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
448 return OldInterruptFunction();
449
450 if (Sig == SIGPIPE || IsIntSig) {
451 raise(Sig); // Execute the default handler.
452 return;
453 }
454 }
455
456 // Otherwise if it is a fault (like SEGV) run any handler.
458
459#ifdef __s390__
460 // On S/390, certain signals are delivered with PSW Address pointing to
461 // *after* the faulting instruction. Simply returning from the signal
462 // handler would continue execution after that point, instead of
463 // re-raising the signal. Raise the signal manually in those cases.
464 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
465 raise(Sig);
466#endif
467
468#if defined(__linux__)
469 // Re-raising a signal via `raise` loses the original siginfo. Recent
470 // versions of linux (>= 3.9) support processes sending a signal to itself
471 // with arbitrary signal information using a syscall. If this syscall is
472 // unsupported, errno will be set to EPERM and `raise` will be used instead.
473 int retval =
474 syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), Sig, Info);
475 if (retval != 0 && errno == EPERM)
476 raise(Sig);
477#else
478 // Signal sent from another userspace process, do not assume that continuing
479 // the execution would re-raise it.
480 if (Info->si_pid != getpid() && Info->si_pid != 0)
481 raise(Sig);
482#endif
483}
484
485static void SignalHandlerTerminate(int Sig, siginfo_t *Info, void *Context) {
486 SignalHandler(Sig, Info, Context);
487
488 // Resignal if it is a kill signal so that the exit code contains the
489 // terminating signal number.
490 if (llvm::is_contained(KillSigs, Sig))
491 raise(Sig); // Execute the default handler.
492}
493
494static void InfoSignalHandler(int Sig) {
495 SaveAndRestore SaveErrnoDuringASignalHandler(errno);
496 if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
497 CurrentInfoFunction();
498}
499
500static void InfoSignalHandlerTerminate(int Sig) {
501 InfoSignalHandler(Sig);
502
503 if (Sig == SIGUSR1) {
505 raise(Sig);
506 }
507}
508
510 // Let's not interfere with stack trace symbolication and friends.
511 auto BypassSandbox = sandbox::scopedDisable();
512
513 RemoveFilesToRemove();
514}
515
516void llvm::sys::SetInterruptFunction(void (*IF)()) {
517 InterruptFunction.exchange(IF);
518 RegisterHandlers();
519}
520
521void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
522 InfoSignalFunction.exchange(Handler);
523 RegisterHandlers();
524}
525
526void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
527 OneShotPipeSignalFunction.exchange(Handler);
528 RegisterHandlers();
529}
530
532 // Send a special return code that drivers can check for, from sysexits.h.
533 exit(EX_IOERR);
534}
535
536// The public API
537bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) {
538 // Ensure that cleanup will occur as soon as one file is added.
539 static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup;
540 *FilesToRemoveCleanup;
541 FileToRemoveList::insert(FilesToRemove, Filename.str());
542 RegisterHandlers();
543 return false;
544}
545
546// The public API
548 FileToRemoveList::erase(FilesToRemove, Filename.str());
549}
550
551/// Add a function to be called when a signal is delivered to the process. The
552/// handler can have a cookie passed to it to identify what instance of the
553/// handler it is.
555 bool NeedsPOSIXUtilitySignalHandling) {
556 // Signal-safe.
557 insertSignalHandler(FnPtr, Cookie);
558 RegisterHandlers(NeedsPOSIXUtilitySignalHandling);
559}
560
561#if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \
562 (defined(__linux__) || defined(__FreeBSD__) || \
563 defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \
564 defined(__OpenBSD__) || defined(__DragonFly__))
565struct DlIteratePhdrData {
566 void **StackTrace;
567 int depth;
568 bool first;
569 const char **modules;
570 intptr_t *offsets;
571 const char *main_exec_name;
572};
573
574static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
575 DlIteratePhdrData *data = (DlIteratePhdrData *)arg;
576 const char *name = data->first ? data->main_exec_name : info->dlpi_name;
577 data->first = false;
578 for (int i = 0; i < info->dlpi_phnum; i++) {
579 const auto *phdr = &info->dlpi_phdr[i];
580 if (phdr->p_type != PT_LOAD)
581 continue;
582 intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
583 intptr_t end = beg + phdr->p_memsz;
584 for (int j = 0; j < data->depth; j++) {
585 if (data->modules[j])
586 continue;
587 intptr_t addr = (intptr_t)data->StackTrace[j];
588 if (beg <= addr && addr < end) {
589 data->modules[j] = name;
590 data->offsets[j] = addr - info->dlpi_addr;
591 }
592 }
593 }
594 return 0;
595}
596
597#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
598#if !defined(HAVE_BACKTRACE)
599#error DebugLoc origin-tracking currently requires `backtrace()`.
600#endif
601namespace llvm {
602namespace sys {
603template <unsigned long MaxDepth>
604int getStackTrace(std::array<void *, MaxDepth> &StackTrace) {
605 return backtrace(StackTrace.data(), MaxDepth);
606}
607template int getStackTrace<16ul>(std::array<void *, 16ul> &);
608} // namespace sys
609} // namespace llvm
610#endif
611
612/// If this is an ELF platform, we can find all loaded modules and their virtual
613/// addresses with dl_iterate_phdr.
614static bool findModulesAndOffsets(void **StackTrace, int Depth,
615 const char **Modules, intptr_t *Offsets,
616 const char *MainExecutableName,
617 StringSaver &StrPool) {
618 DlIteratePhdrData data = {StackTrace, Depth, true,
619 Modules, Offsets, MainExecutableName};
620 dl_iterate_phdr(dl_iterate_phdr_cb, &data);
621 return true;
622}
623
624class DSOMarkupPrinter {
626 const char *MainExecutableName;
627 size_t ModuleCount = 0;
628 bool IsFirst = true;
629
630public:
631 DSOMarkupPrinter(llvm::raw_ostream &OS, const char *MainExecutableName)
632 : OS(OS), MainExecutableName(MainExecutableName) {}
633
634 /// Print llvm-symbolizer markup describing the layout of the given DSO.
635 void printDSOMarkup(dl_phdr_info *Info) {
636 bool WasFirst = IsFirst;
637 IsFirst = false;
638 ArrayRef<uint8_t> BuildID = findBuildID(Info);
639 if (BuildID.empty())
640 return;
641 OS << format("{{{module:%d:%s:elf:", ModuleCount,
642 WasFirst ? MainExecutableName : Info->dlpi_name);
643 for (uint8_t X : BuildID)
644 OS << format("%02x", X);
645 OS << "}}}\n";
646
647 for (int I = 0; I < Info->dlpi_phnum; I++) {
648 const auto *Phdr = &Info->dlpi_phdr[I];
649 if (Phdr->p_type != PT_LOAD)
650 continue;
651 uintptr_t StartAddress = Info->dlpi_addr + Phdr->p_vaddr;
652 uintptr_t ModuleRelativeAddress = Phdr->p_vaddr;
653 std::array<char, 4> ModeStr = modeStrFromFlags(Phdr->p_flags);
654 OS << format("{{{mmap:%#016x:%#x:load:%d:%s:%#016x}}}\n", StartAddress,
655 Phdr->p_memsz, ModuleCount, &ModeStr[0],
656 ModuleRelativeAddress);
657 }
658 ModuleCount++;
659 }
660
661 /// Callback for use with dl_iterate_phdr. The last dl_iterate_phdr argument
662 /// must be a pointer to an instance of this class.
663 static int printDSOMarkup(dl_phdr_info *Info, size_t Size, void *Arg) {
664 static_cast<DSOMarkupPrinter *>(Arg)->printDSOMarkup(Info);
665 return 0;
666 }
667
668 // Returns the build ID for the given DSO as an array of bytes. Returns an
669 // empty array if none could be found.
670 ArrayRef<uint8_t> findBuildID(dl_phdr_info *Info) {
671 for (int I = 0; I < Info->dlpi_phnum; I++) {
672 const auto *Phdr = &Info->dlpi_phdr[I];
673 if (Phdr->p_type != PT_NOTE)
674 continue;
675
676 ArrayRef<uint8_t> Notes(
677 reinterpret_cast<const uint8_t *>(Info->dlpi_addr + Phdr->p_vaddr),
678 Phdr->p_memsz);
679 while (Notes.size() > 12) {
680 uint32_t NameSize = *reinterpret_cast<const uint32_t *>(Notes.data());
681 Notes = Notes.drop_front(4);
682 uint32_t DescSize = *reinterpret_cast<const uint32_t *>(Notes.data());
683 Notes = Notes.drop_front(4);
684 uint32_t Type = *reinterpret_cast<const uint32_t *>(Notes.data());
685 Notes = Notes.drop_front(4);
686
687 ArrayRef<uint8_t> Name = Notes.take_front(NameSize);
688 auto CurPos = reinterpret_cast<uintptr_t>(Notes.data());
689 uint32_t BytesUntilDesc =
690 alignToPowerOf2(CurPos + NameSize, 4) - CurPos;
691 if (BytesUntilDesc >= Notes.size())
692 break;
693 Notes = Notes.drop_front(BytesUntilDesc);
694
695 ArrayRef<uint8_t> Desc = Notes.take_front(DescSize);
696 CurPos = reinterpret_cast<uintptr_t>(Notes.data());
697 uint32_t BytesUntilNextNote =
698 alignToPowerOf2(CurPos + DescSize, 4) - CurPos;
699 if (BytesUntilNextNote > Notes.size())
700 break;
701 Notes = Notes.drop_front(BytesUntilNextNote);
702
703 if (Type == 3 /*NT_GNU_BUILD_ID*/ && Name.size() >= 3 &&
704 Name[0] == 'G' && Name[1] == 'N' && Name[2] == 'U')
705 return Desc;
706 }
707 }
708 return {};
709 }
710
711 // Returns a symbolizer markup string describing the permissions on a DSO
712 // with the given p_flags.
713 std::array<char, 4> modeStrFromFlags(uint32_t Flags) {
714 std::array<char, 4> Mode;
715 char *Cur = &Mode[0];
716 if (Flags & PF_R)
717 *Cur++ = 'r';
718 if (Flags & PF_W)
719 *Cur++ = 'w';
720 if (Flags & PF_X)
721 *Cur++ = 'x';
722 *Cur = '\0';
723 return Mode;
724 }
725};
726
728 const char *MainExecutableName) {
729 OS << "{{{reset}}}\n";
730 DSOMarkupPrinter MP(OS, MainExecutableName);
731 dl_iterate_phdr(DSOMarkupPrinter::printDSOMarkup, &MP);
732 return true;
733}
734
735#elif ENABLE_BACKTRACES && defined(__APPLE__) && defined(__LP64__)
736static bool findModulesAndOffsets(void **StackTrace, int Depth,
737 const char **Modules, intptr_t *Offsets,
738 const char *MainExecutableName,
739 StringSaver &StrPool) {
740 uint32_t NumImgs = _dyld_image_count();
741 for (uint32_t ImageIndex = 0; ImageIndex < NumImgs; ImageIndex++) {
742 const char *Name = _dyld_get_image_name(ImageIndex);
743 intptr_t Slide = _dyld_get_image_vmaddr_slide(ImageIndex);
744 auto *Header =
745 (const struct mach_header_64 *)_dyld_get_image_header(ImageIndex);
746 if (Header == NULL)
747 continue;
748 auto Cmd = (const struct load_command *)(&Header[1]);
749 for (uint32_t CmdNum = 0; CmdNum < Header->ncmds; ++CmdNum) {
750 uint32_t BaseCmd = Cmd->cmd & ~LC_REQ_DYLD;
751 if (BaseCmd == LC_SEGMENT_64) {
752 auto CmdSeg64 = (const struct segment_command_64 *)Cmd;
753 for (int j = 0; j < Depth; j++) {
754 if (Modules[j])
755 continue;
756 intptr_t Addr = (intptr_t)StackTrace[j];
757 if ((intptr_t)CmdSeg64->vmaddr + Slide <= Addr &&
758 Addr < intptr_t(CmdSeg64->vmaddr + CmdSeg64->vmsize + Slide)) {
759 Modules[j] = Name;
760 Offsets[j] = Addr - Slide;
761 }
762 }
763 }
764 Cmd = (const load_command *)(((const char *)Cmd) + (Cmd->cmdsize));
765 }
766 }
767 return true;
768}
769
771 const char *MainExecutableName) {
772 return false;
773}
774#else
775/// Backtraces are not enabled or we don't yet know how to find all loaded DSOs
776/// on this platform.
777static bool findModulesAndOffsets(void **StackTrace, int Depth,
778 const char **Modules, intptr_t *Offsets,
779 const char *MainExecutableName,
780 StringSaver &StrPool) {
781 return false;
782}
783
785 const char *MainExecutableName) {
786 return false;
787}
788#endif // ENABLE_BACKTRACES && ... (findModulesAndOffsets variants)
789
790#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
791static int unwindBacktrace(void **StackTrace, int MaxEntries) {
792 if (MaxEntries < 0)
793 return 0;
794
795 // Skip the first frame ('unwindBacktrace' itself).
796 int Entries = -1;
797
798 auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
799 // Apparently we need to detect reaching the end of the stack ourselves.
800 void *IP = (void *)_Unwind_GetIP(Context);
801 if (!IP)
802 return _URC_END_OF_STACK;
803
804 assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
805 if (Entries >= 0)
806 StackTrace[Entries] = IP;
807
808 if (++Entries == MaxEntries)
809 return _URC_END_OF_STACK;
810 return _URC_NO_REASON;
811 };
812
813 _Unwind_Backtrace(
814 [](_Unwind_Context *Context, void *Handler) {
815 return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
816 },
817 static_cast<void *>(&HandleFrame));
818 return std::max(Entries, 0);
819}
820#endif
821
822#if ENABLE_BACKTRACES && defined(__MVS__)
823static void zosbacktrace(raw_ostream &OS) {
824 // A function name in the PPA1 can have length 16k.
825 constexpr size_t MAX_ENTRY_NAME = UINT16_MAX;
826 // Limit all other strings to 8 byte.
827 constexpr size_t MAX_OTHER = 8;
828 int32_t dsa_format = -1; // Input/Output
829 void *caaptr = _gtca(); // Input
830 int32_t member_id; // Output
831 char compile_unit_name[MAX_OTHER]; // Output
832 void *compile_unit_address; // Output
833 void *call_instruction_address = nullptr; // Input/Output
834 char entry_name[MAX_ENTRY_NAME]; // Output
835 void *entry_address; // Output
836 void *callers_instruction_address; // Output
837 void *callers_dsaptr; // Output
838 int32_t callers_dsa_format; // Output
839 char statement_id[MAX_OTHER]; // Output
840 void *cibptr; // Output
841 int32_t main_program; // Output
842 _FEEDBACK fc; // Output
843
844 // The DSA pointer is the value of the stack pointer r4.
845 // __builtin_frame_address() returns a pointer to the stack frame, so the
846 // stack bias has to be considered to get the expected DSA value.
847 void *dsaptr = static_cast<char *>(__builtin_frame_address(0)) - 2048;
848 int count = 0;
849 OS << " DSA Adr EP +EP DSA "
850 " Entry\n";
851 while (1) {
852 // After the call, these variables contain the length of the string.
853 int32_t compile_unit_name_length = sizeof(compile_unit_name);
854 int32_t entry_name_length = sizeof(entry_name);
855 int32_t statement_id_length = sizeof(statement_id);
856 // See
857 // https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service
858 // for documentation of the parameters.
859 __CELQTBCK(&dsaptr, &dsa_format, &caaptr, &member_id, &compile_unit_name[0],
860 &compile_unit_name_length, &compile_unit_address,
861 &call_instruction_address, &entry_name[0], &entry_name_length,
862 &entry_address, &callers_instruction_address, &callers_dsaptr,
863 &callers_dsa_format, &statement_id[0], &statement_id_length,
864 &cibptr, &main_program, &fc);
865 if (fc.tok_sev) {
866 OS << format("error: CELQTBCK returned severity %d message %d\n",
867 fc.tok_sev, fc.tok_msgno);
868 break;
869 }
870
871 if (count) { // Omit first entry.
872 uintptr_t diff = reinterpret_cast<uintptr_t>(call_instruction_address) -
873 reinterpret_cast<uintptr_t>(entry_address);
874 OS << format(" %3d. 0x%016lX", count, call_instruction_address);
875 OS << format(" 0x%016lX +0x%08lX 0x%016lX", entry_address, diff, dsaptr);
877 ConverterEBCDIC::convertToUTF8(StringRef(entry_name, entry_name_length),
878 Str);
879 OS << ' ' << Str << '\n';
880 }
881 ++count;
882 if (callers_dsaptr) {
883 dsaptr = callers_dsaptr;
884 dsa_format = callers_dsa_format;
885 call_instruction_address = callers_instruction_address;
886 } else
887 break;
888 }
889}
890#endif
891
892// In the case of a program crash or fault, print out a stack trace so that the
893// user has an indication of why and where we died.
894//
895// On glibc systems we have the 'backtrace' function, which works nicely, but
896// doesn't demangle symbols.
898#if ENABLE_BACKTRACES
899#ifdef __MVS__
900 zosbacktrace(OS);
901#else
902 static void *StackTrace[256];
903 int depth = 0;
904#if defined(HAVE_BACKTRACE)
905 // Use backtrace() to output a backtrace on Linux systems with glibc.
906 if (!depth)
907 depth = backtrace(StackTrace, static_cast<int>(std::size(StackTrace)));
908#endif
909#if defined(HAVE__UNWIND_BACKTRACE)
910 // Try _Unwind_Backtrace() if backtrace() failed.
911 if (!depth)
912 depth =
913 unwindBacktrace(StackTrace, static_cast<int>(std::size(StackTrace)));
914#endif
915 if (!depth)
916 return;
917 // If "Depth" is not provided by the caller, use the return value of
918 // backtrace() for printing a symbolized stack trace.
919 if (!Depth)
920 Depth = depth;
921 if (printMarkupStackTrace(Argv0, StackTrace, Depth, OS))
922 return;
923 if (printSymbolizedStackTrace(Argv0, StackTrace, Depth, OS))
924 return;
925 OS << "Stack dump without symbol names (ensure you have llvm-symbolizer in "
926 "your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point "
927 "to it):\n";
928#if HAVE_DLOPEN && !defined(_AIX)
929 int width = 0;
930 for (int i = 0; i < depth; ++i) {
931 Dl_info dlinfo;
932 int nwidth;
933 if (dladdr(StackTrace[i], &dlinfo) == 0) {
934 nwidth = 7; // "(error)"
935 } else {
936 const char *name = strrchr(dlinfo.dli_fname, '/');
937
938 if (!name)
939 nwidth = strlen(dlinfo.dli_fname);
940 else
941 nwidth = strlen(name) - 1;
942 }
943
944 width = std::max(nwidth, width);
945 }
946
947 for (int i = 0; i < depth; ++i) {
948 Dl_info dlinfo;
949
950 OS << format("%-2d", i);
951
952 if (dladdr(StackTrace[i], &dlinfo) == 0) {
953 OS << format(" %-*s", width, static_cast<const char *>("(error)"));
954 dlinfo.dli_sname = nullptr;
955 } else {
956 const char *name = strrchr(dlinfo.dli_fname, '/');
957 if (!name)
958 OS << format(" %-*s", width, dlinfo.dli_fname);
959 else
960 OS << format(" %-*s", width, name + 1);
961 }
962
963 OS << format(" %#0*lx", (int)(sizeof(void *) * 2) + 2,
964 (unsigned long)StackTrace[i]);
965
966 if (dlinfo.dli_sname != nullptr) {
967 OS << ' ';
968 if (char *d = itaniumDemangle(dlinfo.dli_sname)) {
969 OS << d;
970 free(d);
971 } else {
972 OS << dlinfo.dli_sname;
973 }
974
975 OS << format(" + %tu", (static_cast<const char *>(StackTrace[i]) -
976 static_cast<const char *>(dlinfo.dli_saddr)));
977 }
978 OS << '\n';
979 }
980#elif defined(HAVE_BACKTRACE)
981 backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);
982#endif
983#endif
984#endif
985}
986
987static void PrintStackTraceSignalHandler(void *) {
989}
990
992
993/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
994/// process, print a stack trace and then exit.
996 bool DisableCrashReporting) {
997 ::Argv0 = Argv0;
998
999 AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
1000
1001#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
1002 // Environment variable to disable any kind of crash dialog.
1003 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
1004 mach_port_t self = mach_task_self();
1005
1006 exception_mask_t mask = EXC_MASK_CRASH;
1007
1008 kern_return_t ret = task_set_exception_ports(
1009 self, mask, MACH_PORT_NULL,
1010 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
1011 (void)ret;
1012 }
1013#endif
1014}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static constexpr unsigned long long mask(BlockVerifier::State S)
#define LLVM_ATTRIBUTE_USED
Definition Compiler.h:238
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
This file contains definitions of exit codes for exit() function.
#define STDERR_FILENO
Definition InitLLVM.cpp:31
lazy value info
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
static constexpr StringLiteral Filename
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file contains some templates that are useful if you are working with the STL at all.
static const char * name
This file provides utility classes that use RAII to save and restore values.
static LLVM_ATTRIBUTE_USED bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, int Depth, llvm::raw_ostream &OS)
Helper that launches llvm-symbolizer and symbolizes a backtrace.
Definition Signals.cpp:263
static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, const char *MainExecutableName, StringSaver &StrPool)
static bool printMarkupContext(raw_ostream &OS, const char *MainExecutableName)
static LLVM_ATTRIBUTE_USED bool printMarkupStackTrace(StringRef Argv0, void **StackTrace, int Depth, raw_ostream &OS)
Definition Signals.cpp:343
static void insertSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie)
Definition Signals.cpp:115
static Split data
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
Definition StringSaver.h:22
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
LLVM_ABI void convertToUTF8(StringRef Source, SmallVectorImpl< char > &Result)
Offsets
Offsets in bytes from the start of the input buffer.
constexpr size_t NameSize
Definition XCOFF.h:30
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
Definition BuildID.h:27
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:594
ScopedSetting scopedDisable()
Definition IOSandbox.h:36
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition Mutex.h:69
LLVM_ABI void DefaultOneShotPipeSignalHandler()
On Unix systems and Windows, this function exits with an "IO error" exit code.
LLVM_ABI void PrintStackTrace(raw_ostream &OS, int Depth=0)
Print the stack trace using the given raw_ostream object.
LLVM_ABI void DisableSystemDialogsOnCrash()
Disable all system dialog boxes that appear when the process crashes.
LLVM_ABI void unregisterHandlers()
LLVM_ABI void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie, bool NeedsPOSIXUtilitySignalHandling=false)
Add a function to be called when an abort/kill signal is delivered to the process.
LLVM_ABI 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...
LLVM_ABI void SetInfoSignalFunction(void(*Handler)())
Registers a function to be called when an "info" signal is delivered to the process.
LLVM_ABI void SetOneShotPipeSignalFunction(void(*Handler)())
Registers a function to be called in a "one-shot" manner when a pipe signal is delivered to the proce...
LLVM_ABI void SetInterruptFunction(void(*IF)())
This function registers a function to be called when the user "interrupts" the program (typically by ...
LLVM_ABI void RunSignalHandlers()
Definition Signals.cpp:98
LLVM_ABI void CleanupOnSignal(uintptr_t Context)
This function does the following:
LLVM_ABI void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
LLVM_ABI void PrintStackTraceOnErrorSignal(StringRef Argv0, bool DisableCrashReporting=false)
When an error signal (such as SIGABRT or SIGSEGV) is delivered to the process, print a stack trace an...
void(*)(void *) SignalHandlerCallback
Definition Signals.h:98
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
Op::Description Desc
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition STLExtras.h:2200
DEMANGLE_ABI char * itaniumDemangle(std::string_view mangled_name, bool ParseParams=true)
Returns a non-NULL pointer to a NUL-terminated C style string that should be explicitly freed,...
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
Definition MathExtras.h:493
LLVM_ATTRIBUTE_RETURNS_NONNULL void * safe_malloc(size_t Sz)
Definition MemAlloc.h:25
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:94
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2012
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
#define N
A utility class that uses RAII to save and restore the value of a variable.