[lld] unified COFF and ELF error handling on new Common/ErrorHandler

Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.

Reviewers: ruiu

Reviewed By: ruiu

Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits

Differential Revision: https://reviews.llvm.org/D39259

llvm-svn: 316624
This commit is contained in:
Bob Haarman 2017-10-25 22:28:38 +00:00
parent 5e6cb9022c
commit b8a59c8aa5
50 changed files with 249 additions and 405 deletions

View File

@ -11,7 +11,6 @@ add_lld_library(lldCOFF
DLL.cpp DLL.cpp
Driver.cpp Driver.cpp
DriverUtils.cpp DriverUtils.cpp
Error.cpp
ICF.cpp ICF.cpp
InputFiles.cpp InputFiles.cpp
LTO.cpp LTO.cpp

View File

@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Chunks.h" #include "Chunks.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h" #include "llvm/Object/COFF.h"

View File

@ -84,13 +84,10 @@ struct Configuration {
bool NoEntry = false; bool NoEntry = false;
std::string OutputFile; std::string OutputFile;
std::string ImportName; std::string ImportName;
bool ColorDiagnostics;
bool DoGC = true; bool DoGC = true;
bool DoICF = true; bool DoICF = true;
uint64_t ErrorLimit = 20;
bool Relocatable = true; bool Relocatable = true;
bool Force = false; bool Force = false;
bool FatalWarnings = false;
bool Debug = false; bool Debug = false;
bool WriteSymtab = true; bool WriteSymtab = true;
unsigned DebugTypes = static_cast<unsigned>(DebugType::None); unsigned DebugTypes = static_cast<unsigned>(DebugType::None);

View File

@ -9,7 +9,6 @@
#include "Driver.h" #include "Driver.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Memory.h" #include "Memory.h"
#include "MinGW.h" #include "MinGW.h"
@ -17,6 +16,7 @@
#include "Symbols.h" #include "Symbols.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/Driver.h" #include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Version.h" #include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h" #include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
@ -55,12 +55,14 @@ StringSaver Saver{BAlloc};
std::vector<SpecificAllocBase *> SpecificAllocBase::Instances; std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) { bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
ErrorCount = 0; errorHandler().LogName = Args[0];
ErrorOS = &Diag; errorHandler().ErrorOS = &Diag;
errorHandler().ColorDiagnostics = Diag.has_colors();
errorHandler().ErrorLimitExceededMsg =
"too many errors emitted, stopping now"
" (use /ERRORLIMIT:0 to see all errors)";
Config = make<Configuration>(); Config = make<Configuration>();
Config->Argv = {Args.begin(), Args.end()}; Config->Argv = {Args.begin(), Args.end()};
Config->ColorDiagnostics = ErrorOS->has_colors();
Config->CanExitEarly = CanExitEarly; Config->CanExitEarly = CanExitEarly;
Symtab = make<SymbolTable>(); Symtab = make<SymbolTable>();
@ -70,10 +72,10 @@ bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
// Call exit() if we can to avoid calling destructors. // Call exit() if we can to avoid calling destructors.
if (CanExitEarly) if (CanExitEarly)
exitLld(ErrorCount ? 1 : 0); exitLld(errorCount() ? 1 : 0);
freeArena(); freeArena();
return !ErrorCount; return !errorCount();
} }
// Drop directory components and replace extension with ".exe" or ".dll". // Drop directory components and replace extension with ".exe" or ".dll".
@ -212,8 +214,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C,
enqueueTask([=]() { enqueueTask([=]() {
auto MBOrErr = Future->get(); auto MBOrErr = Future->get();
if (MBOrErr.second) if (MBOrErr.second)
fatal(MBOrErr.second, fatal("could not get the buffer for the member defining " + SymName +
"could not get the buffer for the member defining " + SymName); ": " + MBOrErr.second.message());
Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName, Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,
ParentName); ParentName);
}); });
@ -619,7 +621,7 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) {
SmallString<128> S; SmallString<128> S;
if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path), if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path),
".lib", S)) ".lib", S))
fatal(EC, "cannot create a temporary file"); fatal("cannot create a temporary file: " + EC.message());
std::string Temp = S.str(); std::string Temp = S.str();
TemporaryFiles.push_back(Temp); TemporaryFiles.push_back(Temp);
@ -648,7 +650,7 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) {
int Fd; int Fd;
if (auto EC = sys::fs::createTemporaryFile( if (auto EC = sys::fs::createTemporaryFile(
"lld-" + sys::path::filename(Obj->ParentName), ".obj", Fd, S)) "lld-" + sys::path::filename(Obj->ParentName), ".obj", Fd, S))
fatal(EC, "cannot create a temporary file"); fatal("cannot create a temporary file: " + EC.message());
raw_fd_ostream OS(Fd, /*shouldClose*/ true); raw_fd_ostream OS(Fd, /*shouldClose*/ true);
OS << Obj->MB.getBuffer(); OS << Obj->MB.getBuffer();
Temps.push_back(S.str()); Temps.push_back(S.str());
@ -736,7 +738,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
StringRef S = Arg->getValue(); StringRef S = Arg->getValue();
if (S.getAsInteger(10, N)) if (S.getAsInteger(10, N))
error(Arg->getSpelling() + " number expected, but got " + S); error(Arg->getSpelling() + " number expected, but got " + S);
Config->ErrorLimit = N; errorHandler().ErrorLimit = N;
} }
// Handle /help // Handle /help
@ -792,6 +794,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Handle /verbose // Handle /verbose
if (Args.hasArg(OPT_verbose)) if (Args.hasArg(OPT_verbose))
Config->Verbose = true; Config->Verbose = true;
errorHandler().Verbose = Config->Verbose;
// Handle /force or /force:unresolved // Handle /force or /force:unresolved
if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved)) if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved))
@ -1010,7 +1013,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Config->MapFile = getMapFile(Args); Config->MapFile = getMapFile(Args);
if (ErrorCount) if (errorCount())
return; return;
bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag); bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
@ -1191,7 +1194,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
addUndefined(mangle("_load_config_used")); addUndefined(mangle("_load_config_used"));
} while (run()); } while (run());
if (ErrorCount) if (errorCount())
return; return;
// If /msvclto is given, we use the MSVC linker to link LTO output files. // If /msvclto is given, we use the MSVC linker to link LTO output files.
@ -1208,7 +1211,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Make sure we have resolved all symbols. // Make sure we have resolved all symbols.
Symtab->reportRemainingUndefines(); Symtab->reportRemainingUndefines();
if (ErrorCount) if (errorCount())
return; return;
// Windows specific -- if no /subsystem is given, we need to infer // Windows specific -- if no /subsystem is given, we need to infer
@ -1224,7 +1227,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
for (ObjFile *File : ObjFile::Instances) for (ObjFile *File : ObjFile::Instances)
if (!File->SEHCompat) if (!File->SEHCompat)
error("/safeseh: " + File->getName() + " is not compatible with SEH"); error("/safeseh: " + File->getName() + " is not compatible with SEH");
if (ErrorCount) if (errorCount())
return; return;
} }

