Coverage Report

Created: 2020-06-26 05:44

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