summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2015-01-07 01:13:08 +0000
committerRui Ueyama <ruiu@google.com>2015-01-07 01:13:08 +0000
commit5a25fd596238556a447d3e004624dafa0dfd59a4 (patch)
tree870c26ad68bcb286ab72726c6e92feecfb5568bf
parent5310c1e9549c18af257eaf2c13782e29419dc28d (diff)
downloadbcm5719-llvm-5a25fd596238556a447d3e004624dafa0dfd59a4.tar.gz
bcm5719-llvm-5a25fd596238556a447d3e004624dafa0dfd59a4.zip
[ELF] Remove {ELF,}GNULinkerScript.
Instead of representing a linker script file as an "InputElement", parse and evaluate scripts in the driver as we see them. Linker scripts are not regular input files (regular file is one of object, archive, or shared library file). They are more like extended command line options. Linker script handling was needlessly complicated because of that inappropriate abstraction (besides excessive class hierarchy -- there is no such thing like ELF linker script but we had two classes there for some reason.) LinkerScript was one of a few remaining InputElement subclasses that can be expanded to multiple files. With this patch, we are one step closer to retire InputElement. http://reviews.llvm.org/D6648 llvm-svn: 225330
-rw-r--r--lld/include/lld/Driver/GnuLdInputGraph.h36
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp65
-rw-r--r--lld/lib/Driver/GnuLdInputGraph.cpp65
3 files changed, 57 insertions, 109 deletions
diff --git a/lld/include/lld/Driver/GnuLdInputGraph.h b/lld/include/lld/Driver/GnuLdInputGraph.h
index 69b81f9fd18..ba06a87bc04 100644
--- a/lld/include/lld/Driver/GnuLdInputGraph.h
+++ b/lld/include/lld/Driver/GnuLdInputGraph.h
@@ -21,7 +21,6 @@
#include "lld/Core/InputGraph.h"
#include "lld/Core/Resolver.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "lld/ReaderWriter/LinkerScript.h"
namespace lld {
@@ -81,41 +80,6 @@ private:
const Attributes _attributes;
};
-/// \brief Parse GNU Linker scripts.
-class GNULdScript : public FileNode {
-public:
- GNULdScript(ELFLinkingContext &ctx, StringRef userPath)
- : FileNode(userPath), _elfLinkingContext(ctx), _linkerScript(nullptr) {}
-
- /// \brief Parse the linker script.
- std::error_code parse(const LinkingContext &, raw_ostream &) override;
-
-protected:
- ELFLinkingContext &_elfLinkingContext;
- std::unique_ptr<script::Parser> _parser;
- std::unique_ptr<script::Lexer> _lexer;
- script::LinkerScript *_linkerScript;
-};
-
-/// \brief Handle ELF style with GNU Linker scripts.
-class ELFGNULdScript : public GNULdScript {
-public:
- ELFGNULdScript(ELFLinkingContext &ctx, StringRef userPath)
- : GNULdScript(ctx, userPath) {}
-
- std::error_code parse(const LinkingContext &ctx,
- raw_ostream &diagnostics) override;
-
- bool getReplacements(InputGraph::InputElementVectorT &result) override {
- for (std::unique_ptr<InputElement> &elt : _expandElements)
- result.push_back(std::move(elt));
- return true;
- }
-
-private:
- InputGraph::InputElementVectorT _expandElements;
-};
-
} // namespace lld
#endif
diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp
index 2451ac818cc..8ec7d15751a 100644
--- a/lld/lib/Driver/GnuLdDriver.cpp
+++ b/lld/lib/Driver/GnuLdDriver.cpp
@@ -15,6 +15,7 @@
#include "lld/Driver/Driver.h"
#include "lld/Driver/GnuLdInputGraph.h"
+#include "lld/ReaderWriter/LinkerScript.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
@@ -217,6 +218,54 @@ static bool isLinkerScript(StringRef path, raw_ostream &diag) {
return magic == llvm::sys::fs::file_magic::unknown;
}
+static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
+ if (sysroot.empty())
+ return false;
+ while (!path.empty() && !llvm::sys::fs::equivalent(sysroot, path))
+ path = llvm::sys::path::parent_path(path);
+ return !path.empty();
+}
+
+static std::error_code
+evaluateLinkerScript(ELFLinkingContext &ctx, InputGraph *inputGraph,
+ StringRef path, raw_ostream &diag) {
+ // Read the script file from disk and parse.
+ ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
+ MemoryBuffer::getFileOrSTDIN(path);
+ if (std::error_code ec = mb.getError())
+ return ec;
+ if (ctx.logInputFiles())
+ diag << path << "\n";
+ auto lexer = llvm::make_unique<script::Lexer>(std::move(mb.get()));
+ auto parser = llvm::make_unique<script::Parser>(*lexer);
+ script::LinkerScript *script = parser->parse();
+ if (!script)
+ return LinkerScriptReaderError::parse_error;
+
+ // Evaluate script commands.
+ // Currently we only recognize GROUP() command.
+ bool sysroot = (!ctx.getSysroot().empty()
+ && isPathUnderSysroot(ctx.getSysroot(), path));
+ for (const script::Command *c : script->_commands) {
+ auto *group = dyn_cast<script::Group>(c);
+ if (!group)
+ continue;
+ int numfiles = 0;
+ for (const script::Path &path : group->getPaths()) {
+ // TODO : Propagate Set WholeArchive/dashlPrefix
+ ELFFileNode::Attributes attr;
+ attr.setSysRooted(sysroot);
+ attr.setAsNeeded(path._asNeeded);
+ attr.setDashlPrefix(path._isDashlPrefix);
+ ++numfiles;
+ inputGraph->addInputElement(llvm::make_unique<ELFFileNode>(
+ ctx, ctx.allocateString(path._path), attr));
+ }
+ inputGraph->addInputElement(llvm::make_unique<GroupEnd>(numfiles));
+ }
+ return std::error_code();
+}
+
bool GnuLdDriver::applyEmulation(llvm::Triple &triple,
llvm::opt::InputArgList &args,
raw_ostream &diagnostics) {
@@ -529,19 +578,19 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
bool isScript =
(!path.endswith(".objtxt") && isLinkerScript(realpath, diagnostics));
- FileNode *inputNode = nullptr;
if (isScript) {
- inputNode = new ELFGNULdScript(*ctx, realpath);
- if (inputNode->parse(*ctx, diagnostics)) {
- diagnostics << path << ": Error parsing linker script\n";
+ std::error_code ec = evaluateLinkerScript(
+ *ctx, inputGraph.get(), realpath, diagnostics);
+ if (ec) {
+ diagnostics << path << ": Error parsing linker script: "
+ << ec.message() << "\n";
return false;
}
- } else {
- inputNode = new ELFFileNode(*ctx, path, attributes);
+ break;
}
- std::unique_ptr<InputElement> inputFile(inputNode);
++numfiles;
- inputGraph->addInputElement(std::move(inputFile));
+ inputGraph->addInputElement(
+ llvm::make_unique<ELFFileNode>(*ctx, path, attributes));
break;
}
diff --git a/lld/lib/Driver/GnuLdInputGraph.cpp b/lld/lib/Driver/GnuLdInputGraph.cpp
index d13dbde6731..588576a0d1a 100644
--- a/lld/lib/Driver/GnuLdInputGraph.cpp
+++ b/lld/lib/Driver/GnuLdInputGraph.cpp
@@ -63,68 +63,3 @@ std::error_code ELFFileNode::parse(const LinkingContext &ctx,
}
return ctx.registry().parseFile(std::move(mb.get()), _files);
}
-
-/// \brief Parse the GnuLD Script
-std::error_code GNULdScript::parse(const LinkingContext &ctx,
- raw_ostream &diagnostics) {
- ErrorOr<StringRef> filePath = getPath(ctx);
- if (std::error_code ec = filePath.getError())
- return ec;
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(*filePath);
- if (std::error_code ec = mb.getError())
- return ec;
-
- if (ctx.logInputFiles())
- diagnostics << *filePath << "\n";
-
- _lexer.reset(new script::Lexer(std::move(mb.get())));
- _parser.reset(new script::Parser(*_lexer.get()));
-
- _linkerScript = _parser->parse();
-
- if (!_linkerScript)
- return LinkerScriptReaderError::parse_error;
-
- return std::error_code();
-}
-
-static bool isPathUnderSysroot(StringRef sysroot, StringRef path) {
- if (sysroot.empty())
- return false;
-
- while (!path.empty() && !llvm::sys::fs::equivalent(sysroot, path))
- path = llvm::sys::path::parent_path(path);
-
- return !path.empty();
-}
-
-/// \brief Handle GnuLD script for ELF.
-std::error_code ELFGNULdScript::parse(const LinkingContext &ctx,
- raw_ostream &diagnostics) {
- ELFFileNode::Attributes attributes;
- if (std::error_code ec = GNULdScript::parse(ctx, diagnostics))
- return ec;
- StringRef sysRoot = _elfLinkingContext.getSysroot();
- if (!sysRoot.empty() && isPathUnderSysroot(sysRoot, *getPath(ctx)))
- attributes.setSysRooted(true);
- for (const script::Command *c : _linkerScript->_commands) {
- auto *group = dyn_cast<script::Group>(c);
- if (!group)
- continue;
- size_t numfiles = 0;
- for (const script::Path &path : group->getPaths()) {
- // TODO : Propagate Set WholeArchive/dashlPrefix
- attributes.setAsNeeded(path._asNeeded);
- attributes.setDashlPrefix(path._isDashlPrefix);
- auto inputNode = new ELFFileNode(
- _elfLinkingContext, _elfLinkingContext.allocateString(path._path),
- attributes);
- std::unique_ptr<InputElement> inputFile(inputNode);
- _expandElements.push_back(std::move(inputFile));
- ++numfiles;
- }
- _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));
- }
- return std::error_code();
-}
OpenPOWER on IntegriCloud