View File

@ -15,9 +15,9 @@
#include "Config.h" #include "Config.h"
#include "Driver.h" #include "Driver.h"
#include "Error.h"
#include "Memory.h" #include "Memory.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Optional.h" #include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/COFF.h"
@ -57,7 +57,7 @@ public:
void run() { void run() {
ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog); ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog);
if (auto EC = ExeOrErr.getError()) if (auto EC = ExeOrErr.getError())
fatal(EC, "unable to find " + Prog + " in PATH"); fatal("unable to find " + Prog + " in PATH: " + EC.message());
StringRef Exe = Saver.save(*ExeOrErr); StringRef Exe = Saver.save(*ExeOrErr);
Args.insert(Args.begin(), Exe); Args.insert(Args.begin(), Exe);
@ -288,14 +288,14 @@ public:
TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") {
SmallString<128> S; SmallString<128> S;
if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S))
fatal(EC, "cannot create a temporary file"); fatal("cannot create a temporary file: " + EC.message());
Path = S.str(); Path = S.str();
if (!Contents.empty()) { if (!Contents.empty()) {
std::error_code EC; std::error_code EC;
raw_fd_ostream OS(Path, EC, sys::fs::F_None); raw_fd_ostream OS(Path, EC, sys::fs::F_None);
if (EC) if (EC)
fatal(EC, "failed to open " + Path); fatal("failed to open " + Path + ": " + EC.message());
OS << Contents; OS << Contents;
} }
} }
@ -363,13 +363,15 @@ static std::string createManifestXmlWithInternalMt(StringRef DefaultXml) {
windows_manifest::WindowsManifestMerger Merger; windows_manifest::WindowsManifestMerger Merger;
if (auto E = Merger.merge(*DefaultXmlCopy.get())) if (auto E = Merger.merge(*DefaultXmlCopy.get()))
fatal(E, "internal manifest tool failed on default xml"); fatal("internal manifest tool failed on default xml: " +
toString(std::move(E)));
for (StringRef Filename : Config->ManifestInput) { for (StringRef Filename : Config->ManifestInput) {
std::unique_ptr<MemoryBuffer> Manifest = std::unique_ptr<MemoryBuffer> Manifest =
check(MemoryBuffer::getFile(Filename)); check(MemoryBuffer::getFile(Filename));
if (auto E = Merger.merge(*Manifest.get())) if (auto E = Merger.merge(*Manifest.get()))
fatal(E, "internal manifest tool failed on file " + Filename); fatal("internal manifest tool failed on file " + Filename + ": " +
toString(std::move(E)));
} }
return Merger.getMergedManifest().get()->getBuffer(); return Merger.getMergedManifest().get()->getBuffer();
@ -381,7 +383,7 @@ static std::string createManifestXmlWithExternalMt(StringRef DefaultXml) {
std::error_code EC; std::error_code EC;
raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text); raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text);
if (EC) if (EC)
fatal(EC, "failed to open " + Default.Path); fatal("failed to open " + Default.Path + ": " + EC.message());
OS << DefaultXml; OS << DefaultXml;
OS.close(); OS.close();
@ -482,7 +484,7 @@ void createSideBySideManifest() {
std::error_code EC; std::error_code EC;
raw_fd_ostream Out(Path, EC, sys::fs::F_Text); raw_fd_ostream Out(Path, EC, sys::fs::F_Text);
if (EC) if (EC)
fatal(EC, "failed to create manifest"); fatal("failed to create manifest: " + EC.message());
Out << createManifestXml(); Out << createManifestXml();
} }
@ -649,13 +651,13 @@ MemoryBufferRef convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
if (!RF) if (!RF)
fatal("cannot compile non-resource file as resource"); fatal("cannot compile non-resource file as resource");
if (auto EC = Parser.parse(RF)) if (auto EC = Parser.parse(RF))
fatal(EC, "failed to parse .res file"); fatal("failed to parse .res file: " + toString(std::move(EC)));
} }
Expected<std::unique_ptr<MemoryBuffer>> E = Expected<std::unique_ptr<MemoryBuffer>> E =
llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser); llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);
if (!E) if (!E)
fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF"); fatal("failed to write .res to COFF: " + toString(E.takeError()));
MemoryBufferRef MBRef = **E; MemoryBufferRef MBRef = **E;
make<std::unique_ptr<MemoryBuffer>>(std::move(*E)); // take ownership make<std::unique_ptr<MemoryBuffer>>(std::move(*E)); // take ownership
@ -739,7 +741,7 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
} }
// Handle /WX early since it converts missing argument warnings to errors. // Handle /WX early since it converts missing argument warnings to errors.
Config->FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false); errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
if (MissingCount) if (MissingCount)
fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");

View File

@ -1,120 +0,0 @@
//===- Error.cpp ----------------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Error.h"
#include "Config.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <mutex>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#endif
using namespace llvm;
namespace lld {
// The functions defined in this file can be called from multiple threads,
// but outs() or errs() are not thread-safe. We protect them using a mutex.
static std::mutex Mu;
namespace coff {
uint64_t ErrorCount;
raw_ostream *ErrorOS;
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
// Dealloc/destroy ManagedStatic variables before calling
// _exit(). In a non-LTO build, this is a nop. In an LTO
// build allows us to get the output of -time-passes.
llvm_shutdown();
outs().flush();
errs().flush();
_exit(Val);
}
static void print(StringRef S, raw_ostream::Colors C) {
*ErrorOS << Config->Argv[0] << ": ";
if (Config->ColorDiagnostics) {
ErrorOS->changeColor(C, true);
*ErrorOS << S;
ErrorOS->resetColor();
} else {
*ErrorOS << S;
}
}
void log(const Twine &Msg) {
if (Config->Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Config->Argv[0] << ": " << Msg << "\n";
outs().flush();
}
}
void message(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Msg << "\n";
outs().flush();
}
void error(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << Msg << "\n";
} else if (ErrorCount == Config->ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << "too many errors emitted, stopping now"
<< " (use /ERRORLIMIT:0 to see all errors)\n";
if (Config->CanExitEarly)
exitLld(1);
}
++ErrorCount;
}
void fatal(const Twine &Msg) {
if (Config->ColorDiagnostics) {
errs().changeColor(raw_ostream::RED, /*bold=*/true);
errs() << "error: ";
errs().resetColor();
} else {
errs() << "error: ";
}
errs() << Msg << "\n";
exitLld(1);
}
void fatal(std::error_code EC, const Twine &Msg) {
fatal(Msg + ": " + EC.message());
}
void fatal(llvm::Error &Err, const Twine &Msg) {
fatal(errorToErrorCode(std::move(Err)), Msg);
}
void warn(const Twine &Msg) {
if (Config->FatalWarnings) {
error(Msg);
return;
}
std::lock_guard<std::mutex> Lock(Mu);
print("warning: ", raw_ostream::MAGENTA);
*ErrorOS << Msg << "\n";
}
} // namespace coff
} // namespace lld

