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