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