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