summaryrefslogtreecommitdiff
path: root/COFF/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'COFF/Driver.cpp')
-rw-r--r--COFF/Driver.cpp55
1 files changed, 35 insertions, 20 deletions
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index 4cacf0ff552a..bb6a60e4fc4c 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -14,6 +14,7 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
+#include "lld/Driver/Driver.h"
#include "llvm/ADT/Optional.h"
#include "llvm/LibDriver/LibDriver.h"
#include "llvm/Option/Arg.h"
@@ -40,27 +41,28 @@ namespace coff {
Configuration *Config;
LinkerDriver *Driver;
-void link(llvm::ArrayRef<const char *> Args) {
+bool link(llvm::ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
Config = &C;
Driver = &D;
- return Driver->link(Args);
+ Driver->link(Args);
+ return true;
}
-// Drop directory components and replace extension with ".exe".
+// Drop directory components and replace extension with ".exe" or ".dll".
static std::string getOutputPath(StringRef Path) {
auto P = Path.find_last_of("\\/");
StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
- return (S.substr(0, S.rfind('.')) + ".exe").str();
+ const char* E = Config->DLL ? ".dll" : ".exe";
+ return (S.substr(0, S.rfind('.')) + E).str();
}
// Opens a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
- auto MBOrErr = MemoryBuffer::getFile(Path);
- error(MBOrErr, Twine("Could not open ") + Path);
- std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
+ std::unique_ptr<MemoryBuffer> MB =
+ check(MemoryBuffer::getFile(Path), "could not open " + Path);
MemoryBufferRef MBRef = MB->getMemBufferRef();
OwningMBs.push_back(std::move(MB)); // take ownership
return MBRef;
@@ -116,12 +118,16 @@ void LinkerDriver::parseDirectives(StringRef S) {
case OPT_nodefaultlib:
Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
break;
+ case OPT_section:
+ parseSection(Arg->getValue());
+ break;
case OPT_editandcontinue:
+ case OPT_fastfail:
case OPT_guardsym:
case OPT_throwingnew:
break;
default:
- error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
+ fatal(Arg->getSpelling() + " is not allowed in .drectve");
}
}
}
@@ -246,7 +252,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// We call our own implementation of lib.exe that understands bitcode files.
if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) {
if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)
- error("lib failed");
+ fatal("lib failed");
return;
}
@@ -268,7 +274,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
}
if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
- error("no input files.");
+ fatal("no input files");
// Construct search path list.
SearchPaths.push_back("");
@@ -295,7 +301,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
if (!Args.hasArg(OPT_dll))
- error("/noentry must be specified with /dll");
+ fatal("/noentry must be specified with /dll");
Config->NoEntry = true;
}
@@ -308,7 +314,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /fixed
if (Args.hasArg(OPT_fixed)) {
if (Args.hasArg(OPT_dynamicbase))
- error("/fixed must not be specified with /dynamicbase");
+ fatal("/fixed must not be specified with /dynamicbase");
Config->Relocatable = false;
Config->DynamicBase = false;
}
@@ -382,17 +388,17 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
StringRef OptLevel = StringRef(S).substr(7);
if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
Config->LTOOptLevel > 3)
- error("/opt:lldlto: invalid optimization level: " + OptLevel);
+ fatal("/opt:lldlto: invalid optimization level: " + OptLevel);
continue;
}
if (StringRef(S).startswith("lldltojobs=")) {
StringRef Jobs = StringRef(S).substr(11);
if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0)
- error("/opt:lldltojobs: invalid job count: " + Jobs);
+ fatal("/opt:lldltojobs: invalid job count: " + Jobs);
continue;
}
if (S != "ref" && S != "lbr" && S != "nolbr")
- error(Twine("/opt: unknown option: ") + S);
+ fatal("/opt: unknown option: " + S);
}
}
@@ -404,6 +410,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_merge))
parseMerge(Arg->getValue());
+ // Handle /section
+ for (auto *Arg : Args.filtered(OPT_section))
+ parseSection(Arg->getValue());
+
// Handle /manifest
if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
parseManifest(Arg->getValue());
@@ -420,6 +430,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_manifestfile))
Config->ManifestFile = Arg->getValue();
+ // Handle /manifestinput
+ for (auto *Arg : Args.filtered(OPT_manifestinput))
+ Config->ManifestInput.push_back(Arg->getValue());
+
// Handle miscellaneous boolean flags.
if (Args.hasArg(OPT_allowbind_no))
Config->AllowBind = false;
@@ -485,7 +499,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
continue;
}
if (Config->Machine != MT)
- error(Twine(File->getShortName()) + ": machine type " + machineToStr(MT) +
+ fatal(File->getShortName() + ": machine type " + machineToStr(MT) +
" conflicts with " + machineToStr(Config->Machine));
}
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
@@ -520,7 +534,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// infer that from user-defined entry name.
StringRef S = findDefaultEntry();
if (S.empty())
- error("entry point must be defined");
+ fatal("entry point must be defined");
Config->Entry = addUndefined(S);
if (Config->Verbose)
llvm::outs() << "Entry name inferred: " << S << "\n";
@@ -627,14 +641,14 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
Config->Subsystem = inferSubsystem();
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
- error("subsystem must be defined");
+ fatal("subsystem must be defined");
}
// Handle /safeseh.
if (Args.hasArg(OPT_safeseh))
for (ObjectFile *File : Symtab.ObjectFiles)
if (!File->SEHCompat)
- error("/safeseh: " + File->getName() + " is not compatible with SEH");
+ fatal("/safeseh: " + File->getName() + " is not compatible with SEH");
// Windows specific -- when we are creating a .dll file, we also
// need to create a .lib file.
@@ -668,7 +682,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_lldmap)) {
std::error_code EC;
llvm::raw_fd_ostream Out(Arg->getValue(), EC, OpenFlags::F_Text);
- error(EC, "Could not create the symbol map");
+ if (EC)
+ fatal(EC, "could not create the symbol map");
Symtab.printMap(Out);
}
// Call exit to avoid calling destructors.