37#include "llvm/Config/config.h"
51#include BACKTRACE_HEADER
64#include <mach-o/dyld.h>
66#if __has_include(<link.h>)
69#ifdef HAVE__UNWIND_BACKTRACE
77#undef HAVE__UNWIND_BACKTRACE
80#if ENABLE_BACKTRACES && defined(__MVS__)
87static void SignalHandler(
int Sig);
88static void InfoSignalHandler(
int Sig);
90using SignalHandlerFunctionType = void (*)();
92static std::atomic<SignalHandlerFunctionType> InterruptFunction =
nullptr;
93static std::atomic<SignalHandlerFunctionType> InfoSignalFunction =
nullptr;
95static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction =
103class FileToRemoveList {
104 std::atomic<char *>
Filename =
nullptr;
105 std::atomic<FileToRemoveList *> Next =
nullptr;
107 FileToRemoveList() =
default;
109 FileToRemoveList(
const std::string &str) :
Filename(strdup(str.
c_str())) {}
113 ~FileToRemoveList() {
114 if (FileToRemoveList *
N = Next.exchange(
nullptr))
116 if (
char *
F =
Filename.exchange(
nullptr))
121 static void insert(std::atomic<FileToRemoveList *> &Head,
122 const std::string &Filename) {
124 FileToRemoveList *NewHead =
new FileToRemoveList(Filename);
126 FileToRemoveList *OldHead =
nullptr;
127 while (!
InsertionPoint->compare_exchange_strong(OldHead, NewHead)) {
134 static void erase(std::atomic<FileToRemoveList *> &Head,
135 const std::string &Filename) {
141 for (FileToRemoveList *Current = Head.load(); Current;
142 Current = Current->Next.load()) {
143 if (
char *OldFilename = Current->Filename.load()) {
144 if (OldFilename != Filename)
147 OldFilename = Current->Filename.exchange(
nullptr);
157 static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) {
162 FileToRemoveList *OldHead = Head.exchange(
nullptr);
164 for (FileToRemoveList *currentFile = OldHead; currentFile;
165 currentFile = currentFile->Next.load()) {
168 if (
char *path = currentFile->Filename.exchange(
nullptr)) {
172 if (stat(path, &buf) != 0)
178 if (!S_ISREG(buf.st_mode))
186 currentFile->Filename.exchange(path);
191 Head.exchange(OldHead);
194static std::atomic<FileToRemoveList *> FilesToRemove =
nullptr;
199struct FilesToRemoveCleanup {
201 ~FilesToRemoveCleanup() {
202 FileToRemoveList *Head = FilesToRemove.exchange(
nullptr);
214static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2};
218static const int KillSigs[] = {SIGILL,
244static const int InfoSigs[] = {SIGUSR1
251static const size_t NumSigs = std::size(IntSigs) + std::size(KillSigs) +
252 std::size(InfoSigs) + 1 ;
254static std::atomic<unsigned> NumRegisteredSignals = 0;
258} RegisteredSignalInfo[NumSigs];
260#if defined(HAVE_SIGALTSTACK)
265static stack_t OldAltStack;
268static void CreateSigAltStack() {
269 const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
275 if (sigaltstack(
nullptr, &OldAltStack) != 0 ||
276 OldAltStack.ss_flags & SS_ONSTACK ||
277 (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
280 stack_t AltStack = {};
281 AltStack.ss_sp =
static_cast<char *
>(
safe_malloc(AltStackSize));
282 NewAltStackPointer = AltStack.ss_sp;
283 AltStack.ss_size = AltStackSize;
284 if (sigaltstack(&AltStack, &OldAltStack) != 0)
285 free(AltStack.ss_sp);
288static void CreateSigAltStack() {}
291static void RegisterHandlers() {
299 if (NumRegisteredSignals.load() != 0)
306 enum class SignalKind { IsKill, IsInfo };
307 auto registerHandler = [&](
int Signal, SignalKind
Kind) {
308 unsigned Index = NumRegisteredSignals.load();
310 "Out of space for signal handlers!");
312 struct sigaction NewHandler;
315 case SignalKind::IsKill:
316 NewHandler.sa_handler = SignalHandler;
317 NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
319 case SignalKind::IsInfo:
320 NewHandler.sa_handler = InfoSignalHandler;
321 NewHandler.sa_flags = SA_ONSTACK;
324 sigemptyset(&NewHandler.sa_mask);
327 sigaction(Signal, &NewHandler, &RegisteredSignalInfo[
Index].SA);
328 RegisteredSignalInfo[
Index].SigNo = Signal;
329 ++NumRegisteredSignals;
332 for (
auto S : IntSigs)
333 registerHandler(S, SignalKind::IsKill);
334 for (
auto S : KillSigs)
335 registerHandler(S, SignalKind::IsKill);
336 if (OneShotPipeSignalFunction)
337 registerHandler(SIGPIPE, SignalKind::IsKill);
338 for (
auto S : InfoSigs)
339 registerHandler(S, SignalKind::IsInfo);
342void sys::unregisterHandlers() {
344 for (
unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) {
345 sigaction(RegisteredSignalInfo[i].SigNo, &RegisteredSignalInfo[i].SA,
347 --NumRegisteredSignals;
352static void RemoveFilesToRemove() {
353 FileToRemoveList::removeAllFiles(FilesToRemove);
356void sys::CleanupOnSignal(uintptr_t Context) {
357 int Sig = (int)Context;
360 InfoSignalHandler(Sig);
364 RemoveFilesToRemove();
373static void SignalHandler(
int Sig) {
378 sys::unregisterHandlers();
382 sigfillset(&SigMask);
383 sigprocmask(SIG_UNBLOCK, &SigMask,
nullptr);
386 RemoveFilesToRemove();
389 if (
auto OldOneShotPipeFunction =
390 OneShotPipeSignalFunction.exchange(
nullptr))
391 return OldOneShotPipeFunction();
395 if (
auto OldInterruptFunction = InterruptFunction.exchange(
nullptr))
396 return OldInterruptFunction();
398 if (Sig == SIGPIPE || IsIntSig) {
412 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
417static void InfoSignalHandler(
int Sig) {
419 if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
420 CurrentInfoFunction();
426 InterruptFunction.exchange(IF);
431 InfoSignalFunction.exchange(Handler);
436 OneShotPipeSignalFunction.exchange(Handler);
449 *FilesToRemoveCleanup;
450 FileToRemoveList::insert(FilesToRemove,
Filename.str());
457 FileToRemoveList::erase(FilesToRemove,
Filename.str());
469#if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \
470 (defined(__linux__) || defined(__FreeBSD__) || \
471 defined(__FreeBSD_kernel__) || defined(__NetBSD__))
472struct DlIteratePhdrData {
476 const char **modules;
478 const char *main_exec_name;
481static int dl_iterate_phdr_cb(dl_phdr_info *
info,
size_t size,
void *arg) {
482 DlIteratePhdrData *data = (DlIteratePhdrData *)arg;
483 const char *
name = data->first ? data->main_exec_name :
info->dlpi_name;
485 for (
int i = 0; i <
info->dlpi_phnum; i++) {
486 const auto *phdr = &
info->dlpi_phdr[i];
487 if (phdr->p_type != PT_LOAD)
489 intptr_t beg =
info->dlpi_addr + phdr->p_vaddr;
490 intptr_t
end = beg + phdr->p_memsz;
491 for (
int j = 0;
j < data->depth;
j++) {
492 if (data->modules[j])
494 intptr_t addr = (intptr_t)data->StackTrace[j];
495 if (beg <= addr && addr < end) {
496 data->modules[
j] =
name;
497 data->offsets[
j] = addr -
info->dlpi_addr;
507 const char **Modules, intptr_t *Offsets,
508 const char *MainExecutableName,
510 DlIteratePhdrData data = {StackTrace,
Depth,
true,
511 Modules,
Offsets, MainExecutableName};
512 dl_iterate_phdr(dl_iterate_phdr_cb, &data);
516class DSOMarkupPrinter {
518 const char *MainExecutableName;
519 size_t ModuleCount = 0;
524 :
OS(
OS), MainExecutableName(MainExecutableName) {}
527 void printDSOMarkup(dl_phdr_info *
Info) {
531 OS <<
format(
"{{{module:%d:%s:elf:", ModuleCount,
532 IsFirst ? MainExecutableName :
Info->dlpi_name);
537 for (
int I = 0;
I <
Info->dlpi_phnum;
I++) {
538 const auto *Phdr = &
Info->dlpi_phdr[
I];
539 if (Phdr->p_type != PT_LOAD)
541 uintptr_t StartAddress =
Info->dlpi_addr + Phdr->p_vaddr;
542 uintptr_t ModuleRelativeAddress = Phdr->p_vaddr;
543 std::array<char, 4> ModeStr = modeStrFromFlags(Phdr->p_flags);
544 OS <<
format(
"{{{mmap:%#016x:%#x:load:%d:%s:%#016x}}}\n", StartAddress,
545 Phdr->p_memsz, ModuleCount, &ModeStr[0],
546 ModuleRelativeAddress);
554 static int printDSOMarkup(dl_phdr_info *
Info,
size_t Size,
void *Arg) {
555 static_cast<DSOMarkupPrinter *
>(Arg)->printDSOMarkup(
Info);
562 for (
int I = 0;
I <
Info->dlpi_phnum;
I++) {
563 const auto *Phdr = &
Info->dlpi_phdr[
I];
564 if (Phdr->p_type != PT_NOTE)
568 reinterpret_cast<const uint8_t *
>(
Info->dlpi_addr + Phdr->p_vaddr),
570 while (Notes.size() > 12) {
572 Notes = Notes.drop_front(4);
574 Notes = Notes.drop_front(4);
576 Notes = Notes.drop_front(4);
579 auto CurPos =
reinterpret_cast<uintptr_t
>(Notes.data());
582 if (BytesUntilDesc >= Notes.size())
584 Notes = Notes.drop_front(BytesUntilDesc);
587 CurPos =
reinterpret_cast<uintptr_t
>(Notes.data());
590 if (BytesUntilNextNote > Notes.size())
592 Notes = Notes.drop_front(BytesUntilNextNote);
594 if (
Type == 3 &&
Name.size() >= 3 &&
604 std::array<char, 4> modeStrFromFlags(
uint32_t Flags) {
605 std::array<char, 4>
Mode;
606 char *Cur = &
Mode[0];
619 const char *MainExecutableName) {
620 OS <<
"{{{reset}}}\n";
621 DSOMarkupPrinter MP(
OS, MainExecutableName);
622 dl_iterate_phdr(DSOMarkupPrinter::printDSOMarkup, &MP);
626#elif ENABLE_BACKTRACES && defined(__APPLE__) && defined(__LP64__)
628 const char **Modules, intptr_t *Offsets,
629 const char *MainExecutableName,
631 uint32_t NumImgs = _dyld_image_count();
632 for (
uint32_t ImageIndex = 0; ImageIndex < NumImgs; ImageIndex++) {
633 const char *
Name = _dyld_get_image_name(ImageIndex);
634 intptr_t Slide = _dyld_get_image_vmaddr_slide(ImageIndex);
636 (
const struct mach_header_64 *)_dyld_get_image_header(ImageIndex);
639 auto Cmd = (
const struct load_command *)(&Header[1]);
640 for (
uint32_t CmdNum = 0; CmdNum < Header->ncmds; ++CmdNum) {
641 uint32_t BaseCmd = Cmd->cmd & ~LC_REQ_DYLD;
642 if (BaseCmd == LC_SEGMENT_64) {
643 auto CmdSeg64 = (
const struct segment_command_64 *)Cmd;
644 for (
int j = 0;
j <
Depth;
j++) {
647 intptr_t
Addr = (intptr_t)StackTrace[j];
648 if ((intptr_t)CmdSeg64->vmaddr + Slide <=
Addr &&
649 Addr < intptr_t(CmdSeg64->vmaddr + CmdSeg64->vmsize + Slide)) {
655 Cmd = (
const load_command *)(((
const char *)Cmd) + (Cmd->cmdsize));
662 const char *MainExecutableName) {
669 const char **Modules, intptr_t *Offsets,
670 const char *MainExecutableName,
676 const char *MainExecutableName) {
681#if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
682static int unwindBacktrace(
void **StackTrace,
int MaxEntries) {
689 auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
691 void *IP = (
void *)_Unwind_GetIP(Context);
693 return _URC_END_OF_STACK;
695 assert(Entries < MaxEntries &&
"recursively called after END_OF_STACK?");
697 StackTrace[Entries] = IP;
699 if (++Entries == MaxEntries)
700 return _URC_END_OF_STACK;
701 return _URC_NO_REASON;
705 [](_Unwind_Context *Context,
void *Handler) {
706 return (*
static_cast<decltype(HandleFrame) *
>(Handler))(Context);
708 static_cast<void *
>(&HandleFrame));
709 return std::max(Entries, 0);
713#if ENABLE_BACKTRACES && defined(__MVS__)
716 constexpr size_t MAX_ENTRY_NAME = UINT16_MAX;
718 constexpr size_t MAX_OTHER = 8;
719 int32_t dsa_format = -1;
720 void *caaptr = _gtca();
722 char compile_unit_name[MAX_OTHER];
723 void *compile_unit_address;
724 void *call_instruction_address =
nullptr;
725 char entry_name[MAX_ENTRY_NAME];
727 void *callers_instruction_address;
728 void *callers_dsaptr;
729 int32_t callers_dsa_format;
730 char statement_id[MAX_OTHER];
732 int32_t main_program;
738 void *dsaptr =
static_cast<char *
>(__builtin_frame_address(0)) - 2048;
740 OS <<
" DSA Adr EP +EP DSA "
744 int32_t compile_unit_name_length =
sizeof(compile_unit_name);
745 int32_t entry_name_length =
sizeof(entry_name);
746 int32_t statement_id_length =
sizeof(statement_id);
750 __CELQTBCK(&dsaptr, &dsa_format, &caaptr, &member_id, &compile_unit_name[0],
751 &compile_unit_name_length, &compile_unit_address,
752 &call_instruction_address, &entry_name[0], &entry_name_length,
753 &entry_address, &callers_instruction_address, &callers_dsaptr,
754 &callers_dsa_format, &statement_id[0], &statement_id_length,
755 &cibptr, &main_program, &fc);
757 OS <<
format(
"error: CELQTBCK returned severity %d message %d\n",
758 fc.tok_sev, fc.tok_msgno);
763 uintptr_t diff =
reinterpret_cast<uintptr_t
>(call_instruction_address) -
764 reinterpret_cast<uintptr_t
>(entry_address);
765 OS <<
format(
" %3d. 0x%016lX", count, call_instruction_address);
766 OS <<
format(
" 0x%016lX +0x%08lX 0x%016lX", entry_address, diff, dsaptr);
768 ConverterEBCDIC::convertToUTF8(
StringRef(entry_name, entry_name_length),
770 OS <<
' ' << Str <<
'\n';
773 if (callers_dsaptr) {
774 dsaptr = callers_dsaptr;
775 dsa_format = callers_dsa_format;
776 call_instruction_address = callers_instruction_address;
793 static void *StackTrace[256];
795#if defined(HAVE_BACKTRACE)
798 depth = backtrace(StackTrace,
static_cast<int>(std::size(StackTrace)));
800#if defined(HAVE__UNWIND_BACKTRACE)
804 unwindBacktrace(StackTrace,
static_cast<int>(std::size(StackTrace)));
816 OS <<
"Stack dump without symbol names (ensure you have llvm-symbolizer in "
817 "your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point "
819#if HAVE_DLFCN_H && HAVE_DLADDR
821 for (
int i = 0; i < depth; ++i) {
823 dladdr(StackTrace[i], &dlinfo);
824 const char *
name = strrchr(dlinfo.dli_fname,
'/');
828 nwidth = strlen(dlinfo.dli_fname);
830 nwidth = strlen(
name) - 1;
836 for (
int i = 0; i < depth; ++i) {
838 dladdr(StackTrace[i], &dlinfo);
842 const char *
name = strrchr(dlinfo.dli_fname,
'/');
844 OS <<
format(
" %-*s", width, dlinfo.dli_fname);
848 OS <<
format(
" %#0*lx", (
int)(
sizeof(
void *) * 2) + 2,
849 (
unsigned long)StackTrace[i]);
851 if (dlinfo.dli_sname !=
nullptr) {
857 OS << dlinfo.dli_sname;
860 OS <<
format(
" + %tu", (
static_cast<const char *
>(StackTrace[i]) -
861 static_cast<const char *
>(dlinfo.dli_saddr)));
865#elif defined(HAVE_BACKTRACE)
866 backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);
872static void PrintStackTraceSignalHandler(
void *) {
881 bool DisableCrashReporting) {
886#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
888 if (DisableCrashReporting || getenv(
"LLVM_DISABLE_CRASH_REPORT")) {
889 mach_port_t
self = mach_task_self();
891 exception_mask_t
mask = EXC_MASK_CRASH;
893 kern_return_t ret = task_set_exception_ports(
894 self, mask, MACH_PORT_NULL,
895 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
Analysis containing CSE Info
#define LLVM_ATTRIBUTE_USED
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file contains definitions of exit codes for exit() function.
ToRemove erase(NewLastIter, ToRemove.end())
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())
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.
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)
static void insertSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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...
StringRef - Represent a constant reference to a string, i.e.
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
The instances of the Type class are immutable: once they are created, they are never changed.
This class implements an extremely fast bulk output stream that can only output to a stream.
SmallVector< uint8_t, 10 > BuildID
A build ID in binary form.
const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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
void(*)(void *) SignalHandlerCallback
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
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.
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.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * safe_malloc(size_t Sz)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
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...
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
auto mask(ShuffFunc S, unsigned Length, OptArgs... args) -> MaskT
Description of the encoding of one expression Op.
A utility class that uses RAII to save and restore the value of a variable.