942 lines · plain
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines some helpful functions for dealing with the possibility of10// 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 a15// signal handler. In particular, memory allocation and acquiring a mutex16// while in a signal handler should never occur. ManagedStatic isn't usable from17// 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, in21// which case the ManagedStatic is in an unknown state because it could22// 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 handler26// behavior is only modified by one thread at a time. A signal handler can still27// fire while this occurs!28//29// Adding work to a signal handler requires lock-freedom (and assume atomics are30// always lock-free) because the signal handler could fire while new work is31// being added.32//33//===----------------------------------------------------------------------===//34 35#include "Unix.h"36#include "llvm/ADT/STLExtras.h"37#include "llvm/Config/config.h"38#include "llvm/Demangle/Demangle.h"39#include "llvm/Support/ExitCodes.h"40#include "llvm/Support/FileSystem.h"41#include "llvm/Support/FileUtilities.h"42#include "llvm/Support/Format.h"43#include "llvm/Support/MemoryBuffer.h"44#include "llvm/Support/Mutex.h"45#include "llvm/Support/Program.h"46#include "llvm/Support/SaveAndRestore.h"47#include "llvm/Support/raw_ostream.h"48#include <algorithm>49#include <string>50#ifdef HAVE_BACKTRACE51#include BACKTRACE_HEADER // For backtrace().52#endif53#include <signal.h>54#include <sys/stat.h>55#include <dlfcn.h>56#if HAVE_MACH_MACH_H57#include <mach/mach.h>58#endif59#ifdef __APPLE__60#include <mach-o/dyld.h>61#endif62#if __has_include(<link.h>)63#include <link.h>64#endif65#ifdef HAVE__UNWIND_BACKTRACE66// FIXME: We should be able to use <unwind.h> for any target that has an67// _Unwind_Backtrace function, but on FreeBSD the configure test passes68// despite the function not existing, and on Android, <unwind.h> conflicts69// with <link.h>.70#ifdef __GLIBC__71#include <unwind.h>72#else73#undef HAVE__UNWIND_BACKTRACE74#endif75#endif76#if ENABLE_BACKTRACES && defined(__MVS__)77#include "llvm/Support/ConvertEBCDIC.h"78#include <__le_cwi.h>79#endif80 81#if defined(__linux__)82#include <sys/syscall.h>83#endif84 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 files101/// themselves is signal-safe. Memory is freed when the head is freed, deletion102/// 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 access137 // 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 we149 // 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 we158 // 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 removal164 // of special files like /dev/null, even if the compiler is being run165 // 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 is170 // 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're178 // 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 look185 // 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 should202/// 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} // namespace212 213static StringRef Argv0;214 215/// Signals that represent requested termination. There's no bug or failure, or216/// if there is, it's not our direct responsibility. For whatever reason, our217/// 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 has221/// been ordered.222static const int KillSigs[] = {SIGILL,223 SIGTRAP,224 SIGABRT,225 SIGFPE,226 SIGBUS,227 SIGSEGV,228 SIGQUIT229#ifdef SIGSYS230 ,231 SIGSYS232#endif233#ifdef SIGXCPU234 ,235 SIGXCPU236#endif237#ifdef SIGXFSZ238 ,239 SIGXFSZ240#endif241#ifdef SIGEMT242 ,243 SIGEMT244#endif245};246 247/// Signals that represent requests for status.248static const int InfoSigs[] = {SIGUSR1249#ifdef SIGINFO250 ,251 SIGINFO252#endif253};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 not266// reported as a leak. We don't make any attempt to remove our alt signal267// stack if we remove our signal handlers; that can't be done reliably if268// 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 alternate276 // signal stack that we're happy with, there's nothing for us to do. Don't277 // reduce the size, some other part of the process might need a larger stack278 // 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#else292static void CreateSigAltStack() {}293#endif294 295static void RegisterHandlers() { // Not signal-safe.296 // The mutex prevents other threads from registering handlers while we're297 // doing it. We also have to protect the handlers and their count because298 // 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 to307 // 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 346void sys::unregisterHandlers() {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 373 llvm::sys::RunSignalHandlers();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 actually379 // crashes when we return and the signal reissues. This also ensures that if380 // we crash in our signal handler that the program will terminate immediately381 // instead of recursing in the signal handler.382 sys::unregisterHandlers();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.409 llvm::sys::RunSignalHandlers();410 411#ifdef __s390__412 // On S/390, certain signals are delivered with PSW Address pointing to413 // *after* the faulting instruction. Simply returning from the signal414 // handler would continue execution after that point, instead of415 // re-raising the signal. Raise the signal manually in those cases.416 if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)417 raise(Sig);418#endif419 420#if defined(__linux__)421 // Re-raising a signal via `raise` loses the original siginfo. Recent422 // versions of linux (>= 3.9) support processes sending a signal to itself423 // with arbitrary signal information using a syscall. If this syscall is424 // 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#else430 // Signal sent from another userspace process, do not assume that continuing431 // the execution would re-raise it.432 if (Info->si_pid != getpid() && Info->si_pid != 0)433 raise(Sig);434#endif435}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 460void llvm::sys::DefaultOneShotPipeSignalHandler() {461 // Send a special return code that drivers can check for, from sysexits.h.462 exit(EX_IOERR);463}464 465// The public API466bool 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 API476void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {477 FileToRemoveList::erase(FilesToRemove, Filename.str());478}479 480/// Add a function to be called when a signal is delivered to the process. The481/// handler can have a cookie passed to it to identify what instance of the482/// handler it is.483void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,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_ORIGIN526#if !defined(HAVE_BACKTRACE)527#error DebugLoc origin-tracking currently requires `backtrace()`.528#endif529namespace 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 sys537} // namespace llvm538#endif539 540/// If this is an ELF platform, we can find all loaded modules and their virtual541/// 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 {553 llvm::raw_ostream &OS;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 argument589 /// 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 an596 // 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 DSO639 // 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 654static bool printMarkupContext(llvm::raw_ostream &OS,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 697static bool printMarkupContext(llvm::raw_ostream &OS,698 const char *MainExecutableName) {699 return false;700}701#else702/// Backtraces are not enabled or we don't yet know how to find all loaded DSOs703/// 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 711static bool printMarkupContext(llvm::raw_ostream &OS,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#endif748 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/Output756 void *caaptr = _gtca(); // Input757 int32_t member_id; // Output758 char compile_unit_name[MAX_OTHER]; // Output759 void *compile_unit_address; // Output760 void *call_instruction_address = nullptr; // Input/Output761 char entry_name[MAX_ENTRY_NAME]; // Output762 void *entry_address; // Output763 void *callers_instruction_address; // Output764 void *callers_dsaptr; // Output765 int32_t callers_dsa_format; // Output766 char statement_id[MAX_OTHER]; // Output767 void *cibptr; // Output768 int32_t main_program; // Output769 _FEEDBACK fc; // Output770 771 // The DSA pointer is the value of the stack pointer r4.772 // __builtin_frame_address() returns a pointer to the stack frame, so the773 // 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 // See784 // https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service785 // 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);803 SmallString<256> Str;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 } else814 break;815 }816}817#endif818 819// In the case of a program crash or fault, print out a stack trace so that the820// user has an indication of why and where we died.821//822// On glibc systems we have the 'backtrace' function, which works nicely, but823// doesn't demangle symbols.824void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) {825#if ENABLE_BACKTRACES826#ifdef __MVS__827 zosbacktrace(OS);828#else829 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#endif836#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#endif842 if (!depth)843 return;844 // If "Depth" is not provided by the caller, use the return value of845 // 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 else868 nwidth = strlen(name) - 1;869 }870 871 width = std::max(nwidth, width);872 }873 874 for (int i = 0; i < depth; ++i) {875 Dl_info dlinfo;876 877 OS << format("%-2d", i);878 879 if (dladdr(StackTrace[i], &dlinfo) == 0) {880 OS << format(" %-*s", width, static_cast<const char *>("(error)"));881 dlinfo.dli_sname = nullptr;882 } else {883 const char *name = strrchr(dlinfo.dli_fname, '/');884 if (!name)885 OS << format(" %-*s", width, dlinfo.dli_fname);886 else887 OS << format(" %-*s", width, name + 1);888 }889 890 OS << format(" %#0*lx", (int)(sizeof(void *) * 2) + 2,891 (unsigned long)StackTrace[i]);892 893 if (dlinfo.dli_sname != nullptr) {894 OS << ' ';895 if (char *d = itaniumDemangle(dlinfo.dli_sname)) {896 OS << d;897 free(d);898 } else {899 OS << dlinfo.dli_sname;900 }901 902 OS << format(" + %tu", (static_cast<const char *>(StackTrace[i]) -903 static_cast<const char *>(dlinfo.dli_saddr)));904 }905 OS << '\n';906 }907#elif defined(HAVE_BACKTRACE)908 backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO);909#endif910#endif911#endif912}913 914static void PrintStackTraceSignalHandler(void *) {915 sys::PrintStackTrace(llvm::errs());916}917 918void llvm::sys::DisableSystemDialogsOnCrash() {}919 920/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the921/// process, print a stack trace and then exit.922void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0,923 bool DisableCrashReporting) {924 ::Argv0 = Argv0;925 926 AddSignalHandler(PrintStackTraceSignalHandler, nullptr);927 928#if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES929 // Environment variable to disable any kind of crash dialog.930 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {931 mach_port_t self = mach_task_self();932 933 exception_mask_t mask = EXC_MASK_CRASH;934 935 kern_return_t ret = task_set_exception_ports(936 self, mask, MACH_PORT_NULL,937 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);938 (void)ret;939 }940#endif941}942