1 //===- ErrorHandler.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 "lld/Common/ErrorHandler.h" 10 11 #include "lld/Common/CommonLinkerContext.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/IR/DiagnosticInfo.h" 14 #include "llvm/IR/DiagnosticPrinter.h" 15 #include "llvm/Support/CrashRecoveryContext.h" 16 #include "llvm/Support/ManagedStatic.h" 17 #include "llvm/Support/Process.h" 18 #include "llvm/Support/Program.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <regex> 21 22 using namespace llvm; 23 using namespace lld; 24 25 static StringRef getSeparator(const Twine &msg) { 26 if (StringRef(msg.str()).contains('\n')) 27 return "\n"; 28 return ""; 29 } 30 31 ErrorHandler::~ErrorHandler() { 32 if (cleanupCallback) 33 cleanupCallback(); 34 } 35 36 void ErrorHandler::initialize(llvm::raw_ostream &stdoutOS, 37 llvm::raw_ostream &stderrOS, bool exitEarly, 38 bool disableOutput) { 39 this->stdoutOS = &stdoutOS; 40 this->stderrOS = &stderrOS; 41 stderrOS.enable_colors(stderrOS.has_colors()); 42 this->exitEarly = exitEarly; 43 this->disableOutput = disableOutput; 44 } 45 46 void ErrorHandler::flushStreams() { 47 std::lock_guard<std::mutex> lock(mu); 48 outs().flush(); 49 errs().flush(); 50 } 51 52 ErrorHandler &lld::errorHandler() { return context().e; } 53 54 void lld::error(const Twine &msg) { errorHandler().error(msg); } 55 void lld::error(const Twine &msg, ErrorTag tag, ArrayRef<StringRef> args) { 56 errorHandler().error(msg, tag, args); 57 } 58 void lld::fatal(const Twine &msg) { errorHandler().fatal(msg); } 59 void lld::log(const Twine &msg) { errorHandler().log(msg); } 60 void lld::message(const Twine &msg, llvm::raw_ostream &s) { 61 errorHandler().message(msg, s); 62 } 63 void lld::warn(const Twine &msg) { errorHandler().warn(msg); } 64 uint64_t lld::errorCount() { return errorHandler().errorCount; } 65 66 raw_ostream &lld::outs() { 67 ErrorHandler &e = errorHandler(); 68 return e.outs(); 69 } 70 71 raw_ostream &ErrorHandler::outs() { 72 if (disableOutput) 73 return llvm::nulls(); 74 return stdoutOS ? *stdoutOS : llvm::outs(); 75 } 76 77 raw_ostream &ErrorHandler::errs() { 78 if (disableOutput) 79 return llvm::nulls(); 80 return stderrOS ? *stderrOS : llvm::errs(); 81 } 82 83 void lld::exitLld(int val) { 84 if (hasContext()) { 85 ErrorHandler &e = errorHandler(); 86 // Delete any temporary file, while keeping the memory mapping open. 87 if (e.outputBuffer) 88 e.outputBuffer->discard(); 89 } 90 91 // Re-throw a possible signal or exception once/if it was caught by 92 // safeLldMain(). 93 CrashRecoveryContext::throwIfCrash(val); 94 95 // Dealloc/destroy ManagedStatic variables before calling _exit(). 96 // In an LTO build, allows us to get the output of -time-passes. 97 // Ensures that the thread pool for the parallel algorithms is stopped to 98 // avoid intermittent crashes on Windows when exiting. 99 if (!CrashRecoveryContext::GetCurrent()) 100 llvm_shutdown(); 101 102 if (hasContext()) 103 lld::errorHandler().flushStreams(); 104 105 // When running inside safeLldMain(), restore the control flow back to the 106 // CrashRecoveryContext. Otherwise simply use _exit(), meanning no cleanup, 107 // since we want to avoid further crashes on shutdown. 108 llvm::sys::Process::Exit(val, /*NoCleanup=*/true); 109 } 110 111 void lld::diagnosticHandler(const DiagnosticInfo &di) { 112 SmallString<128> s; 113 raw_svector_ostream os(s); 114 DiagnosticPrinterRawOStream dp(os); 115 116 // For an inline asm diagnostic, prepend the module name to get something like 117 // "$module <inline asm>:1:5: ". 118 if (auto *dism = dyn_cast<DiagnosticInfoSrcMgr>(&di)) 119 if (dism->isInlineAsmDiag()) 120 os << dism->getModuleName() << ' '; 121 122 di.print(dp); 123 switch (di.getSeverity()) { 124 case DS_Error: 125 error(s); 126 break; 127 case DS_Warning: 128 warn(s); 129 break; 130 case DS_Remark: 131 case DS_Note: 132 message(s); 133 break; 134 } 135 } 136 137 void lld::checkError(Error e) { 138 handleAllErrors(std::move(e), 139 [&](ErrorInfoBase &eib) { error(eib.message()); }); 140 } 141 142 void lld::checkError(ErrorHandler &eh, Error e) { 143 handleAllErrors(std::move(e), 144 [&](ErrorInfoBase &eib) { eh.error(eib.message()); }); 145 } 146 147 // This is for --vs-diagnostics. 148 // 149 // Normally, lld's error message starts with argv[0]. Therefore, it usually 150 // looks like this: 151 // 152 // ld.lld: error: ... 153 // 154 // This error message style is unfortunately unfriendly to Visual Studio 155 // IDE. VS interprets the first word of the first line as an error location 156 // and make it clickable, thus "ld.lld" in the above message would become a 157 // clickable text. When you click it, VS opens "ld.lld" executable file with 158 // a binary editor. 159 // 160 // As a workaround, we print out an error location instead of "ld.lld" if 161 // lld is running in VS diagnostics mode. As a result, error message will 162 // look like this: 163 // 164 // src/foo.c(35): error: ... 165 // 166 // This function returns an error location string. An error location is 167 // extracted from an error message using regexps. 168 std::string ErrorHandler::getLocation(const Twine &msg) { 169 if (!vsDiagnostics) 170 return std::string(logName); 171 172 static std::regex regexes[] = { 173 std::regex( 174 R"(^undefined (?:\S+ )?symbol:.*\n)" 175 R"(>>> referenced by .+\((\S+):(\d+)\))"), 176 std::regex( 177 R"(^undefined (?:\S+ )?symbol:.*\n>>> referenced by (\S+):(\d+))"), 178 std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"), 179 std::regex( 180 R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"), 181 std::regex( 182 R"(^duplicate symbol: .*\n>>> defined at .+\((\S+):(\d+)\))"), 183 std::regex(R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+))"), 184 std::regex( 185 R"(.*\n>>> defined in .*\n>>> referenced by .+\((\S+):(\d+)\))"), 186 std::regex(R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"), 187 std::regex(R"((\S+):(\d+): unclosed quote)"), 188 }; 189 190 std::string str = msg.str(); 191 for (std::regex &re : regexes) { 192 std::smatch m; 193 if (!std::regex_search(str, m, re)) 194 continue; 195 196 assert(m.size() == 2 || m.size() == 3); 197 if (m.size() == 2) 198 return m.str(1); 199 return m.str(1) + "(" + m.str(2) + ")"; 200 } 201 202 return std::string(logName); 203 } 204 205 void ErrorHandler::reportDiagnostic(StringRef location, Colors c, 206 StringRef diagKind, const Twine &msg) { 207 SmallString<256> buf; 208 raw_svector_ostream os(buf); 209 os << sep << location << ": "; 210 if (!diagKind.empty()) { 211 if (errs().colors_enabled()) { 212 os.enable_colors(true); 213 os << c << diagKind << ": " << Colors::RESET; 214 } else { 215 os << diagKind << ": "; 216 } 217 } 218 os << msg << '\n'; 219 errs() << buf; 220 // If msg contains a newline, ensure that the next diagnostic is preceded by 221 // a blank line separator. 222 sep = getSeparator(msg); 223 } 224 225 void ErrorHandler::log(const Twine &msg) { 226 if (!verbose || disableOutput) 227 return; 228 std::lock_guard<std::mutex> lock(mu); 229 reportDiagnostic(logName, Colors::RESET, "", msg); 230 } 231 232 void ErrorHandler::message(const Twine &msg, llvm::raw_ostream &s) { 233 if (disableOutput) 234 return; 235 std::lock_guard<std::mutex> lock(mu); 236 s << msg << "\n"; 237 s.flush(); 238 } 239 240 void ErrorHandler::warn(const Twine &msg) { 241 if (fatalWarnings) { 242 error(msg); 243 return; 244 } 245 246 if (suppressWarnings) 247 return; 248 249 std::lock_guard<std::mutex> lock(mu); 250 reportDiagnostic(getLocation(msg), Colors::MAGENTA, "warning", msg); 251 } 252 253 void ErrorHandler::error(const Twine &msg) { 254 // If Visual Studio-style error message mode is enabled, 255 // this particular error is printed out as two errors. 256 if (vsDiagnostics) { 257 static std::regex re(R"(^(duplicate symbol: .*))" 258 R"((\n>>> defined at \S+:\d+.*\n>>>.*))" 259 R"((\n>>> defined at \S+:\d+.*\n>>>.*))"); 260 std::string str = msg.str(); 261 std::smatch m; 262 263 if (std::regex_match(str, m, re)) { 264 error(m.str(1) + m.str(2)); 265 error(m.str(1) + m.str(3)); 266 return; 267 } 268 } 269 270 bool exit = false; 271 { 272 std::lock_guard<std::mutex> lock(mu); 273 274 if (errorLimit == 0 || errorCount < errorLimit) { 275 reportDiagnostic(getLocation(msg), Colors::RED, "error", msg); 276 } else if (errorCount == errorLimit) { 277 reportDiagnostic(logName, Colors::RED, "error", errorLimitExceededMsg); 278 exit = exitEarly; 279 } 280 281 ++errorCount; 282 } 283 284 if (exit) 285 exitLld(1); 286 } 287 288 void ErrorHandler::error(const Twine &msg, ErrorTag tag, 289 ArrayRef<StringRef> args) { 290 if (errorHandlingScript.empty() || disableOutput) { 291 error(msg); 292 return; 293 } 294 SmallVector<StringRef, 4> scriptArgs; 295 scriptArgs.push_back(errorHandlingScript); 296 switch (tag) { 297 case ErrorTag::LibNotFound: 298 scriptArgs.push_back("missing-lib"); 299 break; 300 case ErrorTag::SymbolNotFound: 301 scriptArgs.push_back("undefined-symbol"); 302 break; 303 } 304 scriptArgs.insert(scriptArgs.end(), args.begin(), args.end()); 305 int res = llvm::sys::ExecuteAndWait(errorHandlingScript, scriptArgs); 306 if (res == 0) { 307 return error(msg); 308 } else { 309 // Temporarily disable error limit to make sure the two calls to error(...) 310 // only count as one. 311 uint64_t currentErrorLimit = errorLimit; 312 errorLimit = 0; 313 error(msg); 314 errorLimit = currentErrorLimit; 315 --errorCount; 316 317 switch (res) { 318 case -1: 319 error("error handling script '" + errorHandlingScript + 320 "' failed to execute"); 321 break; 322 case -2: 323 error("error handling script '" + errorHandlingScript + 324 "' crashed or timeout"); 325 break; 326 default: 327 error("error handling script '" + errorHandlingScript + 328 "' exited with code " + Twine(res)); 329 } 330 } 331 } 332 333 void ErrorHandler::fatal(const Twine &msg) { 334 error(msg); 335 exitLld(1); 336 } 337 338 SyncStream::~SyncStream() { 339 switch (level) { 340 case DiagLevel::None: 341 break; 342 case DiagLevel::Log: 343 e.log(buf); 344 break; 345 case DiagLevel::Msg: 346 e.message(buf, e.outs()); 347 break; 348 case DiagLevel::Warn: 349 e.warn(buf); 350 break; 351 case DiagLevel::Err: 352 e.error(buf); 353 break; 354 case DiagLevel::Fatal: 355 e.fatal(buf); 356 break; 357 } 358 } 359