View File

@ -1,64 +0,0 @@
//===- Error.h --------------------------------------------------*- C++ -*-===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_COFF_ERROR_H
#define LLD_COFF_ERROR_H
#include "lld/Common/LLVM.h"
#include "llvm/Support/Error.h"
namespace lld {
namespace coff {
extern uint64_t ErrorCount;
extern llvm::raw_ostream *ErrorOS;
void log(const Twine &Msg);
void message(const Twine &Msg);
void warn(const Twine &Msg);
void error(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
template <class T> T check(ErrorOr<T> V, const Twine &Prefix) {
if (auto EC = V.getError())
fatal(EC, Prefix);
return std::move(*V);
}
template <class T> T check(Expected<T> E, const Twine &Prefix) {
if (llvm::Error Err = E.takeError())
fatal(Err, Prefix);
return std::move(*E);
}
template <class T> T check(ErrorOr<T> EO) {
if (!EO)
fatal(EO.getError().message());
return std::move(*EO);
}
template <class T> T check(Expected<T> E) {
if (!E) {
std::string Buf;
llvm::raw_string_ostream OS(Buf);
logAllUnhandledErrors(E.takeError(), OS, "");
OS.flush();
fatal(Buf);
}
return std::move(*E);
}
} // namespace coff
} // namespace lld
#endif

View File

@ -19,8 +19,8 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Chunks.h" #include "Chunks.h"
#include "Error.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/Parallel.h" #include "llvm/Support/Parallel.h"

View File

@ -11,10 +11,10 @@
#include "Chunks.h" #include "Chunks.h"
#include "Config.h" #include "Config.h"
#include "Driver.h" #include "Driver.h"
#include "Error.h"
#include "Memory.h" #include "Memory.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm-c/lto.h" #include "llvm-c/lto.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
@ -127,9 +127,9 @@ void ObjFile::initializeChunks() {
const coff_section *Sec; const coff_section *Sec;
StringRef Name; StringRef Name;
if (auto EC = COFFObj->getSection(I, Sec)) if (auto EC = COFFObj->getSection(I, Sec))
fatal(EC, "getSection failed: #" + Twine(I)); fatal("getSection failed: #" + Twine(I) + ": " + EC.message());
if (auto EC = COFFObj->getSectionName(Sec, Name)) if (auto EC = COFFObj->getSectionName(Sec, Name))
fatal(EC, "getSectionName failed: #" + Twine(I)); fatal("getSectionName failed: #" + Twine(I) + ": " + EC.message());
if (Name == ".sxdata") { if (Name == ".sxdata") {
SXData = Sec; SXData = Sec;
continue; continue;
@ -179,7 +179,6 @@ void ObjFile::initializeSymbols() {
int32_t LastSectionNumber = 0; int32_t LastSectionNumber = 0;
for (uint32_t I = 0; I < NumSymbols; ++I) { for (uint32_t I = 0; I < NumSymbols; ++I) {
// Get a COFFSymbolRef object.
COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
const void *AuxP = nullptr; const void *AuxP = nullptr;

View File

@ -9,9 +9,9 @@
#include "LTO.h" #include "LTO.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"

View File

@ -20,11 +20,11 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "MapFile.h" #include "MapFile.h"
#include "Error.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Parallel.h" #include "llvm/Support/Parallel.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "MinGW.h" #include "MinGW.h"
#include "Error.h" #include "lld/Common/ErrorHandler.h"
#include "llvm/Object/COFF.h" #include "llvm/Object/COFF.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"

View File

@ -11,10 +11,10 @@
#include "Chunks.h" #include "Chunks.h"
#include "Config.h" #include "Config.h"
#include "Driver.h" #include "Driver.h"
#include "Error.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@ -188,7 +188,7 @@ maybeReadTypeServerRecord(CVTypeArray &Types) {
return None; return None;
TypeServer2Record TS; TypeServer2Record TS;
if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS))
fatal(EC, "error reading type server record"); fatal("error reading type server record: " + toString(std::move(EC)));
return std::move(TS); return std::move(TS);
} }
@ -202,7 +202,7 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
CVTypeArray Types; CVTypeArray Types;
BinaryStreamReader Reader(Stream); BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength())) if (auto EC = Reader.readArray(Types, Reader.getLength()))
fatal(EC, "Reader::readArray failed"); fatal("Reader::readArray failed: " + toString(std::move(EC)));
// Look through type servers. If we've already seen this type server, don't // Look through type servers. If we've already seen this type server, don't
// merge any type information. // merge any type information.
@ -213,7 +213,8 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
// ObjectIndexMap. // ObjectIndexMap.
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
ObjectIndexMap.TPIMap, Types)) ObjectIndexMap.TPIMap, Types))
fatal(Err, "codeview::mergeTypeAndIdRecords failed"); fatal("codeview::mergeTypeAndIdRecords failed: " +
toString(std::move(Err)));
return ObjectIndexMap; return ObjectIndexMap;
} }
@ -275,23 +276,23 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
ExpectedSession = tryToLoadPDB(TS.getGuid(), Path); ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
} }
if (auto E = ExpectedSession.takeError()) if (auto E = ExpectedSession.takeError())
fatal(E, "Type server PDB was not found"); fatal("Type server PDB was not found: " + toString(std::move(E)));
// Merge TPI first, because the IPI stream will reference type indices. // Merge TPI first, because the IPI stream will reference type indices.
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream(); auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError()) if (auto E = ExpectedTpi.takeError())
fatal(E, "Type server does not have TPI stream"); fatal("Type server does not have TPI stream: " + toString(std::move(E)));
if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap, if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
ExpectedTpi->typeArray())) ExpectedTpi->typeArray()))
fatal(Err, "codeview::mergeTypeRecords failed"); fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
// Merge IPI. // Merge IPI.
auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream(); auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
if (auto E = ExpectedIpi.takeError()) if (auto E = ExpectedIpi.takeError())
fatal(E, "Type server does not have TPI stream"); fatal("Type server does not have TPI stream: " + toString(std::move(E)));
if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap, if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
ExpectedIpi->typeArray())) ExpectedIpi->typeArray()))
fatal(Err, "codeview::mergeIdRecords failed"); fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
return IndexMap; return IndexMap;
} }

View File

@ -10,10 +10,10 @@
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Config.h" #include "Config.h"
#include "Driver.h" #include "Driver.h"
#include "Error.h"
#include "LTO.h" #include "LTO.h"
#include "Memory.h" #include "Memory.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"

View File

@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Symbols.h" #include "Symbols.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Memory.h" #include "Memory.h"
#include "Strings.h" #include "Strings.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"

View File

