aboutsummaryrefslogtreecommitdiff
path: root/lld/Common/ErrorHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/Common/ErrorHandler.cpp')
-rw-r--r--lld/Common/ErrorHandler.cpp83
1 files changed, 73 insertions, 10 deletions
diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp
index 94ff23173d69..269a0f62ec65 100644
--- a/lld/Common/ErrorHandler.cpp
+++ b/lld/Common/ErrorHandler.cpp
@@ -13,15 +13,14 @@
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <mutex>
#include <regex>
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#endif
-
using namespace llvm;
using namespace lld;
@@ -43,31 +42,48 @@ static StringRef getSeparator(const Twine &msg) {
raw_ostream *lld::stdoutOS;
raw_ostream *lld::stderrOS;
-raw_ostream &lld::outs() { return stdoutOS ? *stdoutOS : llvm::outs(); }
-raw_ostream &lld::errs() { return stderrOS ? *stderrOS : llvm::errs(); }
-
ErrorHandler &lld::errorHandler() {
static ErrorHandler handler;
return handler;
}
+raw_ostream &lld::outs() {
+ if (errorHandler().disableOutput)
+ return llvm::nulls();
+ return stdoutOS ? *stdoutOS : llvm::outs();
+}
+
+raw_ostream &lld::errs() {
+ if (errorHandler().disableOutput)
+ return llvm::nulls();
+ return stderrOS ? *stderrOS : llvm::errs();
+}
+
void lld::exitLld(int val) {
// Delete any temporary file, while keeping the memory mapping open.
if (errorHandler().outputBuffer)
errorHandler().outputBuffer->discard();
+ // Re-throw a possible signal or exception once/if it was catched by
+ // safeLldMain().
+ CrashRecoveryContext::throwIfCrash(val);
+
// Dealloc/destroy ManagedStatic variables before calling _exit().
// In an LTO build, allows us to get the output of -time-passes.
// Ensures that the thread pool for the parallel algorithms is stopped to
// avoid intermittent crashes on Windows when exiting.
- llvm_shutdown();
+ if (!CrashRecoveryContext::GetCurrent())
+ llvm_shutdown();
{
std::lock_guard<std::mutex> lock(mu);
lld::outs().flush();
lld::errs().flush();
}
- _exit(val);
+ // When running inside safeLldMain(), restore the control flow back to the
+ // CrashRecoveryContext. Otherwise simply use _exit(), meanning no cleanup,
+ // since we want to avoid further crashes on shutdown.
+ llvm::sys::Process::Exit(val, /*NoCleanup=*/true);
}
void lld::diagnosticHandler(const DiagnosticInfo &di) {
@@ -153,13 +169,15 @@ std::string ErrorHandler::getLocation(const Twine &msg) {
}
void ErrorHandler::log(const Twine &msg) {
- if (!verbose)
+ if (!verbose || disableOutput)
return;
std::lock_guard<std::mutex> lock(mu);
lld::errs() << logName << ": " << msg << "\n";
}
void ErrorHandler::message(const Twine &msg) {
+ if (disableOutput)
+ return;
std::lock_guard<std::mutex> lock(mu);
lld::outs() << msg << "\n";
lld::outs().flush();
@@ -216,6 +234,51 @@ void ErrorHandler::error(const Twine &msg) {
exitLld(1);
}
+void ErrorHandler::error(const Twine &msg, ErrorTag tag,
+ ArrayRef<StringRef> args) {
+ if (errorHandlingScript.empty()) {
+ error(msg);
+ return;
+ }
+ SmallVector<StringRef, 4> scriptArgs;
+ scriptArgs.push_back(errorHandlingScript);
+ switch (tag) {
+ case ErrorTag::LibNotFound:
+ scriptArgs.push_back("missing-lib");
+ break;
+ case ErrorTag::SymbolNotFound:
+ scriptArgs.push_back("undefined-symbol");
+ break;
+ }
+ scriptArgs.insert(scriptArgs.end(), args.begin(), args.end());
+ int res = llvm::sys::ExecuteAndWait(errorHandlingScript, scriptArgs);
+ if (res == 0) {
+ return error(msg);
+ } else {
+ // Temporarily disable error limit to make sure the two calls to error(...)
+ // only count as one.
+ uint64_t currentErrorLimit = errorLimit;
+ errorLimit = 0;
+ error(msg);
+ errorLimit = currentErrorLimit;
+ --errorCount;
+
+ switch (res) {
+ case -1:
+ error("error handling script '" + errorHandlingScript +
+ "' failed to execute");
+ break;
+ case -2:
+ error("error handling script '" + errorHandlingScript +
+ "' crashed or timeout");
+ break;
+ default:
+ error("error handling script '" + errorHandlingScript +
+ "' exited with code " + Twine(res));
+ }
+ }
+}
+
void ErrorHandler::fatal(const Twine &msg) {
error(msg);
exitLld(1);