mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-08 02:18:43 +00:00
[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:
parent
5e6cb9022c
commit
b8a59c8aa5
@ -11,7 +11,6 @@ add_lld_library(lldCOFF
|
||||
DLL.cpp
|
||||
Driver.cpp
|
||||
DriverUtils.cpp
|
||||
Error.cpp
|
||||
ICF.cpp
|
||||
InputFiles.cpp
|
||||
LTO.cpp
|
||||
|
@ -8,10 +8,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Chunks.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
|
@ -84,13 +84,10 @@ struct Configuration {
|
||||
bool NoEntry = false;
|
||||
std::string OutputFile;
|
||||
std::string ImportName;
|
||||
bool ColorDiagnostics;
|
||||
bool DoGC = true;
|
||||
bool DoICF = true;
|
||||
uint64_t ErrorLimit = 20;
|
||||
bool Relocatable = true;
|
||||
bool Force = false;
|
||||
bool FatalWarnings = false;
|
||||
bool Debug = false;
|
||||
bool WriteSymtab = true;
|
||||
unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "Driver.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Memory.h"
|
||||
#include "MinGW.h"
|
||||
@ -17,6 +16,7 @@
|
||||
#include "Symbols.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/Driver.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Version.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
@ -55,12 +55,14 @@ StringSaver Saver{BAlloc};
|
||||
std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
|
||||
|
||||
bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
|
||||
ErrorCount = 0;
|
||||
ErrorOS = &Diag;
|
||||
|
||||
errorHandler().LogName = Args[0];
|
||||
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->Argv = {Args.begin(), Args.end()};
|
||||
Config->ColorDiagnostics = ErrorOS->has_colors();
|
||||
Config->CanExitEarly = CanExitEarly;
|
||||
|
||||
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.
|
||||
if (CanExitEarly)
|
||||
exitLld(ErrorCount ? 1 : 0);
|
||||
exitLld(errorCount() ? 1 : 0);
|
||||
|
||||
freeArena();
|
||||
return !ErrorCount;
|
||||
return !errorCount();
|
||||
}
|
||||
|
||||
// Drop directory components and replace extension with ".exe" or ".dll".
|
||||
@ -212,8 +214,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &C,
|
||||
enqueueTask([=]() {
|
||||
auto MBOrErr = Future->get();
|
||||
if (MBOrErr.second)
|
||||
fatal(MBOrErr.second,
|
||||
"could not get the buffer for the member defining " + SymName);
|
||||
fatal("could not get the buffer for the member defining " + SymName +
|
||||
": " + MBOrErr.second.message());
|
||||
Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,
|
||||
ParentName);
|
||||
});
|
||||
@ -619,7 +621,7 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) {
|
||||
SmallString<128> S;
|
||||
if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path),
|
||||
".lib", S))
|
||||
fatal(EC, "cannot create a temporary file");
|
||||
fatal("cannot create a temporary file: " + EC.message());
|
||||
std::string Temp = S.str();
|
||||
TemporaryFiles.push_back(Temp);
|
||||
|
||||
@ -648,7 +650,7 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) {
|
||||
int Fd;
|
||||
if (auto EC = sys::fs::createTemporaryFile(
|
||||
"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);
|
||||
OS << Obj->MB.getBuffer();
|
||||
Temps.push_back(S.str());
|
||||
@ -736,7 +738,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
StringRef S = Arg->getValue();
|
||||
if (S.getAsInteger(10, N))
|
||||
error(Arg->getSpelling() + " number expected, but got " + S);
|
||||
Config->ErrorLimit = N;
|
||||
errorHandler().ErrorLimit = N;
|
||||
}
|
||||
|
||||
// Handle /help
|
||||
@ -792,6 +794,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
// Handle /verbose
|
||||
if (Args.hasArg(OPT_verbose))
|
||||
Config->Verbose = true;
|
||||
errorHandler().Verbose = Config->Verbose;
|
||||
|
||||
// Handle /force or /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);
|
||||
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
|
||||
@ -1191,7 +1194,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
addUndefined(mangle("_load_config_used"));
|
||||
} while (run());
|
||||
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// 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.
|
||||
Symtab->reportRemainingUndefines();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// 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)
|
||||
if (!File->SEHCompat)
|
||||
error("/safeseh: " + File->getName() + " is not compatible with SEH");
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -15,9 +15,9 @@
|
||||
|
||||
#include "Config.h"
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "Memory.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/BinaryFormat/COFF.h"
|
||||
@ -57,7 +57,7 @@ public:
|
||||
void run() {
|
||||
ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog);
|
||||
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);
|
||||
Args.insert(Args.begin(), Exe);
|
||||
|
||||
@ -288,14 +288,14 @@ public:
|
||||
TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") {
|
||||
SmallString<128> 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();
|
||||
|
||||
if (!Contents.empty()) {
|
||||
std::error_code EC;
|
||||
raw_fd_ostream OS(Path, EC, sys::fs::F_None);
|
||||
if (EC)
|
||||
fatal(EC, "failed to open " + Path);
|
||||
fatal("failed to open " + Path + ": " + EC.message());
|
||||
OS << Contents;
|
||||
}
|
||||
}
|
||||
@ -363,13 +363,15 @@ static std::string createManifestXmlWithInternalMt(StringRef DefaultXml) {
|
||||
|
||||
windows_manifest::WindowsManifestMerger Merger;
|
||||
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) {
|
||||
std::unique_ptr<MemoryBuffer> Manifest =
|
||||
check(MemoryBuffer::getFile(Filename));
|
||||
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();
|
||||
@ -381,7 +383,7 @@ static std::string createManifestXmlWithExternalMt(StringRef DefaultXml) {
|
||||
std::error_code EC;
|
||||
raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text);
|
||||
if (EC)
|
||||
fatal(EC, "failed to open " + Default.Path);
|
||||
fatal("failed to open " + Default.Path + ": " + EC.message());
|
||||
OS << DefaultXml;
|
||||
OS.close();
|
||||
|
||||
@ -482,7 +484,7 @@ void createSideBySideManifest() {
|
||||
std::error_code EC;
|
||||
raw_fd_ostream Out(Path, EC, sys::fs::F_Text);
|
||||
if (EC)
|
||||
fatal(EC, "failed to create manifest");
|
||||
fatal("failed to create manifest: " + EC.message());
|
||||
Out << createManifestXml();
|
||||
}
|
||||
|
||||
@ -649,13 +651,13 @@ MemoryBufferRef convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
|
||||
if (!RF)
|
||||
fatal("cannot compile non-resource file as resource");
|
||||
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 =
|
||||
llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);
|
||||
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;
|
||||
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.
|
||||
Config->FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
|
||||
errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
|
||||
|
||||
if (MissingCount)
|
||||
fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
|
||||
|
@ -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
|
@ -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
|
@ -19,8 +19,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Chunks.h"
|
||||
#include "Error.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Parallel.h"
|
||||
|
@ -11,10 +11,10 @@
|
||||
#include "Chunks.h"
|
||||
#include "Config.h"
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "Memory.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm-c/lto.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
@ -127,9 +127,9 @@ void ObjFile::initializeChunks() {
|
||||
const coff_section *Sec;
|
||||
StringRef Name;
|
||||
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))
|
||||
fatal(EC, "getSectionName failed: #" + Twine(I));
|
||||
fatal("getSectionName failed: #" + Twine(I) + ": " + EC.message());
|
||||
if (Name == ".sxdata") {
|
||||
SXData = Sec;
|
||||
continue;
|
||||
@ -179,7 +179,6 @@ void ObjFile::initializeSymbols() {
|
||||
int32_t LastSectionNumber = 0;
|
||||
|
||||
for (uint32_t I = 0; I < NumSymbols; ++I) {
|
||||
// Get a COFFSymbolRef object.
|
||||
COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
|
||||
|
||||
const void *AuxP = nullptr;
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
#include "LTO.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/TargetOptionsCommandFlags.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
|
@ -20,11 +20,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MapFile.h"
|
||||
#include "Error.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "Writer.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Support/Parallel.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MinGW.h"
|
||||
#include "Error.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -11,10 +11,10 @@
|
||||
#include "Chunks.h"
|
||||
#include "Config.h"
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
|
||||
@ -188,7 +188,7 @@ maybeReadTypeServerRecord(CVTypeArray &Types) {
|
||||
return None;
|
||||
TypeServer2Record 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);
|
||||
}
|
||||
|
||||
@ -202,7 +202,7 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
|
||||
CVTypeArray Types;
|
||||
BinaryStreamReader Reader(Stream);
|
||||
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
|
||||
// merge any type information.
|
||||
@ -213,7 +213,8 @@ const CVIndexMap &PDBLinker::mergeDebugT(ObjFile *File,
|
||||
// ObjectIndexMap.
|
||||
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
|
||||
ObjectIndexMap.TPIMap, Types))
|
||||
fatal(Err, "codeview::mergeTypeAndIdRecords failed");
|
||||
fatal("codeview::mergeTypeAndIdRecords failed: " +
|
||||
toString(std::move(Err)));
|
||||
return ObjectIndexMap;
|
||||
}
|
||||
|
||||
@ -275,23 +276,23 @@ const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjFile *File,
|
||||
ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
|
||||
}
|
||||
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.
|
||||
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
|
||||
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,
|
||||
ExpectedTpi->typeArray()))
|
||||
fatal(Err, "codeview::mergeTypeRecords failed");
|
||||
fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
|
||||
|
||||
// Merge IPI.
|
||||
auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
|
||||
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,
|
||||
ExpectedIpi->typeArray()))
|
||||
fatal(Err, "codeview::mergeIdRecords failed");
|
||||
fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
|
||||
|
||||
return IndexMap;
|
||||
}
|
||||
|
@ -10,10 +10,10 @@
|
||||
#include "SymbolTable.h"
|
||||
#include "Config.h"
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "LTO.h"
|
||||
#include "Memory.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -8,10 +8,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Symbols.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Memory.h"
|
||||
#include "Strings.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
@ -10,13 +10,13 @@
|
||||
#include "Writer.h"
|
||||
#include "Config.h"
|
||||
#include "DLL.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "MapFile.h"
|
||||
#include "Memory.h"
|
||||
#include "PDB.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
@ -316,7 +316,7 @@ void Writer::run() {
|
||||
writeMapFile(OutputSections);
|
||||
|
||||
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) {
|
||||
|
@ -3,6 +3,7 @@ if(NOT LLD_BUILT_STANDALONE)
|
||||
endif()
|
||||
|
||||
add_lld_library(lldCommon
|
||||
ErrorHandler.cpp
|
||||
Reproduce.cpp
|
||||
TargetOptionsCommandFlags.cpp
|
||||
Threads.cpp
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- Error.cpp ----------------------------------------------------------===//
|
||||
//===- ErrorHandler.cpp ---------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@ -7,8 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "Config.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
||||
#include "lld/Common/Threads.h"
|
||||
|
||||
@ -25,10 +24,6 @@
|
||||
using namespace llvm;
|
||||
|
||||
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,
|
||||
// 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
|
||||
// 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".
|
||||
// We want to separate multi-line error messages with a newline.
|
||||
static bool Flag;
|
||||
@ -46,64 +41,15 @@ static void newline(const Twine &Msg) {
|
||||
Flag = StringRef(Msg.str()).contains('\n');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
namespace lld {
|
||||
|
||||
ErrorHandler &errorHandler() {
|
||||
static ErrorHandler Handler;
|
||||
return Handler;
|
||||
}
|
||||
|
||||
void elf::log(const Twine &Msg) {
|
||||
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) {
|
||||
void exitLld(int Val) {
|
||||
waitForBackgroundThreads();
|
||||
|
||||
// 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.
|
||||
@ -114,7 +60,63 @@ void elf::exitLld(int 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);
|
||||
exitLld(1);
|
||||
}
|
||||
|
||||
} // end namespace lld
|
@ -7,11 +7,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "Thunks.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -7,10 +7,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -7,12 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "Thunks.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -26,10 +26,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -7,13 +7,13 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "OutputSections.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "Thunks.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -11,11 +11,11 @@
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Writer.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/MipsABIFlags.h"
|
||||
|
@ -7,9 +7,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "Symbols.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -7,10 +7,10 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -7,11 +7,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -7,11 +7,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -7,11 +7,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
||||
|
@ -21,7 +21,6 @@ add_lld_library(lldELF
|
||||
Driver.cpp
|
||||
DriverUtils.cpp
|
||||
EhFrame.cpp
|
||||
Error.cpp
|
||||
Filesystem.cpp
|
||||
GdbIndex.cpp
|
||||
ICF.cpp
|
||||
|
@ -108,7 +108,6 @@ struct Configuration {
|
||||
bool AsNeeded = false;
|
||||
bool Bsymbolic;
|
||||
bool BsymbolicFunctions;
|
||||
bool ColorDiagnostics = false;
|
||||
bool CompressDebugSections;
|
||||
bool DefineCommon;
|
||||
bool Demangle = true;
|
||||
@ -117,7 +116,6 @@ struct Configuration {
|
||||
bool EmitRelocs;
|
||||
bool EnableNewDtags;
|
||||
bool ExportDynamic;
|
||||
bool FatalWarnings;
|
||||
bool GcSections;
|
||||
bool GdbIndex;
|
||||
bool GnuHash = false;
|
||||
@ -167,7 +165,6 @@ struct Configuration {
|
||||
ELFKind EKind = ELFNoneKind;
|
||||
uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
|
||||
uint16_t EMachine = llvm::ELF::EM_NONE;
|
||||
uint64_t ErrorLimit = 20;
|
||||
llvm::Optional<uint64_t> ImageBase;
|
||||
uint64_t MaxPageSize;
|
||||
uint64_t ZStackSize;
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include "Driver.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "Filesystem.h"
|
||||
#include "ICF.h"
|
||||
#include "InputFiles.h"
|
||||
@ -40,6 +39,7 @@
|
||||
#include "Target.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/Driver.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Threads.h"
|
||||
#include "lld/Common/Version.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
@ -72,8 +72,12 @@ static void setConfigs();
|
||||
|
||||
bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
|
||||
raw_ostream &Error) {
|
||||
ErrorCount = 0;
|
||||
ErrorOS = &Error;
|
||||
errorHandler().LogName = Args[0];
|
||||
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();
|
||||
OutputSections.clear();
|
||||
Tar = nullptr;
|
||||
@ -95,10 +99,10 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
|
||||
// This saves time because the overhead of calling destructors
|
||||
// for all globally-allocated objects is not negligible.
|
||||
if (Config->ExitEarly)
|
||||
exitLld(ErrorCount ? 1 : 0);
|
||||
exitLld(errorCount() ? 1 : 0);
|
||||
|
||||
freeArena();
|
||||
return !ErrorCount;
|
||||
return !errorCount();
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// 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
|
||||
if (Args.hasArg(OPT_help)) {
|
||||
@ -365,6 +369,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
|
||||
return;
|
||||
|
||||
Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
|
||||
errorHandler().ExitEarly = Config->ExitEarly;
|
||||
|
||||
if (const char *Path = getReproduceOption(Args)) {
|
||||
// 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();
|
||||
setConfigs();
|
||||
checkOptions(Args);
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
switch (Config->EKind) {
|
||||
@ -645,7 +650,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||
Config->Entry = Args.getLastArgValue(OPT_entry);
|
||||
Config->ExportDynamic =
|
||||
Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
|
||||
Config->FatalWarnings =
|
||||
errorHandler().FatalWarnings =
|
||||
Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
|
||||
Config->FilterList = getArgs(Args, OPT_filter);
|
||||
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
|
||||
@ -694,6 +699,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||
Config->Undefined = getArgs(Args, OPT_undefined);
|
||||
Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
|
||||
Config->Verbose = Args.hasArg(OPT_verbose);
|
||||
errorHandler().Verbose = Config->Verbose;
|
||||
Config->WarnCommon = Args.hasArg(OPT_warn_common);
|
||||
Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
|
||||
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");
|
||||
}
|
||||
|
||||
@ -1009,7 +1015,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
||||
error("cannot open output file " + Config->OutputFile + ": " + E.message());
|
||||
if (auto E = tryCreateFile(Config->MapFile))
|
||||
error("cannot open map file " + Config->MapFile + ": " + E.message());
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// 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);
|
||||
|
||||
// Return if there were name resolution errors.
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// 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->addCombinedLTOObject<ELFT>();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// Apply symbol renames for -wrap and -defsym
|
||||
|
@ -14,8 +14,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Driver.h"
|
||||
#include "Error.h"
|
||||
#include "Memory.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Reproduce.h"
|
||||
#include "lld/Common/Version.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
@ -51,25 +51,26 @@ static const opt::OptTable::Info OptInfo[] = {
|
||||
|
||||
ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
|
||||
|
||||
// Parse -color-diagnostics={auto,always,never} or -no-color-diagnostics.
|
||||
static bool getColorDiagnostics(opt::InputArgList &Args) {
|
||||
// Set color diagnostics according to -color-diagnostics={auto,always,never}
|
||||
// or -no-color-diagnostics flags.
|
||||
static void handleColorDiagnostics(opt::InputArgList &Args) {
|
||||
auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
|
||||
OPT_no_color_diagnostics);
|
||||
if (!Arg)
|
||||
return ErrorOS->has_colors();
|
||||
if (Arg->getOption().getID() == OPT_color_diagnostics)
|
||||
return true;
|
||||
if (Arg->getOption().getID() == OPT_no_color_diagnostics)
|
||||
return false;
|
||||
|
||||
StringRef S = Arg->getValue();
|
||||
if (S == "auto")
|
||||
return ErrorOS->has_colors();
|
||||
if (S == "always")
|
||||
return true;
|
||||
if (S != "never")
|
||||
error("unknown option: -color-diagnostics=" + S);
|
||||
return false;
|
||||
return;
|
||||
else if (Arg->getOption().getID() == OPT_color_diagnostics)
|
||||
errorHandler().ColorDiagnostics = true;
|
||||
else if (Arg->getOption().getID() == OPT_no_color_diagnostics)
|
||||
errorHandler().ColorDiagnostics = false;
|
||||
else {
|
||||
StringRef S = Arg->getValue();
|
||||
if (S == "always")
|
||||
errorHandler().ColorDiagnostics = true;
|
||||
else if (S == "never")
|
||||
errorHandler().ColorDiagnostics = false;
|
||||
else if (S != "auto")
|
||||
error("unknown option: -color-diagnostics=" + S);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
|
||||
|
||||
// Interpret -color-diagnostics early so that error messages
|
||||
// for unknown flags are colored.
|
||||
Config->ColorDiagnostics = getColorDiagnostics(Args);
|
||||
handleColorDiagnostics(Args);
|
||||
if (MissingCount)
|
||||
error(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
|
||||
|
||||
|
@ -17,11 +17,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "EhFrame.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "Relocations.h"
|
||||
#include "Strings.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
@ -8,13 +8,13 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InputFiles.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/Analysis.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
|
@ -11,9 +11,9 @@
|
||||
#define LLD_ELF_INPUT_FILES_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
|
||||
#include "lld/Common/LLVM.h"
|
||||
#include "lld/Common/Reproduce.h"
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "InputSection.h"
|
||||
#include "Config.h"
|
||||
#include "EhFrame.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
@ -19,6 +18,7 @@
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "Thunks.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/Decompressor.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
|
@ -9,11 +9,11 @@
|
||||
|
||||
#include "LTO.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/TargetOptionsCommandFlags.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
|
@ -927,7 +927,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
|
||||
Expr = fromPlt(Expr);
|
||||
|
||||
Expr = adjustExpr<ELFT>(Body, Expr, Type, Sec, Rel.r_offset);
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
continue;
|
||||
|
||||
// This relocation does not require got entry, but it is relative to got and
|
||||
|
@ -33,7 +33,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ScriptLexer.h"
|
||||
#include "Error.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
||||
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.
|
||||
void ScriptLexer::setError(const Twine &Msg) {
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
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.
|
||||
bool ScriptLexer::atEOF() { return ErrorCount || Tokens.size() == Pos; }
|
||||
bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }
|
||||
|
||||
// Split a given string as an expression.
|
||||
// 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.
|
||||
void ScriptLexer::maybeSplitExpr() {
|
||||
if (!InExpr || ErrorCount || atEOF())
|
||||
if (!InExpr || errorCount() || atEOF())
|
||||
return;
|
||||
|
||||
std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
|
||||
@ -220,7 +220,7 @@ void ScriptLexer::maybeSplitExpr() {
|
||||
StringRef ScriptLexer::next() {
|
||||
maybeSplitExpr();
|
||||
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return "";
|
||||
if (atEOF()) {
|
||||
setError("unexpected EOF");
|
||||
@ -231,7 +231,7 @@ StringRef ScriptLexer::next() {
|
||||
|
||||
StringRef ScriptLexer::peek() {
|
||||
StringRef Tok = next();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return "";
|
||||
Pos = Pos - 1;
|
||||
return Tok;
|
||||
@ -260,7 +260,7 @@ bool ScriptLexer::consumeLabel(StringRef Tok) {
|
||||
void ScriptLexer::skip() { (void)next(); }
|
||||
|
||||
void ScriptLexer::expect(StringRef Expect) {
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
StringRef Tok = next();
|
||||
if (Tok != Expect)
|
||||
|
@ -209,7 +209,7 @@ void ScriptParser::readVersionScriptCommand() {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!atEOF() && !ErrorCount && peek() != "}") {
|
||||
while (!atEOF() && !errorCount() && peek() != "}") {
|
||||
StringRef VerStr = next();
|
||||
if (VerStr == "{") {
|
||||
setError("anonymous version definition is used in "
|
||||
@ -303,7 +303,7 @@ void ScriptParser::readAsNeeded() {
|
||||
expect("(");
|
||||
bool Orig = Config->AsNeeded;
|
||||
Config->AsNeeded = true;
|
||||
while (!ErrorCount && !consume(")"))
|
||||
while (!errorCount() && !consume(")"))
|
||||
addFile(unquote(next()));
|
||||
Config->AsNeeded = Orig;
|
||||
}
|
||||
@ -319,13 +319,13 @@ void ScriptParser::readEntry() {
|
||||
|
||||
void ScriptParser::readExtern() {
|
||||
expect("(");
|
||||
while (!ErrorCount && !consume(")"))
|
||||
while (!errorCount() && !consume(")"))
|
||||
Config->Undefined.push_back(next());
|
||||
}
|
||||
|
||||
void ScriptParser::readGroup() {
|
||||
expect("(");
|
||||
while (!ErrorCount && !consume(")")) {
|
||||
while (!errorCount() && !consume(")")) {
|
||||
if (consume("AS_NEEDED"))
|
||||
readAsNeeded();
|
||||
else
|
||||
@ -369,7 +369,7 @@ void ScriptParser::readOutput() {
|
||||
void ScriptParser::readOutputArch() {
|
||||
// OUTPUT_ARCH is ignored for now.
|
||||
expect("(");
|
||||
while (!ErrorCount && !consume(")"))
|
||||
while (!errorCount() && !consume(")"))
|
||||
skip();
|
||||
}
|
||||
|
||||
@ -389,12 +389,12 @@ void ScriptParser::readOutputFormat() {
|
||||
void ScriptParser::readPhdrs() {
|
||||
expect("{");
|
||||
|
||||
while (!ErrorCount && !consume("}")) {
|
||||
while (!errorCount() && !consume("}")) {
|
||||
PhdrsCommand Cmd;
|
||||
Cmd.Name = next();
|
||||
Cmd.Type = readPhdrType();
|
||||
|
||||
while (!ErrorCount && !consume(";")) {
|
||||
while (!errorCount() && !consume(";")) {
|
||||
if (consume("FILEHDR"))
|
||||
Cmd.HasFilehdr = true;
|
||||
else if (consume("PHDRS"))
|
||||
@ -442,7 +442,7 @@ void ScriptParser::readSections() {
|
||||
Config->SingleRoRx = true;
|
||||
|
||||
expect("{");
|
||||
while (!ErrorCount && !consume("}")) {
|
||||
while (!errorCount() && !consume("}")) {
|
||||
StringRef Tok = next();
|
||||
BaseCommand *Cmd = readProvideOrAssignment(Tok);
|
||||
if (!Cmd) {
|
||||
@ -467,7 +467,7 @@ static int precedence(StringRef Op) {
|
||||
|
||||
StringMatcher ScriptParser::readFilePatterns() {
|
||||
std::vector<StringRef> V;
|
||||
while (!ErrorCount && !consume(")"))
|
||||
while (!errorCount() && !consume(")"))
|
||||
V.push_back(next());
|
||||
return StringMatcher(V);
|
||||
}
|
||||
@ -499,7 +499,7 @@ SortSectionPolicy ScriptParser::readSortKind() {
|
||||
// any file but a.o, and section .baz in any file but b.o.
|
||||
std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
|
||||
std::vector<SectionPattern> Ret;
|
||||
while (!ErrorCount && peek() != ")") {
|
||||
while (!errorCount() && peek() != ")") {
|
||||
StringMatcher ExcludeFilePat;
|
||||
if (consume("EXCLUDE_FILE")) {
|
||||
expect("(");
|
||||
@ -507,7 +507,7 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
|
||||
}
|
||||
|
||||
std::vector<StringRef> V;
|
||||
while (!ErrorCount && peek() != ")" && peek() != "EXCLUDE_FILE")
|
||||
while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
|
||||
V.push_back(next());
|
||||
|
||||
if (!V.empty())
|
||||
@ -534,7 +534,7 @@ ScriptParser::readInputSectionRules(StringRef FilePattern) {
|
||||
auto *Cmd = make<InputSectionDescription>(FilePattern);
|
||||
expect("(");
|
||||
|
||||
while (!ErrorCount && !consume(")")) {
|
||||
while (!errorCount() && !consume(")")) {
|
||||
SortSectionPolicy Outer = readSortKind();
|
||||
SortSectionPolicy Inner = SortSectionPolicy::Default;
|
||||
std::vector<SectionPattern> V;
|
||||
@ -676,7 +676,7 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
|
||||
Cmd->Constraint = ConstraintKind::ReadWrite;
|
||||
expect("{");
|
||||
|
||||
while (!ErrorCount && !consume("}")) {
|
||||
while (!errorCount() && !consume("}")) {
|
||||
StringRef Tok = next();
|
||||
if (Tok == ";") {
|
||||
// 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
|
||||
// assumes that the remaining token stream starts with an operator.
|
||||
Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {
|
||||
while (!atEOF() && !ErrorCount) {
|
||||
while (!atEOF() && !errorCount()) {
|
||||
// Read an operator and an expression.
|
||||
if (consume("?"))
|
||||
return readTernary(Lhs);
|
||||
@ -1098,7 +1098,7 @@ Expr ScriptParser::readParenExpr() {
|
||||
|
||||
std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
|
||||
std::vector<StringRef> Phdrs;
|
||||
while (!ErrorCount && peek().startswith(":")) {
|
||||
while (!errorCount() && peek().startswith(":")) {
|
||||
StringRef Tok = next();
|
||||
Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1));
|
||||
}
|
||||
@ -1201,7 +1201,7 @@ ScriptParser::readSymbols() {
|
||||
std::vector<SymbolVersion> Globals;
|
||||
std::vector<SymbolVersion> *V = &Globals;
|
||||
|
||||
while (!ErrorCount) {
|
||||
while (!errorCount()) {
|
||||
if (consume("}"))
|
||||
break;
|
||||
if (consumeLabel("local")) {
|
||||
@ -1235,7 +1235,7 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
|
||||
expect("{");
|
||||
|
||||
std::vector<SymbolVersion> Ret;
|
||||
while (!ErrorCount && peek() != "}") {
|
||||
while (!errorCount() && peek() != "}") {
|
||||
StringRef Tok = next();
|
||||
bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok);
|
||||
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 ... }
|
||||
void ScriptParser::readMemory() {
|
||||
expect("{");
|
||||
while (!ErrorCount && !consume("}")) {
|
||||
while (!errorCount() && !consume("}")) {
|
||||
StringRef Name = next();
|
||||
|
||||
uint32_t Flags = 0;
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "Strings.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
#include "SymbolTable.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -91,7 +91,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
|
||||
if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
|
||||
// DSOs are uniquified not by filename but by soname.
|
||||
F->parseSoName();
|
||||
if (ErrorCount || !SoNames.insert(F->SoName).second)
|
||||
if (errorCount() || !SoNames.insert(F->SoName).second)
|
||||
return;
|
||||
SharedFiles.push_back(F);
|
||||
F->parseRest();
|
||||
|
@ -8,7 +8,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Symbols.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "InputSection.h"
|
||||
#include "OutputSections.h"
|
||||
@ -17,6 +16,7 @@
|
||||
#include "Target.h"
|
||||
#include "Writer.h"
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include <cstring>
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include "SyntheticSections.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "LinkerScript.h"
|
||||
#include "Memory.h"
|
||||
@ -25,6 +24,7 @@
|
||||
#include "SymbolTable.h"
|
||||
#include "Target.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Threads.h"
|
||||
#include "lld/Common/Version.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
|
@ -25,11 +25,11 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Target.h"
|
||||
#include "Error.h"
|
||||
#include "InputFiles.h"
|
||||
#include "OutputSections.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
@ -10,8 +10,8 @@
|
||||
#ifndef LLD_ELF_TARGET_H
|
||||
#define LLD_ELF_TARGET_H
|
||||
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/Object/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
|
@ -23,13 +23,13 @@
|
||||
|
||||
#include "Thunks.h"
|
||||
#include "Config.h"
|
||||
#include "Error.h"
|
||||
#include "InputSection.h"
|
||||
#include "Memory.h"
|
||||
#include "OutputSections.h"
|
||||
#include "Symbols.h"
|
||||
#include "SyntheticSections.h"
|
||||
#include "Target.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
|
@ -188,7 +188,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
||||
// to the string table, and add entries to .got and .plt.
|
||||
// finalizeSections does that.
|
||||
finalizeSections();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// 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.
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
// Write the result down to a file.
|
||||
openFile();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
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
|
||||
// because the content is usually a hash value of the entire output file.
|
||||
writeBuildId();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
// Handle -Map option.
|
||||
writeMapFile<ELFT>();
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
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.
|
||||
if (ErrorCount)
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
addPredefinedSections();
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===- Error.h --------------------------------------------------*- C++ -*-===//
|
||||
//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
@ -25,24 +25,48 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_ELF_ERROR_H
|
||||
#define LLD_ELF_ERROR_H
|
||||
#ifndef LLD_COMMON_ERRORHANDLER_H
|
||||
#define LLD_COMMON_ERRORHANDLER_H
|
||||
|
||||
#include "lld/Common/LLVM.h"
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
||||
extern uint64_t ErrorCount;
|
||||
extern llvm::raw_ostream *ErrorOS;
|
||||
class ErrorHandler {
|
||||
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 message(const Twine &Msg);
|
||||
void warn(const Twine &Msg);
|
||||
void error(const Twine &Msg);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
|
||||
void error(const Twine &Msg);
|
||||
LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
|
||||
void log(const Twine &Msg);
|
||||
void message(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);
|
||||
|
||||
@ -72,7 +96,6 @@ template <class T> T check(Expected<T> E, const Twine &Prefix) {
|
||||
return std::move(*E);
|
||||
}
|
||||
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user