forked from OSchip/llvm-project
109 lines
3.6 KiB
C++
109 lines
3.6 KiB
C++
//===- lib/Driver/GnuLdInputGraph.cpp -------------------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lld/Driver/GnuLdInputGraph.h"
|
|
#include "lld/ReaderWriter/LinkerScript.h"
|
|
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace lld;
|
|
|
|
/// \brief Parse the input file to lld::File.
|
|
std::error_code ELFFileNode::parse(const LinkingContext &ctx,
|
|
raw_ostream &diagnostics) {
|
|
ErrorOr<StringRef> filePath = getPath(ctx);
|
|
if (std::error_code ec = filePath.getError())
|
|
return ec;
|
|
if (std::error_code ec = getBuffer(*filePath))
|
|
return ec;
|
|
if (ctx.logInputFiles())
|
|
diagnostics << *filePath << "\n";
|
|
|
|
if (_attributes._isWholeArchive) {
|
|
std::vector<std::unique_ptr<File>> parsedFiles;
|
|
if (std::error_code ec = ctx.registry().parseFile(_buffer, parsedFiles))
|
|
return ec;
|
|
assert(parsedFiles.size() == 1);
|
|
std::unique_ptr<File> f(parsedFiles[0].release());
|
|
if (const auto *archive = dyn_cast<ArchiveLibraryFile>(f.get())) {
|
|
// Have this node own the FileArchive object.
|
|
_archiveFile.reset(archive);
|
|
f.release();
|
|
// Add all members to _files vector
|
|
return archive->parseAllMembers(_files);
|
|
}
|
|
// if --whole-archive is around non-archive, just use it as normal.
|
|
_files.push_back(std::move(f));
|
|
return std::error_code();
|
|
}
|
|
return ctx.registry().parseFile(_buffer, _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;
|
|
if (std::error_code ec = getBuffer(*filePath))
|
|
return ec;
|
|
|
|
if (ctx.logInputFiles())
|
|
diagnostics << *filePath << "\n";
|
|
|
|
_lexer.reset(new script::Lexer(std::move(_buffer)));
|
|
_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;
|
|
std::unique_ptr<Group> groupStart(new Group());
|
|
for (const script::Path &path : group->getPaths()) {
|
|
// TODO : Propagate Set WholeArchive/dashlPrefix
|
|
attributes.setAsNeeded(path._asNeeded);
|
|
auto inputNode = new ELFFileNode(
|
|
_elfLinkingContext, _elfLinkingContext.allocateString(path._path),
|
|
attributes);
|
|
std::unique_ptr<InputElement> inputFile(inputNode);
|
|
groupStart.get()->addFile(std::move(inputFile));
|
|
}
|
|
_expandElements.push_back(std::move(groupStart));
|
|
}
|
|
return std::error_code();
|
|
}
|