@ -10,13 +10,13 @@
#include "Writer.h" #include "Writer.h"
#include "Config.h" #include "Config.h"
#include "DLL.h" #include "DLL.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "MapFile.h" #include "MapFile.h"
#include "Memory.h" #include "Memory.h"
#include "PDB.h" #include "PDB.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
@ -316,7 +316,7 @@ void Writer::run() {
writeMapFile(OutputSections); writeMapFile(OutputSections);
if (auto EC = Buffer->commit()) if (auto EC = Buffer->commit())
fatal(EC, "failed to write the output file"); fatal("failed to write the output file: " + EC.message());
} }
static StringRef getOutputSection(StringRef Name) { static StringRef getOutputSection(StringRef Name) {

View File

@ -3,6 +3,7 @@ if(NOT LLD_BUILT_STANDALONE)
endif() endif()
add_lld_library(lldCommon add_lld_library(lldCommon
ErrorHandler.cpp
Reproduce.cpp Reproduce.cpp
TargetOptionsCommandFlags.cpp TargetOptionsCommandFlags.cpp
Threads.cpp Threads.cpp

View File

@ -1,4 +1,4 @@
//===- Error.cpp ----------------------------------------------------------===// //===- ErrorHandler.cpp ---------------------------------------------------===//
// //
// The LLVM Linker // The LLVM Linker
// //
@ -7,8 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h" #include "lld/Common/ErrorHandler.h"
#include "Config.h"
#include "lld/Common/Threads.h" #include "lld/Common/Threads.h"
@ -25,10 +24,6 @@
using namespace llvm; using namespace llvm;
using namespace lld; using namespace lld;
using namespace lld::elf;
uint64_t elf::ErrorCount;
raw_ostream *elf::ErrorOS;
// The functions defined in this file can be called from multiple threads, // The functions defined in this file can be called from multiple threads,
// but outs() or errs() are not thread-safe. We protect them using a mutex. // but outs() or errs() are not thread-safe. We protect them using a mutex.
@ -36,7 +31,7 @@ static std::mutex Mu;
// Prints "\n" or does nothing, depending on Msg contents of // Prints "\n" or does nothing, depending on Msg contents of
// the previous call of this function. // the previous call of this function.
static void newline(const Twine &Msg) { static void newline(raw_ostream *ErrorOS, const Twine &Msg) {
// True if the previous error message contained "\n". // True if the previous error message contained "\n".
// We want to separate multi-line error messages with a newline. // We want to separate multi-line error messages with a newline.
static bool Flag; static bool Flag;
@ -46,64 +41,15 @@ static void newline(const Twine &Msg) {
Flag = StringRef(Msg.str()).contains('\n'); Flag = StringRef(Msg.str()).contains('\n');
} }
static void print(StringRef S, raw_ostream::Colors C) { namespace lld {
*ErrorOS << Config->Argv[0] << ": ";
if (Config->ColorDiagnostics) { ErrorHandler &errorHandler() {
ErrorOS->changeColor(C, true); static ErrorHandler Handler;
*ErrorOS << S; return Handler;
ErrorOS->resetColor();
} else {
*ErrorOS << S;
}
} }
void elf::log(const Twine &Msg) { void exitLld(int Val) {
if (Config->Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Config->Argv[0] << ": " << Msg << "\n";
outs().flush();
}
}
void elf::message(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Msg << "\n";
outs().flush();
}
void elf::warn(const Twine &Msg) {
if (Config->FatalWarnings) {
error(Msg);
return;
}
std::lock_guard<std::mutex> Lock(Mu);
newline(Msg);
print("warning: ", raw_ostream::MAGENTA);
*ErrorOS << Msg << "\n";
}
void elf::error(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
newline(Msg);
if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << Msg << "\n";
} else if (ErrorCount == Config->ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << "too many errors emitted, stopping now"
<< " (use -error-limit=0 to see all errors)\n";
if (Config->ExitEarly)
exitLld(1);
}
++ErrorCount;
}
void elf::exitLld(int Val) {
waitForBackgroundThreads(); waitForBackgroundThreads();
// Dealloc/destroy ManagedStatic variables before calling // Dealloc/destroy ManagedStatic variables before calling
// _exit(). In a non-LTO build, this is a nop. In an LTO // _exit(). In a non-LTO build, this is a nop. In an LTO
// build allows us to get the output of -time-passes. // build allows us to get the output of -time-passes.
@ -114,7 +60,63 @@ void elf::exitLld(int Val) {
_exit(Val); _exit(Val);
} }
void elf::fatal(const Twine &Msg) { void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {
*ErrorOS << LogName << ": ";
if (ColorDiagnostics) {
ErrorOS->changeColor(C, true);
*ErrorOS << S;
ErrorOS->resetColor();
} else {
*ErrorOS << S;
}
}
void ErrorHandler::log(const Twine &Msg) {
if (Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << LogName << ": " << Msg << "\n";
outs().flush();
}
}
void ErrorHandler::message(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Msg << "\n";
outs().flush();
}
void ErrorHandler::warn(const Twine &Msg) {
if (FatalWarnings) {
error(Msg);
return;
}
std::lock_guard<std::mutex> Lock(Mu);
newline(ErrorOS, Msg);
print("warning: ", raw_ostream::MAGENTA);
*ErrorOS << Msg << "\n";
}
void ErrorHandler::error(const Twine &Msg) {
std::lock_guard<std::mutex> Lock(Mu);
newline(ErrorOS, Msg);
if (ErrorLimit == 0 || ErrorCount < ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << Msg << "\n";
} else if (ErrorCount == ErrorLimit) {
print("error: ", raw_ostream::RED);
*ErrorOS << ErrorLimitExceededMsg << "\n";
if (ExitEarly)
exitLld(1);
}
++ErrorCount;
}
void ErrorHandler::fatal(const Twine &Msg) {
error(Msg); error(Msg);
exitLld(1); exitLld(1);
} }
} // end namespace lld

View File

@ -7,11 +7,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "Thunks.h" #include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -7,10 +7,10 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -7,12 +7,12 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "Thunks.h" #include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -26,10 +26,10 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -7,13 +7,13 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "OutputSections.h" #include "OutputSections.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "Thunks.h" #include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -11,11 +11,11 @@
// //
//===---------------------------------------------------------------------===// //===---------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/ELF.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/MipsABIFlags.h"

View File

@ -7,9 +7,9 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "Symbols.h" #include "Symbols.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
using namespace llvm; using namespace llvm;

View File

@ -7,10 +7,10 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
using namespace llvm; using namespace llvm;

View File

@ -7,11 +7,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
using namespace llvm; using namespace llvm;

View File

@ -7,11 +7,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"
using namespace llvm; using namespace llvm;

View File

@ -7,11 +7,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -21,7 +21,6 @@ add_lld_library(lldELF
Driver.cpp Driver.cpp
DriverUtils.cpp DriverUtils.cpp
EhFrame.cpp EhFrame.cpp
Error.cpp
Filesystem.cpp Filesystem.cpp
GdbIndex.cpp GdbIndex.cpp
ICF.cpp ICF.cpp

View File

@ -108,7 +108,6 @@ struct Configuration {
bool AsNeeded = false; bool AsNeeded = false;
bool Bsymbolic; bool Bsymbolic;
bool BsymbolicFunctions; bool BsymbolicFunctions;
bool ColorDiagnostics = false;
bool CompressDebugSections; bool CompressDebugSections;
bool DefineCommon; bool DefineCommon;
bool Demangle = true; bool Demangle = true;
@ -117,7 +116,6 @@ struct Configuration {
bool EmitRelocs; bool EmitRelocs;
bool EnableNewDtags; bool EnableNewDtags;
bool ExportDynamic; bool ExportDynamic;
bool FatalWarnings;
bool GcSections; bool GcSections;
bool GdbIndex; bool GdbIndex;
bool GnuHash = false; bool GnuHash = false;
@ -167,7 +165,6 @@ struct Configuration {
ELFKind EKind = ELFNoneKind; ELFKind EKind = ELFNoneKind;
uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
uint16_t EMachine = llvm::ELF::EM_NONE; uint16_t EMachine = llvm::ELF::EM_NONE;
uint64_t ErrorLimit = 20;
llvm::Optional<uint64_t> ImageBase; llvm::Optional<uint64_t> ImageBase;
uint64_t MaxPageSize; uint64_t MaxPageSize;
uint64_t ZStackSize; uint64_t ZStackSize;

View File

@ -25,7 +25,6 @@
#include "Driver.h" #include "Driver.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "Filesystem.h" #include "Filesystem.h"
#include "ICF.h" #include "ICF.h"
#include "InputFiles.h" #include "InputFiles.h"
@ -40,6 +39,7 @@
#include "Target.h" #include "Target.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/Driver.h" #include "lld/Common/Driver.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Threads.h" #include "lld/Common/Threads.h"
#include "lld/Common/Version.h" #include "lld/Common/Version.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
@ -72,8 +72,12 @@ static void setConfigs();
bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
raw_ostream &Error) { raw_ostream &Error) {
ErrorCount = 0; errorHandler().LogName = Args[0];
ErrorOS = &Error; errorHandler().ErrorLimitExceededMsg =
"too many errors emitted, stopping now (use "
"-error-limit=0 to see all errors)";
errorHandler().ErrorOS = &Error;
errorHandler().ColorDiagnostics = Error.has_colors();
InputSections.clear(); InputSections.clear();
OutputSections.clear(); OutputSections.clear();
Tar = nullptr; Tar = nullptr;
@ -95,10 +99,10 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
// This saves time because the overhead of calling destructors // This saves time because the overhead of calling destructors
// for all globally-allocated objects is not negligible. // for all globally-allocated objects is not negligible.
if (Config->ExitEarly) if (Config->ExitEarly)
exitLld(ErrorCount ? 1 : 0); exitLld(errorCount() ? 1 : 0);
freeArena(); freeArena();
return !ErrorCount; return !errorCount();
} }
// Parses a linker -m option. // Parses a linker -m option.
@ -332,7 +336,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
// Interpret this flag early because error() depends on them. // Interpret this flag early because error() depends on them.
Config->ErrorLimit = getInteger(Args, OPT_error_limit, 20); errorHandler().ErrorLimit = getInteger(Args, OPT_error_limit, 20);
// Handle -help // Handle -help
if (Args.hasArg(OPT_help)) { if (Args.hasArg(OPT_help)) {
@ -365,6 +369,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
return; return;
Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown); Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
errorHandler().ExitEarly = Config->ExitEarly;
if (const char *Path = getReproduceOption(Args)) { if (const char *Path = getReproduceOption(Args)) {
// Note that --reproduce is a debug option so you can ignore it // Note that --reproduce is a debug option so you can ignore it
@ -388,7 +393,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
inferMachineType(); inferMachineType();
setConfigs(); setConfigs();
checkOptions(Args); checkOptions(Args);
if (ErrorCount) if (errorCount())
return; return;
switch (Config->EKind) { switch (Config->EKind) {
@ -645,7 +650,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->Entry = Args.getLastArgValue(OPT_entry); Config->Entry = Args.getLastArgValue(OPT_entry);
Config->ExportDynamic = Config->ExportDynamic =
Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false); Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
Config->FatalWarnings = errorHandler().FatalWarnings =
Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
Config->FilterList = getArgs(Args, OPT_filter); Config->FilterList = getArgs(Args, OPT_filter);
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
@ -694,6 +699,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->Undefined = getArgs(Args, OPT_undefined); Config->Undefined = getArgs(Args, OPT_undefined);
Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
Config->Verbose = Args.hasArg(OPT_verbose); Config->Verbose = Args.hasArg(OPT_verbose);
errorHandler().Verbose = Config->Verbose;
Config->WarnCommon = Args.hasArg(OPT_warn_common); Config->WarnCommon = Args.hasArg(OPT_warn_common);
Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
Config->ZExecstack = hasZOption(Args, "execstack"); Config->ZExecstack = hasZOption(Args, "execstack");
@ -881,7 +887,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
} }
} }
if (Files.empty() && ErrorCount == 0) if (Files.empty() && errorCount() == 0)
error("no input files"); error("no input files");
} }
@ -1009,7 +1015,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
error("cannot open output file " + Config->OutputFile + ": " + E.message()); error("cannot open output file " + Config->OutputFile + ": " + E.message());
if (auto E = tryCreateFile(Config->MapFile)) if (auto E = tryCreateFile(Config->MapFile))
error("cannot open map file " + Config->MapFile + ": " + E.message()); error("cannot open map file " + Config->MapFile + ": " + E.message());
if (ErrorCount) if (errorCount())
return; return;
// Use default entry point name if no name was given via the command // Use default entry point name if no name was given via the command
@ -1053,7 +1059,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
Symtab->fetchIfLazy<ELFT>(Config->Entry); Symtab->fetchIfLazy<ELFT>(Config->Entry);
// Return if there were name resolution errors. // Return if there were name resolution errors.
if (ErrorCount) if (errorCount())
return; return;
// Handle undefined symbols in DSOs. // Handle undefined symbols in DSOs.
@ -1075,7 +1081,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
Symtab->addSymbolAlias<ELFT>(Def.first, Def.second); Symtab->addSymbolAlias<ELFT>(Def.first, Def.second);
Symtab->addCombinedLTOObject<ELFT>(); Symtab->addCombinedLTOObject<ELFT>();
if (ErrorCount) if (errorCount())
return; return;
// Apply symbol renames for -wrap and -defsym // Apply symbol renames for -wrap and -defsym

View File

@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Driver.h" #include "Driver.h"
#include "Error.h"
#include "Memory.h" #include "Memory.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Reproduce.h" #include "lld/Common/Reproduce.h"
#include "lld/Common/Version.h" #include "lld/Common/Version.h"
#include "llvm/ADT/Optional.h" #include "llvm/ADT/Optional.h"
@ -51,25 +51,26 @@ static const opt::OptTable::Info OptInfo[] = {
ELFOptTable::ELFOptTable() : OptTable(OptInfo) {} ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
// Parse -color-diagnostics={auto,always,never} or -no-color-diagnostics. // Set color diagnostics according to -color-diagnostics={auto,always,never}
static bool getColorDiagnostics(opt::InputArgList &Args) { // or -no-color-diagnostics flags.
static void handleColorDiagnostics(opt::InputArgList &Args) {
auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq, auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
OPT_no_color_diagnostics); OPT_no_color_diagnostics);
if (!Arg) if (!Arg)
return ErrorOS->has_colors(); return;
if (Arg->getOption().getID() == OPT_color_diagnostics) else if (Arg->getOption().getID() == OPT_color_diagnostics)
return true; errorHandler().ColorDiagnostics = true;
if (Arg->getOption().getID() == OPT_no_color_diagnostics) else if (Arg->getOption().getID() == OPT_no_color_diagnostics)
return false; errorHandler().ColorDiagnostics = false;
else {
StringRef S = Arg->getValue(); StringRef S = Arg->getValue();
if (S == "auto") if (S == "always")
return ErrorOS->has_colors(); errorHandler().ColorDiagnostics = true;
if (S == "always") else if (S == "never")
return true; errorHandler().ColorDiagnostics = false;
if (S != "never") else if (S != "auto")
error("unknown option: -color-diagnostics=" + S); error("unknown option: -color-diagnostics=" + S);
return false; }
} }
static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) { static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
@ -103,9 +104,7 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec); cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
Args = this->ParseArgs(Vec, MissingIndex, MissingCount); Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
// Interpret -color-diagnostics early so that error messages handleColorDiagnostics(Args);
// for unknown flags are colored.
Config->ColorDiagnostics = getColorDiagnostics(Args);
if (MissingCount) if (MissingCount)
error(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); error(Twine(Args.getArgString(MissingIndex)) + ": missing argument");

View File

@ -17,11 +17,11 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "EhFrame.h" #include "EhFrame.h"
#include "Error.h"
#include "InputSection.h" #include "InputSection.h"
#include "Relocations.h" #include "Relocations.h"
#include "Strings.h" #include "Strings.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "InputFiles.h" #include "InputFiles.h"
#include "Error.h"
#include "InputSection.h" #include "InputSection.h"
#include "LinkerScript.h" #include "LinkerScript.h"
#include "Memory.h" #include "Memory.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/Analysis.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h"

View File

@ -11,9 +11,9 @@
#define LLD_ELF_INPUT_FILES_H #define LLD_ELF_INPUT_FILES_H
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputSection.h" #include "InputSection.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h" #include "lld/Common/LLVM.h"
#include "lld/Common/Reproduce.h" #include "lld/Common/Reproduce.h"

View File

@ -10,7 +10,6 @@
#include "InputSection.h" #include "InputSection.h"
#include "Config.h" #include "Config.h"
#include "EhFrame.h" #include "EhFrame.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "LinkerScript.h" #include "LinkerScript.h"
#include "Memory.h" #include "Memory.h"
@ -19,6 +18,7 @@
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "Thunks.h" #include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/Decompressor.h" #include "llvm/Object/Decompressor.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/Compression.h" #include "llvm/Support/Compression.h"

View File

@ -9,11 +9,11 @@
#include "LTO.h" #include "LTO.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "LinkerScript.h" #include "LinkerScript.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/TargetOptionsCommandFlags.h" #include "lld/Common/TargetOptionsCommandFlags.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"

View File

@ -927,7 +927,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
Expr = fromPlt(Expr); Expr = fromPlt(Expr);
Expr = adjustExpr<ELFT>(Body, Expr, Type, Sec, Rel.r_offset); Expr = adjustExpr<ELFT>(Body, Expr, Type, Sec, Rel.r_offset);
if (ErrorCount) if (errorCount())
continue; continue;
// This relocation does not require got entry, but it is relative to got and // This relocation does not require got entry, but it is relative to got and

View File

@ -33,7 +33,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "ScriptLexer.h" #include "ScriptLexer.h"
#include "Error.h" #include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
using namespace llvm; using namespace llvm;
@ -75,7 +75,7 @@ ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); }
// We don't want to record cascading errors. Keep only the first one. // We don't want to record cascading errors. Keep only the first one.
void ScriptLexer::setError(const Twine &Msg) { void ScriptLexer::setError(const Twine &Msg) {
if (ErrorCount) if (errorCount())
return; return;
std::string S = (getCurrentLocation() + ": " + Msg).str(); std::string S = (getCurrentLocation() + ": " + Msg).str();
@ -159,7 +159,7 @@ StringRef ScriptLexer::skipSpace(StringRef S) {
} }
// An erroneous token is handled as if it were the last token before EOF. // An erroneous token is handled as if it were the last token before EOF.
bool ScriptLexer::atEOF() { return ErrorCount || Tokens.size() == Pos; } bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }
// Split a given string as an expression. // Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example. // This function returns "3", "*" and "5" for "3*5" for example.
@ -207,7 +207,7 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) {
// //
// This function may split the current token into multiple tokens. // This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() { void ScriptLexer::maybeSplitExpr() {
if (!InExpr || ErrorCount || atEOF()) if (!InExpr || errorCount() || atEOF())
return; return;
std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]); std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
@ -220,7 +220,7 @@ void ScriptLexer::maybeSplitExpr() {
StringRef ScriptLexer::next() { StringRef ScriptLexer::next() {
maybeSplitExpr(); maybeSplitExpr();
if (ErrorCount) if (errorCount())
return ""; return "";
if (atEOF()) { if (atEOF()) {
setError("unexpected EOF"); setError("unexpected EOF");
@ -231,7 +231,7 @@ StringRef ScriptLexer::next() {
StringRef ScriptLexer::peek() { StringRef ScriptLexer::peek() {
StringRef Tok = next(); StringRef Tok = next();
if (ErrorCount) if (errorCount())
return ""; return "";
Pos = Pos - 1; Pos = Pos - 1;
return Tok; return Tok;
@ -260,7 +260,7 @@ bool ScriptLexer::consumeLabel(StringRef Tok) {
void ScriptLexer::skip() { (void)next(); } void ScriptLexer::skip() { (void)next(); }
void ScriptLexer::expect(StringRef Expect) { void ScriptLexer::expect(StringRef Expect) {
if (ErrorCount) if (errorCount())
return; return;
StringRef Tok = next(); StringRef Tok = next();
if (Tok != Expect) if (Tok != Expect)

View File

@ -209,7 +209,7 @@ void ScriptParser::readVersionScriptCommand() {
return; return;
} }
while (!atEOF() && !ErrorCount && peek() != "}") { while (!atEOF() && !errorCount() && peek() != "}") {
StringRef VerStr = next(); StringRef VerStr = next();
if (VerStr == "{") { if (VerStr == "{") {
setError("anonymous version definition is used in " setError("anonymous version definition is used in "
@ -303,7 +303,7 @@ void ScriptParser::readAsNeeded() {
expect("("); expect("(");
bool Orig = Config->AsNeeded; bool Orig = Config->AsNeeded;
Config->AsNeeded = true; Config->AsNeeded = true;
while (!ErrorCount && !consume(")")) while (!errorCount() && !consume(")"))
addFile(unquote(next())); addFile(unquote(next()));
Config->AsNeeded = Orig; Config->AsNeeded = Orig;
} }
@ -319,13 +319,13 @@ void ScriptParser::readEntry() {
void ScriptParser::readExtern() { void ScriptParser::readExtern() {
expect("("); expect("(");
while (!ErrorCount && !consume(")")) while (!errorCount() && !consume(")"))
Config->Undefined.push_back(next()); Config->Undefined.push_back(next());
} }
void ScriptParser::readGroup() { void ScriptParser::readGroup() {
expect("("); expect("(");
while (!ErrorCount && !consume(")")) { while (!errorCount() && !consume(")")) {
if (consume("AS_NEEDED")) if (consume("AS_NEEDED"))
readAsNeeded(); readAsNeeded();
else else
@ -369,7 +369,7 @@ void ScriptParser::readOutput() {
void ScriptParser::readOutputArch() { void ScriptParser::readOutputArch() {
// OUTPUT_ARCH is ignored for now. // OUTPUT_ARCH is ignored for now.
expect("("); expect("(");
while (!ErrorCount && !consume(")")) while (!errorCount() && !consume(")"))
skip(); skip();
} }
@ -389,12 +389,12 @@ void ScriptParser::readOutputFormat() {
void ScriptParser::readPhdrs() { void ScriptParser::readPhdrs() {
expect("{"); expect("{");
while (!ErrorCount && !consume("}")) { while (!errorCount() && !consume("}")) {
PhdrsCommand Cmd; PhdrsCommand Cmd;
Cmd.Name = next(); Cmd.Name = next();
Cmd.Type = readPhdrType(); Cmd.Type = readPhdrType();
while (!ErrorCount && !consume(";")) { while (!errorCount() && !consume(";")) {
if (consume("FILEHDR")) if (consume("FILEHDR"))
Cmd.HasFilehdr = true; Cmd.HasFilehdr = true;
else if (consume("PHDRS")) else if (consume("PHDRS"))
@ -442,7 +442,7 @@ void ScriptParser::readSections() {
Config->SingleRoRx = true; Config->SingleRoRx = true;
expect("{"); expect("{");
while (!ErrorCount && !consume("}")) { while (!errorCount() && !consume("}")) {
StringRef Tok = next(); StringRef Tok = next();
BaseCommand *Cmd = readProvideOrAssignment(Tok); BaseCommand *Cmd = readProvideOrAssignment(Tok);
if (!Cmd) { if (!Cmd) {
@ -467,7 +467,7 @@ static int precedence(StringRef Op) {
StringMatcher ScriptParser::readFilePatterns() { StringMatcher ScriptParser::readFilePatterns() {
std::vector<StringRef> V; std::vector<StringRef> V;
while (!ErrorCount && !consume(")")) while (!errorCount() && !consume(")"))
V.push_back(next()); V.push_back(next());
return StringMatcher(V); return StringMatcher(V);
} }
@ -499,7 +499,7 @@ SortSectionPolicy ScriptParser::readSortKind() {
// any file but a.o, and section .baz in any file but b.o. // any file but a.o, and section .baz in any file but b.o.
std::vector<SectionPattern> ScriptParser::readInputSectionsList() { std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
std::vector<SectionPattern> Ret; std::vector<SectionPattern> Ret;
while (!ErrorCount && peek() != ")") { while (!errorCount() && peek() != ")") {
StringMatcher ExcludeFilePat; StringMatcher ExcludeFilePat;
if (consume("EXCLUDE_FILE")) { if (consume("EXCLUDE_FILE")) {
expect("("); expect("(");
@ -507,7 +507,7 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
} }
std::vector<StringRef> V; std::vector<StringRef> V;
while (!ErrorCount && peek() != ")" && peek() != "EXCLUDE_FILE") while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
V.push_back(next()); V.push_back(next());
if (!V.empty()) if (!V.empty())
@ -534,7 +534,7 @@ ScriptParser::readInputSectionRules(StringRef FilePattern) {
auto *Cmd = make<InputSectionDescription>(FilePattern); auto *Cmd = make<InputSectionDescription>(FilePattern);
expect("("); expect("(");
while (!ErrorCount && !consume(")")) { while (!errorCount() && !consume(")")) {
SortSectionPolicy Outer = readSortKind(); SortSectionPolicy Outer = readSortKind();
SortSectionPolicy Inner = SortSectionPolicy::Default; SortSectionPolicy Inner = SortSectionPolicy::Default;
std::vector<SectionPattern> V; std::vector<SectionPattern> V;
@ -676,7 +676,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
Cmd->Constraint = ConstraintKind::ReadWrite; Cmd->Constraint = ConstraintKind::ReadWrite;
expect("{"); expect("{");
while (!ErrorCount && !consume("}")) { while (!errorCount() && !consume("}")) {
StringRef Tok = next(); StringRef Tok = next();
if (Tok == ";") { if (Tok == ";") {
// Empty commands are allowed. Do nothing here. // Empty commands are allowed. Do nothing here.
@ -820,7 +820,7 @@ static Expr combine(StringRef Op, Expr L, Expr R) {
// This is a part of the operator-precedence parser. This function // This is a part of the operator-precedence parser. This function
// assumes that the remaining token stream starts with an operator. // assumes that the remaining token stream starts with an operator.
Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {
while (!atEOF() && !ErrorCount) { while (!atEOF() && !errorCount()) {
// Read an operator and an expression. // Read an operator and an expression.
if (consume("?")) if (consume("?"))
return readTernary(Lhs); return readTernary(Lhs);
@ -1098,7 +1098,7 @@ Expr ScriptParser::readParenExpr() {
std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() { std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
std::vector<StringRef> Phdrs; std::vector<StringRef> Phdrs;
while (!ErrorCount && peek().startswith(":")) { while (!errorCount() && peek().startswith(":")) {
StringRef Tok = next(); StringRef Tok = next();
Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1)); Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1));
} }
@ -1201,7 +1201,7 @@ ScriptParser::readSymbols() {
std::vector<SymbolVersion> Globals; std::vector<SymbolVersion> Globals;
std::vector<SymbolVersion> *V = &Globals; std::vector<SymbolVersion> *V = &Globals;
while (!ErrorCount) { while (!errorCount()) {
if (consume("}")) if (consume("}"))
break; break;
if (consumeLabel("local")) { if (consumeLabel("local")) {
@ -1235,7 +1235,7 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
expect("{"); expect("{");
std::vector<SymbolVersion> Ret; std::vector<SymbolVersion> Ret;
while (!ErrorCount && peek() != "}") { while (!errorCount() && peek() != "}") {
StringRef Tok = next(); StringRef Tok = next();
bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok); bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok);
Ret.push_back({unquote(Tok), IsCXX, HasWildcard}); Ret.push_back({unquote(Tok), IsCXX, HasWildcard});
@ -1262,7 +1262,7 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2,
// MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... } // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
void ScriptParser::readMemory() { void ScriptParser::readMemory() {
expect("{"); expect("{");
while (!ErrorCount && !consume("}")) { while (!errorCount() && !consume("}")) {
StringRef Name = next(); StringRef Name = next();
uint32_t Flags = 0; uint32_t Flags = 0;

View File

@ -9,7 +9,7 @@
#include "Strings.h" #include "Strings.h"
#include "Config.h" #include "Config.h"
#include "Error.h" #include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"

View File

@ -16,10 +16,10 @@
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "LinkerScript.h" #include "LinkerScript.h"
#include "Memory.h" #include "Memory.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
using namespace llvm; using namespace llvm;
@ -91,7 +91,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
// DSOs are uniquified not by filename but by soname. // DSOs are uniquified not by filename but by soname.
F->parseSoName(); F->parseSoName();
if (ErrorCount || !SoNames.insert(F->SoName).second) if (errorCount() || !SoNames.insert(F->SoName).second)
return; return;
SharedFiles.push_back(F); SharedFiles.push_back(F);
F->parseRest(); F->parseRest();

View File

@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Symbols.h" #include "Symbols.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "InputSection.h" #include "InputSection.h"
#include "OutputSections.h" #include "OutputSections.h"
@ -17,6 +16,7 @@
#include "Target.h" #include "Target.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include <cstring> #include <cstring>

View File

@ -16,7 +16,6 @@
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "LinkerScript.h" #include "LinkerScript.h"
#include "Memory.h" #include "Memory.h"
@ -25,6 +24,7 @@
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Target.h" #include "Target.h"
#include "Writer.h" #include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Threads.h" #include "lld/Common/Threads.h"
#include "lld/Common/Version.h" #include "lld/Common/Version.h"
#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/Dwarf.h"

View File

@ -25,11 +25,11 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "Target.h" #include "Target.h"
#include "Error.h"
#include "InputFiles.h" #include "InputFiles.h"
#include "OutputSections.h" #include "OutputSections.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Symbols.h" #include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
using namespace llvm; using namespace llvm;

View File

@ -10,8 +10,8 @@
#ifndef LLD_ELF_TARGET_H #ifndef LLD_ELF_TARGET_H
#define LLD_ELF_TARGET_H #define LLD_ELF_TARGET_H
#include "Error.h"
#include "InputSection.h" #include "InputSection.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/Object/ELF.h" #include "llvm/Object/ELF.h"
namespace lld { namespace lld {

View File

@ -23,13 +23,13 @@
#include "Thunks.h" #include "Thunks.h"
#include "Config.h" #include "Config.h"
#include "Error.h"
#include "InputSection.h" #include "InputSection.h"
#include "Memory.h" #include "Memory.h"
#include "OutputSections.h" #include "OutputSections.h"
#include "Symbols.h" #include "Symbols.h"
#include "SyntheticSections.h" #include "SyntheticSections.h"
#include "Target.h" #include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h" #include "llvm/Support/Endian.h"

View File

@ -188,7 +188,7 @@ template <class ELFT> void Writer<ELFT>::run() {
// to the string table, and add entries to .got and .plt. // to the string table, and add entries to .got and .plt.
// finalizeSections does that. // finalizeSections does that.
finalizeSections(); finalizeSections();
if (ErrorCount) if (errorCount())
return; return;
// If -compressed-debug-sections is specified, we need to compress // If -compressed-debug-sections is specified, we need to compress
@ -218,11 +218,11 @@ template <class ELFT> void Writer<ELFT>::run() {
} }
// It does not make sense try to open the file if we have error already. // It does not make sense try to open the file if we have error already.
if (ErrorCount) if (errorCount())
return; return;
// Write the result down to a file. // Write the result down to a file.
openFile(); openFile();
if (ErrorCount) if (errorCount())
return; return;
if (!Config->OFormatBinary) { if (!Config->OFormatBinary) {
@ -236,12 +236,12 @@ template <class ELFT> void Writer<ELFT>::run() {
// Backfill .note.gnu.build-id section content. This is done at last // Backfill .note.gnu.build-id section content. This is done at last
// because the content is usually a hash value of the entire output file. // because the content is usually a hash value of the entire output file.
writeBuildId(); writeBuildId();
if (ErrorCount) if (errorCount())
return; return;
// Handle -Map option. // Handle -Map option.
writeMapFile<ELFT>(); writeMapFile<ELFT>();
if (ErrorCount) if (errorCount())
return; return;
if (auto EC = Buffer->commit()) if (auto EC = Buffer->commit())
@ -1287,7 +1287,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
} }
// Do not proceed if there was an undefined symbol. // Do not proceed if there was an undefined symbol.
if (ErrorCount) if (errorCount())
return; return;
addPredefinedSections(); addPredefinedSections();

View File

@ -1,4 +1,4 @@
//===- Error.h --------------------------------------------------*- C++ -*-===// //===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
// //
// The LLVM Linker // The LLVM Linker
// //
@ -25,24 +25,48 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLD_ELF_ERROR_H #ifndef LLD_COMMON_ERRORHANDLER_H
#define LLD_ELF_ERROR_H #define LLD_COMMON_ERRORHANDLER_H
#include "lld/Common/LLVM.h" #include "lld/Common/LLVM.h"
#include "llvm/Support/Error.h" #include "llvm/Support/Error.h"
namespace lld { namespace lld {
namespace elf {
extern uint64_t ErrorCount; class ErrorHandler {
extern llvm::raw_ostream *ErrorOS; public:
uint64_t ErrorCount = 0;
uint64_t ErrorLimit = 20;
StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now";
StringRef LogName = "lld";
llvm::raw_ostream *ErrorOS = &llvm::errs();
bool ColorDiagnostics = llvm::errs().has_colors();
bool ExitEarly = true;
bool FatalWarnings = false;
bool Verbose = false;
void log(const Twine &Msg); void error(const Twine &Msg);
void message(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
void warn(const Twine &Msg); void log(const Twine &Msg);
void error(const Twine &Msg); void message(const Twine &Msg);
LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); void warn(const Twine &Msg);
private:
void print(StringRef S, raw_ostream::Colors C);
};
/// Returns the default error handler.
ErrorHandler &errorHandler();
inline void error(const Twine &Msg) { errorHandler().error(Msg); }
inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) {
errorHandler().fatal(Msg);
}
inline void log(const Twine &Msg) { errorHandler().log(Msg); }
inline void message(const Twine &Msg) { errorHandler().message(Msg); }
inline void warn(const Twine &Msg) { errorHandler().warn(Msg); }
inline uint64_t errorCount() { return errorHandler().ErrorCount; }
LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
@ -72,7 +96,6 @@ template <class T> T check(Expected<T> E, const Twine &Prefix) {
return std::move(*E); return std::move(*E);
} }
} // namespace elf
} // namespace lld } // namespace lld
#endif #endif