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/Threads.h"
12 
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/IR/DiagnosticInfo.h"
15 #include "llvm/IR/DiagnosticPrinter.h"
16 #include "llvm/Support/ManagedStatic.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <mutex>
19 #include <regex>
20 
21 #if !defined(_MSC_VER) && !defined(__MINGW32__)
22 #include <unistd.h>
23 #endif
24 
25 using namespace llvm;
26 using namespace lld;
27 
28 // The functions defined in this file can be called from multiple threads,
29 // but outs() or errs() are not thread-safe. We protect them using a mutex.
30 static std::mutex mu;
31 
32 // Prints "\n" or does nothing, depending on Msg contents of
33 // the previous call of this function.
34 static void newline(raw_ostream *errorOS, const Twine &msg) {
35   // True if the previous error message contained "\n".
36   // We want to separate multi-line error messages with a newline.
37   static bool flag;
38 
39   if (flag)
40     *errorOS << "\n";
41   flag = StringRef(msg.str()).contains('\n');
42 }
43 
44 ErrorHandler &lld::errorHandler() {
45   static ErrorHandler handler;
46   return handler;
47 }
48 
49 void lld::exitLld(int val) {
50   // Delete any temporary file, while keeping the memory mapping open.
51   if (errorHandler().outputBuffer)
52     errorHandler().outputBuffer->discard();
53 
54   // Dealloc/destroy ManagedStatic variables before calling
55   // _exit(). In a non-LTO build, this is a nop. In an LTO
56   // build allows us to get the output of -time-passes.
57   llvm_shutdown();
58 
59   outs().flush();
60   errs().flush();
61   _exit(val);
62 }
63 
64 void lld::diagnosticHandler(const DiagnosticInfo &di) {
65   SmallString<128> s;
66   raw_svector_ostream os(s);
67   DiagnosticPrinterRawOStream dp(os);
68   di.print(dp);
69   switch (di.getSeverity()) {
70   case DS_Error:
71     error(s);
72     break;
73   case DS_Warning:
74     warn(s);
75     break;
76   case DS_Remark:
77   case DS_Note:
78     message(s);
79     break;
80   }
81 }
82 
83 void lld::checkError(Error e) {
84   handleAllErrors(std::move(e),
85                   [&](ErrorInfoBase &eib) { error(eib.message()); });
86 }
87 
88 static std::string getLocation(std::string msg, std::string defaultMsg) {
89   static std::vector<std::regex> Regexes{
90       std::regex(R"(^undefined (?:\S+ )?symbol:.*\n>>> referenced by (\S+):(\d+)\n.*)"),
91       std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"),
92       std::regex(
93           R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"),
94       std::regex(
95           R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+).*)"),
96       std::regex(
97           R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"),
98       std::regex(R"((\S+):(\d+): unclosed quote)"),
99   };
100 
101   std::smatch Match;
102   for (std::regex &Re : Regexes) {
103     if (std::regex_search(msg, Match, Re)) {
104       return Match.size() > 2 ? Match.str(1) + "(" + Match.str(2) + ")"
105                               : Match.str(1);
106     }
107   }
108   return defaultMsg;
109 }
110 
111 void ErrorHandler::printHeader(StringRef s, raw_ostream::Colors c,
112                                const Twine &msg) {
113 
114   if (vsDiagnostics) {
115     // A Visual Studio-style error message starts with an error location.
116     // If a location cannot be extracted then we default to LogName.
117     *errorOS << getLocation(msg.str(), logName) << ": ";
118   } else {
119     *errorOS << logName << ": ";
120   }
121 
122   if (colorDiagnostics) {
123     errorOS->changeColor(c, true);
124     *errorOS << s;
125     errorOS->resetColor();
126   } else {
127     *errorOS << s;
128   }
129 }
130 
131 void ErrorHandler::log(const Twine &msg) {
132   if (verbose) {
133     std::lock_guard<std::mutex> lock(mu);
134     *errorOS << logName << ": " << msg << "\n";
135   }
136 }
137 
138 void ErrorHandler::message(const Twine &msg) {
139   std::lock_guard<std::mutex> lock(mu);
140   outs() << msg << "\n";
141   outs().flush();
142 }
143 
144 void ErrorHandler::warn(const Twine &msg) {
145   if (fatalWarnings) {
146     error(msg);
147     return;
148   }
149 
150   std::lock_guard<std::mutex> lock(mu);
151   newline(errorOS, msg);
152   printHeader("warning: ", raw_ostream::MAGENTA, msg);
153   *errorOS << msg << "\n";
154 }
155 
156 void ErrorHandler::printErrorMsg(const Twine &msg) {
157   newline(errorOS, msg);
158   printHeader("error: ", raw_ostream::RED, msg);
159   *errorOS << msg << "\n";
160 }
161 
162 void ErrorHandler::printError(const Twine &msg) {
163   if (vsDiagnostics) {
164     static std::regex reDuplicateSymbol(
165         R"(^(duplicate symbol: .*))"
166         R"((\n>>> defined at \S+:\d+\n>>>.*))"
167         R"((\n>>> defined at \S+:\d+\n>>>.*))");
168     std::string msgStr = msg.str();
169     std::smatch match;
170     if (std::regex_match(msgStr, match, reDuplicateSymbol)) {
171       printErrorMsg(match.str(1) + match.str(2));
172       printErrorMsg(match.str(1) + match.str(3));
173       return;
174     }
175   }
176   printErrorMsg(msg);
177 }
178 
179 void ErrorHandler::error(const Twine &msg) {
180   std::lock_guard<std::mutex> lock(mu);
181 
182   if (errorLimit == 0 || errorCount < errorLimit) {
183     printError(msg);
184   } else if (errorCount == errorLimit) {
185     newline(errorOS, msg);
186     printHeader("error: ", raw_ostream::RED, msg);
187     *errorOS << errorLimitExceededMsg << "\n";
188     if (exitEarly)
189       exitLld(1);
190   }
191 
192   ++errorCount;
193 }
194 
195 void ErrorHandler::fatal(const Twine &msg) {
196   error(msg);
197   exitLld(1);
198 }
199