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

Generated by: LCOV version 1.13