summaryrefslogtreecommitdiffstats
path: root/lld/lib/Driver/GnuLdDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/Driver/GnuLdDriver.cpp')
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp279
1 files changed, 155 insertions, 124 deletions
diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp
index 01c7c489b1a..96fa31905fc 100644
--- a/lld/lib/Driver/GnuLdDriver.cpp
+++ b/lld/lib/Driver/GnuLdDriver.cpp
@@ -14,7 +14,7 @@
//===----------------------------------------------------------------------===//
#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
+#include "lld/Driver/GnuLDInputGraph.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
@@ -71,10 +71,20 @@ public:
} // namespace
+std::unique_ptr<lld::LinkerInput>
+ELFFileNode::createLinkerInput(const LinkingContext &ctx) {
+ std::unique_ptr<LinkerInput> inputFile(new LinkerInput(path(ctx)));
+ inputFile->setAsNeeded(_asNeeded);
+ inputFile->setForceLoad(_isWholeArchive);
+ return std::move(inputFile);
+}
+StringRef ELFFileNode::path(const LinkingContext &) const {
+ return _elfLinkingContext.searchLibrary(_path, _libraryPaths);
+}
bool GnuLdDriver::linkELF(int argc, const char *argv[],
- raw_ostream &diagnostics) {
+ raw_ostream &diagnostics) {
std::unique_ptr<ELFLinkingContext> options;
bool error = parse(argc, argv, options, diagnostics);
if (error)
@@ -93,6 +103,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
GnuLdOptTable table;
unsigned missingIndex;
unsigned missingCount;
+
parsedArgs.reset(
table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
if (missingCount) {
@@ -102,13 +113,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
return true;
}
- for (auto it = parsedArgs->filtered_begin(OPT_UNKNOWN),
- ie = parsedArgs->filtered_end(); it != ie; ++it) {
- diagnostics << "warning: ignoring unknown argument: " << (*it)->getAsString(
- *parsedArgs)
- << "\n";
- }
-
// Handle --help
if (parsedArgs->getLastArg(OPT_help)) {
table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
@@ -121,154 +125,181 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
triple = llvm::Triple(trip->getValue());
else
triple = getDefaultTarget(argv[0]);
- std::unique_ptr<ELFLinkingContext> options(ELFLinkingContext::create(triple));
+ std::unique_ptr<ELFLinkingContext> ctx(ELFLinkingContext::create(triple));
- if (!options) {
+ if (!ctx) {
diagnostics << "unknown target triple\n";
return true;
}
- // Handle -e xxx
- if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
- options->setEntrySymbolName(entry->getValue());
-
- // Handle -emit-yaml
- if (parsedArgs->getLastArg(OPT_emit_yaml))
- options->setOutputYAML(true);
-
- // Handle -o xxx
- if (llvm::opt::Arg *output = parsedArgs->getLastArg(OPT_output))
- options->setOutputPath(output->getValue());
- else if (options->outputYAML())
- options->setOutputPath("-"); // yaml writes to stdout by default
- else
- options->setOutputPath("a.out");
-
- // Handle -r, -shared, or -static
- if (llvm::opt::Arg *kind =
- parsedArgs->getLastArg(OPT_relocatable, OPT_shared, OPT_static)) {
- switch (kind->getOption().getID()) {
+ std::unique_ptr<InputGraph> inputGraph(new InputGraph());
+ std::stack<InputElement *> controlNodeStack;
+
+ // Positional options for an Input File
+ std::vector<StringRef> searchPath;
+ bool isWholeArchive = false;
+ bool asNeeded = false;
+ bool _outputOptionSet = false;
+
+ // Create a dynamic executable by default
+ ctx->setOutputFileType(llvm::ELF::ET_EXEC);
+ ctx->setIsStaticExecutable(false);
+ ctx->setAllowShlibUndefines(false);
+ ctx->setUseShlibUndefines(true);
+
+ // Set the output file to be a.out
+ ctx->setOutputPath("a.out");
+
+ // Process all the arguments and create Input Elements
+ for (auto inputArg : *parsedArgs) {
+ switch (inputArg->getOption().getID()) {
+ case OPT_mllvm:
+ ctx->appendLLVMOption(inputArg->getValue());
+ break;
case OPT_relocatable:
- options->setOutputFileType(llvm::ELF::ET_REL);
- options->setPrintRemainingUndefines(false);
- options->setAllowRemainingUndefines(true);
+ ctx->setOutputFileType(llvm::ELF::ET_REL);
+ ctx->setPrintRemainingUndefines(false);
+ ctx->setAllowRemainingUndefines(true);
+ break;
+ case OPT_static:
+ ctx->setOutputFileType(llvm::ELF::ET_EXEC);
+ ctx->setIsStaticExecutable(true);
break;
case OPT_shared:
- options->setOutputFileType(llvm::ELF::ET_DYN);
- options->setAllowShlibUndefines(true);
- options->setUseShlibUndefines(false);
+ ctx->setOutputFileType(llvm::ELF::ET_DYN);
+ ctx->setAllowShlibUndefines(true);
+ ctx->setUseShlibUndefines(false);
break;
- case OPT_static:
- options->setOutputFileType(llvm::ELF::ET_EXEC);
- options->setIsStaticExecutable(true);
+ case OPT_entry:
+ ctx->setEntrySymbolName(inputArg->getValue());
break;
- }
- } else {
- options->setOutputFileType(llvm::ELF::ET_EXEC);
- options->setIsStaticExecutable(false);
- options->setAllowShlibUndefines(false);
- options->setUseShlibUndefines(true);
- }
-
- // Handle --noinhibit-exec
- if (parsedArgs->getLastArg(OPT_noinhibit_exec))
- options->setAllowRemainingUndefines(true);
- // Handle --force-load
- if (parsedArgs->getLastArg(OPT_force_load))
- options->setForceLoadAllArchives(true);
+ case OPT_output:
+ _outputOptionSet = true;
+ ctx->setOutputPath(inputArg->getValue());
+ break;
- // Handle --merge-strings
- if (parsedArgs->getLastArg(OPT_merge_strings))
- options->setMergeCommonStrings(true);
+ case OPT_noinhibit_exec:
+ ctx->setAllowRemainingUndefines(true);
+ break;
- // Handle -t
- if (parsedArgs->getLastArg(OPT_t))
- options->setLogInputFiles(true);
+ case OPT_merge_strings:
+ ctx->setMergeCommonStrings(true);
+ break;
- // Handle --no-allow-shlib-undefined
- if (parsedArgs->getLastArg(OPT_no_allow_shlib_undefs))
- options->setAllowShlibUndefines(false);
+ case OPT_all_load:
+ ctx->setForceLoadAllArchives(true);
+ break;
- // Handle --allow-shlib-undefined
- if (parsedArgs->getLastArg(OPT_allow_shlib_undefs))
- options->setAllowShlibUndefines(true);
+ case OPT_t:
+ ctx->setLogInputFiles(true);
+ break;
- // Handle --use-shlib-undefs
- if (parsedArgs->getLastArg(OPT_use_shlib_undefs))
- options->setUseShlibUndefines(true);
+ case OPT_no_allow_shlib_undefs:
+ ctx->setAllowShlibUndefines(false);
+ break;
- // Handle --dynamic-linker
- if (llvm::opt::Arg *dynamicLinker =
- parsedArgs->getLastArg(OPT_dynamic_linker))
- options->setInterpreter(dynamicLinker->getValue());
+ case OPT_allow_shlib_undefs:
+ ctx->setAllowShlibUndefines(true);
+ break;
- // Handle NMAGIC
- if (parsedArgs->getLastArg(OPT_nmagic))
- options->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
+ case OPT_use_shlib_undefs:
+ ctx->setUseShlibUndefines(true);
+ break;
- // Handle OMAGIC
- if (parsedArgs->getLastArg(OPT_omagic))
- options->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
+ case OPT_dynamic_linker:
+ ctx->setInterpreter(inputArg->getValue());
+ break;
- // Handle --no-omagic
- if (parsedArgs->getLastArg(OPT_no_omagic)) {
- options->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
- options->setNoAllowDynamicLibraries();
- }
+ case OPT_nmagic:
+ ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
+ ctx->setIsStaticExecutable(true);
+ break;
- // If either of the options NMAGIC/OMAGIC have been set, make the executable
- // static
- if (!options->allowLinkWithDynamicLibraries())
- options->setIsStaticExecutable(true);
+ case OPT_omagic:
+ ctx->setOutputMagic(ELFLinkingContext::OutputMagic::OMAGIC);
+ ctx->setIsStaticExecutable(true);
+ break;
- // Handle -u, --undefined option
- for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_u),
- ie = parsedArgs->filtered_end();
- it != ie; ++it) {
- options->addInitialUndefinedSymbol((*it)->getValue());
- }
+ case OPT_no_omagic:
+ ctx->setOutputMagic(ELFLinkingContext::OutputMagic::DEFAULT);
+ ctx->setNoAllowDynamicLibraries();
+ break;
- // Handle -Lxxx
- for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_L),
- ie = parsedArgs->filtered_end();
- it != ie; ++it) {
- options->appendSearchPath((*it)->getValue());
- }
+ case OPT_u:
+ ctx->addInitialUndefinedSymbol(inputArg->getValue());
+ break;
- // Copy mllvm
- for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
- ie = parsedArgs->filtered_end();
- it != ie; ++it) {
- options->appendLLVMOption((*it)->getValue());
- }
+ case OPT_emit_yaml:
+ if (!_outputOptionSet)
+ ctx->setOutputPath("-");
+ ctx->setOutputYAML(true);
+ break;
- // Handle input files (full paths and -lxxx)
- for (llvm::opt::arg_iterator
- it = parsedArgs->filtered_begin(OPT_INPUT, OPT_l),
- ie = parsedArgs->filtered_end();
- it != ie; ++it) {
- switch ((*it)->getOption().getID()) {
- case OPT_INPUT:
- options->appendInputFile((*it)->getValue());
+ case OPT_no_whole_archive:
+ isWholeArchive = false;
+ break;
+ case OPT_whole_archive:
+ isWholeArchive = true;
+ break;
+ case OPT_as_needed:
+ asNeeded = true;
break;
- case OPT_l:
- if (options->appendLibrary((*it)->getValue())) {
- diagnostics << "Failed to find library for " << (*it)->getValue()
- << "\n";
- return true;
- }
+ case OPT_no_as_needed:
+ asNeeded = false;
break;
+ case OPT_L:
+ searchPath.push_back(inputArg->getValue());
+ break;
+
+ case OPT_start_group: {
+ std::unique_ptr<InputElement> controlStart(new ELFGroup(*ctx));
+ controlNodeStack.push(controlStart.get());
+ (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+ ->processControlEnter();
+ inputGraph->addInputElement(std::move(controlStart));
+ } break;
+
+ case OPT_end_group:
+ (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+ ->processControlExit();
+ controlNodeStack.pop();
+ return false;
+
+ case OPT_INPUT:
+ case OPT_l: {
+ std::unique_ptr<InputElement> inputFile =
+ std::move(std::unique_ptr<InputElement>(
+ new ELFFileNode(*ctx, inputArg->getValue(), isWholeArchive,
+ asNeeded, searchPath)));
+ if (controlNodeStack.empty())
+ inputGraph->addInputElement(std::move(inputFile));
+ else
+ (llvm::dyn_cast<ControlNode>)(controlNodeStack.top())
+ ->processInputElement(std::move(inputFile));
+ } break;
+
default:
- llvm_unreachable("input option type not handled");
- }
+ break;
+ } // end switch on option ID
+ } // end for
+
+ if (!inputGraph->numFiles()) {
+ diagnostics << "No input files\n";
+ return true;
}
+ if (ctx->outputYAML())
+ inputGraph->dump(diagnostics);
+
// Validate the combination of options used.
- if (options->validate(diagnostics))
+ if (ctx->validate(diagnostics))
return true;
- context.swap(options);
+ ctx->setInputGraph(std::move(inputGraph));
+
+ context.swap(ctx);
+
return false;
}
OpenPOWER on IntegriCloud