LLVM 22.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 *);
88static void InfoSignalHandler(int Sig); // defined below.
89
90using SignalHandlerFunctionType = void (*)();
91/// The function to call if ctrl-c is pressed.
92static std::atomic<SignalHandlerFunctionType> InterruptFunction = nullptr;
93static std::atomic<SignalHandlerFunctionType> InfoSignalFunction = nullptr;
94/// The function to call on SIGPIPE (one-time use only).
95static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction =
96 nullptr;
97
98namespace {
99/// Signal-safe removal of files.
100/// Inserting and erasing from the list isn't signal-safe, but removal of files
101/// themselves is signal-safe. Memory is freed when the head is freed, deletion
102/// is therefore not signal-safe either.
103class FileToRemoveList {
104 std::atomic<char *> Filename = nullptr;
105 std::atomic<FileToRemoveList *> Next = nullptr;
106
107 FileToRemoveList() = default;
108 // Not signal-safe.
109 FileToRemoveList(const std::string &str) : Filename(strdup(str.c_str())) {}
110
111public:
112 // Not signal-safe.
113 ~FileToRemoveList() {
114 if (FileToRemoveList *N = Next.exchange(nullptr))
115 delete N;
116 if (char *F = Filename.exchange(nullptr))
117 free(F);
118 }
119
120 // Not signal-safe.
121 static void insert(std::atomic<FileToRemoveList *> &Head,
122 const std::string &Filename) {
123 // Insert the new file at the end of the list.
124 FileToRemoveList *NewHead = new FileToRemoveList(Filename);
125 std::atomic<FileToRemoveList *> *InsertionPoint = &Head;
126 FileToRemoveList *OldHead = nullptr;
127 while (!InsertionPoint->compare_exchange_strong(OldHead, NewHead)) {
128 InsertionPoint = &OldHead->Next;
129 OldHead = nullptr;
130 }
131 }
132
133 // Not signal-safe.
134 static void erase(std::atomic<FileToRemoveList *> &Head,
135 const std::string &Filename) {
136 // Use a lock to avoid concurrent erase: the comparison would access
137 // free'd memory.
138 static ManagedStatic<sys::SmartMutex<true>> Lock;
139 sys::SmartScopedLock<true> Writer(*Lock);
140
141 for (FileToRemoveList *Current = Head.load(); Current;
142 Current = Current->Next.load()) {
143 if (char *OldFilename = Current->Filename.load()) {
144 if (OldFilename != Filename)
145 continue;
146 // Leave an empty filename.
147 OldFilename = Current->Filename.exchange(nullptr);
148 // The filename might have become null between the time we
149 // compared it and we exchanged it.
150 if (OldFilename)
151 free(OldFilename);
152 }
153 }
154 }
155
156 static void removeFile(char *path) {
157 // Get the status so we can determine if it's a file or directory. If we
158 // can't stat the file, ignore it.
159 struct stat buf;
160 if (stat(path, &buf) != 0)
161 return;
162
163 // If this is not a regular file, ignore it. We want to prevent removal
164 // of special files like /dev/null, even if the compiler is being run
165 // with the super-user permissions.
166 if (!S_ISREG(buf.st_mode))
167 return;
168
169 // Otherwise, remove the file. We ignore any errors here as there is
170 // nothing else we can do.
171 unlink(path);
172 }
173
174 // Signal-safe.
175 static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) {
176 // If cleanup were to occur while we're removing files we'd have a bad time.
177 // Make sure we're OK by preventing cleanup from doing anything while we're
178 // removing files. If cleanup races with us and we win we'll have a leak,
179 // but we won't crash.
180 FileToRemoveList *OldHead = Head.exchange(nullptr);
181
182 for (FileToRemoveList *currentFile = OldHead; currentFile;
183 currentFile = currentFile->Next.load()) {
184 // If erasing was occuring while we're trying to remove files we'd look
185 // at free'd data. Take away the path and put it back when done.
186 if (char *path = currentFile->Filename.exchange(nullptr)) {
187 removeFile(path);
188
189 // We're done removing the file, erasing can safely proceed.
190 currentFile->Filename.exchange(path);
191 }
192 }
193
194 // We're done removing files, cleanup can safely proceed.
195 Head.exchange(OldHead);
196 }
197};
198static std::atomic<FileToRemoveList *> FilesToRemove = nullptr;
199
200/// Clean up the list in a signal-friendly manner.
201/// Recall that signals can fire during llvm_shutdown. If this occurs we should
202/// either clean something up or nothing at all, but we shouldn't crash!
203struct FilesToRemoveCleanup {
204 // Not signal-safe.
205 ~FilesToRemoveCleanup() {
206 FileToRemoveList *Head = FilesToRemove.exchange(nullptr);
207 if (Head)
208 delete Head;
209 }
210};
211} // namespace
212
213static StringRef Argv0;
214
215/// Signals that represent requested termination. There's no bug or failure, or
216/// if there is, it's not our direct responsibility. For whatever reason, our
217/// continued execution is no longer desirable.
218static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2};
219
220/// Signals that represent that we have a bug, and our prompt termination has
221/// been ordered.
222static const int KillSigs[] = {SIGILL,
223 SIGTRAP,
224 SIGABRT,
225 SIGFPE,
226 SIGBUS,
227 SIGSEGV,
228 SIGQUIT
229#ifdef SIGSYS
230 ,
231 SIGSYS
232#endif
233#ifdef SIGXCPU
234 ,
235 SIGXCPU
236#endif
237#ifdef SIGXFSZ
238 ,
239 SIGXFSZ
240#endif
241#ifdef SIGEMT
242 ,
243 SIGEMT
244#endif
245};
246
247/// Signals that represent requests for status.
248static const int InfoSigs[] = {SIGUSR1
249#ifdef SIGINFO
250 ,
251 SIGINFO
252#endif
253};
254
255static const size_t NumSigs = std::size(IntSigs) + std::size(KillSigs) +
256 std::size(InfoSigs) + 1 /* SIGPIPE */;
257
258static std::atomic<unsigned> NumRegisteredSignals = 0;
259static struct {
260 struct sigaction SA;
261 int SigNo;
262} RegisteredSignalInfo[NumSigs];
263
264#if defined(HAVE_SIGALTSTACK)
265// Hold onto both the old and new alternate signal stack so that it's not
266// reported as a leak. We don't make any attempt to remove our alt signal
267// stack if we remove our signal handlers; that can't be done reliably if
268// someone else is also trying to do the same thing.
269static stack_t OldAltStack;
270LLVM_ATTRIBUTE_USED static void *NewAltStackPointer;
271
272static void CreateSigAltStack() {
273 const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
274
275 // If we're executing on the alternate stack, or we already have an alternate
276 // signal stack that we're happy with, there's nothing for us to do. Don't
277 // reduce the size, some other part of the process might need a larger stack
278 // than we do.
279 if (sigaltstack(nullptr, &OldAltStack) != 0 ||
280 OldAltStack.ss_flags & SS_ONSTACK ||
281 (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
282 return;
283
284 stack_t AltStack = {};
285 AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
286 NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
287 AltStack.ss_size = AltStackSize;
288 if (sigaltstack(&AltStack, &OldAltStack) != 0)
289 free(AltStack.ss_sp);
290}
291#else
292static void CreateSigAltStack() {}
293#endif
294
295static void RegisterHandlers() { // Not signal-safe.
296 // The mutex prevents other threads from registering handlers while we're
297 // doing it. We also have to protect the handlers and their count because
298 // a signal handler could fire while we're registering handlers.
299 static ManagedStatic<sys::SmartMutex<true>> SignalHandlerRegistrationMutex;
300 sys::SmartScopedLock<true> Guard(*SignalHandlerRegistrationMutex);
301
302 // If the handlers are already registered, we're done.
303 if (NumRegisteredSignals.load() != 0)
304 return;
305
306 // Create an alternate stack for signal handling. This is necessary for us to
307 // be able to reliably handle signals due to stack overflow.
308 CreateSigAltStack();
309
310 enum class SignalKind { IsKill, IsInfo };
311 auto registerHandler = [&](int Signal, SignalKind Kind) {
312 unsigned Index = NumRegisteredSignals.load();
313 assert(Index < std::size(RegisteredSignalInfo) &&
314 "Out of space for signal handlers!");
315
316 struct sigaction NewHandler;
317
318 switch (Kind) {
319 case SignalKind::IsKill:
320 NewHandler.sa_sigaction = SignalHandler;
321 NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO;
322 break;
323 case SignalKind::IsInfo:
324 NewHandler.sa_handler = InfoSignalHandler;
325 NewHandler.sa_flags = SA_ONSTACK;
326 break;
327 }
328 sigemptyset(&NewHandler.sa_mask);
329
330 // Install the new handler, save the old one in RegisteredSignalInfo.
331 sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
332 RegisteredSignalInfo[Index].SigNo = Signal;
333 ++NumRegisteredSignals;
334 };
335
336 for (auto S : IntSigs)
337 registerHandler(S, SignalKind::IsKill);
338 for (auto S : KillSigs)
339 registerHandler(S, SignalKind::IsKill);
340 if (OneShotPipeSignalFunction)
341 registerHandler(SIGPIPE, SignalKind::IsKill);
342 for (auto S : InfoSigs)
343 registerHandler(S, SignalKind::IsInfo);
344}
345
347 // Restore all of the signal handlers to how they were before we showed up.
348 for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) {
349 sigaction(RegisteredSignalInfo[i].SigNo, &RegisteredSignalInfo[i].SA,
350 nullptr);
351 --NumRegisteredSignals;
352 }
353}
354
355/// Process the FilesToRemove list.
356static void RemoveFilesToRemove() {
357 FileToRemoveList::removeAllFiles(FilesToRemove);
358}
359
360void sys::CleanupOnSignal(uintptr_t Context) {
361 int Sig = (int)Context;
362
363 if (llvm::is_contained(InfoSigs, Sig)) {
364 InfoSignalHandler(Sig);
365 return;
366 }
367
368 RemoveFilesToRemove();
369
370 if (llvm::is_contained(IntSigs, Sig) || Sig == SIGPIPE)
371 return;
372
374}
375
376// The signal handler that runs.
377static void SignalHandler(int Sig, siginfo_t *Info, void *) {
378 // Restore the signal behavior to default, so that the program actually
379 // crashes when we return and the signal reissues. This also ensures that if
380 // we crash in our signal handler that the program will terminate immediately
381 // instead of recursing in the signal handler.
383
384 // Unmask all potentially blocked kill signals.
385 sigset_t SigMask;
386 sigfillset(&SigMask);
387 sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
388
389 {
390 RemoveFilesToRemove();
391
392 if (Sig == SIGPIPE)
393 if (auto OldOneShotPipeFunction =
394 OneShotPipeSignalFunction.exchange(nullptr))
395 return OldOneShotPipeFunction();
396
397 bool IsIntSig = llvm::is_contained(IntSigs, Sig);
398 if (IsIntSig)
399 if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
400 return OldInterruptFunction();
401
402 if (Sig == SIGPIPE || IsIntSig) {
403 raise(Sig); // Execute the default handler.
404 return;
405 }
406 }
407
408 // Otherwise if it is a fault (like SEGV) run any handler.
410
411#ifdef __s390__
412 // On S/390, certain signals are delivered with PSW Address pointing to
413 // *after* the faulting instruction. Simply returning from the signal
414 // handler would continue execution after that point, instead of
415 // re-raising the signal. Raise the signal manually in those cases.
416 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
417 raise(Sig);
418#endif
419
420#if defined(__linux__)
421 // Re-raising a signal via `raise` loses the original siginfo. Recent
422 // versions of linux (>= 3.9) support processes sending a signal to itself
423 // with arbitrary signal information using a syscall. If this syscall is
424 // unsupported, errno will be set to EPERM and `raise` will be used instead.
425 int retval =
426 syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), Sig, Info);
427 if (retval != 0 && errno == EPERM)
428 raise(Sig);
429#else
430 // Signal sent from another userspace process, do not assume that continuing
431 // the execution would re-raise it.
432 if (Info->si_pid != getpid() && Info->si_pid != 0)
433 raise(Sig);
434#endif
435}
436
437static void InfoSignalHandler(int Sig) {
438 SaveAndRestore SaveErrnoDuringASignalHandler(errno);
439 if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
440 CurrentInfoFunction();
441}
442
443void llvm::sys::RunInterruptHandlers() { RemoveFilesToRemove(); }
444
445void llvm::sys::SetInterruptFunction(void (*IF)()) {
446 InterruptFunction.exchange(IF);
447 RegisterHandlers();
448}
449
450void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
451 InfoSignalFunction.exchange(Handler);
452 RegisterHandlers();
453}
454
455void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
456 OneShotPipeSignalFunction.exchange(Handler);
457 RegisterHandlers();
458}
459
461 // Send a special return code that drivers can check for, from sysexits.h.
462 exit(EX_IOERR);
463}
464
465// The public API
466bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) {
467 // Ensure that cleanup will occur as soon as one file is added.
468 static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup;
469 *FilesToRemoveCleanup;
470 FileToRemoveList::insert(FilesToRemove, Filename.str());
471 RegisterHandlers();
472 return false;
473}
474
475// The public API
477 FileToRemoveList::erase(FilesToRemove, Filename.str());
478}
479
480/// Add a function to be called when a signal is delivered to the process. The
481/// handler can have a cookie passed to it to identify what instance of the
482/// handler it is.
484 void *Cookie) { // Signal-safe.
485 insertSignalHandler(FnPtr, Cookie);
486 RegisterHandlers();
487}
488
489#if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \
490 (defined(__linux__) || defined(__FreeBSD__) || \
491 defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \
492 defined(__OpenBSD__) || defined(__DragonFly__))
493struct DlIteratePhdrData {
494 void **StackTrace;
495 int depth;
496 bool first;
497 const char **modules;
498 intptr_t *offsets;
499 const char *main_exec_name;
500};
501
502static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
503 DlIteratePhdrData *data = (DlIteratePhdrData *)arg;
504 const char *name = data->first ? data->main_exec_name : info->dlpi_name;
505 data->first = false;
506 for (int i = 0; i < info->dlpi_phnum; i++) {
507 const auto *phdr = &info->dlpi_phdr[i];
508 if (phdr->p_type != PT_LOAD)
509 continue;
510 intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
511 intptr_t end = beg + phdr->p_memsz;
512 for (int j = 0; j < data->depth; j++) {
513 if (data->modules[j])
514 continue;
515 intptr_t addr = (intptr_t)data->StackTrace[j];
516 if (beg <= addr && addr < end) {
517 data->modules[j] = name;
518 data->offsets[j] = addr - info->dlpi_addr;
519 }
520 }
521 }
522 return 0;
523}
524
525#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN
526#if !defined(HAVE_BACKTRACE)
527#error DebugLoc origin-tracking currently requires `backtrace()`.
528#endif
529namespace llvm {
530namespace sys {
531template <unsigned long MaxDepth>
532int getStackTrace(std::array<void *, MaxDepth> &StackTrace) {
533 return backtrace(StackTrace.data(), MaxDepth);
534}
535template int getStackTrace<16ul>(std::array<void *, 16ul> &);
536} // namespace sys
537} // namespace llvm
538#endif
539
540/// If this is an ELF platform, we can find all loaded modules and their virtual
541/// addresses with dl_iterate_phdr.
542static bool findModulesAndOffsets(void **StackTrace, int Depth,
543 const char **Modules, intptr_t *Offsets,
544 const char *MainExecutableName,
545 StringSaver &StrPool) {
546 DlIteratePhdrData data = {StackTrace, Depth, true,
547 Modules, Offsets, MainExecutableName};
548 dl_iterate_phdr(dl_iterate_phdr_cb, &data);
549 return true;
550}
551
552class DSOMarkupPrinter {
554 const char *MainExecutableName;
555 size_t ModuleCount = 0;
556 bool IsFirst = true;
557
558public:
559 DSOMarkupPrinter(llvm::raw_ostream &OS, const char *MainExecutableName)
560 : OS(OS), MainExecutableName(MainExecutableName) {}
561
562 /// Print llvm-symbolizer markup describing the layout of the given DSO.
563 void printDSOMarkup(dl_phdr_info *Info) {
564 ArrayRef<uint8_t> BuildID = findBuildID(Info);
565 if (BuildID.empty())
566 return;
567 OS << format("{{{module:%d:%s:elf:", ModuleCount,
568 IsFirst ? MainExecutableName : Info->dlpi_name);
569 for (uint8_t X : BuildID)
570 OS << format("%02x", X);
571 OS << "}}}\n";
572
573 for (int I = 0; I < Info->dlpi_phnum; I++) {
574 const auto *Phdr = &Info->dlpi_phdr[I];
575 if (Phdr->p_type != PT_LOAD)
576 continue;
577 uintptr_t StartAddress = Info->dlpi_addr + Phdr->p_vaddr;
578 uintptr_t ModuleRelativeAddress = Phdr->p_vaddr;
579 std::array<char, 4> ModeStr = modeStrFromFlags(Phdr->p_flags);
580 OS << format("{{{mmap:%#016x:%#x:load:%d:%s:%#016x}}}\n", StartAddress,
581 Phdr->p_memsz, ModuleCount, &ModeStr[0],
582 ModuleRelativeAddress);
583 }
584 IsFirst = false;
585 ModuleCount++;
586 }
587
588 /// Callback for use with dl_iterate_phdr. The last dl_iterate_phdr argument
589 /// must be a pointer to an instance of this class.
590 static int printDSOMarkup(dl_phdr_info *Info, size_t Size, void *Arg) {
591 static_cast<DSOMarkupPrinter *>(Arg)->printDSOMarkup(Info);
592 return 0;
593 }
594
595 // Returns the build ID for the given DSO as an array of bytes. Returns an
596 // empty array if none could be found.
597 ArrayRef<uint8_t> findBuildID(dl_phdr_info *Info) {
598 for (int I = 0; I < Info->dlpi_phnum; I++) {
599 const auto *Phdr = &Info->dlpi_phdr[I];
600 if (Phdr->p_type != PT_NOTE)
601 continue;
602
603 ArrayRef<uint8_t> Notes(
604 reinterpret_cast<const uint8_t *>(Info->dlpi_addr + Phdr->p_vaddr),
605 Phdr->p_memsz);
606 while (Notes.size() > 12) {
607 uint32_t NameSize = *reinterpret_cast<const uint32_t *>(Notes.data());
608 Notes = Notes.drop_front(4);
609 uint32_t DescSize = *reinterpret_cast<const uint32_t *>(Notes.data());
610 Notes = Notes.drop_front(4);
611 uint32_t Type = *reinterpret_cast<const uint32_t *>(Notes.data());
612 Notes = Notes.drop_front(4);
613
614 ArrayRef<uint8_t> Name = Notes.take_front(NameSize);
615 auto CurPos = reinterpret_cast<uintptr_t>(Notes.data());
616 uint32_t BytesUntilDesc =
617 alignToPowerOf2(CurPos + NameSize, 4) - CurPos;
618 if (BytesUntilDesc >= Notes.size())
619 break;
620 Notes = Notes.drop_front(BytesUntilDesc);
621
622 ArrayRef<uint8_t> Desc = Notes.take_front(DescSize);
623 CurPos = reinterpret_cast<uintptr_t>(Notes.data());
624 uint32_t BytesUntilNextNote =
625 alignToPowerOf2(CurPos + DescSize, 4) - CurPos;
626 if (BytesUntilNextNote > Notes.size())
627 break;
628 Notes = Notes.drop_front(BytesUntilNextNote);
629
630 if (Type == 3 /*NT_GNU_BUILD_ID*/ && Name.size() >= 3 &&
631 Name[0] == 'G' && Name[1] == 'N' && Name[2] == 'U')
632 return Desc;
633 }
634 }
635 return {};
636 }
637
638 // Returns a symbolizer markup string describing the permissions on a DSO
639 // with the given p_flags.
640 std::array<char, 4> modeStrFromFlags(uint32_t Flags) {
641 std::array<char, 4> Mode;
642 char *Cur = &Mode[0];
643 if (Flags & PF_R)
644 *Cur++ = 'r';
645 if (Flags & PF_W)
646 *Cur++ = 'w';
647 if (Flags & PF_X)
648 *Cur++ = 'x';
649 *Cur = '\0';
650 return Mode;
651 }
652};
653
655 const char *MainExecutableName) {
656 OS << "{{{reset}}}\n";
657 DSOMarkupPrinter MP(OS, MainExecutableName);
658 dl_iterate_phdr(DSOMarkupPrinter::printDSOMarkup, &MP);
659 return true;
660}
661
662#elif ENABLE_BACKTRACES && defined(__APPLE__) && defined(__LP64__)
663static bool findModulesAndOffsets(void **StackTrace, int Depth,
664 const char **Modules, intptr_t *Offsets,
665 const char *MainExecutableName,
666 StringSaver &StrPool) {
667 uint32_t NumImgs = _dyld_image_count();
668 for (uint32_t ImageIndex = 0; ImageIndex < NumImgs; ImageIndex++) {
669 const char *Name = _dyld_get_image_name(ImageIndex);
670 intptr_t Slide = _dyld_get_image_vmaddr_slide(ImageIndex);
671 auto *Header =
672 (const struct mach_header_64 *)_dyld_get_image_header(ImageIndex);
673 if (Header == NULL)
674 continue;
675 auto Cmd = (const struct load_command *)(&Header[1]);
676 for (uint32_t CmdNum = 0; CmdNum < Header->ncmds; ++CmdNum) {
677 uint32_t BaseCmd = Cmd->cmd & ~LC_REQ_DYLD;
678 if (BaseCmd == LC_SEGMENT_64) {
679 auto CmdSeg64 = (const struct segment_command_64 *)Cmd;
680 for (int j = 0; j < Depth; j++) {
681 if (Modules[j])
682 continue;
683 intptr_t Addr = (intptr_t)StackTrace[j];
684 if ((intptr_t)CmdSeg64->vmaddr + Slide <= Addr &&
685 Addr < intptr_t(CmdSeg64->vmaddr + CmdSeg64->vmsize + Slide)) {
686 Modules[j] = Name;
687 Offsets[j] = Addr - Slide;
688 }
689 }
690 }
691 Cmd = (const load_command *)(((const char *)Cmd) + (Cmd->cmdsize));
692 }
693 }
694 return true;
695}
696
698 const char *MainExecutableName) {
699 return false;
700}
701#else
702/// Backtraces are not enabled or we don't yet know how to find all loaded DSOs
703/// on this platform.
704static bool findModulesAndOffsets(void **StackTrace, int Depth,
705 const char **Modules, intptr_t *Offsets,
706 const char *MainExecutableName,
707 StringSaver &StrPool) {
708 return false;
709}
710
712 const char *MainExecutableName) {
713 return false;
714}
715#endif // ENABLE_BACKTRACES && ... (findModulesAndOffsets variants)
716
717#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
718static int unwindBacktrace(void **StackTrace, int MaxEntries) {
719 if (MaxEntries < 0)
720 return 0;
721
722 // Skip the first frame ('unwindBacktrace' itself).
723 int Entries = -1;
724
725 auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
726 // Apparently we need to detect reaching the end of the stack ourselves.
727 void *IP = (void *)_Unwind_GetIP(Context);
728 if (!IP)
729 return _URC_END_OF_STACK;
730
731 assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
732 if (Entries >= 0)
733 StackTrace[Entries] = IP;
734
735 if (++Entries == MaxEntries)
736 return _URC_END_OF_STACK;
737 return _URC_NO_REASON;
738 };
739
740 _Unwind_Backtrace(
741 [](_Unwind_Context *Context, void *Handler) {
742 return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
743 },
744 static_cast<void *>(&HandleFrame));
745 return std::max(Entries, 0);
746}
747#endif
748
749#if ENABLE_BACKTRACES && defined(__MVS__)
750static void zosbacktrace(raw_ostream &OS) {
751 // A function name in the PPA1 can have length 16k.
752 constexpr size_t MAX_ENTRY_NAME = UINT16_MAX;
753 // Limit all other strings to 8 byte.
754 constexpr size_t MAX_OTHER = 8;
755 int32_t dsa_format = -1; // Input/Output
756 void *caaptr = _gtca(); // Input
757 int32_t member_id; // Output
758 char compile_unit_name[MAX_OTHER]; // Output
759 void *compile_unit_address; // Output
760 void *call_instruction_address = nullptr; // Input/Output
761 char entry_name[MAX_ENTRY_NAME]; // Output
762 void *entry_address; // Output
763 void *callers_instruction_address; // Output
764 void *callers_dsaptr; // Output
765 int32_t callers_dsa_format; // Output
766 char statement_id[MAX_OTHER]; // Output
767 void *cibptr; // Output
768 int32_t main_program; // Output
769 _FEEDBACK fc; // Output
770
771 // The DSA pointer is the value of the stack pointer r4.
772 // __builtin_frame_address() returns a pointer to the stack frame, so the
773 // stack bias has to be considered to get the expected DSA value.
774 void *dsaptr = static_cast<char *>(__builtin_frame_address(0)) - 2048;
775 int count = 0;
776 OS << " DSA Adr EP +EP DSA "
777 " Entry\n";
778 while (1) {
779 // After the call, these variables contain the length of the string.
780 int32_t compile_unit_name_length = sizeof(compile_unit_name);
781 int32_t entry_name_length = sizeof(entry_name);
782 int32_t statement_id_length = sizeof(statement_id);
783 // See
784 // https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service
785 // for documentation of the parameters.
786 __CELQTBCK(&dsaptr, &dsa_format, &caaptr, &member_id, &compile_unit_name[0],
787 &compile_unit_name_length, &compile_unit_address,
788 &call_instruction_address, &entry_name[0], &entry_name_length,
789 &entry_address, &callers_instruction_address, &callers_dsaptr,
790 &callers_dsa_format, &statement_id[0], &statement_id_length,
791 &cibptr, &main_program, &fc);
792 if (fc.tok_sev) {
793 OS << format("error: CELQTBCK returned severity %d message %d\n",
794 fc.tok_sev, fc.tok_msgno);
795 break;
796 }
797
798 if (count) { // Omit first entry.
799 uintptr_t diff = reinterpret_cast<uintptr_t>(call_instruction_address) -
800 reinterpret_cast<uintptr_t>(entry_address);
801 OS << format(" %3d. 0x%016lX", count, call_instruction_address);
802 OS << format(" 0x%016lX +0x%08lX 0x%016lX", entry_address, diff, dsaptr);
804 ConverterEBCDIC::convertToUTF8(StringRef(entry_name, entry_name_length),
805 Str);
806 OS << ' ' << Str << '\n';
807 }
808 ++count;
809 if (callers_dsaptr) {
810 dsaptr = callers_dsaptr;
811 dsa_format = callers_dsa_format;
812 call_instruction_address = callers_instruction_address;
813 } else
814 break;
815 }
816}
817#endif
818
819// In the case of a program crash or fault, print out a stack trace so that the
820// user has an indication of why and where we died.
821//
822// On glibc systems we have the 'backtrace' function, which works nicely, but
823// doesn't demangle symbols.
825#if ENABLE_BACKTRACES
826#ifdef __MVS__
827 zosbacktrace(OS);
828#else
829 static void *StackTrace[256];
830 int depth = 0;
831#if defined(HAVE_BACKTRACE)
832 // Use backtrace() to output a backtrace on Linux systems with glibc.
833 if (!depth)
834 depth = backtrace(StackTrace, static_cast<int>(std::size(StackTrace)));
835#endif
836#if defined(HAVE__UNWIND_BACKTRACE)
837 // Try _Unwind_Backtrace() if backtrace() failed.
838 if (!depth)
839 depth =
840 unwindBacktrace(StackTrace, static_cast<int>(std::size(StackTrace)));
841#endif
842 if (!depth)
843 return;
844 // If "Depth" is not provided by the caller, use the return value of
845 // backtrace() for printing a symbolized stack trace.
846 if (!Depth)
847 Depth = depth;
848 if (printMarkupStackTrace(Argv0, StackTrace, Depth, OS))
849 return;
850 if (printSymbolizedStackTrace(Argv0, StackTrace, Depth, OS))
851 return;
852 OS << "Stack dump without symbol names (ensure you have llvm-symbolizer in "
853 "your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point "
854 "to it):\n";
855#if HAVE_DLOPEN && !defined(_AIX)
856 int width = 0;
857 for (int i = 0; i < depth; ++i) {
858 Dl_info dlinfo;
859 int nwidth;
860 if (dladdr(StackTrace[i], &dlinfo) == 0) {
861 nwidth = 7; // "(error)"
862 } else {
863 const char *name = strrchr(dlinfo.dli_fname, '/');
864
865 if (!name)
866 nwidth = strlen(dlinfo.dli_fname);
867 else
868 nwidth = strlen(name) - 1;
869 }
870
871 if (nwidth > width)
872 width = nwidth;
873 }
874
875 for (int i = 0; i < depth; ++i) {
876 Dl_info dlinfo;
877
878 OS << format("%-2d", i);
879
880 if (dladdr(StackTrace[i], &dlinfo) == 0) {
881 OS << format(" %-*s", width, static_cast<const char *>("(error)"));
882 dlinfo.dli_sname = nullptr;
883 } else {
884 const char *name = strrchr(dlinfo.dli_fname, '/');
885 if (!name)
886 OS << format(" %-*s", width, dlinfo.dli_fname);
887 else
888 OS << format(" %-*s", width, name + 1);
889 }
890
891 OS << format(" %#0*lx", (int)(sizeof(void *) * 2) + 2,
892 (unsigned long)StackTrace[i]);
893
894 if (dlinfo.dli_sname != nullptr) {
895 OS << ' ';
896 if (char *d = itaniumDemangle(dlinfo.dli_sname)) {
897 OS << d;
898 free(d);
899 } else {
900 OS << dlinfo.dli_sname;
901 }
902
903 OS << format(" + %tu", (static_cast<const char *>(StackTrace[i]) -
904 static_cast<const char *>(dlinfo.dli_saddr)));
905 }
906 OS << '\n';
907 }
908#elif defined(HAVE_BACKTRACE)
909 backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);
910#endif
911#endif
912#endif
913}
914
915static void PrintStackTraceSignalHandler(void *) {
917}
918
920
921/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
922/// process, print a stack trace and then exit.
924 bool DisableCrashReporting) {
925 ::Argv0 = Argv0;
926
927 AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
928
929#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
930 // Environment variable to disable any kind of crash dialog.
931 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
932 mach_port_t self = mach_task_self();
933
934 exception_mask_t mask = EXC_MASK_CRASH;
935
936 kern_return_t ret = task_set_exception_ports(
937 self, mask, MACH_PORT_NULL,
938 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
939 (void)ret;
940 }
941#endif
942}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
#define LLVM_ATTRIBUTE_USED
Definition Compiler.h:236
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:55
#define I(x, y, z)
Definition MD5.cpp:58
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")))
static const char * name
This file contains some templates that are useful if you are working with the STL at all.
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:259
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:335
static void insertSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie)
Definition Signals.cpp:111
static Split data
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
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
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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:26
iterator end() const
Definition BasicBlock.h:89
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 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:97
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
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:1666
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
Op::Description Desc
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition STLExtras.h:2117
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:504
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:126
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
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:1943
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1886
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
#define N
A utility class that uses RAII to save and restore the value of a variable.