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/ExitCodes.h" |
40 | #include "llvm/Support/FileSystem.h" |
41 | #include "llvm/Support/FileUtilities.h" |
42 | #include "llvm/Support/Format.h" |
43 | #include "llvm/Support/MemoryBuffer.h" |
44 | #include "llvm/Support/Mutex.h" |
45 | #include "llvm/Support/Program.h" |
46 | #include "llvm/Support/SaveAndRestore.h" |
47 | #include "llvm/Support/raw_ostream.h" |
48 | #include <algorithm> |
49 | #include <string> |
50 | #ifdef HAVE_BACKTRACE |
51 | #include BACKTRACE_HEADER // For backtrace(). |
52 | #endif |
53 | #include <signal.h> |
54 | #include <sys/stat.h> |
55 | #include <dlfcn.h> |
56 | #if HAVE_MACH_MACH_H |
57 | #include <mach/mach.h> |
58 | #endif |
59 | #ifdef __APPLE__ |
60 | #include <mach-o/dyld.h> |
61 | #endif |
62 | #if __has_include(<link.h>) |
63 | #include <link.h> |
64 | #endif |
65 | #ifdef HAVE__UNWIND_BACKTRACE |
66 | // FIXME: We should be able to use <unwind.h> for any target that has an |
67 | // _Unwind_Backtrace function, but on FreeBSD the configure test passes |
68 | // despite the function not existing, and on Android, <unwind.h> conflicts |
69 | // with <link.h>. |
70 | #ifdef __GLIBC__ |
71 | #include <unwind.h> |
72 | #else |
73 | #undef HAVE__UNWIND_BACKTRACE |
74 | #endif |
75 | #endif |
76 | #if ENABLE_BACKTRACES && defined(__MVS__) |
77 | #include "llvm/Support/ConvertEBCDIC.h" |
78 | #include <__le_cwi.h> |
79 | #endif |
80 | |
81 | using namespace llvm; |
82 | |
83 | static void SignalHandler(int Sig, siginfo_t *Info, void *); |
84 | static void InfoSignalHandler(int Sig); // defined below. |
85 | |
86 | using SignalHandlerFunctionType = void (*)(); |
87 | /// The function to call if ctrl-c is pressed. |
88 | static std::atomic<SignalHandlerFunctionType> InterruptFunction = nullptr; |
89 | static std::atomic<SignalHandlerFunctionType> InfoSignalFunction = nullptr; |
90 | /// The function to call on SIGPIPE (one-time use only). |
91 | static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction = |
92 | nullptr; |
93 | |
94 | namespace { |
95 | /// Signal-safe removal of files. |
96 | /// Inserting and erasing from the list isn't signal-safe, but removal of files |
97 | /// themselves is signal-safe. Memory is freed when the head is freed, deletion |
98 | /// is therefore not signal-safe either. |
99 | class FileToRemoveList { |
100 | std::atomic<char *> Filename = nullptr; |
101 | std::atomic<FileToRemoveList *> Next = nullptr; |
102 | |
103 | FileToRemoveList() = default; |
104 | // Not signal-safe. |
105 | FileToRemoveList(const std::string &str) : Filename(strdup(s: str.c_str())) {} |
106 | |
107 | public: |
108 | // Not signal-safe. |
109 | ~FileToRemoveList() { |
110 | if (FileToRemoveList *N = Next.exchange(p: nullptr)) |
111 | delete N; |
112 | if (char *F = Filename.exchange(p: nullptr)) |
113 | free(ptr: F); |
114 | } |
115 | |
116 | // Not signal-safe. |
117 | static void insert(std::atomic<FileToRemoveList *> &Head, |
118 | const std::string &Filename) { |
119 | // Insert the new file at the end of the list. |
120 | FileToRemoveList *NewHead = new FileToRemoveList(Filename); |
121 | std::atomic<FileToRemoveList *> *InsertionPoint = &Head; |
122 | FileToRemoveList *OldHead = nullptr; |
123 | while (!InsertionPoint->compare_exchange_strong(p1&: OldHead, p2: NewHead)) { |
124 | InsertionPoint = &OldHead->Next; |
125 | OldHead = nullptr; |
126 | } |
127 | } |
128 | |
129 | // Not signal-safe. |
130 | static void erase(std::atomic<FileToRemoveList *> &Head, |
131 | const std::string &Filename) { |
132 | // Use a lock to avoid concurrent erase: the comparison would access |
133 | // free'd memory. |
134 | static ManagedStatic<sys::SmartMutex<true>> Lock; |
135 | sys::SmartScopedLock<true> Writer(*Lock); |
136 | |
137 | for (FileToRemoveList *Current = Head.load(); Current; |
138 | Current = Current->Next.load()) { |
139 | if (char *OldFilename = Current->Filename.load()) { |
140 | if (OldFilename != Filename) |
141 | continue; |
142 | // Leave an empty filename. |
143 | OldFilename = Current->Filename.exchange(p: nullptr); |
144 | // The filename might have become null between the time we |
145 | // compared it and we exchanged it. |
146 | if (OldFilename) |
147 | free(ptr: OldFilename); |
148 | } |
149 | } |
150 | } |
151 | |
152 | static void removeFile(char *path) { |
153 | // Get the status so we can determine if it's a file or directory. If we |
154 | // can't stat the file, ignore it. |
155 | struct stat buf; |
156 | if (stat(file: path, buf: &buf) != 0) |
157 | return; |
158 | |
159 | // If this is not a regular file, ignore it. We want to prevent removal |
160 | // of special files like /dev/null, even if the compiler is being run |
161 | // with the super-user permissions. |
162 | if (!S_ISREG(buf.st_mode)) |
163 | return; |
164 | |
165 | // Otherwise, remove the file. We ignore any errors here as there is |
166 | // nothing else we can do. |
167 | unlink(name: path); |
168 | } |
169 | |
170 | // Signal-safe. |
171 | static void removeAllFiles(std::atomic<FileToRemoveList *> &Head) { |
172 | // If cleanup were to occur while we're removing files we'd have a bad time. |
173 | // Make sure we're OK by preventing cleanup from doing anything while we're |
174 | // removing files. If cleanup races with us and we win we'll have a leak, |
175 | // but we won't crash. |
176 | FileToRemoveList *OldHead = Head.exchange(p: nullptr); |
177 | |
178 | for (FileToRemoveList *currentFile = OldHead; currentFile; |
179 | currentFile = currentFile->Next.load()) { |
180 | // If erasing was occuring while we're trying to remove files we'd look |
181 | // at free'd data. Take away the path and put it back when done. |
182 | if (char *path = currentFile->Filename.exchange(p: nullptr)) { |
183 | removeFile(path); |
184 | |
185 | // We're done removing the file, erasing can safely proceed. |
186 | currentFile->Filename.exchange(p: path); |
187 | } |
188 | } |
189 | |
190 | // We're done removing files, cleanup can safely proceed. |
191 | Head.exchange(p: OldHead); |
192 | } |
193 | }; |
194 | static std::atomic<FileToRemoveList *> FilesToRemove = nullptr; |
195 | |
196 | /// Clean up the list in a signal-friendly manner. |
197 | /// Recall that signals can fire during llvm_shutdown. If this occurs we should |
198 | /// either clean something up or nothing at all, but we shouldn't crash! |
199 | struct FilesToRemoveCleanup { |
200 | // Not signal-safe. |
201 | ~FilesToRemoveCleanup() { |
202 | FileToRemoveList *Head = FilesToRemove.exchange(p: nullptr); |
203 | if (Head) |
204 | delete Head; |
205 | } |
206 | }; |
207 | } // namespace |
208 | |
209 | static StringRef Argv0; |
210 | |
211 | /// Signals that represent requested termination. There's no bug or failure, or |
212 | /// if there is, it's not our direct responsibility. For whatever reason, our |
213 | /// continued execution is no longer desirable. |
214 | static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2}; |
215 | |
216 | /// Signals that represent that we have a bug, and our prompt termination has |
217 | /// been ordered. |
218 | static const int KillSigs[] = {SIGILL, |
219 | SIGTRAP, |
220 | SIGABRT, |
221 | SIGFPE, |
222 | SIGBUS, |
223 | SIGSEGV, |
224 | SIGQUIT |
225 | #ifdef SIGSYS |
226 | , |
227 | SIGSYS |
228 | #endif |
229 | #ifdef SIGXCPU |
230 | , |
231 | SIGXCPU |
232 | #endif |
233 | #ifdef SIGXFSZ |
234 | , |
235 | SIGXFSZ |
236 | #endif |
237 | #ifdef SIGEMT |
238 | , |
239 | SIGEMT |
240 | #endif |
241 | }; |
242 | |
243 | /// Signals that represent requests for status. |
244 | static const int InfoSigs[] = {SIGUSR1 |
245 | #ifdef SIGINFO |
246 | , |
247 | SIGINFO |
248 | #endif |
249 | }; |
250 | |
251 | static const size_t NumSigs = std::size(IntSigs) + std::size(KillSigs) + |
252 | std::size(InfoSigs) + 1 /* SIGPIPE */; |
253 | |
254 | static std::atomic<unsigned> NumRegisteredSignals = 0; |
255 | static struct { |
256 | struct sigaction SA; |
257 | int SigNo; |
258 | } RegisteredSignalInfo[NumSigs]; |
259 | |
260 | #if defined(HAVE_SIGALTSTACK) |
261 | // Hold onto both the old and new alternate signal stack so that it's not |
262 | // reported as a leak. We don't make any attempt to remove our alt signal |
263 | // stack if we remove our signal handlers; that can't be done reliably if |
264 | // someone else is also trying to do the same thing. |
265 | static stack_t OldAltStack; |
266 | LLVM_ATTRIBUTE_USED static void *NewAltStackPointer; |
267 | |
268 | static void CreateSigAltStack() { |
269 | const size_t AltStackSize = MINSIGSTKSZ + 64 * 1024; |
270 | |
271 | // If we're executing on the alternate stack, or we already have an alternate |
272 | // signal stack that we're happy with, there's nothing for us to do. Don't |
273 | // reduce the size, some other part of the process might need a larger stack |
274 | // than we do. |
275 | if (sigaltstack(ss: nullptr, oss: &OldAltStack) != 0 || |
276 | OldAltStack.ss_flags & SS_ONSTACK || |
277 | (OldAltStack.ss_sp && OldAltStack.ss_size >= AltStackSize)) |
278 | return; |
279 | |
280 | stack_t AltStack = {}; |
281 | AltStack.ss_sp = static_cast<char *>(safe_malloc(Sz: AltStackSize)); |
282 | NewAltStackPointer = AltStack.ss_sp; // Save to avoid reporting a leak. |
283 | AltStack.ss_size = AltStackSize; |
284 | if (sigaltstack(ss: &AltStack, oss: &OldAltStack) != 0) |
285 | free(ptr: AltStack.ss_sp); |
286 | } |
287 | #else |
288 | static void CreateSigAltStack() {} |
289 | #endif |
290 | |
291 | static void RegisterHandlers() { // Not signal-safe. |
292 | // The mutex prevents other threads from registering handlers while we're |
293 | // doing it. We also have to protect the handlers and their count because |
294 | // a signal handler could fire while we're registering handlers. |
295 | static ManagedStatic<sys::SmartMutex<true>> SignalHandlerRegistrationMutex; |
296 | sys::SmartScopedLock<true> Guard(*SignalHandlerRegistrationMutex); |
297 | |
298 | // If the handlers are already registered, we're done. |
299 | if (NumRegisteredSignals.load() != 0) |
300 | return; |
301 | |
302 | // Create an alternate stack for signal handling. This is necessary for us to |
303 | // be able to reliably handle signals due to stack overflow. |
304 | CreateSigAltStack(); |
305 | |
306 | enum class SignalKind { IsKill, IsInfo }; |
307 | auto registerHandler = [&](int Signal, SignalKind Kind) { |
308 | unsigned Index = NumRegisteredSignals.load(); |
309 | assert(Index < std::size(RegisteredSignalInfo) && |
310 | "Out of space for signal handlers!" ); |
311 | |
312 | struct sigaction NewHandler; |
313 | |
314 | switch (Kind) { |
315 | case SignalKind::IsKill: |
316 | NewHandler.sa_sigaction = SignalHandler; |
317 | NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO; |
318 | break; |
319 | case SignalKind::IsInfo: |
320 | NewHandler.sa_handler = InfoSignalHandler; |
321 | NewHandler.sa_flags = SA_ONSTACK; |
322 | break; |
323 | } |
324 | sigemptyset(set: &NewHandler.sa_mask); |
325 | |
326 | // Install the new handler, save the old one in RegisteredSignalInfo. |
327 | sigaction(sig: Signal, act: &NewHandler, oact: &RegisteredSignalInfo[Index].SA); |
328 | RegisteredSignalInfo[Index].SigNo = Signal; |
329 | ++NumRegisteredSignals; |
330 | }; |
331 | |
332 | for (auto S : IntSigs) |
333 | registerHandler(S, SignalKind::IsKill); |
334 | for (auto S : KillSigs) |
335 | registerHandler(S, SignalKind::IsKill); |
336 | if (OneShotPipeSignalFunction) |
337 | registerHandler(SIGPIPE, SignalKind::IsKill); |
338 | for (auto S : InfoSigs) |
339 | registerHandler(S, SignalKind::IsInfo); |
340 | } |
341 | |
342 | void sys::unregisterHandlers() { |
343 | // Restore all of the signal handlers to how they were before we showed up. |
344 | for (unsigned i = 0, e = NumRegisteredSignals.load(); i != e; ++i) { |
345 | sigaction(sig: RegisteredSignalInfo[i].SigNo, act: &RegisteredSignalInfo[i].SA, |
346 | oact: nullptr); |
347 | --NumRegisteredSignals; |
348 | } |
349 | } |
350 | |
351 | /// Process the FilesToRemove list. |
352 | static void RemoveFilesToRemove() { |
353 | FileToRemoveList::removeAllFiles(Head&: FilesToRemove); |
354 | } |
355 | |
356 | void sys::CleanupOnSignal(uintptr_t Context) { |
357 | int Sig = (int)Context; |
358 | |
359 | if (llvm::is_contained(Range: InfoSigs, Element: Sig)) { |
360 | InfoSignalHandler(Sig); |
361 | return; |
362 | } |
363 | |
364 | RemoveFilesToRemove(); |
365 | |
366 | if (llvm::is_contained(Range: IntSigs, Element: Sig) || Sig == SIGPIPE) |
367 | return; |
368 | |
369 | llvm::sys::RunSignalHandlers(); |
370 | } |
371 | |
372 | // The signal handler that runs. |
373 | static void SignalHandler(int Sig, siginfo_t *Info, void *) { |
374 | // Restore the signal behavior to default, so that the program actually |
375 | // crashes when we return and the signal reissues. This also ensures that if |
376 | // we crash in our signal handler that the program will terminate immediately |
377 | // instead of recursing in the signal handler. |
378 | sys::unregisterHandlers(); |
379 | |
380 | // Unmask all potentially blocked kill signals. |
381 | sigset_t SigMask; |
382 | sigfillset(set: &SigMask); |
383 | sigprocmask(SIG_UNBLOCK, set: &SigMask, oset: nullptr); |
384 | |
385 | { |
386 | RemoveFilesToRemove(); |
387 | |
388 | if (Sig == SIGPIPE) |
389 | if (auto OldOneShotPipeFunction = |
390 | OneShotPipeSignalFunction.exchange(p: nullptr)) |
391 | return OldOneShotPipeFunction(); |
392 | |
393 | bool IsIntSig = llvm::is_contained(Range: IntSigs, Element: Sig); |
394 | if (IsIntSig) |
395 | if (auto OldInterruptFunction = InterruptFunction.exchange(p: nullptr)) |
396 | return OldInterruptFunction(); |
397 | |
398 | if (Sig == SIGPIPE || IsIntSig) { |
399 | raise(sig: Sig); // Execute the default handler. |
400 | return; |
401 | } |
402 | } |
403 | |
404 | // Otherwise if it is a fault (like SEGV) run any handler. |
405 | llvm::sys::RunSignalHandlers(); |
406 | |
407 | #ifdef __s390__ |
408 | // On S/390, certain signals are delivered with PSW Address pointing to |
409 | // *after* the faulting instruction. Simply returning from the signal |
410 | // handler would continue execution after that point, instead of |
411 | // re-raising the signal. Raise the signal manually in those cases. |
412 | if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP) |
413 | raise(Sig); |
414 | #endif |
415 | |
416 | // Signal sent from another process, do not assume that continuing the |
417 | // execution would re-raise it. |
418 | if (Info->si_pid != getpid()) |
419 | raise(sig: Sig); |
420 | } |
421 | |
422 | static void InfoSignalHandler(int Sig) { |
423 | SaveAndRestore SaveErrnoDuringASignalHandler(errno); |
424 | if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction) |
425 | CurrentInfoFunction(); |
426 | } |
427 | |
428 | void llvm::sys::RunInterruptHandlers() { RemoveFilesToRemove(); } |
429 | |
430 | void llvm::sys::SetInterruptFunction(void (*IF)()) { |
431 | InterruptFunction.exchange(p: IF); |
432 | RegisterHandlers(); |
433 | } |
434 | |
435 | void llvm::sys::SetInfoSignalFunction(void (*Handler)()) { |
436 | InfoSignalFunction.exchange(p: Handler); |
437 | RegisterHandlers(); |
438 | } |
439 | |
440 | void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { |
441 | OneShotPipeSignalFunction.exchange(p: Handler); |
442 | RegisterHandlers(); |
443 | } |
444 | |
445 | void llvm::sys::DefaultOneShotPipeSignalHandler() { |
446 | // Send a special return code that drivers can check for, from sysexits.h. |
447 | exit(EX_IOERR); |
448 | } |
449 | |
450 | // The public API |
451 | bool llvm::sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) { |
452 | // Ensure that cleanup will occur as soon as one file is added. |
453 | static ManagedStatic<FilesToRemoveCleanup> FilesToRemoveCleanup; |
454 | *FilesToRemoveCleanup; |
455 | FileToRemoveList::insert(Head&: FilesToRemove, Filename: Filename.str()); |
456 | RegisterHandlers(); |
457 | return false; |
458 | } |
459 | |
460 | // The public API |
461 | void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) { |
462 | FileToRemoveList::erase(Head&: FilesToRemove, Filename: Filename.str()); |
463 | } |
464 | |
465 | /// Add a function to be called when a signal is delivered to the process. The |
466 | /// handler can have a cookie passed to it to identify what instance of the |
467 | /// handler it is. |
468 | void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, |
469 | void *Cookie) { // Signal-safe. |
470 | insertSignalHandler(FnPtr, Cookie); |
471 | RegisterHandlers(); |
472 | } |
473 | |
474 | #if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \ |
475 | (defined(__linux__) || defined(__FreeBSD__) || \ |
476 | defined(__FreeBSD_kernel__) || defined(__NetBSD__) || \ |
477 | defined(__OpenBSD__) || defined(__DragonFly__)) |
478 | struct DlIteratePhdrData { |
479 | void **StackTrace; |
480 | int depth; |
481 | bool first; |
482 | const char **modules; |
483 | intptr_t *offsets; |
484 | const char *main_exec_name; |
485 | }; |
486 | |
487 | static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { |
488 | DlIteratePhdrData *data = (DlIteratePhdrData *)arg; |
489 | const char *name = data->first ? data->main_exec_name : info->dlpi_name; |
490 | data->first = false; |
491 | for (int i = 0; i < info->dlpi_phnum; i++) { |
492 | const auto *phdr = &info->dlpi_phdr[i]; |
493 | if (phdr->p_type != PT_LOAD) |
494 | continue; |
495 | intptr_t beg = info->dlpi_addr + phdr->p_vaddr; |
496 | intptr_t end = beg + phdr->p_memsz; |
497 | for (int j = 0; j < data->depth; j++) { |
498 | if (data->modules[j]) |
499 | continue; |
500 | intptr_t addr = (intptr_t)data->StackTrace[j]; |
501 | if (beg <= addr && addr < end) { |
502 | data->modules[j] = name; |
503 | data->offsets[j] = addr - info->dlpi_addr; |
504 | } |
505 | } |
506 | } |
507 | return 0; |
508 | } |
509 | |
510 | #if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN |
511 | #if !defined(HAVE_BACKTRACE) |
512 | #error DebugLoc origin-tracking currently requires `backtrace()`. |
513 | #endif |
514 | namespace llvm { |
515 | namespace sys { |
516 | template <unsigned long MaxDepth> |
517 | int getStackTrace(std::array<void *, MaxDepth> &StackTrace) { |
518 | return backtrace(StackTrace.data(), MaxDepth); |
519 | } |
520 | template int getStackTrace<16ul>(std::array<void *, 16ul> &); |
521 | } // namespace sys |
522 | } // namespace llvm |
523 | #endif |
524 | |
525 | /// If this is an ELF platform, we can find all loaded modules and their virtual |
526 | /// addresses with dl_iterate_phdr. |
527 | static bool findModulesAndOffsets(void **StackTrace, int Depth, |
528 | const char **Modules, intptr_t *Offsets, |
529 | const char *MainExecutableName, |
530 | StringSaver &StrPool) { |
531 | DlIteratePhdrData data = {.StackTrace: StackTrace, .depth: Depth, .first: true, |
532 | .modules: Modules, .offsets: Offsets, .main_exec_name: MainExecutableName}; |
533 | dl_iterate_phdr(callback: dl_iterate_phdr_cb, data: &data); |
534 | return true; |
535 | } |
536 | |
537 | class DSOMarkupPrinter { |
538 | llvm::raw_ostream &OS; |
539 | const char *MainExecutableName; |
540 | size_t ModuleCount = 0; |
541 | bool IsFirst = true; |
542 | |
543 | public: |
544 | DSOMarkupPrinter(llvm::raw_ostream &OS, const char *MainExecutableName) |
545 | : OS(OS), MainExecutableName(MainExecutableName) {} |
546 | |
547 | /// Print llvm-symbolizer markup describing the layout of the given DSO. |
548 | void printDSOMarkup(dl_phdr_info *Info) { |
549 | ArrayRef<uint8_t> BuildID = findBuildID(Info); |
550 | if (BuildID.empty()) |
551 | return; |
552 | OS << format(Fmt: "{{{module:%d:%s:elf:" , Vals: ModuleCount, |
553 | Vals: IsFirst ? MainExecutableName : Info->dlpi_name); |
554 | for (uint8_t X : BuildID) |
555 | OS << format(Fmt: "%02x" , Vals: X); |
556 | OS << "}}}\n" ; |
557 | |
558 | for (int I = 0; I < Info->dlpi_phnum; I++) { |
559 | const auto *Phdr = &Info->dlpi_phdr[I]; |
560 | if (Phdr->p_type != PT_LOAD) |
561 | continue; |
562 | uintptr_t StartAddress = Info->dlpi_addr + Phdr->p_vaddr; |
563 | uintptr_t ModuleRelativeAddress = Phdr->p_vaddr; |
564 | std::array<char, 4> ModeStr = modeStrFromFlags(Flags: Phdr->p_flags); |
565 | OS << format(Fmt: "{{{mmap:%#016x:%#x:load:%d:%s:%#016x}}}\n" , Vals: StartAddress, |
566 | Vals: Phdr->p_memsz, Vals: ModuleCount, Vals: &ModeStr[0], |
567 | Vals: ModuleRelativeAddress); |
568 | } |
569 | IsFirst = false; |
570 | ModuleCount++; |
571 | } |
572 | |
573 | /// Callback for use with dl_iterate_phdr. The last dl_iterate_phdr argument |
574 | /// must be a pointer to an instance of this class. |
575 | static int printDSOMarkup(dl_phdr_info *Info, size_t Size, void *Arg) { |
576 | static_cast<DSOMarkupPrinter *>(Arg)->printDSOMarkup(Info); |
577 | return 0; |
578 | } |
579 | |
580 | // Returns the build ID for the given DSO as an array of bytes. Returns an |
581 | // empty array if none could be found. |
582 | ArrayRef<uint8_t> findBuildID(dl_phdr_info *Info) { |
583 | for (int I = 0; I < Info->dlpi_phnum; I++) { |
584 | const auto *Phdr = &Info->dlpi_phdr[I]; |
585 | if (Phdr->p_type != PT_NOTE) |
586 | continue; |
587 | |
588 | ArrayRef<uint8_t> Notes( |
589 | reinterpret_cast<const uint8_t *>(Info->dlpi_addr + Phdr->p_vaddr), |
590 | Phdr->p_memsz); |
591 | while (Notes.size() > 12) { |
592 | uint32_t NameSize = *reinterpret_cast<const uint32_t *>(Notes.data()); |
593 | Notes = Notes.drop_front(N: 4); |
594 | uint32_t DescSize = *reinterpret_cast<const uint32_t *>(Notes.data()); |
595 | Notes = Notes.drop_front(N: 4); |
596 | uint32_t Type = *reinterpret_cast<const uint32_t *>(Notes.data()); |
597 | Notes = Notes.drop_front(N: 4); |
598 | |
599 | ArrayRef<uint8_t> Name = Notes.take_front(N: NameSize); |
600 | auto CurPos = reinterpret_cast<uintptr_t>(Notes.data()); |
601 | uint32_t BytesUntilDesc = |
602 | alignToPowerOf2(Value: CurPos + NameSize, Align: 4) - CurPos; |
603 | if (BytesUntilDesc >= Notes.size()) |
604 | break; |
605 | Notes = Notes.drop_front(N: BytesUntilDesc); |
606 | |
607 | ArrayRef<uint8_t> Desc = Notes.take_front(N: DescSize); |
608 | CurPos = reinterpret_cast<uintptr_t>(Notes.data()); |
609 | uint32_t BytesUntilNextNote = |
610 | alignToPowerOf2(Value: CurPos + DescSize, Align: 4) - CurPos; |
611 | if (BytesUntilNextNote > Notes.size()) |
612 | break; |
613 | Notes = Notes.drop_front(N: BytesUntilNextNote); |
614 | |
615 | if (Type == 3 /*NT_GNU_BUILD_ID*/ && Name.size() >= 3 && |
616 | Name[0] == 'G' && Name[1] == 'N' && Name[2] == 'U') |
617 | return Desc; |
618 | } |
619 | } |
620 | return {}; |
621 | } |
622 | |
623 | // Returns a symbolizer markup string describing the permissions on a DSO |
624 | // with the given p_flags. |
625 | std::array<char, 4> modeStrFromFlags(uint32_t Flags) { |
626 | std::array<char, 4> Mode; |
627 | char *Cur = &Mode[0]; |
628 | if (Flags & PF_R) |
629 | *Cur++ = 'r'; |
630 | if (Flags & PF_W) |
631 | *Cur++ = 'w'; |
632 | if (Flags & PF_X) |
633 | *Cur++ = 'x'; |
634 | *Cur = '\0'; |
635 | return Mode; |
636 | } |
637 | }; |
638 | |
639 | static bool printMarkupContext(llvm::raw_ostream &OS, |
640 | const char *MainExecutableName) { |
641 | OS << "{{{reset}}}\n" ; |
642 | DSOMarkupPrinter MP(OS, MainExecutableName); |
643 | dl_iterate_phdr(callback: DSOMarkupPrinter::printDSOMarkup, data: &MP); |
644 | return true; |
645 | } |
646 | |
647 | #elif ENABLE_BACKTRACES && defined(__APPLE__) && defined(__LP64__) |
648 | static bool findModulesAndOffsets(void **StackTrace, int Depth, |
649 | const char **Modules, intptr_t *Offsets, |
650 | const char *MainExecutableName, |
651 | StringSaver &StrPool) { |
652 | uint32_t NumImgs = _dyld_image_count(); |
653 | for (uint32_t ImageIndex = 0; ImageIndex < NumImgs; ImageIndex++) { |
654 | const char *Name = _dyld_get_image_name(ImageIndex); |
655 | intptr_t Slide = _dyld_get_image_vmaddr_slide(ImageIndex); |
656 | auto *Header = |
657 | (const struct mach_header_64 *)_dyld_get_image_header(ImageIndex); |
658 | if (Header == NULL) |
659 | continue; |
660 | auto Cmd = (const struct load_command *)(&Header[1]); |
661 | for (uint32_t CmdNum = 0; CmdNum < Header->ncmds; ++CmdNum) { |
662 | uint32_t BaseCmd = Cmd->cmd & ~LC_REQ_DYLD; |
663 | if (BaseCmd == LC_SEGMENT_64) { |
664 | auto CmdSeg64 = (const struct segment_command_64 *)Cmd; |
665 | for (int j = 0; j < Depth; j++) { |
666 | if (Modules[j]) |
667 | continue; |
668 | intptr_t Addr = (intptr_t)StackTrace[j]; |
669 | if ((intptr_t)CmdSeg64->vmaddr + Slide <= Addr && |
670 | Addr < intptr_t(CmdSeg64->vmaddr + CmdSeg64->vmsize + Slide)) { |
671 | Modules[j] = Name; |
672 | Offsets[j] = Addr - Slide; |
673 | } |
674 | } |
675 | } |
676 | Cmd = (const load_command *)(((const char *)Cmd) + (Cmd->cmdsize)); |
677 | } |
678 | } |
679 | return true; |
680 | } |
681 | |
682 | static bool printMarkupContext(llvm::raw_ostream &OS, |
683 | const char *MainExecutableName) { |
684 | return false; |
685 | } |
686 | #else |
687 | /// Backtraces are not enabled or we don't yet know how to find all loaded DSOs |
688 | /// on this platform. |
689 | static bool findModulesAndOffsets(void **StackTrace, int Depth, |
690 | const char **Modules, intptr_t *Offsets, |
691 | const char *MainExecutableName, |
692 | StringSaver &StrPool) { |
693 | return false; |
694 | } |
695 | |
696 | static bool printMarkupContext(llvm::raw_ostream &OS, |
697 | const char *MainExecutableName) { |
698 | return false; |
699 | } |
700 | #endif // ENABLE_BACKTRACES && ... (findModulesAndOffsets variants) |
701 | |
702 | #if ENABLE_BACKTRACES && defined(HAVE__UNWIND_BACKTRACE) |
703 | static int unwindBacktrace(void **StackTrace, int MaxEntries) { |
704 | if (MaxEntries < 0) |
705 | return 0; |
706 | |
707 | // Skip the first frame ('unwindBacktrace' itself). |
708 | int Entries = -1; |
709 | |
710 | auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code { |
711 | // Apparently we need to detect reaching the end of the stack ourselves. |
712 | void *IP = (void *)_Unwind_GetIP(Context); |
713 | if (!IP) |
714 | return _URC_END_OF_STACK; |
715 | |
716 | assert(Entries < MaxEntries && "recursively called after END_OF_STACK?" ); |
717 | if (Entries >= 0) |
718 | StackTrace[Entries] = IP; |
719 | |
720 | if (++Entries == MaxEntries) |
721 | return _URC_END_OF_STACK; |
722 | return _URC_NO_REASON; |
723 | }; |
724 | |
725 | _Unwind_Backtrace( |
726 | [](_Unwind_Context *Context, void *Handler) { |
727 | return (*static_cast<decltype(HandleFrame) *>(Handler))(Context); |
728 | }, |
729 | static_cast<void *>(&HandleFrame)); |
730 | return std::max(a: Entries, b: 0); |
731 | } |
732 | #endif |
733 | |
734 | #if ENABLE_BACKTRACES && defined(__MVS__) |
735 | static void zosbacktrace(raw_ostream &OS) { |
736 | // A function name in the PPA1 can have length 16k. |
737 | constexpr size_t MAX_ENTRY_NAME = UINT16_MAX; |
738 | // Limit all other strings to 8 byte. |
739 | constexpr size_t MAX_OTHER = 8; |
740 | int32_t dsa_format = -1; // Input/Output |
741 | void *caaptr = _gtca(); // Input |
742 | int32_t member_id; // Output |
743 | char compile_unit_name[MAX_OTHER]; // Output |
744 | void *compile_unit_address; // Output |
745 | void *call_instruction_address = nullptr; // Input/Output |
746 | char entry_name[MAX_ENTRY_NAME]; // Output |
747 | void *entry_address; // Output |
748 | void *callers_instruction_address; // Output |
749 | void *callers_dsaptr; // Output |
750 | int32_t callers_dsa_format; // Output |
751 | char statement_id[MAX_OTHER]; // Output |
752 | void *cibptr; // Output |
753 | int32_t main_program; // Output |
754 | _FEEDBACK fc; // Output |
755 | |
756 | // The DSA pointer is the value of the stack pointer r4. |
757 | // __builtin_frame_address() returns a pointer to the stack frame, so the |
758 | // stack bias has to be considered to get the expected DSA value. |
759 | void *dsaptr = static_cast<char *>(__builtin_frame_address(0)) - 2048; |
760 | int count = 0; |
761 | OS << " DSA Adr EP +EP DSA " |
762 | " Entry\n" ; |
763 | while (1) { |
764 | // After the call, these variables contain the length of the string. |
765 | int32_t compile_unit_name_length = sizeof(compile_unit_name); |
766 | int32_t entry_name_length = sizeof(entry_name); |
767 | int32_t statement_id_length = sizeof(statement_id); |
768 | // See |
769 | // https://www.ibm.com/docs/en/zos/3.1.0?topic=cwicsa6a-celqtbck-also-known-as-celqtbck-64-bit-traceback-service |
770 | // for documentation of the parameters. |
771 | __CELQTBCK(&dsaptr, &dsa_format, &caaptr, &member_id, &compile_unit_name[0], |
772 | &compile_unit_name_length, &compile_unit_address, |
773 | &call_instruction_address, &entry_name[0], &entry_name_length, |
774 | &entry_address, &callers_instruction_address, &callers_dsaptr, |
775 | &callers_dsa_format, &statement_id[0], &statement_id_length, |
776 | &cibptr, &main_program, &fc); |
777 | if (fc.tok_sev) { |
778 | OS << format("error: CELQTBCK returned severity %d message %d\n" , |
779 | fc.tok_sev, fc.tok_msgno); |
780 | break; |
781 | } |
782 | |
783 | if (count) { // Omit first entry. |
784 | uintptr_t diff = reinterpret_cast<uintptr_t>(call_instruction_address) - |
785 | reinterpret_cast<uintptr_t>(entry_address); |
786 | OS << format(" %3d. 0x%016lX" , count, call_instruction_address); |
787 | OS << format(" 0x%016lX +0x%08lX 0x%016lX" , entry_address, diff, dsaptr); |
788 | SmallString<256> Str; |
789 | ConverterEBCDIC::convertToUTF8(StringRef(entry_name, entry_name_length), |
790 | Str); |
791 | OS << ' ' << Str << '\n'; |
792 | } |
793 | ++count; |
794 | if (callers_dsaptr) { |
795 | dsaptr = callers_dsaptr; |
796 | dsa_format = callers_dsa_format; |
797 | call_instruction_address = callers_instruction_address; |
798 | } else |
799 | break; |
800 | } |
801 | } |
802 | #endif |
803 | |
804 | // In the case of a program crash or fault, print out a stack trace so that the |
805 | // user has an indication of why and where we died. |
806 | // |
807 | // On glibc systems we have the 'backtrace' function, which works nicely, but |
808 | // doesn't demangle symbols. |
809 | void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) { |
810 | #if ENABLE_BACKTRACES |
811 | #ifdef __MVS__ |
812 | zosbacktrace(OS); |
813 | #else |
814 | static void *StackTrace[256]; |
815 | int depth = 0; |
816 | #if defined(HAVE_BACKTRACE) |
817 | // Use backtrace() to output a backtrace on Linux systems with glibc. |
818 | if (!depth) |
819 | depth = backtrace(array: StackTrace, size: static_cast<int>(std::size(StackTrace))); |
820 | #endif |
821 | #if defined(HAVE__UNWIND_BACKTRACE) |
822 | // Try _Unwind_Backtrace() if backtrace() failed. |
823 | if (!depth) |
824 | depth = |
825 | unwindBacktrace(StackTrace, MaxEntries: static_cast<int>(std::size(StackTrace))); |
826 | #endif |
827 | if (!depth) |
828 | return; |
829 | // If "Depth" is not provided by the caller, use the return value of |
830 | // backtrace() for printing a symbolized stack trace. |
831 | if (!Depth) |
832 | Depth = depth; |
833 | if (printMarkupStackTrace(Argv0, StackTrace, Depth, OS)) |
834 | return; |
835 | if (printSymbolizedStackTrace(Argv0, StackTrace, Depth, OS)) |
836 | return; |
837 | OS << "Stack dump without symbol names (ensure you have llvm-symbolizer in " |
838 | "your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point " |
839 | "to it):\n" ; |
840 | #if HAVE_DLOPEN && !defined(_AIX) |
841 | int width = 0; |
842 | for (int i = 0; i < depth; ++i) { |
843 | Dl_info dlinfo; |
844 | int nwidth; |
845 | if (dladdr(address: StackTrace[i], info: &dlinfo) == 0) { |
846 | nwidth = 7; // "(error)" |
847 | } else { |
848 | const char *name = strrchr(s: dlinfo.dli_fname, c: '/'); |
849 | |
850 | if (!name) |
851 | nwidth = strlen(s: dlinfo.dli_fname); |
852 | else |
853 | nwidth = strlen(s: name) - 1; |
854 | } |
855 | |
856 | if (nwidth > width) |
857 | width = nwidth; |
858 | } |
859 | |
860 | for (int i = 0; i < depth; ++i) { |
861 | Dl_info dlinfo; |
862 | |
863 | OS << format(Fmt: "%-2d" , Vals: i); |
864 | |
865 | if (dladdr(address: StackTrace[i], info: &dlinfo) == 0) { |
866 | OS << format(Fmt: " %-*s" , Vals: width, Vals: static_cast<const char *>("(error)" )); |
867 | dlinfo.dli_sname = nullptr; |
868 | } else { |
869 | const char *name = strrchr(s: dlinfo.dli_fname, c: '/'); |
870 | if (!name) |
871 | OS << format(Fmt: " %-*s" , Vals: width, |
872 | Vals: static_cast<const char *>(dlinfo.dli_fname)); |
873 | else |
874 | OS << format(Fmt: " %-*s" , Vals: width, Vals: name + 1); |
875 | } |
876 | |
877 | OS << format(Fmt: " %#0*lx" , Vals: (int)(sizeof(void *) * 2) + 2, |
878 | Vals: (unsigned long)StackTrace[i]); |
879 | |
880 | if (dlinfo.dli_sname != nullptr) { |
881 | OS << ' '; |
882 | if (char *d = itaniumDemangle(mangled_name: dlinfo.dli_sname)) { |
883 | OS << d; |
884 | free(ptr: d); |
885 | } else { |
886 | OS << dlinfo.dli_sname; |
887 | } |
888 | |
889 | OS << format(Fmt: " + %tu" , Vals: (static_cast<const char *>(StackTrace[i]) - |
890 | static_cast<const char *>(dlinfo.dli_saddr))); |
891 | } |
892 | OS << '\n'; |
893 | } |
894 | #elif defined(HAVE_BACKTRACE) |
895 | backtrace_symbols_fd(StackTrace, Depth, STDERR_FILENO); |
896 | #endif |
897 | #endif |
898 | #endif |
899 | } |
900 | |
901 | static void PrintStackTraceSignalHandler(void *) { |
902 | sys::PrintStackTrace(OS&: llvm::errs()); |
903 | } |
904 | |
905 | void llvm::sys::DisableSystemDialogsOnCrash() {} |
906 | |
907 | /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the |
908 | /// process, print a stack trace and then exit. |
909 | void llvm::sys::PrintStackTraceOnErrorSignal(StringRef Argv0, |
910 | bool DisableCrashReporting) { |
911 | ::Argv0 = Argv0; |
912 | |
913 | AddSignalHandler(FnPtr: PrintStackTraceSignalHandler, Cookie: nullptr); |
914 | |
915 | #if defined(__APPLE__) && ENABLE_CRASH_OVERRIDES |
916 | // Environment variable to disable any kind of crash dialog. |
917 | if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT" )) { |
918 | mach_port_t self = mach_task_self(); |
919 | |
920 | exception_mask_t mask = EXC_MASK_CRASH; |
921 | |
922 | kern_return_t ret = task_set_exception_ports( |
923 | self, mask, MACH_PORT_NULL, |
924 | EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); |
925 | (void)ret; |
926 | } |
927 | #endif |
928 | } |
929 | |