LCOV - code coverage report
Current view: top level - lib/Support/Unix - Signals.inc (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 97 146 66.4 %
Date: 2018-06-17 00:07:59 Functions: 18 25 72.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- Signals.cpp - Generic Unix Signals Implementation -----*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file defines some helpful functions for dealing with the possibility of
      11             : // Unix signals occurring while your program is running.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : //
      15             : // This file is extremely careful to only do signal-safe things while in a
      16             : // signal handler. In particular, memory allocation and acquiring a mutex
      17             : // while in a signal handler should never occur. ManagedStatic isn't usable from
      18             : // a signal handler for 2 reasons:
      19             : //
      20             : //  1. Creating a new one allocates.
      21             : //  2. The signal handler could fire while llvm_shutdown is being processed, in
      22             : //     which case the ManagedStatic is in an unknown state because it could
      23             : //     already have been destroyed, or be in the process of being destroyed.
      24             : //
      25             : // Modifying the behavior of the signal handlers (such as registering new ones)
      26             : // can acquire a mutex, but all this guarantees is that the signal handler
      27             : // behavior is only modified by one thread at a time. A signal handler can still
      28             : // fire while this occurs!
      29             : //
      30             : // Adding work to a signal handler requires lock-freedom (and assume atomics are
      31             : // always lock-free) because the signal handler could fire while new work is
      32             : // being added.
      33             : //
      34             : //===----------------------------------------------------------------------===//
      35             : 
      36             : #include "Unix.h"
      37             : #include "llvm/ADT/STLExtras.h"
      38             : #include "llvm/Config/config.h"
      39             : #include "llvm/Demangle/Demangle.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/UniqueLock.h"
      47             : #include "llvm/Support/raw_ostream.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             : #if HAVE_LINK_H
      66             : #include <link.h>
      67             : #endif
      68             : #ifdef HAVE__UNWIND_BACKTRACE
      69             : // FIXME: We should be able to use <unwind.h> for any target that has an
      70             : // _Unwind_Backtrace function, but on FreeBSD the configure test passes
      71             : // despite the function not existing, and on Android, <unwind.h> conflicts
      72             : // with <link.h>.
      73             : #ifdef __GLIBC__
      74             : #include <unwind.h>
      75             : #else
      76             : #undef HAVE__UNWIND_BACKTRACE
      77             : #endif
      78             : #endif
      79             : 
      80             : using namespace llvm;
      81             : 
      82             : static RETSIGTYPE SignalHandler(int Sig);  // defined below.
      83             : 
      84             : /// The function to call if ctrl-c is pressed.
      85             : using InterruptFunctionType = void (*)();
      86             : static std::atomic<InterruptFunctionType> InterruptFunction =
      87             :     ATOMIC_VAR_INIT(nullptr);
      88             : 
      89             : /// Signal-safe removal of files.
      90             : /// Inserting and erasing from the list isn't signal-safe, but removal of files
      91             : /// themselves is signal-safe. Memory is freed when the head is freed, deletion
      92             : /// is therefore not signal-safe either.
      93             : class FileToRemoveList {
      94             :   std::atomic<char *> Filename = ATOMIC_VAR_INIT(nullptr);
      95             :   std::atomic<FileToRemoveList *> Next = ATOMIC_VAR_INIT(nullptr);
      96             : 
      97             :   FileToRemoveList() = default;
      98             :   // Not signal-safe.
      99       49538 :   FileToRemoveList(const std::string &str) : Filename(strdup(str.c_str())) {}
     100             : 
     101             : public:
     102             :   // Not signal-safe.
     103       49066 :   ~FileToRemoveList() {
     104       24533 :     if (FileToRemoveList *N = Next.exchange(nullptr))
     105        4255 :       delete N;
     106       24533 :     if (char *F = Filename.exchange(nullptr))
     107       12487 :       free(F);
     108       24533 :   }
     109             : 
     110             :   // Not signal-safe.
     111       24769 :   static void insert(std::atomic<FileToRemoveList *> &Head,
     112             :                      const std::string &Filename) {
     113             :     // Insert the new file at the end of the list.
     114       24769 :     FileToRemoveList *NewHead = new FileToRemoveList(Filename);
     115             :     std::atomic<FileToRemoveList *> *InsertionPoint = &Head;
     116             :     FileToRemoveList *OldHead = nullptr;
     117       40725 :     while (!InsertionPoint->compare_exchange_strong(OldHead, NewHead)) {
     118        7978 :       InsertionPoint = &OldHead->Next;
     119             :       OldHead = nullptr;
     120             :     }
     121       24769 :   }
     122             : 
     123             :   // Not signal-safe.
     124       12284 :   static void erase(std::atomic<FileToRemoveList *> &Head,
     125             :                     const std::string &Filename) {
     126             :     // Use a lock to avoid concurrent erase: the comparison would access
     127             :     // free'd memory.
     128       12284 :     static ManagedStatic<sys::SmartMutex<true>> Lock;
     129       12284 :     sys::SmartScopedLock<true> Writer(*Lock);
     130             : 
     131       53526 :     for (FileToRemoveList *Current = Head.load(); Current;
     132             :          Current = Current->Next.load()) {
     133       20621 :       if (char *OldFilename = Current->Filename.load()) {
     134       13435 :         if (OldFilename != Filename)
     135        1185 :           continue;
     136             :         // Leave an empty filename.
     137             :         OldFilename = Current->Filename.exchange(nullptr);
     138             :         // The filename might have become null between the time we
     139             :         // compared it and we exchanged it.
     140       12250 :         if (OldFilename)
     141       12250 :           free(OldFilename);
     142             :       }
     143             :     }
     144       12284 :   }
     145             : 
     146             :   // Signal-safe.
     147         322 :   static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) {
     148             :     // If cleanup were to occur while we're removing files we'd have a bad time.
     149             :     // Make sure we're OK by preventing cleanup from doing anything while we're
     150             :     // removing files. If cleanup races with us and we win we'll have a leak,
     151             :     // but we won't crash.
     152             :     FileToRemoveList *OldHead = Head.exchange(nullptr);
     153             : 
     154         386 :     for (FileToRemoveList *currentFile = OldHead; currentFile;
     155             :          currentFile = currentFile->Next.load()) {
     156             :       // If erasing was occuring while we're trying to remove files we'd look
     157             :       // at free'd data. Take away the path and put it back when done.
     158          32 :       if (char *path = currentFile->Filename.exchange(nullptr)) {
     159             :         // Get the status so we can determine if it's a file or directory. If we
     160             :         // can't stat the file, ignore it.
     161             :         struct stat buf;
     162          29 :         if (stat(path, &buf) != 0)
     163          24 :           continue;
     164             : 
     165             :         // If this is not a regular file, ignore it. We want to prevent removal
     166             :         // of special files like /dev/null, even if the compiler is being run
     167             :         // with the super-user permissions.
     168          28 :         if (!S_ISREG(buf.st_mode))
     169          22 :           continue;
     170             : 
     171             :         // Otherwise, remove the file. We ignore any errors here as there is
     172             :         // nothing else we can do.
     173           6 :         unlink(path);
     174             : 
     175             :         // We're done removing the file, erasing can safely proceed.
     176             :         currentFile->Filename.exchange(path);
     177             :       }
     178             :     }
     179             : 
     180             :     // We're done removing files, cleanup can safely proceed.
     181             :     Head.exchange(OldHead);
     182         322 :   }
     183             : };
     184             : static std::atomic<FileToRemoveList *> FilesToRemove = ATOMIC_VAR_INIT(nullptr);
     185             : 
     186             : /// Clean up the list in a signal-friendly manner.
     187             : /// Recall that signals can fire during llvm_shutdown. If this occurs we should
     188             : /// either clean something up or nothing at all, but we shouldn't crash!
     189             : struct FilesToRemoveCleanup {
     190             :   // Not signal-safe.
     191       20278 :   ~FilesToRemoveCleanup() {
     192             :     FileToRemoveList *Head = FilesToRemove.exchange(nullptr);
     193       20278 :     if (Head)
     194       20278 :       delete Head;
     195       20278 :   }
     196             : };
     197             : 
     198             : static StringRef Argv0;
     199             : 
     200             : // Signals that represent requested termination. There's no bug or failure, or
     201             : // if there is, it's not our direct responsibility. For whatever reason, our
     202             : // continued execution is no longer desirable.
     203             : static const int IntSigs[] = {
     204             :   SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
     205             : };
     206             : 
     207             : // Signals that represent that we have a bug, and our prompt termination has
     208             : // been ordered.
     209             : static const int KillSigs[] = {
     210             :   SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
     211             : #ifdef SIGSYS
     212             :   , SIGSYS
     213             : #endif
     214             : #ifdef SIGXCPU
     215             :   , SIGXCPU
     216             : #endif
     217             : #ifdef SIGXFSZ
     218             :   , SIGXFSZ
     219             : #endif
     220             : #ifdef SIGEMT
     221             :   , SIGEMT
     222             : #endif
     223             : };
     224             : 
     225             : static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0);
     226             : static struct {
     227             :   struct sigaction SA;
     228             :   int SigNo;
     229             : } RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)];
     230             : 
     231             : #if defined(HAVE_SIGALTSTACK)
     232             : // Hold onto both the old and new alternate signal stack so that it's not
     233             : // reported as a leak. We don't make any attempt to remove our alt signal
     234             : // stack if we remove our signal handlers; that can't be done reliably if
     235             : // someone else is also trying to do the same thing.
     236             : static stack_t OldAltStack;
     237             : static void* NewAltStackPointer;
     238             : 
     239      156993 : static void CreateSigAltStack() {
     240             :   const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024;
     241             : 
     242             :   // If we're executing on the alternate stack, or we already have an alternate
     243             :   // signal stack that we're happy with, there's nothing for us to do. Don't
     244             :   // reduce the size, some other part of the process might need a larger stack
     245             :   // than we do.
     246      313986 :   if (sigaltstack(nullptr, &OldAltStack) != 0 ||
     247      313986 :       OldAltStack.ss_flags & SS_ONSTACK ||
     248      156993 :       (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize))
     249           0 :     return;
     250             : 
     251      156993 :   stack_t AltStack = {};
     252      156993 :   AltStack.ss_sp = static_cast<char *>(safe_malloc(AltStackSize));
     253      156993 :   NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak.
     254      156993 :   AltStack.ss_size = AltStackSize;
     255      156993 :   if (sigaltstack(&AltStack, &OldAltStack) != 0)
     256           0 :     free(AltStack.ss_sp);
     257             : }
     258             : #else
     259             : static void CreateSigAltStack() {}
     260             : #endif
     261             : 
     262      329313 : static void RegisterHandlers() { // Not signal-safe.
     263             :   // The mutex prevents other threads from registering handlers while we're
     264             :   // doing it. We also have to protect the handlers and their count because
     265             :   // a signal handler could fire while we're registeting handlers.
     266      329313 :   static ManagedStatic<sys::SmartMutex<true>> SignalHandlerRegistrationMutex;
     267      329313 :   sys::SmartScopedLock<true> Guard(*SignalHandlerRegistrationMutex);
     268             : 
     269             :   // If the handlers are already registered, we're done.
     270      329313 :   if (NumRegisteredSignals.load() != 0)
     271             :     return;
     272             : 
     273             :   // Create an alternate stack for signal handling. This is necessary for us to
     274             :   // be able to reliably handle signals due to stack overflow.
     275      156993 :   CreateSigAltStack();
     276             : 
     277     2511888 :   auto registerHandler = [&](int Signal) {
     278             :     unsigned Index = NumRegisteredSignals.load();
     279             :     assert(Index < array_lengthof(RegisteredSignalInfo) &&
     280             :            "Out of space for signal handlers!");
     281             : 
     282             :     struct sigaction NewHandler;
     283             : 
     284     2511888 :     NewHandler.sa_handler = SignalHandler;
     285     2511888 :     NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
     286     2511888 :     sigemptyset(&NewHandler.sa_mask);
     287             : 
     288             :     // Install the new handler, save the old one in RegisteredSignalInfo.
     289     2511888 :     sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
     290     2511888 :     RegisteredSignalInfo[Index].SigNo = Signal;
     291             :     ++NumRegisteredSignals;
     292     2511888 :   };
     293             : 
     294     2040909 :   for (auto S : IntSigs)
     295      941958 :     registerHandler(S);
     296     3296853 :   for (auto S : KillSigs)
     297     1569930 :     registerHandler(S);
     298             : }
     299             : 
     300           9 : static void UnregisterHandlers() {
     301             :   // Restore all of the signal handlers to how they were before we showed up.
     302         297 :   for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) {
     303         144 :     sigaction(RegisteredSignalInfo[i].SigNo,
     304         144 :               &RegisteredSignalInfo[i].SA, nullptr);
     305             :     --NumRegisteredSignals;
     306             :   }
     307           9 : }
     308             : 
     309             : /// Process the FilesToRemove list.
     310             : static void RemoveFilesToRemove() {
     311         322 :   FileToRemoveList::removeAllFiles(FilesToRemove);
     312             : }
     313             : 
     314             : // The signal handler that runs.
     315           9 : static RETSIGTYPE SignalHandler(int Sig) {
     316             :   // Restore the signal behavior to default, so that the program actually
     317             :   // crashes when we return and the signal reissues.  This also ensures that if
     318             :   // we crash in our signal handler that the program will terminate immediately
     319             :   // instead of recursing in the signal handler.
     320           9 :   UnregisterHandlers();
     321             : 
     322             :   // Unmask all potentially blocked kill signals.
     323             :   sigset_t SigMask;
     324           9 :   sigfillset(&SigMask);
     325           9 :   sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
     326             : 
     327             :   {
     328             :     RemoveFilesToRemove();
     329             : 
     330           9 :     if (std::find(std::begin(IntSigs), std::end(IntSigs), Sig)
     331             :         != std::end(IntSigs)) {
     332           9 :       if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
     333           9 :         return OldInterruptFunction();
     334             : 
     335           9 :       raise(Sig);   // Execute the default handler.
     336           9 :       return;
     337             :    }
     338             :   }
     339             : 
     340             :   // Otherwise if it is a fault (like SEGV) run any handler.
     341           0 :   llvm::sys::RunSignalHandlers();
     342             : 
     343             : #ifdef __s390__
     344             :   // On S/390, certain signals are delivered with PSW Address pointing to
     345             :   // *after* the faulting instruction.  Simply returning from the signal
     346             :   // handler would continue execution after that point, instead of
     347             :   // re-raising the signal.  Raise the signal manually in those cases.
     348             :   if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
     349             :     raise(Sig);
     350             : #endif
     351             : }
     352             : 
     353         313 : void llvm::sys::RunInterruptHandlers() {
     354             :   RemoveFilesToRemove();
     355         313 : }
     356             : 
     357          11 : void llvm::sys::SetInterruptFunction(void (*IF)()) {
     358             :   InterruptFunction.exchange(IF);
     359          11 :   RegisterHandlers();
     360          11 : }
     361             : 
     362             : // The public API
     363       24769 : bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
     364             :                                    std::string* ErrMsg) {
     365             :   // Ensure that cleanup will occur as soon as one file is added.
     366       24769 :   static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup;
     367       24769 :   *FilesToRemoveCleanup;
     368       49538 :   FileToRemoveList::insert(FilesToRemove, Filename.str());
     369       24769 :   RegisterHandlers();
     370       24769 :   return false;
     371             : }
     372             : 
     373             : // The public API
     374       12284 : void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
     375       24568 :   FileToRemoveList::erase(FilesToRemove, Filename.str());
     376       12284 : }
     377             : 
     378             : /// Add a function to be called when a signal is delivered to the process. The
     379             : /// handler can have a cookie passed to it to identify what instance of the
     380             : /// handler it is.
     381      304533 : void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
     382             :                                  void *Cookie) { // Signal-safe.
     383      304533 :   insertSignalHandler(FnPtr, Cookie);
     384      304533 :   RegisterHandlers();
     385      304533 : }
     386             : 
     387             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && HAVE_LINK_H &&    \
     388             :     (defined(__linux__) || defined(__FreeBSD__) ||                             \
     389             :      defined(__FreeBSD_kernel__) || defined(__NetBSD__))
     390             : struct DlIteratePhdrData {
     391             :   void **StackTrace;
     392             :   int depth;
     393             :   bool first;
     394             :   const char **modules;
     395             :   intptr_t *offsets;
     396             :   const char *main_exec_name;
     397             : };
     398             : 
     399           0 : static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
     400             :   DlIteratePhdrData *data = (DlIteratePhdrData*)arg;
     401           0 :   const char *name = data->first ? data->main_exec_name : info->dlpi_name;
     402           0 :   data->first = false;
     403           0 :   for (int i = 0; i < info->dlpi_phnum; i++) {
     404           0 :     const auto *phdr = &info->dlpi_phdr[i];
     405           0 :     if (phdr->p_type != PT_LOAD)
     406           0 :       continue;
     407           0 :     intptr_t beg = info->dlpi_addr + phdr->p_vaddr;
     408           0 :     intptr_t end = beg + phdr->p_memsz;
     409           0 :     for (int j = 0; j < data->depth; j++) {
     410           0 :       if (data->modules[j])
     411           0 :         continue;
     412           0 :       intptr_t addr = (intptr_t)data->StackTrace[j];
     413           0 :       if (beg <= addr && addr < end) {
     414           0 :         data->modules[j] = name;
     415           0 :         data->offsets[j] = addr - info->dlpi_addr;
     416             :       }
     417             :     }
     418             :   }
     419           0 :   return 0;
     420             : }
     421             : 
     422             : /// If this is an ELF platform, we can find all loaded modules and their virtual
     423             : /// addresses with dl_iterate_phdr.
     424             : static bool findModulesAndOffsets(void **StackTrace, int Depth,
     425             :                                   const char **Modules, intptr_t *Offsets,
     426             :                                   const char *MainExecutableName,
     427             :                                   StringSaver &StrPool) {
     428           0 :   DlIteratePhdrData data = {StackTrace, Depth,   true,
     429           0 :                             Modules,    Offsets, MainExecutableName};
     430           0 :   dl_iterate_phdr(dl_iterate_phdr_cb, &data);
     431             :   return true;
     432             : }
     433             : #else
     434             : /// This platform does not have dl_iterate_phdr, so we do not yet know how to
     435             : /// find all loaded DSOs.
     436             : static bool findModulesAndOffsets(void **StackTrace, int Depth,
     437             :                                   const char **Modules, intptr_t *Offsets,
     438             :                                   const char *MainExecutableName,
     439             :                                   StringSaver &StrPool) {
     440             :   return false;
     441             : }
     442             : #endif // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES && ...
     443             : 
     444             : #if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE)
     445           0 : static int unwindBacktrace(void **StackTrace, int MaxEntries) {
     446           0 :   if (MaxEntries < 0)
     447             :     return 0;
     448             : 
     449             :   // Skip the first frame ('unwindBacktrace' itself).
     450           0 :   int Entries = -1;
     451             : 
     452           0 :   auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
     453             :     // Apparently we need to detect reaching the end of the stack ourselves.
     454           0 :     void *IP = (void *)_Unwind_GetIP(Context);
     455           0 :     if (!IP)
     456             :       return _URC_END_OF_STACK;
     457             : 
     458             :     assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
     459           0 :     if (Entries >= 0)
     460           0 :       StackTrace[Entries] = IP;
     461             : 
     462           0 :     if (++Entries == MaxEntries)
     463             :       return _URC_END_OF_STACK;
     464           0 :     return _URC_NO_REASON;
     465           0 :   };
     466             : 
     467           0 :   _Unwind_Backtrace(
     468           0 :       [](_Unwind_Context *Context, void *Handler) {
     469             :         return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
     470           0 :       },
     471             :       static_cast<void *>(&HandleFrame));
     472           0 :   return std::max(Entries, 0);
     473             : }
     474             : #endif
     475             : 
     476             : // In the case of a program crash or fault, print out a stack trace so that the
     477             : // user has an indication of why and where we died.
     478             : //
     479             : // On glibc systems we have the 'backtrace' function, which works nicely, but
     480             : // doesn't demangle symbols.
     481           0 : void llvm::sys::PrintStackTrace(raw_ostream &OS) {
     482             : #if ENABLE_BACKTRACES
     483             :   static void *StackTrace[256];
     484             :   int depth = 0;
     485             : #if defined(HAVE_BACKTRACE)
     486             :   // Use backtrace() to output a backtrace on Linux systems with glibc.
     487             :   if (!depth)
     488           0 :     depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace)));
     489             : #endif
     490             : #if defined(HAVE__UNWIND_BACKTRACE)
     491             :   // Try _Unwind_Backtrace() if backtrace() failed.
     492           0 :   if (!depth)
     493           0 :     depth = unwindBacktrace(StackTrace,
     494             :                         static_cast<int>(array_lengthof(StackTrace)));
     495             : #endif
     496           0 :   if (!depth)
     497             :     return;
     498             : 
     499           0 :   if (printSymbolizedStackTrace(Argv0, StackTrace, depth, OS))
     500             :     return;
     501             : #if HAVE_DLFCN_H && HAVE_DLADDR
     502             :   int width = 0;
     503             :   for (int i = 0; i < depth; ++i) {
     504             :     Dl_info dlinfo;
     505             :     dladdr(StackTrace[i], &dlinfo);
     506             :     const char* name = strrchr(dlinfo.dli_fname, '/');
     507             : 
     508             :     int nwidth;
     509             :     if (!name) nwidth = strlen(dlinfo.dli_fname);
     510             :     else       nwidth = strlen(name) - 1;
     511             : 
     512             :     if (nwidth > width) width = nwidth;
     513             :   }
     514             : 
     515             :   for (int i = 0; i < depth; ++i) {
     516             :     Dl_info dlinfo;
     517             :     dladdr(StackTrace[i], &dlinfo);
     518             : 
     519             :     OS << format("%-2d", i);
     520             : 
     521             :     const char* name = strrchr(dlinfo.dli_fname, '/');
     522             :     if (!name) OS << format(" %-*s", width, dlinfo.dli_fname);
     523             :     else       OS << format(" %-*s", width, name+1);
     524             : 
     525             :     OS << format(" %#0*lx", (int)(sizeof(void*) * 2) + 2,
     526             :                  (unsigned long)StackTrace[i]);
     527             : 
     528             :     if (dlinfo.dli_sname != nullptr) {
     529             :       OS << ' ';
     530             :       int res;
     531             :       char* d = itaniumDemangle(dlinfo.dli_sname, nullptr, nullptr, &res);
     532             :       if (!d) OS << dlinfo.dli_sname;
     533             :       else    OS << d;
     534             :       free(d);
     535             : 
     536             :       // FIXME: When we move to C++11, use %t length modifier. It's not in
     537             :       // C++03 and causes gcc to issue warnings. Losing the upper 32 bits of
     538             :       // the stack offset for a stack dump isn't likely to cause any problems.
     539             :       OS << format(" + %u",(unsigned)((char*)StackTrace[i]-
     540             :                                       (char*)dlinfo.dli_saddr));
     541             :     }
     542             :     OS << '\n';
     543             :   }
     544             : #elif defined(HAVE_BACKTRACE)
     545           0 :   backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
     546             : #endif
     547             : #endif
     548             : }
     549             : 
     550           0 : static void PrintStackTraceSignalHandler(void *) {
     551           0 :   sys::PrintStackTrace(llvm::errs());
     552           0 : }
     553             : 
     554           0 : void llvm::sys::DisableSystemDialogsOnCrash() {}
     555             : 
     556             : /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
     557             : /// process, print a stack trace and then exit.
     558      154909 : void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0,
     559             :                                              bool DisableCrashReporting) {
     560      154909 :   ::Argv0 = Argv0;
     561             : 
     562      154909 :   AddSignalHandler(PrintStackTraceSignalHandler, nullptr);
     563             : 
     564             : #if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES
     565             :   // Environment variable to disable any kind of crash dialog.
     566             :   if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) {
     567             :     mach_port_t self = mach_task_self();
     568             : 
     569             :     exception_mask_t mask = EXC_MASK_CRASH;
     570             : 
     571             :     kern_return_t ret = task_set_exception_ports(self,
     572             :                              mask,
     573             :                              MACH_PORT_NULL,
     574             :                              EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
     575             :                              THREAD_STATE_NONE);
     576             :     (void)ret;
     577             :   }
     578             : #endif
     579      643918 : }

Generated by: LCOV version 1.13