1 //===-- InitLLVM.cpp -----------------------------------------------------===// 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 #include "llvm/Support/InitLLVM.h" 10 #include "llvm/ADT/StringRef.h" 11 #include "llvm/Support/AutoConvert.h" 12 #include "llvm/Support/Error.h" 13 #include "llvm/Support/ErrorHandling.h" 14 #include "llvm/Support/ManagedStatic.h" 15 #include "llvm/Support/Signals.h" 16 17 #ifdef _WIN32 18 #include "llvm/Support/Windows/WindowsSupport.h" 19 #endif 20 21 #if defined(HAVE_UNISTD_H) 22 #include <unistd.h> 23 #else 24 #ifndef STDIN_FILENO 25 #define STDIN_FILENO 0 26 #endif 27 #ifndef STDOUT_FILENO 28 #define STDOUT_FILENO 1 29 #endif 30 #ifndef STDERR_FILENO 31 #define STDERR_FILENO 2 32 #endif 33 #endif 34 35 void CleanupStdHandles(void *Cookie) { 36 llvm::raw_ostream *Outs = &llvm::outs(), *Errs = &llvm::errs(); 37 Outs->flush(); 38 Errs->flush(); 39 llvm::restoreStdHandleAutoConversion(STDIN_FILENO); 40 llvm::restoreStdHandleAutoConversion(STDOUT_FILENO); 41 llvm::restoreStdHandleAutoConversion(STDERR_FILENO); 42 } 43 44 using namespace llvm; 45 using namespace llvm::sys; 46 47 InitLLVM::InitLLVM(int &Argc, const char **&Argv, 48 bool InstallPipeSignalExitHandler) { 49 #ifndef NDEBUG 50 static std::atomic<bool> Initialized{false}; 51 assert(!Initialized && "InitLLVM was already initialized!"); 52 Initialized = true; 53 #endif 54 55 // Bring stdin/stdout/stderr into a known state. 56 sys::AddSignalHandler(CleanupStdHandles, nullptr); 57 58 if (InstallPipeSignalExitHandler) 59 // The pipe signal handler must be installed before any other handlers are 60 // registered. This is because the Unix \ref RegisterHandlers function does 61 // not perform a sigaction() for SIGPIPE unless a one-shot handler is 62 // present, to allow long-lived processes (like lldb) to fully opt-out of 63 // llvm's SIGPIPE handling and ignore the signal safely. 64 sys::SetOneShotPipeSignalFunction(sys::DefaultOneShotPipeSignalHandler); 65 // Initialize the stack printer after installing the one-shot pipe signal 66 // handler, so we can perform a sigaction() for SIGPIPE on Unix if requested. 67 StackPrinter.emplace(Argc, Argv); 68 sys::PrintStackTraceOnErrorSignal(Argv[0]); 69 install_out_of_memory_new_handler(); 70 71 #ifdef __MVS__ 72 73 // We use UTF-8 as the internal character encoding. On z/OS, all external 74 // output is encoded in EBCDIC. In order to be able to read all 75 // error messages, we turn conversion to EBCDIC on for stderr fd. 76 std::string Banner = std::string(Argv[0]) + ": "; 77 ExitOnError ExitOnErr(Banner); 78 79 // If turning on conversion for stderr fails then the error message 80 // may be garbled. There is no solution to this problem. 81 ExitOnErr(errorCodeToError(llvm::enableAutoConversion(STDERR_FILENO))); 82 ExitOnErr(errorCodeToError(llvm::enableAutoConversion(STDOUT_FILENO))); 83 #endif 84 85 #ifdef _WIN32 86 // We use UTF-8 as the internal character encoding. On Windows, 87 // arguments passed to main() may not be encoded in UTF-8. In order 88 // to reliably detect encoding of command line arguments, we use an 89 // Windows API to obtain arguments, convert them to UTF-8, and then 90 // write them back to the Argv vector. 91 // 92 // There's probably other way to do the same thing (e.g. using 93 // wmain() instead of main()), but this way seems less intrusive 94 // than that. 95 std::string Banner = std::string(Argv[0]) + ": "; 96 ExitOnError ExitOnErr(Banner); 97 98 ExitOnErr(errorCodeToError(windows::GetCommandLineArguments(Args, Alloc))); 99 100 // GetCommandLineArguments doesn't terminate the vector with a 101 // nullptr. Do it to make it compatible with the real argv. 102 Args.push_back(nullptr); 103 104 Argc = Args.size() - 1; 105 Argv = Args.data(); 106 #endif 107 } 108 109 InitLLVM::~InitLLVM() { 110 CleanupStdHandles(nullptr); 111 llvm_shutdown(); 112 } 113